internal static void FindLastRevDtls(OAdEntity record, out string lastAuthor, out DateTime lastChangeDate) { lastAuthor = string.Empty; lastChangeDate = DateTime.MinValue; OAdHistoryFields cqHistFields = CQWrapper.GetHistoryFields(record); int historyFldCount = CQWrapper.HistoryFieldsCount(cqHistFields); for (int histFldIndex = 0; histFldIndex < historyFldCount; histFldIndex++) { object ob = (object)histFldIndex; OAdHistoryField historyField = CQWrapper.HistoryFieldsItem(cqHistFields, ref ob); int historyCount = CQWrapper.HistoryFieldHistoriesCount(historyField); // pick the last history for each historyfield object obHistIndex = (object)(historyCount - 1); OAdHistory aHistory = CQWrapper.HistoryFieldHistoriesItem(historyField, ref obHistIndex); CQHistory cqHistory = new CQHistory(aHistory); // CQ API returns local time DateTime changedDate = DateTime.Parse(cqHistory.Date, CultureInfo.CurrentCulture); if (changedDate.CompareTo(lastChangeDate) > 0) { // found a later change lastChangeDate = changedDate; lastAuthor = cqHistory.User; } } if (lastChangeDate.CompareTo(DateTime.MinValue) == 0) { lastChangeDate = DateTime.Now; lastAuthor = Environment.UserDomainName + "\\" + Environment.UserName; } }
private void ComputeDeltaPerRecord( OAdEntity aRecord) { OAdEntityDef aEntityDef = CQWrapper.GetEntityDef(m_userSession, CQWrapper.GetEntityDefName(aRecord)); string recordDispName = CQWrapper.GetEntityDisplayName(aRecord); string recordEntDefName = CQWrapper.GetEntityDefName(aRecord); #region process history bool recordContentIsModified = false; bool maybeNewRecord = false; Dictionary <string, List <ClearQuestRecordItem> > historyDelta = new Dictionary <string, List <ClearQuestRecordItem> >(); Dictionary <string, int> perHistoryFieldLastIndex = new Dictionary <string, int>(); // needed for updating processed delta // find all history fields OAdHistoryFields aHistFields = CQWrapper.GetHistoryFields(aRecord); int historyFldCount = CQWrapper.HistoryFieldsCount(aHistFields); bool containsNewHistory = false; for (int histFldIndex = 0; histFldIndex < historyFldCount; histFldIndex++) { object ob = (object)histFldIndex; OAdHistoryField aHistoryField = CQWrapper.HistoryFieldsItem(aHistFields, ref ob); string historyFieldName = CQWrapper.GetHistoryFieldName(aHistoryField); // find last processed history entry for this history field string lookupItemId = CQDeltaComputationProgressLookupService.CreateHistoryItemId(recordEntDefName, recordDispName, historyFieldName); int startHistIndex = 1 + DeltaComputeProgressService.GetLastProcessedItemVersion(lookupItemId); // find all history in a particular history field int historyCount = CQWrapper.HistoryFieldHistoriesCount(aHistoryField); for (int histIndex = startHistIndex; histIndex < historyCount; histIndex++) { object obHistIndex = (object)histIndex; OAdHistory aHistory = CQWrapper.HistoryFieldHistoriesItem(aHistoryField, ref obHistIndex); CQHistory cqHistory = new CQHistory(aHistory); CQMigrationItem migrationItem = new CQHistoryMigrationItem(recordDispName, historyFieldName, histIndex); if (TranslationService.IsSyncGeneratedItemVersion(ClearQuestRecordItem.GetMigrationRecordId(recordEntDefName, recordDispName), migrationItem.MigrationItemVersion, m_configurationService.SourceId)) { continue; } if (histIndex == 0) { maybeNewRecord = true; } // add unprocessed history fields for processing if (!historyDelta.ContainsKey(historyFieldName)) { historyDelta.Add(historyFieldName, new List <ClearQuestRecordItem>(historyCount)); } historyDelta[aHistoryField.fieldname].Add(new ClearQuestRecordItem(aRecord, aHistory, historyFieldName, histIndex.ToString())); containsNewHistory = true; // based on action type, we decide whether content change is needed int actionType = CQWrapper.GetActionDefType(aEntityDef, cqHistory.Action); switch (actionType) { case CQConstants.ACTION_SUBMIT: break; case CQConstants.ACTION_MODIFY: recordContentIsModified = true; break; case CQConstants.ACTION_CHANGE: break; case CQConstants.ACTION_DUPLICATE: break; case CQConstants.ACTION_UNDUPLICATE: break; case CQConstants.ACTION_IMPORT: break; case CQConstants.ACTION_DELETE: TraceManager.TraceInformation(ClearQuestResource.ClearQuest_Msg_RecordDeleted, recordEntDefName, recordDispName); break; case CQConstants.ACTION_BASE: break; case CQConstants.ACTION_RECORD_SCRIPT_ALIAS: break; } } perHistoryFieldLastIndex.Add(historyFieldName, historyCount - 1); } #endregion #region generate delta for content and history if (maybeNewRecord || recordContentIsModified) { // the first revision, i.e. "Submit", of a CQ record is always hard-coded to be '1' CQMigrationItem contentMigrationAction = new CQMigrationItem(recordDispName, ClearQuestRecordItem.NewRecordVersion); bool isNewRecord = false; if (maybeNewRecord) { isNewRecord = !(DeltaComputeProgressService.IsMigrationItemProcessed(recordDispName, ClearQuestRecordItem.NewRecordVersionValue)); } if (!isNewRecord) { // all subsequent record "MODIFICATIONs" are hard-coded to be "update@<Now.Ticks>" contentMigrationAction.MigrationItemVersion = ClearQuestRecordItem.RecordUpdateVersion + "@" + DateTime.Now.Ticks; } ClearQuestRecordItem recordContentItem = new ClearQuestRecordItem(aRecord, contentMigrationAction.MigrationItemVersion); recordContentItem.CQSession = m_userSession; recordContentItem.Version = contentMigrationAction.MigrationItemVersion; ChangeGroup contentChangeGroup = recordContentItem.CreateChangeGroup( m_changeGroupService, m_migrationContext, isNewRecord && m_isLastRevisionAutoCorrectionEnabled); contentChangeGroup.Save(); if (isNewRecord && !containsNewHistory) { DeltaComputeProgressService.UpdateCache(recordDispName, ClearQuestRecordItem.NewRecordVersionValue); } } var lastHistoryRecordItem = historyDelta[historyDelta.Keys.Last()].Last(); foreach (string histFieldName in historyDelta.Keys) { foreach (ClearQuestRecordItem recordHistItem in historyDelta[histFieldName]) { recordHistItem.CQSession = m_userSession; ChangeGroup changeGroup = recordHistItem.CreateChangeGroup( m_changeGroupService, m_migrationContext, (CQStringComparer.FieldName.Equals(recordHistItem.HistoryFieldName, lastHistoryRecordItem.HistoryFieldName) && recordHistItem.Version.Equals(lastHistoryRecordItem.Version, StringComparison.OrdinalIgnoreCase) && m_isLastRevisionAutoCorrectionEnabled)); changeGroup.Save(); } Debug.Assert(perHistoryFieldLastIndex.ContainsKey(histFieldName), "perHistoryFieldLastIndex.ContainsKey(histFieldName) returns false"); string deltaComputeProcessLookupId = CQDeltaComputationProgressLookupService.CreateHistoryItemId(recordEntDefName, recordDispName, histFieldName); DeltaComputeProgressService.UpdateCache(deltaComputeProcessLookupId, perHistoryFieldLastIndex[histFieldName]); } #endregion #region process attachment OAdAttachmentFields aAttachmentFields = CQWrapper.GetAttachmentFields(aRecord); for (int aAttachmentFieldsIndex = 0; aAttachmentFieldsIndex < CQWrapper.AttachmentsFieldsCount(aAttachmentFields); aAttachmentFieldsIndex++) { object ob = (object)aAttachmentFieldsIndex; OAdAttachmentField aAttachmentField = CQWrapper.AttachmentsFieldsItem(aAttachmentFields, ref ob); string fieldName = CQWrapper.GetAttachmentFieldName(aAttachmentField); ChangeGroup changeGroup = m_changeGroupService.CreateChangeGroupForDeltaTable( string.Format("{0}:{1}:{2}", recordDispName, "Attachments", fieldName)); // process all attachments OAdAttachments attachments = CQWrapper.GetAttachments(aAttachmentField); for (int attachmentIndex = 0; attachmentIndex < CQWrapper.AttachmentsCount(attachments); attachmentIndex++) { object obIndex = (object)attachmentIndex; OAdAttachment aAttachment = CQWrapper.AttachmentsItem(attachments, ref obIndex); ClearQuestAttachmentItem attachmentItem = new ClearQuestAttachmentItem(aRecord, aAttachmentField, aAttachment, UserSessionConnConfig); attachmentItem.CQSession = m_userSession; attachmentItem.CreateChangeAction(changeGroup, lastHistoryRecordItem.Version); } if (changeGroup.Actions.Count > 0) { changeGroup.Save(); } } #endregion }