diff --git a/PROMS/ReferencedObjects/Exe/RefObj/ROEditor/RO_FST.cs b/PROMS/ReferencedObjects/Exe/RefObj/ROEditor/RO_FST.cs index 44283442..67b47ca0 100644 --- a/PROMS/ReferencedObjects/Exe/RefObj/ROEditor/RO_FST.cs +++ b/PROMS/ReferencedObjects/Exe/RefObj/ROEditor/RO_FST.cs @@ -116,12 +116,12 @@ namespace ROEditor public uint thisoff; public string title; - public FstTmpSTRC(ushort type, uint offset, string tl) + public FstTmpSTRC(ushort type, uint offset, string tl) { thistype = type; thisoff = offset; title = tl; - } + } void WriteString(BinaryWriter bw, string str) { @@ -150,7 +150,7 @@ namespace ROEditor bw.Write(thisoff); bw.Write(thistype); WriteString(bw,title); - } + } } // The Sorted Array was not sorting via the ASCII value of each character in a given string. @@ -565,8 +565,8 @@ namespace ROEditor string RecIdStr = elem.GetAttribute("RecID"); curRecID = System.Convert.ToUInt32(RecIdStr,16); - // Get the current node's parent id - string ParIdStr = elem.GetAttribute("ParentID"); + // Get the current node's parent id + string ParIdStr = elem.GetAttribute("ParentID"); elemParentID = Convert.ToUInt32(ParIdStr,16); string HasKids = elem.GetAttribute("HasChild"); @@ -771,8 +771,8 @@ namespace ROEditor private ushort SaveROToFST(XmlNode RONode,ArrayList InUseList,string RtnValTmplate, string AccPageIDTplate) { ushort RtnVal; - uint startFST = (uint)fhFST.BaseStream.Position; - uint RORecID; + uint startFST = (uint)fhFST.BaseStream.Position; + uint RORecID; uint ParID; byte nullbyte=0; @@ -844,8 +844,12 @@ namespace ROEditor AccPageID = " "; WriteString(AccPageID); - // Save the ID and offset entry for the current ID - IdsAndOffsets.Add(RORecID,startFST); + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + string moddt = ROdatabase.RODB_GetModDateTime(elem.GetAttribute("RecID"), elem.GetAttribute("Table")); + if (!string.IsNullOrEmpty(moddt)) WriteString(moddt); + + // Save the ID and offset entry for the current ID + IdsAndOffsets.Add(RORecID, startFST); // Save the RecID and Accessory Page id IdsAndAccPgIds[AccPageID] = RORecID; diff --git a/PROMS/ReferencedObjects/LibSource/RODBInterface/RODBInterface.cs b/PROMS/ReferencedObjects/LibSource/RODBInterface/RODBInterface.cs index ee29fbcd..d78f1380 100644 --- a/PROMS/ReferencedObjects/LibSource/RODBInterface/RODBInterface.cs +++ b/PROMS/ReferencedObjects/LibSource/RODBInterface/RODBInterface.cs @@ -322,9 +322,9 @@ namespace RODBInterface get { return _PCChildList; } set { _PCChildList = value; } } - #endregion - #region abstracts // need these for each method that must be defined for each database type - public abstract string RODB_GetNextGroupTable(); + #endregion + #region abstracts // need these for each method that must be defined for each database type + public abstract string RODB_GetNextGroupTable(); public abstract string RODB_GetNextRecId(string table); public abstract bool RODB_GetRootGroups(VlnXmlElement root); public abstract bool RODB_DeleteGroup(XmlNode group, string tbname, string toprecid); @@ -355,9 +355,10 @@ namespace RODBInterface public abstract string RODB_GetDBServerForAbout(); public abstract string RODB_HasBeenConverted(); public abstract bool RODB_WriteSqlConnectToAccess(string newConectStr); - #endregion + public abstract string RODB_GetModDateTime(string Recid, string table); + #endregion - public RODB() + public RODB() { } @@ -2382,9 +2383,9 @@ namespace RODBInterface RecID = DBE.GetString(0); MyRecID = RecID; Info = DBE.GetString(1); - // it's defined in the local table if the first character is "<" which starts - // the schema definition string. - if ("<" == Info.Substring(0, 1)) + // it's defined in the local table if the first character is "<" which starts + // the schema definition string. + if ("<" == Info.Substring(0, 1)) { name = ParseEleName(Info); if (name != null) @@ -2425,7 +2426,7 @@ namespace RODBInterface return retlist; } - public override string RODB_GetSchemaPiece(string Recid, string table) + public override string RODB_GetSchemaPiece(string Recid, string table) { string strGetSchemaPiece; string Info; @@ -3082,7 +3083,28 @@ namespace RODBInterface return GrpCnt; } - } + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + //Get the Modification Date / Time for the RO + public override string RODB_GetModDateTime(string Recid, string table) + { + using (System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection(strDatabaseConnectionCommand)) + { + connection.Open(); + using (System.Data.OleDb.OleDbCommand command = connection.CreateCommand()) + { + //Unfortunately Access wont let you paramaterize the table name + command.CommandText = $"SELECT ModDateTime FROM {Regex.Replace(table, "[^a-zA-Z0-9]", "")} WHERE RecID = @Value"; + command.Parameters.Add(new System.Data.OleDb.OleDbParameter + { + OleDbType = System.Data.OleDb.OleDbType.VarChar, + ParameterName = "@Value", + Value = Recid + }); + return command.ExecuteScalar().ToString(); + } + } + } + } } diff --git a/PROMS/ReferencedObjects/LibSource/RODBInterface/SqlRODB.cs b/PROMS/ReferencedObjects/LibSource/RODBInterface/SqlRODB.cs index 10ecf768..fb03f1d2 100644 --- a/PROMS/ReferencedObjects/LibSource/RODBInterface/SqlRODB.cs +++ b/PROMS/ReferencedObjects/LibSource/RODBInterface/SqlRODB.cs @@ -1803,9 +1803,9 @@ namespace RODBInterface RecID = reader.GetString(0); MyRecID = RecID; Info = reader.GetString(1); - // it's defined in the local table if the first character is "<" which starts - // the schema definition string. - if ("<" == Info.Substring(0, 1)) + // it's defined in the local table if the first character is "<" which starts + // the schema definition string. + if ("<" == Info.Substring(0, 1)) { name = ParseEleName(Info); if (name != null) @@ -1859,9 +1859,9 @@ namespace RODBInterface RecID = reader.GetString(0); MyRecID = RecID; Info = reader.GetString(1); - // it's defined in the local table if the first character is "<" which starts - // the schema definition string. - if ("<" == Info.Substring(0, 1)) + // it's defined in the local table if the first character is "<" which starts + // the schema definition string. + if ("<" == Info.Substring(0, 1)) { name = ParseEleName(Info); if (name != null) @@ -2653,8 +2653,36 @@ namespace RODBInterface } return GrpCnt; } - #endregion - public static bool TestConnect(string constring) + + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + //Get the Modification Date / Time for the RO + public override string RODB_GetModDateTime(string Recid, string table) + { + using (SqlConnection connection = new SqlConnection(strDatabaseConnectionCommand)) + { + connection.Open(); + using (SqlCommand command = connection.CreateCommand()) + { + command.CommandText = $"SELECT ModDateTime FROM ROALL WHERE RecID = @Value AND ROTable = @table"; + command.Parameters.Add(new SqlParameter + { + SqlDbType = SqlDbType.VarChar, + ParameterName = "@Value", + Value = Recid + }); + command.Parameters.Add(new SqlParameter + { + SqlDbType = SqlDbType.VarChar, + ParameterName = "@table", + Value = table + }); + + return command.ExecuteScalar().ToString(); + } + } + } + #endregion + public static bool TestConnect(string constring) { bool success = false; using (SqlConnection connection = new SqlConnection(constring)) diff --git a/PROMS/VEPROMS User Interface/PROMSFixes.Sql b/PROMS/VEPROMS User Interface/PROMSFixes.Sql index 7e34dfd6..c4560ef6 100644 --- a/PROMS/VEPROMS User Interface/PROMSFixes.Sql +++ b/PROMS/VEPROMS User Interface/PROMSFixes.Sql @@ -13540,35 +13540,7 @@ GO IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[deleteAllDocVersionPdfs]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1) DROP PROCEDURE [deleteAllDocVersionPdfs]; GO - -/***************************************************************************** - Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE - Copyright 2017 - Volian Enterprises, Inc. All rights reserved. -*****************************************************************************/ -CREATE PROCEDURE [dbo].[deleteAllDocVersionPdfs] -( - @VersionID int -) -WITH EXECUTE AS OWNER -AS -BEGIN TRY -- Try Block - BEGIN TRANSACTION - DELETE [Pdfs] - WHERE [DocID] IN(select EE.DocID from vefn_GetVersionItems(cast(@VersionID as varchar(20))) VI - Join Entries EE ON EE.ContentID= VI.ContentID) - IF( @@TRANCOUNT > 0 ) COMMIT -END TRY -BEGIN CATCH -- Catch Block - IF( @@TRANCOUNT = 1 ) ROLLBACK -- Only rollback if top level - ELSE IF( @@TRANCOUNT > 1 ) COMMIT -- Otherwise commit. Top level will rollback - EXEC vlnErrorHandler -END CATCH -GO --- Display the status of Proc creation -IF (@@Error = 0) PRINT 'Procedure Creation: deleteAllDocVersionPdfs Succeeded' -ELSE PRINT 'Procedure Creation: deleteAllDocVersionPdfs Error on Creation' -GO /****** Object: StoredProcedure [addFiguresByROFstIDandImageIDs] ******/ IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[addFiguresByROFstIDandImageIDs]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1) DROP PROCEDURE [addFiguresByROFstIDandImageIDs]; @@ -17169,6 +17141,7 @@ GO [roid] [varchar](50) NOT NULL, [appid] [varchar](max) NULL, [value] [varchar](max) NULL, + [moddatetime] [datetime] NULL, CONSTRAINT [PK_RofstChild] PRIMARY KEY CLUSTERED ( [RofstChildID] ASC @@ -17303,6 +17276,23 @@ GO End -- Rofst Tables Go + -- ============================================= + -- Author: Matthew Schill + -- Create date: 03/30/2026 + -- Description: Store RO Modification date/time + -- ============================================= + + --- Add Column to store RO Modification date/time if it does not already exist + IF NOT EXISTS(SELECT * + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_NAME = 'RofstChild' + AND COLUMN_NAME = 'moddatetime') + ALTER TABLE RofstChild ADD moddatetime datetime NULL; + go + -- Display the status + IF (@@Error = 0) PRINT 'Altered table [RofstChild] Succeeded for moddatetime' + ELSE PRINT 'Altered table [RofstChild] Error on Alter for moddatetime' + go /* ---------------------------------------------------------------------------------- @@ -19705,6 +19695,7 @@ GO @roid VarChar(50), @appid VarChar(Max) = null, @value VarChar(Max) = null, + @ModDateTime DateTime = null, @missingDefaultValue VarChar(Max) = null ) With Execute as Owner @@ -19722,8 +19713,8 @@ GO Set @missingDefaultValue = '[TBD]'; -- Create Rofst Child/Group Record --> [Roid = (12) Digits] - Insert Into RofstChild (RofstID, ID, ParentID, dbiID, [type], title, roid, appid, [value]) - Values (@RofstID, @ID, @ParentID, @dbiID, @type, @title, @roid, @appid, REPLACE(REPLACE(@value, '&123;', '{'), '&125;', '}')); + Insert Into RofstChild (RofstID, ID, ParentID, dbiID, [type], title, roid, appid, moddatetime, [value]) + Values (@RofstID, @ID, @ParentID, @dbiID, @type, @title, @roid, @appid, @ModDateTime, REPLACE(REPLACE(@value, '&123;', '{'), '&125;', '}')); -- Check for appid, if exists, then insert the default value for each return type if multi-value @@ -24777,6 +24768,146 @@ IF (@@Error = 0) PRINT 'Procedure Creation: [GetMissingDocsByUnit] Succeeded' ELSE PRINT 'Procedure Creation: [GetMissingDocsByUnit] Error on Creation' GO + +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[vefn_ROFST_changes]') AND OBJECTPROPERTY(id,N'IsTableFunction') = 1) + DROP FUNCTION [vefn_ROFST_changes]; +GO + +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO + +/* +========================================================================================================== + Author: Matthew Schill + Create Date: 03/31/2026 + Description: Function for ROs that updated in latest RO FST Load +========================================================================================================== +*/ +CREATE FUNCTION [dbo].[vefn_ROFST_changes](@OrigFSTID int, @NewFSTid int, @VersionID int) +RETURNS @ROIDs TABLE +( +[roid] varchar(50) +) +WITH EXECUTE AS OWNER +AS +BEGIN + + insert into @ROIDs + SELECT DISTINCT ISNULL(RofstChild.roid,previous.roid) + FROM + (SELECT * FROM RofstChild where RofstChild.RofstID = @NewFSTid) RofstChild + FULL OUTER JOIN + (SELECT * FROM RofstChild previous where previous.RofstID = @OrigFSTID) previous + ON previous.dbiID = RofstChild.dbiID AND previous.ID = RofstChild.ID + where + ISNULL(previous.RofstID,'') != ISNULL(RofstChild.RofstID,'') + AND + ( + (RofstChild.RofstID = @NewFSTid OR RofstChild.RofstID IS NULL) + AND + (previous.RofstID = @OrigFSTID OR previous.RofstID IS NULL) + ) + AND + (previous.moddatetime IS NULL + OR RofstChild.moddatetime IS NULL + OR RofstChild.moddatetime != previous.moddatetime + OR RofstChild.title != previous.title + OR RofstChild.value != previous.value + ) + + RETURN +END +go + +IF (@@Error = 0) PRINT 'TableFunction [vefn_ROFST_changes] Succeeded' +ELSE PRINT 'TableFunction [vefn_ROFST_changes] Error on Creation' +go + +/****** Object: StoredProcedure [deleteDocVersionPdfsWithNewROs] ******/ +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[deleteDocVersionPdfsWithNewROs]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1) + DROP PROCEDURE [deleteDocVersionPdfsWithNewROs]; +GO + +/* +========================================================================================================== + Author: Matthew Schill + Create Date: 03/31/2026 + Description: Delete all PDFs with ROs that will need re-resolved +========================================================================================================== +*/ +CREATE PROCEDURE [dbo].[deleteDocVersionPdfsWithNewROs] + +( + @VersionID int, + @OrigFSTid int, + @NewFSTid int +) +WITH EXECUTE AS OWNER +AS + BEGIN + DELETE [Pdfs] + WHERE [DocID] IN + ( + select EE.DocID from vefn_GetVersionItems(cast(@VersionID as varchar(20))) VI + Join Entries EE ON EE.ContentID= VI.ContentID + Join DRoUsages ON DRoUsages.DocID = EE.DocID + Join dbo.vefn_ROFST_changes(@OrigFSTID, @NewFSTid, @VersionID) ROFST_changes on LEFT(DRoUsages.ROID,12) = ROFST_changes.roid + ) + + RETURN + END + +GO + +-- Display the status of Proc creation +IF (@@Error = 0) PRINT 'Procedure Creation: deleteDocVersionPdfsWithNewROs Succeeded' +ELSE PRINT 'Procedure Creation: deleteDocVersionPdfsWithNewROs Error on Creation' +GO + + +/****** Object: StoredProcedure [getItemsWithNewROs] ******/ +IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[getItemsWithNewROs]') AND OBJECTPROPERTY(id,N'IsProcedure') = 1) + DROP PROCEDURE [getItemsWithNewROs]; +GO + +/* +========================================================================================================== + Author: Matthew Schill + Create Date: 03/31/2026 + Description: Get Items with New ROs that will need resolved +========================================================================================================== +*/ +CREATE PROCEDURE [dbo].[getItemsWithNewROs] + +( + @VersionID int, + @OrigFSTid int, + @NewFSTid int +) +WITH EXECUTE AS OWNER +AS + BEGIN + select DISTINCT tblItems.ItemID FROM + dbo.vefn_ROFST_changes(@OrigFSTID, @NewFSTid, @VersionID) ROFST_changes + INNER JOIN RoUsages ON LEFT(RoUsages.ROID,12) = ROFST_changes.roid + INNER JOIN tblItems ON RoUsages.ContentID = tblItems.ContentID + OUTER APPLY (Select VersionID = dbo.vefn_GetVersionIDByItemID(tblItems.ItemID)) ver + INNER JOIN DocVersions DV ON DV.VersionID = ver.VersionID + INNER JOIN Associations ON Associations.VersionID = DV.VersionID + where ver.VersionID = @VersionID + + RETURN + END + +GO + +-- Display the status of Proc creation +IF (@@Error = 0) PRINT 'Procedure Creation: getItemsWithNewROs Succeeded' +ELSE PRINT 'Procedure Creation: getItemsWithNewROs Error on Creation' +GO + /* --------------------------------------------------------------------------- | ADD New Code Before this Block | @@ -24810,8 +24941,8 @@ BEGIN TRY -- Try Block DECLARE @RevDate varchar(255) DECLARE @RevDescription varchar(255) - set @RevDate = '03/13/2026 7:00 AM' - set @RevDescription = 'Added Get Missing Docs by Unit for Generating Pdf table' + set @RevDate = '04/21/2026 7:00 AM' + set @RevDescription = 'Store RO Modification date/time' Select cast(@RevDate as datetime) RevDate, @RevDescription RevDescription PRINT 'SQL Code Revision ' + @RevDate + ' - ' + @RevDescription diff --git a/PROMS/VEPROMS User Interface/frmBatchRefresh.cs b/PROMS/VEPROMS User Interface/frmBatchRefresh.cs index 0af71439..68bbecf5 100644 --- a/PROMS/VEPROMS User Interface/frmBatchRefresh.cs +++ b/PROMS/VEPROMS User Interface/frmBatchRefresh.cs @@ -1036,8 +1036,11 @@ namespace VEPROMS ROFstInfo roFstInfo = dq.DocVersionAssociations[0].MyROFst; string rofstPath = roFstInfo.MyRODb.FolderPath + @"\ro.fst"; - //if (!pathExists(rofstPath)) - if (!File.Exists(rofstPath)) + //must get id before ROFST gets updated so know what to refresh later + int origfstid = roFstInfo.ROFstID; + + //if (!pathExists(rofstPath)) + if (!File.Exists(rofstPath)) { ProgressBar.ColorTable = eProgressBarItemColor.Error; FinalProgressBarMessage = "No existing RO.FST"; @@ -1064,8 +1067,8 @@ namespace VEPROMS roFstInfo = dq.DocVersionAssociations[0].MyROFst; } roFstInfo.ROTableUpdate += new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); - ROFst newrofst = ROFstInfo.RefreshROFst(dv, roFstInfo, DoProgressBarRefresh, txtProcess); - roFstInfo.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); + ROFstInfo.RefreshROFstAtItemLevel(DocVersionInfo.Get(dv.VersionID), DoProgressBarRefresh, txtProcess, roFstInfo, origfstid, roFstInfo.ROFstID); + roFstInfo.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); } Cursor = Cursors.Default; diff --git a/PROMS/VEPROMS User Interface/frmVEPROMS.cs b/PROMS/VEPROMS User Interface/frmVEPROMS.cs index 10210c96..a819a751 100644 --- a/PROMS/VEPROMS User Interface/frmVEPROMS.cs +++ b/PROMS/VEPROMS User Interface/frmVEPROMS.cs @@ -1594,7 +1594,7 @@ namespace VEPROMS displayRO.MyROFST = SelectedROFst; // B2023-021: force Load of Step Prop/RO panel RO tree by passing in // true to LoadTree - displayRO.LoadTree(true); + if (!_WeAreExitingPROMS) displayRO.LoadTree(true); } } @@ -2395,6 +2395,7 @@ namespace VEPROMS tv.MySessionInfo = MySessionInfo; tv.MyUserInfo = MyUserInfo; StepTabRibbon.MySessionInfo = MySessionInfo; + displayRO.MySessionInfo = MySessionInfo; // Initialize Caption with Server name and Database name. SetCaption(tv.TopNode as VETreeNode); @@ -4553,6 +4554,15 @@ namespace VEPROMS SetCaption(tv.SelectedNode as VETreeNode); displayApplicability.MyDisplayTabItem = tc.SelectedDisplayTabItem; + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // DisplayTab was changed + // need to clear the RTB selected + // without resetting the DVI or FST + // (those will be set manually / individually) + // this will prevent DVI and FST from changing to null then back again + // which will trigger reloads + displayRO.ClearRTB(); + if (tc.SelectedDisplayTabItem.MyItemInfo.MyDocVersion.DocVersionAssociationCount > 0) { displayRO.MyROFST = tc.SelectedDisplayTabItem.MyItemInfo.MyDocVersion.DocVersionAssociations[0].MyROFst; @@ -4562,9 +4572,24 @@ namespace VEPROMS displayRO.MyROFST = null; } - // B2022-026 RO Memory reduction coding (Jakes Merge) - // B2022-123: RO Tab Treeview not showing correct RO values when switching between procedures. (Added True for the forceLoad parameter) - displayRO.LoadTree(true); + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // set the DocVersionInfo so that the FST and docversion are in sync + SelectedDVI = tc.SelectedDisplayTabItem.MyItemInfo.MyDocVersion; + if (displayRO.MyDvi != SelectedDVI) + { + displayRO.MyDvi = SelectedDVI; + } + Application.DoEvents(); + + // B2022-026 RO Memory reduction coding (Jakes Merge) + // B2022-123: RO Tab Treeview not showing correct RO values when switching between procedures. (Added True for the forceLoad parameter) + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // if ROFST got updated, + // set the Selected FST so it is in sync + if (!_WeAreExitingPROMS && displayRO.LoadTree(true)) + { + SelectedROFst = displayRO.MyROFST; + } lblUser.Text = tc.SelectedDisplayTabItem.MyUserRole; @@ -4765,7 +4790,13 @@ namespace VEPROMS // B2022-026 RO Memory reduction coding (Jakes Merge) displayRO.ProgressBar = bottomProgBar; displayRO.MyRTB = args.MyEditItem.MyStepRTB; - displayRO.LoadTree(); + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // if ROFST got updated, + // set the Selected FST so it is in sync + if (!_WeAreExitingPROMS && displayRO.LoadTree()) + { + SelectedROFst = displayRO.MyROFST; + } displayBookMarks.MyEditItem = args.MyEditItem; displayHistory.MyEditItem = args.MyEditItem; @@ -4795,7 +4826,7 @@ namespace VEPROMS // B2022-026 RO Memory reduction coding (Jakes Merge) displayRO.SetFindDocROButton(false); - displayRO.LoadTree(); + if (!_WeAreExitingPROMS) displayRO.LoadTree(); //C2019-036 View Only mode work with Checked Out Procedures //In View Only Mode - Step Properties should be disabled @@ -4928,8 +4959,14 @@ namespace VEPROMS displayRO.MyRTB = SelectedStepTabPanel.MyStepPanel.SelectedEditItem.MyStepRTB; displayRO.CurROLink = args.MyLinkText.MyRoUsageInfo; - // B2022-026 RO Memory reduction coding (Jakes Merge) - displayRO.LoadTree(); + // B2022-026 RO Memory reduction coding (Jakes Merge) + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // if ROFST got updated, + // set the Selected FST so it is in sync + if (displayRO.LoadTree()) + { + SelectedROFst = displayRO.MyROFST; + } } #endregion diff --git a/PROMS/VEPROMS User Interface/frmVersionsProperties.cs b/PROMS/VEPROMS User Interface/frmVersionsProperties.cs index ee0efcdd..dc32c284 100644 --- a/PROMS/VEPROMS User Interface/frmVersionsProperties.cs +++ b/PROMS/VEPROMS User Interface/frmVersionsProperties.cs @@ -1527,8 +1527,11 @@ namespace VEPROMS Cursor = Cursors.WaitCursor; - // RO changes placed in file in the Documents\VEPROMS folder - swROUpdate = new System.IO.StreamWriter(ROFstInfo.ROUpdateResultsPath(_DocVersionConfig.MyDocVersion.MyDocVersionInfo)); + //must get id before ROFST gets updated so know what to refresh later + int origfstid = SelectedROFst.ROFstID; + + // RO changes placed in file in the Documents\VEPROMS folder + swROUpdate = new System.IO.StreamWriter(ROFstInfo.ROUpdateResultsPath(_DocVersionConfig.MyDocVersion.MyDocVersionInfo)); DocVersion dv = _DocVersionConfig.MyDocVersion; // B2022-026 RO Memory Reduction code - first load the new ro.fst so that we can assign the ROTableUpdate event to the correct roFstInfo if (dv.ROfstLoadingFigures || dv.NewerRoFst) // B2017-125 see if loading figures was completed @@ -1540,9 +1543,9 @@ namespace VEPROMS ContentInfo.StaticContentInfoChange += ContentInfo_StaticContentInfoChange; // write changes to a text file SelectedROFst.ROTableUpdate += new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); - ROFst newrofst = ROFstInfo.RefreshROFst(_DocVersionConfig.MyDocVersion, SelectedROFst, DoProgressBarRefresh, null); + ROFstInfo.RefreshROFstAtItemLevel(DocVersionInfo.Get(dv.VersionID), DoProgressBarRefresh, null, SelectedROFst, origfstid, SelectedROFst.ROFstID); - ContentInfo.StaticContentInfoChange -= ContentInfo_StaticContentInfoChange; + ContentInfo.StaticContentInfoChange -= ContentInfo_StaticContentInfoChange; SelectedROFst.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); swROUpdate.Close(); diff --git a/PROMS/VEPROMS.CSLA.Library/Config/ROFSTLookup.cs b/PROMS/VEPROMS.CSLA.Library/Config/ROFSTLookup.cs index c9a39132..72eb066c 100644 --- a/PROMS/VEPROMS.CSLA.Library/Config/ROFSTLookup.cs +++ b/PROMS/VEPROMS.CSLA.Library/Config/ROFSTLookup.cs @@ -97,7 +97,8 @@ namespace VEPROMS.CSLA.Library public string appid; public int ID; public int ParentID; - public rochild[] children; + public DateTime? ModDateTime; //C2026-008 Re-Architect RO.FST to include RO Modification date/time + public rochild[] children; }; [Serializable] @@ -110,7 +111,8 @@ namespace VEPROMS.CSLA.Library public string roid; // roid unique identifier public string appid; // accessory page id - user specified unique id public string value; // return value, can be multiple values - public rochild[] children; + public DateTime? ModDateTime; //C2026-008 Re-Architect RO.FST to include RO Modification date/time + public rochild[] children; }; public class RoExtension @@ -686,15 +688,19 @@ namespace VEPROMS.CSLA.Library //return string.Format("{0,10:#####0.00}", TimeSpan.FromTicks(DateTime.Now.Ticks - dtStart.Ticks).TotalSeconds); } - #endregion + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + //return new ROFstID if there is a newer ID that matches the same ROFSTDB + public int GetNewerFSTID() => RofstGetLatestID(RofstID); - #endregion + #endregion - #region Private Methods + #endregion - #region (Database Calls) + #region Private Methods - private bool RofstDataExists(int rofstID) + #region (Database Calls) + + private bool RofstDataExists(int rofstID) { int headerStatusID = RofstDataGetHeaderLoadStatus(rofstID); @@ -888,7 +894,7 @@ namespace VEPROMS.CSLA.Library } } - private void RofstChildInsert(int rofstID, int id, int parentID, int dbiID, int type, string title, string roid, string appid, string value) + private void RofstChildInsert(int rofstID, int id, int parentID, int dbiID, int type, string title, string roid, string appid, string value, DateTime? dt = null) { try { @@ -917,7 +923,10 @@ namespace VEPROMS.CSLA.Library if (!string.IsNullOrEmpty(this.RoMissingDefaultValue)) cmd.Parameters.Add(new SqlParameter("@missingDefaultValue", SqlDbType.VarChar)).Value = this.RoMissingDefaultValue; - cmd.ExecuteNonQuery(); + if (dt != null) + cmd.Parameters.Add(new SqlParameter("@ModDateTime", SqlDbType.DateTime)).Value = dt; + + cmd.ExecuteNonQuery(); } } } @@ -1299,11 +1308,37 @@ namespace VEPROMS.CSLA.Library } } - #endregion + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + //return new ROFstID if there is a newer ID that matches the same ROFSTDB + private int RofstGetLatestID(int rofstID) + { + try + { + using (SqlConnection cn = Database.VEPROMS_SqlConnection) + { + using (SqlCommand cmd = cn.CreateCommand()) + { + cmd.CommandTimeout = 0; + cmd.CommandType = CommandType.Text; + cmd.CommandText = "SELECT ISNULL((SELECT TOP 1 ROFsts.ROFstID FROM ROFsts INNER JOIN ROFsts curFST ON curFST.RODbID = ROFsts.RODbID WHERE curFST.ROFstID = @FSTid order by ROFsts.DTS desc),-1)"; - #region (Core/Base logic for RO Values & UnitInfo RO Values) + cmd.Parameters.Add(new SqlParameter("@FSTid", SqlDbType.Int)).Value = rofstID; - private ROFSTLookup.rochild RofstDataGetChildByRoid(int rofstID, string roid, bool loadChildren = false, bool loadAllChildren = false) + return (int) cmd.ExecuteScalar(); + } + } + } + catch (Exception ex) + { + throw new DbCslaException("RofstData.RofstGetLatestID", ex); + } + } + + #endregion + + #region (Core/Base logic for RO Values & UnitInfo RO Values) + + private ROFSTLookup.rochild RofstDataGetChildByRoid(int rofstID, string roid, bool loadChildren = false, bool loadAllChildren = false) { try { @@ -1512,10 +1547,10 @@ namespace VEPROMS.CSLA.Library int slen = StringLength(ab, myOffset + 6); tmp.title = Encoding.Default.GetString(ab, myOffset + 6, slen); - + myOffset += (7 + slen); - ROFSTLookup.rogrp tmpg = LoadGroup(ab, childOffset, tableID); + ROFSTLookup.rogrp tmpg = LoadGroup(ab, childOffset, tableID); tmp.ID = tmpg.ID; tmp.ParentID = tmpg.ParentID; @@ -1523,8 +1558,12 @@ namespace VEPROMS.CSLA.Library tmp.appid = tmpg.appid; tmp.roid = tableID.ToString("X4") + tmp.ID.ToString("X8"); tmp.children = tmpg.children; + if (tmpg.ModDateTime != null) + { + tmp.ModDateTime = tmpg.ModDateTime; + } - int j; + int j; for (j = i - 1; j >= 0 && tmp.ID < myGrp.children[j].ID; j--) { @@ -1542,7 +1581,13 @@ namespace VEPROMS.CSLA.Library int slen2 = StringLength(ab, offset + 13 + slen); myGrp.appid = Encoding.Default.GetString(ab, offset + 13 + slen, slen2); - _dbRoCnt++; + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + if (myGrp.value != "" && DateTime.TryParseExact(Encoding.Default.GetString(ab, offset + 14 + slen + slen2, 14), "yyyyMMddHHmmss", null, System.Globalization.DateTimeStyles.None, out DateTime dt)) + { + myGrp.ModDateTime = dt; + } + + _dbRoCnt++; } return myGrp; @@ -1655,7 +1700,7 @@ namespace VEPROMS.CSLA.Library private void LoadChild(int rofstID, int dbiID, ROFSTLookup.rochild child) { //Insert Rofst Child - RofstChildInsert(rofstID, child.ID, child.ParentID, dbiID, child.type, child.title, child.roid, child.appid, child.value); + RofstChildInsert(rofstID, child.ID, child.ParentID, dbiID, child.type, child.title, child.roid, child.appid, child.value, child.ModDateTime); //Increment RO Count if RoChild has a return value if (!string.IsNullOrEmpty(child.value)) _curRoCnt++; diff --git a/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs b/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs index a2c4960e..edd3bb83 100644 --- a/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs +++ b/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs @@ -1093,8 +1093,17 @@ namespace VEPROMS.CSLA.Library } } } - // B2022-026 RO Memory Reduction code - pass in ROFstInfo - internal static void MyRefreshReferenceObjects(ItemInfo itemInfo, IVEDrillDownReadOnly itemParent, SectionInfo sectionInfo, DocVersionInfo docVersionInfo, ROFstInfo origROFst) + + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + //Refresh at item level + public static void RefreshReferenceObjects(ItemInfo tmp, ROFstInfo origROFst) + { + if (tmp.MyDocVersion.DocVersionConfig.SelectedSlave <= 0) + MyRefreshReferenceObjects(tmp, null, tmp.GetSectionInfo(), tmp.MyDocVersion, origROFst); + } + + // B2022-026 RO Memory Reduction code - pass in ROFstInfo + internal static void MyRefreshReferenceObjects(ItemInfo itemInfo, IVEDrillDownReadOnly itemParent, SectionInfo sectionInfo, DocVersionInfo docVersionInfo, ROFstInfo origROFst) { if (itemInfo.MyContent.ContentPartCount > 0) { @@ -1219,31 +1228,47 @@ namespace VEPROMS.CSLA.Library return true; } - #region Debug Code + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + public static List GetItemInfoWithChangedROs(int docversionid, int origfstid, int newfstid) + { + List lst = new List(); - //private static void ShowDifference(string oldText, string newText) - //{ - // string nt = newText.Replace(@"\u8209?", "-").Replace(@"\u160?", " ").Replace("\xA0", " "); - // string ot = oldText.Replace(@"\u8209?", "-").Replace(@"\u160?", " ").Replace("\xA0", " "); - // ShowText("OldText", ot); - // ShowText("NewText", nt); - //} - //private static void ShowText(string title, string newText) - //{ - // StringBuilder sb = new StringBuilder(); - // foreach (char c in newText) - // { - // if(c<' ' || c> '\x7F') - // sb.Append(string.Format("\\x{0:X2}",((int) c))); - // else - // sb.Append(c); - // } - // Console.WriteLine("{0}='{1}'",title,sb.ToString()); - //} + foreach (DataRow r in Data_GetItemsWithChangedROs(docversionid, origfstid, newfstid).Rows) + { + using (ItemInfo itm = Get((int)r["ItemID"])) + { + lst.Add(itm); + } + } - #endregion // debug + return lst; + } - internal static void SetParentSectionAndDocVersionPageNum(ItemInfo itemInfo, IVEDrillDownReadOnly itemParent, SectionInfo sectionInfo, ProcedureInfo procInfo, DocVersionInfo docVersionInfo, TransitionLookup tranLookup) + #region Debug Code + + //private static void ShowDifference(string oldText, string newText) + //{ + // string nt = newText.Replace(@"\u8209?", "-").Replace(@"\u160?", " ").Replace("\xA0", " "); + // string ot = oldText.Replace(@"\u8209?", "-").Replace(@"\u160?", " ").Replace("\xA0", " "); + // ShowText("OldText", ot); + // ShowText("NewText", nt); + //} + //private static void ShowText(string title, string newText) + //{ + // StringBuilder sb = new StringBuilder(); + // foreach (char c in newText) + // { + // if(c<' ' || c> '\x7F') + // sb.Append(string.Format("\\x{0:X2}",((int) c))); + // else + // sb.Append(c); + // } + // Console.WriteLine("{0}='{1}'",title,sb.ToString()); + //} + + #endregion // debug + + internal static void SetParentSectionAndDocVersionPageNum(ItemInfo itemInfo, IVEDrillDownReadOnly itemParent, SectionInfo sectionInfo, ProcedureInfo procInfo, DocVersionInfo docVersionInfo, TransitionLookup tranLookup) { if (itemInfo.MyContent.ContentPartCount > 0) { @@ -1890,10 +1915,44 @@ namespace VEPROMS.CSLA.Library foreach (ItemInfo itemInfo in partInfo.MyItems) itemInfo.SpinThroughChildren(); } - #endregion - #region LoadAtOnce - // Method to Get Item and children - public static ItemInfo GetItemAndChildren(int? itemID, int? parentID) + + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + private static DataTable Data_GetItemsWithChangedROs(int docversionid, int origfstid, int newfstid) + { + try + { + using (SqlConnection cn = Database.VEPROMS_SqlConnection) + { + using (SqlCommand cm = cn.CreateCommand()) + { + cm.CommandType = CommandType.StoredProcedure; + cm.CommandText = "getItemsWithNewROs"; + cm.Parameters.AddWithValue("@VersionID", docversionid); + cm.Parameters.AddWithValue("@OrigFSTid", origfstid); + cm.Parameters.AddWithValue("@NewFSTid", newfstid); + cm.CommandTimeout = Database.DefaultTimeout; + + using (SqlDataAdapter da = new SqlDataAdapter(cm)) + { + DataTable dt = new DataTable(); + da.Fill(dt); + return dt; + } + } + + } + } + catch (Exception ex) + { + Database.LogException("ItemInfoList.Data_GetItemsWithChangedROs", ex); + throw new DbCslaException("ItemInfoList.Data_GetItemsWithChangedROs", ex); + } + } + + #endregion + #region LoadAtOnce + // Method to Get Item and children + public static ItemInfo GetItemAndChildren(int? itemID, int? parentID) { try { diff --git a/PROMS/VEPROMS.CSLA.Library/Extension/PdfExt.cs b/PROMS/VEPROMS.CSLA.Library/Extension/PdfExt.cs index 367e3f3b..cd0b2983 100644 --- a/PROMS/VEPROMS.CSLA.Library/Extension/PdfExt.cs +++ b/PROMS/VEPROMS.CSLA.Library/Extension/PdfExt.cs @@ -61,57 +61,47 @@ namespace VEPROMS.CSLA.Library throw new DbCslaException("Pdf.DataPortal_Delete", ex); } } - // used to remove word section PDFs to force ROs to be updated when printed or saved - public static void DeleteAllDocVersion(int versionID) - { - if (!CanDeleteObject()) - throw new System.Security.SecurityException("User not authorized to remove a Pdf"); - try - { - DataPortal.Delete(new VersionIDCriteria(versionID)); - } - catch (Exception ex) - { - throw new DbCslaException("Error on Pdf.DeleteAllDocVersion", ex); - } - } - [Serializable()] - protected class VersionIDCriteria - { - private int _VersionID; - public int VersionID - { get { return _VersionID; } } - public VersionIDCriteria(int versionID) - { - _VersionID = versionID; - } - } - [Transactional(TransactionalTypes.TransactionScope)] - private void DataPortal_Delete(VersionIDCriteria criteria) - { - if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] Pdf.DataPortal_Delete", GetHashCode()); - try - { - using (SqlConnection cn = Database.VEPROMS_SqlConnection) - { - using (SqlCommand cm = cn.CreateCommand()) - { - cm.CommandType = CommandType.StoredProcedure; - cm.CommandTimeout = Database.SQLTimeout; - cm.CommandText = "deleteAllDocVersionPdfs"; - cm.Parameters.AddWithValue("@VersionID", criteria.VersionID); - cm.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - if (_MyLog.IsErrorEnabled) _MyLog.Error("Pdf.DataPortal_Delete", ex); - _ErrorMessage = ex.Message; - throw new DbCslaException("Pdf.DataPortal_Delete", ex); - } - } + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // used to remove word section PDFs to force ROs to be updated when printed or saved + public static void DeleteDocVersionPDFsWithNewROs(int versionID, int origfstid, int newfstid) + { + if (!CanDeleteObject()) + throw new System.Security.SecurityException("User not authorized to remove a Pdf"); + try + { + DeleteWithNewROs(versionID, origfstid, newfstid); + } + catch (Exception ex) + { + throw new DbCslaException("Error on Pdf.DeleteAllDocVersion", ex); + } + } + + static private void DeleteWithNewROs(int docversionID, int origfstid, int newfstid) + { + try + { + using (SqlConnection cn = Database.VEPROMS_SqlConnection) + { + using (SqlCommand cm = cn.CreateCommand()) + { + cm.CommandType = CommandType.StoredProcedure; + cm.CommandTimeout = Database.SQLTimeout; + cm.CommandText = "deleteDocVersionPdfsWithNewROs"; + cm.Parameters.AddWithValue("@VersionID", docversionID); + cm.Parameters.AddWithValue("@OrigFSTid", origfstid); + cm.Parameters.AddWithValue("@NewFSTid", newfstid); + cm.ExecuteNonQuery(); + } + } + } + catch (Exception ex) + { + if (_MyLog.IsErrorEnabled) _MyLog.Error("Pdf.DeleteWithNewROs", ex); + throw new DbCslaException("Pdf.DeleteWithNewROs", ex); + } + } } public partial class PdfInfo { diff --git a/PROMS/VEPROMS.CSLA.Library/Extension/ROFSTExt.cs b/PROMS/VEPROMS.CSLA.Library/Extension/ROFSTExt.cs index 01c43a22..e8e980ad 100644 --- a/PROMS/VEPROMS.CSLA.Library/Extension/ROFSTExt.cs +++ b/PROMS/VEPROMS.CSLA.Library/Extension/ROFSTExt.cs @@ -225,41 +225,54 @@ namespace VEPROMS.CSLA.Library } } - // B2022-026 RO Memory Reduction code - pass in the ROFstInfo - public static int RefreshROFst(DocVersionInfo dvi, ROFstInfoProgressBarRefresh myProgressBarRefresh, System.Windows.Forms.TextBox tbStatus, ROFstInfo origROFst) - { - int fixedROs = 0; + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // Refresh at item level + public static int RefreshROFstAtItemLevel(DocVersionInfo dvi, ROFstInfoProgressBarRefresh myProgressBarRefresh, System.Windows.Forms.TextBox tbStatus, ROFstInfo localROFst, int origfstid, int newfstid) + { + int fixedROs = 0; - if (dvi.DocVersionConfig.SelectedSlave <= 0) - { - myProgressBarRefresh(1, 100, "Update MS Word ROs"); + if (dvi.DocVersionConfig.SelectedSlave <= 0) + { + // remove word section PDFs to force update of RO values when printed + myProgressBarRefresh(1, 100, "Updating MS Word ROs In Progress"); + Pdf.DeleteDocVersionPDFsWithNewROs(dvi.VersionID, origfstid, newfstid); - Pdf.DeleteAllDocVersion(dvi.VersionID); // remove word section PDFs to force update of RO values when printed - int i = 0; + //Loop Through ROs in this docversion that are different than the previous fst + myProgressBarRefresh(50, 100, "Updating ROs In PROMS Steps In Progress"); + int i = 0; + List list = ItemInfo.GetItemInfoWithChangedROs(dvi.VersionID, origfstid, newfstid); + foreach (ItemInfo itm in list) + { + DateTime start = DateTime.Now; - foreach (ProcedureInfo proc in dvi.Procedures) - { - DateTime start = DateTime.Now; + ItemInfo.ResetROCounters(); + myProgressBarRefresh(++i, list.Count, string.Format("{0} ({1}/{2} ROs {3})", itm.MyProcedure.DisplayNumber, i, list.Count, fixedROs)); + ItemInfo.RefreshReferenceObjects(itm, localROFst); + fixedROs += ItemInfo.ROFixCount; - ProcedureInfo.ResetROCounters(); - myProgressBarRefresh(++i, dvi.Procedures.Count, string.Format("{0} ({1}/{2} ROs {3})", proc.DisplayNumber, i, dvi.Procedures.Count, fixedROs)); - ProcedureInfo.RefreshReferenceObjects(proc, origROFst); - fixedROs += ProcedureInfo.ROFixCount; + TimeSpan ts = DateTime.Now - start; - TimeSpan ts = DateTime.Now - start; + if (tbStatus != null) + tbStatus.AppendText(string.Format("Procedure: {1}{0}, Checked {2} Referenced Objects{0}, Fixed {3} Referenced Objects{0}, Elapsed Seconds:{4}{0}{0}", Environment.NewLine, itm.MyProcedure.DisplayNumber, ItemInfo.ROCheckCount, ItemInfo.ROFixCount, ts.TotalSeconds)); + } - if (tbStatus != null) - tbStatus.AppendText(string.Format("Procedure: {1}{0}, Checked {2} Referenced Objects{0}, Fixed {3} Referenced Objects{0}, Elapsed Seconds:{4}{0}{0}", Environment.NewLine, proc.DisplayNumber, ProcedureInfo.ROCheckCount, ProcedureInfo.ROFixCount, ts.TotalSeconds)); - } - } + //Update the DocVersion Associations to link to the new RO FST id and current date/time + using (DocVersion dv = DocVersion.Get(dvi.VersionID)) + { + if (dvi.DocVersionAssociations[0].MyROFst.ROFstID != newfstid) + { + dv.DocVersionAssociations[0].MyROFst = localROFst.GetJustROFst(); + SetAssociationLastCompleted(dv, DateTime.Now.ToString()); + } + } + } - return fixedROs; - } + return fixedROs; + } - - //C2022-028 for Admin tool to check for bad RO links - //B2022-144 we now loop through checked procedures list from Admin Tools and call this method for each procedure we want to process - public static int CheckROLinksInThisProcedure(ProcedureInfo proc, System.Windows.Forms.TextBox tbStatus) + //C2022-028 for Admin tool to check for bad RO links + //B2022-144 we now loop through checked procedures list from Admin Tools and call this method for each procedure we want to process + public static int CheckROLinksInThisProcedure(ProcedureInfo proc, System.Windows.Forms.TextBox tbStatus) { int FoundBadROLinks = 0; DocVersionInfo dvi = DocVersionInfo.Get(proc.MyDocVersion.VersionID); @@ -291,34 +304,6 @@ namespace VEPROMS.CSLA.Library return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\VEPROMS\ROUpdateReport_" + ValidFileName.FixFileName(dvi.MyFolder.Name.Replace(" ", "_") + "_" + DateTime.Now.ToString("MM-dd-yyyy_HH-mm-ss") + ".txt"); } - // B2022-026 RO Memory Reduction code - moved the call to UpdateROFst() to before we call RefreshROFst - // so that we used the correct ROFstInfo which as the needed event methods set when updated RO Table types - public static ROFst RefreshROFst(DocVersion docver, ROFstInfo origROFst, ROFstInfoProgressBarRefresh myProgressBarRefresh, System.Windows.Forms.TextBox tbStatus) - { - ROFst rofst = null; - - rofst = docver.DocVersionAssociations[0].MyROFst; - - DocVersionInfo dvi = DocVersionInfo.Get(docver.VersionID); - - SetAssociationLastCompleted(docver, string.Empty); - int fixedROs = RefreshROFst(dvi, myProgressBarRefresh, tbStatus, origROFst); - SetAssociationLastCompleted(docver, DateTime.Now.ToString()); // RO Update completed successfully and un-interrupted, save the date/time to the Doc Version Association config - - myProgressBarRefresh(100, 100, "RO Update Complete"); // update the progress bar - System.Windows.Forms.Application.DoEvents(); - - // pop up a message window telling the user the RO Update has completed and how many ROs were updated - // If we are updating RO from the Admin Tools (from the V button) and we are updating more than on procedure set, then just append the "RO Update Complete" text - // To the MessageList. Once completed will all procedure sets, Admin Tools will display one message box with all the results in it. - if (MessageList == null) - FlexibleMessageBox.Show(fixedROs == 0 ? "No ROs Required Updating" : string.Format("{0} ROs Updated for {1}", fixedROs, dvi.MyFolder.Name), "RO Update Complete"); - else - MessageList.AppendLine((fixedROs == 0 ? "No ROs Required Updating for " : string.Format("{0} ROs Updated for ", fixedROs)) + dvi.MyFolder.Name); - - return rofst; - } - /// /// Updates an ro.fst into a sql database. /// @@ -670,188 +655,7 @@ namespace VEPROMS.CSLA.Library return sb.ToString(); } - private static void UpdateROValuesText(ROFstInfo origROFstInfo, ROFst newROFst, DocVersionInfo dvi, ROFstInfoProgressBarRefresh myProgressBarRefresh, List MyChangedFigureROIDs) - { - if (myProgressBarRefresh != null) myProgressBarRefresh(0, 100, "Update Ro Values"); - - string versionList = dvi.VersionID.ToString(); - - ROFSTLookup origLookup = new ROFSTLookup(origROFstInfo.ROFstID, dvi); - ROFSTLookup newLookup = new ROFSTLookup(newROFst.ROFstID, dvi); - - List delList = new List(); - List chgList = newLookup.GetValueDifferences(origROFstInfo.ROFstID, ref delList); - - // Any figures which have been changed will be included in the list of values that have changed. - if (MyChangedFigureROIDs != null) - { - foreach (string roid in MyChangedFigureROIDs) - { - if (!chgList.Contains(roid)) chgList.Add(roid); - } - } - - string RoidList = GetRoidList(newROFst.RODbID, chgList); - - if (myProgressBarRefresh != null) myProgressBarRefresh(0, chgList.Count, "Getting List of ROs Used"); - List activeRoids = BuildActiveROIDsForRoUsages12(RoidList, versionList); - - if (myProgressBarRefresh != null) myProgressBarRefresh(0, chgList.Count, "Updating RO Values"); - int iCount = 0; - - if (activeRoids.Count > 0) - { - foreach (string chg in chgList) - { - if (myProgressBarRefresh != null) myProgressBarRefresh(++iCount, chgList.Count, "Updating RO Values"); - if (activeRoids.Contains(chg.Substring(0, 12))) - { - ROFSTLookup.rochild roch = newLookup.GetRoChild(chg); - string desc = string.Format("Change in RO Values: Old value = {0}, New value = {1}", origLookup.GetRoChild(chg).value, roch.value); - - // roid's are stored in database as 16 characters long in the RoUsages table. They may be stored as 12 characters in the ro.fst. - // string padroid = chg.Length <= 12 ? chg + "0000" : chg; - // B2022-088: Find Doc Ro button not working in Word Sections - string padroid = ROFSTLookup.FormatRoidKey(chg, true); - - using (RoUsageInfoList affected = RoUsageInfoList.GetAffected(origROFstInfo.MyRODb.RODbID, padroid, desc, "Changed", versionList)) - { - foreach (RoUsageInfo roUsg in affected) - { - using (Content content = Content.Get(roUsg.MyContent.ContentID)) - { - foreach (ItemInfo ii in roUsg.MyContent.ContentItems) - { - string val = newLookup.GetTranslatedRoValue(padroid, ii.ActiveFormat.PlantFormat.FormatData.SectData.ConvertCaretToDelta, ii.ActiveFormat.PlantFormat.FormatData.SectData.UseTildaPoundCharsForSuperSubScriptInROValues, false, ii); - content.FixContentText(roUsg, val, roch.type, origROFstInfo, true); - - if (content.IsDirty) - { - // Update UserID and DTS when RO Value is updated. - content.UserID = Volian.Base.Library.VlnSettings.UserID; - content.DTS = DateTime.Now; - content.Save(); - - if (content.MyGrid != null) - { - GridInfo.Refresh(content.MyGrid); - } - } - } - } - } - } - } - } - } - - if (myProgressBarRefresh != null) myProgressBarRefresh(0, chgList.Count, "Getting List of ROs Used"); - List activeDRoids = BuildActiveROIDsForDRoUsages12(RoidList, versionList); - iCount = 0; - - if (activeDRoids.Count > 0) - { - foreach (string chg in chgList) - { - // B2022-088: Find Doc Ro button not working in Word Sections - // string padroid = chg.Length <= 12 ? chg + "0000" : chg; - string padroid = ROFSTLookup.FormatRoidKey(chg, true); - - if (myProgressBarRefresh != null) myProgressBarRefresh(++iCount, chgList.Count, "Updating RO Values"); - - if (activeDRoids.Contains(chg.Substring(0, 12))) - { - ROFSTLookup.rochild roch = newLookup.GetRoChild(chg); - - string desc = string.Format("Change in RO Values: Old value = {0}, New value = {1}", origLookup.GetRoChild(chg).value, roch.value); - - // roid's are stored in database as 16 characters long in the rousages table. They may be stored as 12 characters in the ro.fst. - using (DROUsageInfoList affected = DROUsageInfoList.GetAffected(origROFstInfo.MyRODb.RODbID, padroid, desc, "Changed", versionList)) - { - foreach (DROUsageInfo droUsg in affected) - { - Pdf.DeleteAll(droUsg.DocID); - } - } - } - } - } - - iCount = 0; - string RoidDelList = GetRoidList(newROFst.RODbID, delList); - if (myProgressBarRefresh != null) myProgressBarRefresh(0, chgList.Count, "Getting List of ROs Used"); - activeRoids = BuildActiveROIDsForRoUsages12(RoidDelList, versionList); - - if (activeRoids.Count > 0) - { - foreach (string del in delList) - { - // B2022-088: Find Doc Ro button not working in Word Sections - //string padroiddel = del.Length <= 12 ? del + "0000" : del; - string padroiddel = ROFSTLookup.FormatRoidKey(del, true); - - if (myProgressBarRefresh != null) myProgressBarRefresh(++iCount, chgList.Count, "Removing Old RO Values"); - string desc = string.Format("Deleted RO: Value = {0}", origLookup.GetRoChild(del).value); - - if (activeRoids.Contains(del.Substring(0, 12).ToUpper())) - { - using (RoUsageInfoList affected = RoUsageInfoList.GetAffected(origROFstInfo.MyRODb.RODbID, padroiddel, desc, "Deleted", versionList)) - { - foreach (RoUsageInfo roUsg in affected) - { - using (Content content = Content.Get(roUsg.MyContent.ContentID)) - { - content.FixContentText(roUsg, "?", 0, origROFstInfo); - if (content.IsDirty) - { - // Update UserID and DTS when RO Value is updated. - content.UserID = Volian.Base.Library.VlnSettings.UserID; - content.DTS = DateTime.Now; - content.Save(); - } - } - } - } - } - } - } - - if (myProgressBarRefresh != null) myProgressBarRefresh(0, chgList.Count, "Getting List of ROs Used"); - activeDRoids = BuildActiveROIDsForDRoUsages12(RoidDelList, versionList); - iCount = 0; - - if (activeDRoids.Count > 0) - { - foreach (string del in delList) - { - - // B2022-088: Find Doc Ro button not working in Word Sections - string padroiddel = ROFSTLookup.FormatRoidKey(del, true); - if (myProgressBarRefresh != null) myProgressBarRefresh(++iCount, chgList.Count, "Removing Old RO Values"); - - string desc = string.Format("Deleted RO: Value = {0}", origLookup.GetRoChild(del).value); - - // If there's an issue then maybe try getting the RoChild with the Padded roid instead - //string desc = string.Format("Deleted RO: Value = {0}", origLookup.GetRoChild(padroiddel).value); - - if (activeDRoids.Contains(del.Substring(0, 12).ToUpper())) - { - using (DROUsageInfoList Daffected = DROUsageInfoList.GetAffected(origROFstInfo.MyRODb.RODbID, padroiddel, desc, "Deleted", versionList)) - { - foreach (DROUsageInfo droUsg in Daffected) - { - if (myProgressBarRefresh != null) myProgressBarRefresh(++iCount, chgList.Count, "Removing Old RO Values"); - Pdf.DeleteAll(droUsg.DocID); - } - } - } - } - } - - if (myProgressBarRefresh != null) myProgressBarRefresh(100, 100, "RO Values Updated"); - } - - private static DateTime ShowDuration(DateTime dtLast, string message) + private static DateTime ShowDuration(DateTime dtLast, string message) { DateTime dtNext = DateTime.Now; Console.WriteLine("{0,10:#####0.00},'{1}'", TimeSpan.FromTicks(dtNext.Ticks - dtLast.Ticks).TotalSeconds, message); diff --git a/PROMS/Volian.Controls.Library/DisplayRO.cs b/PROMS/Volian.Controls.Library/DisplayRO.cs index b40aa139..47b37dc7 100644 --- a/PROMS/Volian.Controls.Library/DisplayRO.cs +++ b/PROMS/Volian.Controls.Library/DisplayRO.cs @@ -59,11 +59,11 @@ namespace Volian.Controls.Library private DisplayTags displayTags; - #endregion + #endregion - #region Properties + #region Properties - public ProgressBarItem ProgressBar + public ProgressBarItem ProgressBar { get { return _progressBar; } set { _progressBar = value; } @@ -89,7 +89,10 @@ namespace Volian.Controls.Library (_myRTB != null && (_myRTB.IsRoTable != lastRTBwasROTable || _myRTB.IsRoFigure != lastRTBwasROFigure)); } } - public ROFstInfo MyROFST + //This flag will be set when the docversion gets updated to let it know that the full tree needs a refresh + private bool changedDocVersion = false; + + public ROFstInfo MyROFST { get { return _myROFST; } set @@ -128,16 +131,22 @@ namespace Volian.Controls.Library // B2022-135 Submitted for Admin Tools (Check RO Links tool) if (_docVersionInfo == null || _docVersionInfo != value || _docVersionInfo.VersionID != value.VersionID) { - _docVersionInfo = value; + //Set flag for modified the docversion - should check for new ROs + if (_docVersionInfo?.VersionID != value?.VersionID) + { + changedDocVersion = true; + } + + _docVersionInfo = value; if (_myRTB != null && (_docVersionInfo == null || _docVersionInfo.VersionID != _myRTB.MyDVI.VersionID)) { _docVersionInfo = _myRTB.MyDVI; } - } + } - // B2022-123: RO Tab Treeview not showing correct RO values when switching between procedures. - _currDocVersionID = (_docVersionInfo != null) ? (int?)_docVersionInfo.VersionID : null; + // B2022-123: RO Tab Treeview not showing correct RO values when switching between procedures. + _currDocVersionID = (_docVersionInfo != null) ? (int?)_docVersionInfo.VersionID : null; } } @@ -201,7 +210,11 @@ namespace Volian.Controls.Library // B2022-098: [JPR] ROs not being resolved in Word Sections CurROLink = null; _savCurROLink = null; - } + + //Clear flag for modified the docversion (if should check for new ROs) + //clearing this flag here prevents it from checking twice + changedDocVersion = false; + } else if(_myRTB != value) { if (_myRTB != null) @@ -221,9 +234,9 @@ namespace Volian.Controls.Library CurROLink = null; _savCurROLink = null; } - // B2023-004 assign the doc version info associated with the current RTB (rich text box) - // this fixes an issue where unit designators could not be linked in the step edit (BNPP data) - MyDvi = _myRTB.MyItemInfo.MyDocVersion; + // B2023-004 assign the doc version info associated with the current RTB (rich text box) + // this fixes an issue where unit designators could not be linked in the step edit (BNPP data) + MyDvi = _myRTB.MyItemInfo.MyDocVersion; MyROFST = (_myRTB.MyItemInfo.MyDocVersion.DocVersionAssociationCount > 0) ? _myRTB.MyItemInfo.MyDocVersion.DocVersionAssociations[0].MyROFst : null; } @@ -251,11 +264,13 @@ namespace Volian.Controls.Library set { _myUserInfo = value; } } - #endregion + public SessionInfo MySessionInfo { get; set; } - #region Constructors + #endregion - public DisplayRO() + #region Constructors + + public DisplayRO() { InitializeComponent(); @@ -277,48 +292,62 @@ namespace Volian.Controls.Library // Initialize the DisplayTags object displayTags = new DisplayTags(); - _progressBar = null; } - #endregion + #endregion + #region Event Handlers + #region (Progress Bar) - #region Event Handlers + private string InitialProgressBarMessage + { + set + { + if (ProgressBar == null) return; + ProgressBar.Value = 0; + ProgressBar.Maximum = 100; + ProgressBar.Text = value; + Application.DoEvents(); + } + } + private string FinalProgressBarMessage + { + set + { + if (ProgressBar == null) return; + ProgressBar.Value = 100; + ProgressBar.Maximum = 100; + ProgressBar.Text = value; + Application.DoEvents(); + } + } + private void DoProgressBarRefresh(int value, int max, string text) + { + if (ProgressBar == null) return; + ProgressBar.Maximum = max; + ProgressBar.Value = value; + ProgressBar.Text = text; + Application.DoEvents(); + } - #region (Progress Bar) + #endregion - private void ProgressBar_Initialize(int max, string desc) - { - if (_progressBar != null) - { - _progressBar.Maximum = max; - _progressBar.Text = desc; - _progressBar.TextVisible = true; - } - } + #region (RTB) - private void ProgressBar_SetValue(int curval) - { - if (_progressBar != null) - { - _progressBar.Value = curval; - } - } + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // DisplayTab was changed + // need to clear the RTB selected + // without resetting the DVI or FST + // (those will be set manually / individually) + // this will prevent DVI and FST from changing to null then back again + // which will trigger reloads + public void ClearRTB() + { + _myRTB = null; + CurROLink = null; + _savCurROLink = null; + } - private void ProgressBar_Clear() - { - if (_progressBar != null) - { - _progressBar.Text = string.Empty; - _progressBar.Maximum = 0; - _progressBar.Value = 0; - } - } - - #endregion - - #region (RTB) - - public void MyRTB_LinkChanged(object sender, StepPanelLinkEventArgs args) + public void MyRTB_LinkChanged(object sender, StepPanelLinkEventArgs args) { CurROLink = null; if (MyRTB.MyLinkText != null) CurROLink = args.MyLinkText.MyRoUsageInfo; @@ -565,55 +594,102 @@ namespace Volian.Controls.Library } } - private void lbFound_SelectedValueChanged(object sender, EventArgs e) + private void lbFound_SelectedValueChanged(object sender, EventArgs e) + { + if (lbFound.Visible && lbFound.SelectedIndex >= 0 && lbFound.SelectedValue != null) + { + ExpandNode(Convert.ToString(lbFound.SelectedValue)); + } + } + + #endregion + + #region (ROUpdate) + public List roFstInfo_ROTableUpdate(object sender, ROFstInfoROTableUpdateEventArgs args) + { + return VlnFlexGrid.ROTableUpdate(sender, args); + } + + #endregion + + #endregion + + #region Public Methods + + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + // changed to return true if the RO FST got updated + public bool LoadTree(bool forceReload = false) { - if (lbFound.Visible && lbFound.SelectedIndex >= 0 && lbFound.SelectedValue != null) - { - ExpandNode(Convert.ToString(lbFound.SelectedValue)); - } - } + bool updatedROs = false; - #endregion - - #endregion - - #region Public Methods - - public void LoadTree(bool forceReload = false) - { if (MyROFST == null) { tvROFST.Nodes.Clear(); lbFound.Visible = false; - return; + return updatedROs; } - if (forceReload || RoTreeNeedsReloaded || tvROFST.Nodes == null || tvROFST.Nodes.Count <= 0) + if (changedDocVersion || forceReload || RoTreeNeedsReloaded || tvROFST.Nodes == null || tvROFST.Nodes.Count <= 0) { - //B2025-008 - //in cases where a RO table is clicked on - //it will refresh the list - //temp store what the ROID was before the list refreshes - //so can go to it after the refresh - string tmpROID = CurROLink?.ROID; + //C2026-008 Re-Architect RO.FST to include RO Modification date/time + //check if newer data - if there is, check if user wants to update data + int fstid = MyROFSTLookup.GetNewerFSTID(); + int origfstid = MyROFSTLookup.RofstID; - ROFSTLookup.rodbi[] dbs = MyROFSTLookup.GetRODatabaseList(true); + if (_docVersionInfo != null && fstid != -1 && fstid != MyROFSTLookup.RofstID) + { + string message = string.Empty; + if (!MySessionInfo.CanCheckOutItem(_docVersionInfo.VersionID, CheckOutType.DocVersion, ref message)) + { + FlexibleMessageBox.Show(this, message, "Working Draft Has Items Already Checked Out", MessageBoxButtons.OK, MessageBoxIcon.Warning); + FinalProgressBarMessage = "Cannot check-out Working Draft"; + } + else if (changedDocVersion && MessageBox.Show($"There exists a newer ROFST for this RO database that was loaded for other sets.\r\n\r\nDo you want to update this set's ROs to be consistent/use the latest loaded ROFST?", "Load ROs", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + + InitialProgressBarMessage = "Updating ROs"; + + ROFstInfo roFstInfo = ROFstInfo.Get(fstid); + roFstInfo.ROTableUpdate += new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); + ROFstInfo.RefreshROFstAtItemLevel(_docVersionInfo, DoProgressBarRefresh, null, roFstInfo, origfstid, fstid); + roFstInfo.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); + + Application.DoEvents(); + + FinalProgressBarMessage = "ROs values updated"; + MyROFST = roFstInfo; + + updatedROs = true; + } + } + + //B2025-008 + //in cases where a RO table is clicked on + //it will refresh the list + //temp store what the ROID was before the list refreshes + //so can go to it after the refresh + string tmpROID = CurROLink?.ROID; + + ROFSTLookup.rodbi[] dbs = MyROFSTLookup?.GetRODatabaseList(true); // B2022-123: RO Tab Treeview not showing correct RO values when switching between procedures. // Added optional parameter "forceReload" and cleared out any existing nodes before reloading the tree // the clear nodes code below has to be after the GetRODatabaseList database call because of races conditions in the code tvROFST.Nodes.Clear(); ResetSearch(); //B2023-050 need to reset the SaveRO, and any RO info that was selected last time the tree was loaded - for (int i = 0; i < dbs.Length; i++) + if (dbs != null) { - ROFSTLookup.rodbi db = dbs[i]; + for (int i = 0; i < dbs.Length; i++) + { + ROFSTLookup.rodbi db = dbs[i]; - TreeNode tn = new TreeNode(db.dbiTitle); - tn.Tag = db; - tvROFST.Nodes.Add(tn); + TreeNode tn = new TreeNode(db.dbiTitle); + tn.Tag = db; + tvROFST.Nodes.Add(tn); - AddDummyGroup(db, tn); - } + AddDummyGroup(db, tn); + } + } _currRofstID = (IsRofstValid) ? (int?)_myROFST.ROFstID : null; _currDocVersionID = null; @@ -621,7 +697,13 @@ namespace Volian.Controls.Library if(_docVersionInfo != null) _currDocVersionID = (int?)_docVersionInfo.VersionID; if (tmpROID != null) ExpandNode(ROFSTLookup.FormatRoidKey(tmpROID, true)); - } + + //doc version would have updated (if needed) so reset flag + if (_progressBar?.Text != "Cannot check-out Working Draft") + { + changedDocVersion = false; + } + } var unitInfoNode = tvROFST.Nodes.Cast().Where(x => x.Text == "Unit Information").FirstOrDefault(); @@ -672,7 +754,9 @@ namespace Volian.Controls.Library } _curROTypeFilter = _roTypeFilter; - } + + return updatedROs; + } public void SetFindDocROButton(bool enabled) { diff --git a/PROMS/Volian.Controls.Library/StepTabRibbon.cs b/PROMS/Volian.Controls.Library/StepTabRibbon.cs index 1b3ec4c0..4f17d18b 100644 --- a/PROMS/Volian.Controls.Library/StepTabRibbon.cs +++ b/PROMS/Volian.Controls.Library/StepTabRibbon.cs @@ -3556,7 +3556,10 @@ namespace Volian.Controls.Library MyEditItem.SaveContents(); using (DocVersion dv = DocVersion.Get(Mydvi.VersionID)) { - swROUpdate = new System.IO.StreamWriter(ROFstInfo.ROUpdateResultsPath(Mydvi)); + //must get id before ROFST gets updated so know what to refresh later + int origfstid = roFstInfo.ROFstID; + + swROUpdate = new System.IO.StreamWriter(ROFstInfo.ROUpdateResultsPath(Mydvi)); // B2022-026 RO Memory Reduction code - first load the new ro.fst so that we can assign the ROTableUpdate event to the correct roFstInfo if (dv.ROfstLoadingFigures || dv.NewerRoFst) // B2017-125 see if loading figures was completed { @@ -3566,8 +3569,8 @@ namespace Volian.Controls.Library } roFstInfo.ROTableUpdate += new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); ContentInfo.StaticContentInfoChange += ContentInfo_StaticContentInfoChange; // write changes to a text file - ROFst newrofst = ROFstInfo.RefreshROFst(dv, roFstInfo, DoProgressBarRefresh, null); - swROUpdate.Close(); + ROFstInfo.RefreshROFstAtItemLevel(DocVersionInfo.Get(dv.VersionID), DoProgressBarRefresh, null, roFstInfo, origfstid, roFstInfo.ROFstID); + swROUpdate.Close(); ContentInfo.StaticContentInfoChange -= ContentInfo_StaticContentInfoChange; roFstInfo.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); StepPanelTabDisplayEventArgs args = new StepPanelTabDisplayEventArgs("DisplayROUpdateROFST"); diff --git a/PROMS/Volian.Controls.Library/vlnTreeView.cs b/PROMS/Volian.Controls.Library/vlnTreeView.cs index 12fabd03..a7855317 100644 --- a/PROMS/Volian.Controls.Library/vlnTreeView.cs +++ b/PROMS/Volian.Controls.Library/vlnTreeView.cs @@ -2465,7 +2465,11 @@ namespace Volian.Controls.Library } Cursor = Cursors.WaitCursor; // C2023-002: move wait cursor after check out error int ownerid = MySessionInfo.CheckOutItem(MyDVI.VersionID, CheckOutType.DocVersion); - using (DocVersion dv = DocVersion.Get(MyDVI.VersionID)) + + //must get id before ROFST gets updated so know what to refresh later + int origfstid = roFstInfo.ROFstID; + + using (DocVersion dv = DocVersion.Get(MyDVI.VersionID)) { swROUpdate = new System.IO.StreamWriter(ROFstInfo.ROUpdateResultsPath(MyDVI)); // RO changes placed in file in the Documents\VEPROMS folder // B2022-026 RO Memory Reduction code - first load the new ro.fst so that we can assign the ROTableUpdate event to the correct roFstInfo @@ -2477,8 +2481,8 @@ namespace Volian.Controls.Library } roFstInfo.ROTableUpdate += new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); ContentInfo.StaticContentInfoChange += ContentInfo_StaticContentInfoChange; // write changes to a text file - ROFst newrofst = ROFstInfo.RefreshROFst(dv, roFstInfo, DoProgressBarRefresh, null); - swROUpdate.Close(); + ROFstInfo.RefreshROFstAtItemLevel(DocVersionInfo.Get(dv.VersionID), DoProgressBarRefresh, null, roFstInfo, origfstid, roFstInfo.ROFstID); + swROUpdate.Close(); ContentInfo.StaticContentInfoChange -= ContentInfo_StaticContentInfoChange; roFstInfo.ROTableUpdate -= new ROFstInfoROTableUpdateEvent(roFstInfo_ROTableUpdate); OnTabDisplay(this, new StepPanelTabDisplayEventArgs("DisplayROUpdateROFST"));