/// <summary> /// Get all items in this appointments folder. Should be called just once (per folder?) /// when the add-in starts up; initialises the SyncState list. /// </summary> /// <param name="appointmentsFolder">The folder to scan.</param> protected override void GetOutlookItems(Outlook.MAPIFolder appointmentsFolder) { try { foreach (Outlook.AppointmentItem olItem in appointmentsFolder.Items) { if (olItem.Start >= this.GetStartDate()) { Outlook.UserProperty olPropertyModified = olItem.UserProperties[ModifiedDatePropertyName]; Outlook.UserProperty olPropertyType = olItem.UserProperties[TypePropertyName]; Outlook.UserProperty olPropertyEntryId = olItem.UserProperties[CrmIdPropertyName]; if (olPropertyModified != null && olPropertyType != null && olPropertyEntryId != null) { /* The appointment probably already has the three magic properties * required for synchronisation; is that a proxy for believing that it * already exists in CRM? If so, is it reliable? */ LogItemAction(olItem, "AppointmentSyncing.GetOutlookItems: Adding known item to queue"); } else { LogItemAction(olItem, "AppointmentSyncing.GetOutlookItems: Adding unknown item to queue"); } this.AddOrGetSyncState(olItem); } } } catch (Exception ex) { Log.Error("ThisAddIn.GetOutlookCalItems", ex); } }
/// <summary> /// Get the CRM id for this item, if known, else the empty string. /// </summary> /// <param name="olItem">The Outlook item under consideration.</param> /// <returns>the CRM id for this item, if known, else the empty string.</returns> public static CrmId GetCrmId(this Outlook.ContactItem olItem) { Outlook.UserProperty property = olItem.UserProperties[SyncStateManager.CrmIdPropertyName]; CrmId result = property != null?CrmId.Get(property.Value) : CrmId.Empty; return(result); }
/// <summary> /// Add the item implied by this SyncState, which may not exist in CRM, to CRM. /// </summary> /// <param name="syncState">The sync state.</param> /// <returns>The id of the entry added or updated.</returns> internal override string AddOrUpdateItemFromOutlookToCrm(SyncState <Outlook.AppointmentItem> syncState) { Outlook.AppointmentItem olItem = syncState.OutlookItem; Outlook.UserProperty olPropertyType = olItem.UserProperties[TypePropertyName]; var itemType = olPropertyType != null?olPropertyType.Value.ToString() : this.DefaultCrmModule; return(this.AddOrUpdateItemFromOutlookToCrm(syncState, itemType, syncState.CrmEntryId)); }
/// <summary> /// We should delete an item from CRM if it already exists in CRM, but it is now private. /// </summary> /// <param name="olItem">The Outlook item</param> /// <returns>true if the Outlook item should be deleted from CRM.</returns> private bool ShouldDeleteFromCrm(Outlook.AppointmentItem olItem) { Outlook.UserProperty olPropertyEntryId = olItem.UserProperties[CrmIdPropertyName]; bool result = (olPropertyEntryId != null && olItem.Sensitivity != Outlook.OlSensitivity.olNormal); LogItemAction(olItem, $"ShouldDeleteFromCrm returning {result}"); return(result); }
/// <summary> /// Ensure that this Outlook item has a property of this name with this value. /// </summary> /// <param name="olItem">The Outlook item.</param> /// <param name="name">The name.</param> /// <param name="value">The value.</param> protected override void EnsureSynchronisationPropertyForOutlookItem(Outlook.AppointmentItem olItem, string name, string value) { try { Outlook.UserProperty olProperty = olItem.UserProperties[name]; if (olProperty == null) { olProperty = olItem.UserProperties.Add(name, Outlook.OlUserPropertyType.olText); } olProperty.Value = value ?? string.Empty; } finally { this.SaveItem(olItem); } }
/// <summary> /// Log a message regarding this Outlook appointment. /// </summary> /// <param name="olItem">The outlook item.</param> /// <param name="message">The message to be logged.</param> internal override void LogItemAction(Outlook.AppointmentItem olItem, string message) { try { Outlook.UserProperty olPropertyEntryId = olItem.UserProperties[CrmIdPropertyName]; string crmId = olPropertyEntryId == null ? "[not present]" : olPropertyEntryId.Value; StringBuilder bob = new StringBuilder(); bob.Append($"{message}:\n\tOutlook Id : {olItem.EntryID}\n\tCRM Id : {crmId}\n\tSubject : '{olItem.Subject}'\n\tSensitivity : {olItem.Sensitivity}\n\tRecipients:\n"); foreach (Outlook.Recipient recipient in olItem.Recipients) { bob.Append($"\t\t{recipient.Name}: {recipient.GetSmtpAddress()}\n"); } Log.Info(bob.ToString()); } catch (COMException) { // Ignore: happens if the outlook item is already deleted. } }
/// <summary> /// Ensure that this Outlook item has a property of this name with this value. /// </summary> /// <param name="olItem">The Outlook item.</param> /// <param name="name">The name.</param> /// <param name="value">The value.</param> protected override void EnsureSynchronisationPropertyForOutlookItem(Outlook.AppointmentItem olItem, string name, string value) { try { Outlook.UserProperty olProperty = olItem.UserProperties[name]; if (olProperty == null) { olProperty = olItem.UserProperties.Add(name, Outlook.OlUserPropertyType.olText); } olProperty.Value = value ?? string.Empty; Log.Debug($"AppointmentSyncing.EnsureSynchronisationPropertyForOutlookItem: Set property {name} to value {value} on item {olItem.Subject}"); } catch (Exception any) { Log.Error($"AppointmentSyncing.EnsureSynchronisationPropertyForOutlookItem: Failed to set property {name} to value {value} on item {olItem.Subject}", any); } finally { this.SaveItem(olItem); } }
/// <summary> /// Update an existing Outlook item with values taken from a corresponding CRM item. Note that /// this just overwrites all values in the Outlook item. /// </summary> /// <param name="crmType">The CRM type of the item from which values are to be taken.</param> /// <param name="crmItem">The CRM item from which values are to be taken.</param> /// <param name="date_start">The state date/time of the item, adjusted for timezone.</param> /// <param name="syncState">The outlook item assumed to correspond with the CRM item.</param> /// <returns>An appropriate sync state.</returns> private SyncState <Outlook.AppointmentItem> UpdateExistingOutlookItemFromCrm( string crmType, EntryValue crmItem, DateTime date_start, SyncState <Outlook.AppointmentItem> syncState) { LogItemAction(syncState.OutlookItem, "AppointmentSyncing.UpdateExistingOutlookItemFromCrm"); if (!syncState.IsDeletedInOutlook) { Outlook.AppointmentItem olItem = syncState.OutlookItem; Outlook.UserProperty olPropertyModifiedDate = olItem.UserProperties[ModifiedDatePropertyName]; if (olPropertyModifiedDate.Value != crmItem.GetValueAsString("date_modified")) { try { olItem.Subject = crmItem.GetValueAsString("name"); olItem.Body = crmItem.GetValueAsString("description"); if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("date_start"))) { UpdateOutlookStartAndDuration(crmType, crmItem, date_start, olItem); } EnsureSynchronisationPropertiesForOutlookItem(olItem, crmItem, crmType); LogItemAction(syncState.OutlookItem, "AppointmentSyncing.UpdateExistingOutlookItemFromCrm, item saved"); } finally { this.SaveItem(olItem); } } Log.Warn((string)("Not default dResult.date_modified= " + crmItem.GetValueAsString("date_modified"))); syncState.OModifiedDate = DateTime.ParseExact(crmItem.GetValueAsString("date_modified"), "yyyy-MM-dd HH:mm:ss", null); } return(syncState); }