/// <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="oItem">The outlook item assumed to correspond with the CRM item.</param>
        /// <returns>An appropriate sync state.</returns>
        private SyncState <Outlook.AppointmentItem> UpdateExistingOutlookItemFromCrm(
            string crmType,
            eEntryValue crmItem,
            DateTime date_start,
            SyncState <Outlook.AppointmentItem> oItem)
        {
            LogItemAction(oItem.OutlookItem, "AppointmentSyncing.UpdateExistingOutlookItemFromCrm");

            if (!oItem.IsDeletedInOutlook)
            {
                Outlook.AppointmentItem olAppointment          = oItem.OutlookItem;
                Outlook.UserProperty    olPropertyModifiedDate = olAppointment.UserProperties[ModifiedDatePropertyName];

                MaybeAddAcceptDeclineLinks(crmItem, oItem.OutlookItem, crmType);

                if (olPropertyModifiedDate.Value != crmItem.GetValueAsString("date_modified"))
                {
                    olAppointment.Subject = crmItem.GetValueAsString("name");
                    olAppointment.Body    = crmItem.GetValueAsString("description");
                    if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("date_start")))
                    {
                        UpdateOutlookStartAndDuration(crmType, crmItem, date_start, olAppointment);
                    }

                    EnsureSynchronisationPropertiesForOutlookItem(olAppointment, crmItem, crmType);
                    olAppointment.Save();
                    LogItemAction(oItem.OutlookItem, "AppointmentSyncing.UpdateExistingOutlookItemFromCrm, item saved");
                }
                Log.Warn((string)("Not default dResult.date_modified= " + crmItem.GetValueAsString("date_modified")));
                oItem.OModifiedDate = DateTime.ParseExact(crmItem.GetValueAsString("date_modified"), "yyyy-MM-dd HH:mm:ss", null);
            }

            return(oItem);
        }
        /// <summary>
        /// Update a single appointment in the specified Outlook folder with changes from CRM, but
        /// only if its start date is fewer than five days in the past.
        /// </summary>
        /// <param name="folder">The folder to synchronise into.</param>
        /// <param name="crmType">The CRM type of the candidate item.</param>
        /// <param name="candidateItem">The candidate item from CRM.</param>
        /// <returns>The synchronisation state of the item updated (if it was updated).</returns>
        protected override SyncState <Outlook.AppointmentItem> AddOrUpdateItemFromCrmToOutlook(
            Outlook.MAPIFolder folder,
            string crmType,
            eEntryValue crmItem)
        {
            SyncState <Outlook.AppointmentItem> result = null;
            DateTime date_start = DateTime.ParseExact(crmItem.GetValueAsString("date_start"), "yyyy-MM-dd HH:mm:ss", null);

            date_start = date_start.Add(new DateTimeOffset(DateTime.Now).Offset); // correct for offset from UTC.
            if (date_start >= GetStartDate())
            {
                /* search for the item among the sync states I already know about */
                var syncState = this.GetExistingSyncState(crmItem);
                if (syncState == null)
                {
                    /* didn't find it, so add it to Outlook */
                    result = AddNewItemFromCrmToOutlook(folder, crmType, crmItem, date_start);
                }
                else
                {
                    /* found it, so update it from the CRM item */
                    result = UpdateExistingOutlookItemFromCrm(crmType, crmItem, date_start, syncState);
                }

                result.OutlookItem.Save();
            }

            return(result);
        }
        /// <summary>
        /// Update a single appointment in the specified Outlook folder with changes from CRM, but
        /// only if its start date is fewer than five days in the past.
        /// </summary>
        /// <param name="folder">The folder to synchronise into.</param>
        /// <param name="crmType">The CRM type of the candidate item.</param>
        /// <param name="crmItem">The candidate item from CRM.</param>
        /// <returns>The synchronisation state of the item updated (if it was updated).</returns>
        protected override SyncState <Outlook.AppointmentItem> AddOrUpdateItemFromCrmToOutlook(
            Outlook.MAPIFolder folder,
            string crmType,
            EntryValue crmItem)
        {
            SyncState <Outlook.AppointmentItem> result = null;
            DateTime dateStart = crmItem.GetValueAsDateTime("date_start");

            if (dateStart >= GetStartDate())
            {
                /* search for the item among the sync states I already know about */
                var syncState = this.GetExistingSyncState(crmItem);
                if (syncState == null)
                {
                    /* check for howlaround */
                    var matches = this.FindMatches(crmItem);

                    if (matches.Count == 0)
                    {
                        /* didn't find it, so add it to Outlook */
                        result = AddNewItemFromCrmToOutlook(folder, crmType, crmItem, dateStart);
                    }
                    else
                    {
                        this.Log.Warn($"Howlaround detected? Appointment '{crmItem.GetValueAsString("name")}' offered with id {crmItem.GetValueAsString("id")}, expected {matches[0].CrmEntryId}, {matches.Count} duplicates");
                    }
                }
                else
                {
                    /* found it, so update it from the CRM item */
                    result = UpdateExistingOutlookItemFromCrm(crmType, crmItem, dateStart, syncState);

                    result?.OutlookItem.Save();
                }

                if (crmItem?.relationships?.link_list != null)
                {
                    foreach (var list in crmItem.relationships.link_list)
                    {
                        foreach (var record in list.records)
                        {
                            var data = record.data.AsDictionary();
                            try
                            {
                                this.meetingRecipientsCache[data[AddressResolutionData.EmailAddressFieldName].ToString()] =
                                    new AddressResolutionData(list.name, data);
                                Log.Debug($"Successfully cached recipient {data[AddressResolutionData.EmailAddressFieldName]} => {list.name}, {data[AddressResolutionData.ModuleIdFieldName]}.");
                            }
                            catch (KeyNotFoundException kex)
                            {
                                Log.Error($"Key not found while caching meeting recipients.", kex);
                            }
                        }
                    }
                }
            }

            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));
        }
Example #5
0
        /// <summary>
        ///     Override: we get notified of a removal, for a Meeting item, when the meeting is
        ///     cancelled. We do NOT want to remove such an item; instead, we want to update it.
        /// </summary>
        /// <param name="state"></param>
        protected override void RemoveFromCrm(SyncState state)
        {
            var meeting = state as MeetingSyncState;

            if (meeting != null)
            {
                meeting.Cache.Status = OlMeetingStatus.olMeetingCanceled;

                RestAPIWrapper.SetEntry(meeting.Cache.AsNameValues(), DefaultCrmModule);
            }
        }
Example #6
0
        /// <summary>
        /// TODO: I (AF) do not understand the purpose of this logic. (Pre-existing code, slightly cleaned-up.)
        /// </summary>
        /// <param name="contact"></param>
        /// <returns></returns>
        private bool ShouldPerformSyncNow(SyncState <Outlook.ContactItem> contact)
        {
            var modifiedSinceSeconds = Math.Abs((DateTime.UtcNow - contact.OModifiedDate).TotalSeconds);

            if (modifiedSinceSeconds > 5 || modifiedSinceSeconds > 2 && contact.IsUpdate == 0)
            {
                contact.OModifiedDate = DateTime.UtcNow;
                contact.IsUpdate      = 1;
            }

            return(IsCurrentView && contact.IsUpdate == 1);
        }
        /// <summary>
        /// Add the Outlook item referenced by this sync state, which may not exist in CRM, to CRM.
        /// </summary>
        /// <param name="syncState">The sync state referencing the outlook item to add.</param>
        /// <param name="crmType">The CRM type ('module') to which it should be added</param>
        /// <param name="entryId">The id of this item in CRM, if known (in which case I should be doing
        /// an update, not an add).</param>
        /// <returns>The id of the entry added o</returns>
        internal override string AddOrUpdateItemFromOutlookToCrm(SyncState <Outlook.AppointmentItem> syncState, string crmType, string entryId = "")
        {
            string result = entryId;

            Outlook.AppointmentItem olItem = syncState.OutlookItem;

            if (this.ShouldAddOrUpdateItemFromOutlookToCrm(olItem, crmType))
            {
                if (ShouldDeleteFromCrm(olItem))
                {
                    LogItemAction(olItem, "AppointmentSyncing.AddOrUpdateItemFromOutlookToCrm: Deleting");

                    DeleteFromCrm(olItem);
                }
                else if (ShouldDespatchToCrm(olItem))
                {
                    lock (enqueueingLock)
                    {
                        result = base.AddOrUpdateItemFromOutlookToCrm(syncState, crmType, entryId);

                        if (String.IsNullOrEmpty(result))
                        {
                            Log.Warn("AppointmentSyncing.AddOrUpdateItemFromOutlookToCrm: Invalid CRM Id returned; item may not have been stored.");
                        }
                        else
                        {
                            if (string.IsNullOrEmpty(entryId))
                            {
                                /* i.e. this was a new item saved to CRM for the first time */
                                SetCrmRelationshipFromOutlook(result, "Users", RestAPIWrapper.GetUserId());

                                this.SaveItem(olItem);

                                if (olItem.Recipients != null)
                                {
                                    AddMeetingRecipientsFromOutlookToCrm(olItem, result);
                                }
                            }
                        }
                    }
                }
                else
                {
                    LogItemAction(olItem, "AppointmentSyncing.AddItemFromOutlookToCrm, Not despatching");
                }
            }
            else
            {
                LogItemAction(olItem, "AppointmentSyncing.AddItemFromOutlookToCrm, Not enabled");
            }

            return(result);
        }
 /// <summary>
 /// Remove an outlook item and its associated sync state.
 /// </summary>
 /// <remarks>
 /// TODO: candidate for refactoring to superclass.
 /// </remarks>
 /// <param name="syncState">The sync state of the item to remove.</param>
 private void RemoveItemAndSyncState(SyncState <Outlook.AppointmentItem> syncState)
 {
     this.LogItemAction(syncState.OutlookItem, "AppointmentSyncing.SyncFolder, deleting item");
     try
     {
         syncState.OutlookItem.Delete();
     }
     catch (Exception ex)
     {
         Log.Error("AppointmentSyncing.SyncFolder: Exception  oItem.oItem.Delete", ex);
     }
     this.RemoveItemSyncState(syncState);
 }
Example #9
0
 /// <summary>
 /// Remove an outlook item and its associated sync state.
 /// </summary>
 /// <param name="syncState">The sync state of the item to remove.</param>
 protected void RemoveItemAndSyncState(SyncState <OutlookItemType> syncState)
 {
     this.LogItemAction(syncState.OutlookItem, "Synchroniser.RemoveItemAndSyncState, deleting item");
     try
     {
         syncState.DeleteItem();
     }
     catch (Exception ex)
     {
         Log.Error("Synchroniser.RemoveItemAndSyncState: Exception  oItem.oItem.Delete", ex);
     }
     this.RemoveItemSyncState(syncState);
 }
Example #10
0
 /// <summary>
 /// Constructs a new SyncState object for this Outlook item and adds it to my
 /// collection of sync states.
 /// </summary>
 /// <param name="olItem">The Outlook item to wrap</param>
 /// <returns>The sync state added.</returns>
 private SyncState <OutlookItemType> ConstructAndAddSyncState(OutlookItemType olItem)
 {
     try
     {
         SyncState <OutlookItemType> newState = ConstructSyncState(olItem);
         ItemsSyncState.Add(newState);
         return(newState);
     }
     finally
     {
         this.SaveItem(olItem);
     }
 }
        protected override SyncState <Outlook.TaskItem> AddOrUpdateItemFromCrmToOutlook(Outlook.MAPIFolder tasksFolder, string crmType, eEntryValue crmItem)
        {
            SyncState <Outlook.TaskItem> result = null;

            Log.Debug($"TaskSyncing.AddOrUpdateItemFromCrmToOutlook\n\tSubject: {crmItem.GetValueAsString("name")}\n\tCurrent user id {clsSuiteCRMHelper.GetUserId()}\n\tAssigned user id: {crmItem.GetValueAsString("assigned_user_id")}");

            if (clsSuiteCRMHelper.GetUserId() == crmItem.GetValueAsString("assigned_user_id"))
            {
                DateTime?date_start = null;
                DateTime?date_due   = null;

                string time_start = "--:--", time_due = "--:--";

                if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("date_start")))
                {
                    Log.Warn("\tSET date_start = dResult.date_start");
                    date_start = DateTime.ParseExact(crmItem.GetValueAsString("date_start"), "yyyy-MM-dd HH:mm:ss", null);

                    date_start = date_start.Value.Add(new DateTimeOffset(DateTime.Now).Offset);
                    time_start =
                        TimeSpan.FromHours(date_start.Value.Hour)
                        .Add(TimeSpan.FromMinutes(date_start.Value.Minute))
                        .ToString(@"hh\:mm");
                }

                if (date_start != null && date_start >= GetStartDate())
                {
                    if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("date_due")))
                    {
                        date_due = DateTime.ParseExact(crmItem.GetValueAsString("date_due"), "yyyy-MM-dd HH:mm:ss", null);
                        date_due = date_due.Value.Add(new DateTimeOffset(DateTime.Now).Offset);
                        time_due =
                            TimeSpan.FromHours(date_due.Value.Hour).Add(TimeSpan.FromMinutes(date_due.Value.Minute)).ToString(@"hh\:mm");
                        ;
                    }

                    var syncState = this.GetExistingSyncState(crmItem);

                    if (syncState == null)
                    {
                        result = AddNewItemFromCrmToOutlook(tasksFolder, crmItem, date_start, date_due, time_start, time_due);
                    }
                    else
                    {
                        result = UpdateExistingOutlookItemFromCrm(crmItem, date_start, date_due, time_start, time_due, syncState);
                    }
                }
            }

            return(result);
        }
Example #12
0
        protected override SyncState <Outlook.ContactItem> AddOrUpdateItemFromCrmToOutlook(Outlook.MAPIFolder folder, string crmType, eEntryValue crmItem)
        {
            SyncState <Outlook.ContactItem> result;

            String id = crmItem.GetValueAsString("id");
            SyncState <Outlook.ContactItem> syncStateForItem = GetExistingSyncState(crmItem);

            if (ShouldSyncContact(crmItem))
            {
                Log.Info(
                    string.Format(
                        "ContactSyncing.UpdateFromCrm, entry id is '{0}', sync_contact is true, syncing",
                        id));

                if (syncStateForItem == null)
                {
                    result = AddNewItemFromCrmToOutlook(folder, crmItem);
                }
                else
                {
                    result = UpdateExistingOutlookItemFromCrm(crmItem, syncStateForItem);
                }
            }
            else if (syncStateForItem != null &&
                     syncStateForItem.OutlookItem != null)
            {
                /* The date_modified value in CRM does not get updated when the sync_contact value
                 * is changed. But seeing this value can only be updated at the CRM side, if it
                 * has changed the change must have been at the CRM side. It doesn't change to false,
                 * it simply ceases to be sent. Set the item to Private in Outlook. */
                if (syncStateForItem.OutlookItem.Sensitivity != Outlook.OlSensitivity.olPrivate)
                {
                    Log.Info($"ContactSyncing.UpdateFromCrm: setting sensitivity of contact {crmItem.GetValueAsString("first_name")} {crmItem.GetValueAsString("last_name")} ({crmItem.GetValueAsString("email1")}) to private");
                    syncStateForItem.OutlookItem.Sensitivity = Outlook.OlSensitivity.olPrivate;
                }

                result = syncStateForItem;
            }
            else
            {
                Log.Info(
                    string.Format(
                        "ContactSyncing.UpdateFromCrm, entry id is '{0}', sync_contact is false, not syncing",
                        id));

                result = syncStateForItem;
            }

            return(result);
        }
Example #13
0
        protected override SyncState <Outlook.TaskItem> AddOrUpdateItemFromCrmToOutlook(Outlook.MAPIFolder tasksFolder,
                                                                                        string crmType, EntryValue crmItem)
        {
            SyncState <Outlook.TaskItem> result = null;

            Log.Debug(
                $"TaskSyncing.AddOrUpdateItemFromCrmToOutlook\n\tSubject: {crmItem.GetValueAsString("name")}\n\tCurrent user id {RestAPIWrapper.GetUserId()}\n\tAssigned user id: {crmItem.GetValueAsString("assigned_user_id")}");

            var syncState = SyncStateManager.Instance.GetExistingSyncState(crmItem) as SyncState <Outlook.TaskItem>;

            result = syncState == null?MaybeAddNewItemFromCrmToOutlook(tasksFolder, crmItem) : UpdateExistingOutlookItemFromCrm(crmItem, syncState);

            return(result);
        }
 /// <summary>
 /// Delete this Outlook item from CRM, and tidy up afterwards.
 /// </summary>
 /// <param name="olItem">The Outlook item to delete.</param>
 private void DeleteFromCrm(Outlook.AppointmentItem olItem)
 {
     if (olItem != null)
     {
         /* Remove the magic properties */
         RemoveSynchronisationPropertiesFromOutlookItem(olItem);
         SyncState <Outlook.AppointmentItem> syncStateForItem = GetExistingSyncState(olItem);
         if (syncStateForItem != null)
         {
             this.RemoveFromCrm(syncStateForItem);
             RemoveItemSyncState(syncStateForItem);
         }
     }
 }
Example #15
0
        protected override SyncState <Outlook.TaskItem> UpdateFromCrm(Outlook.MAPIFolder tasksFolder, string crmType, eEntryValue crmItem)
        {
            SyncState <Outlook.TaskItem> result = null;

            if (clsSuiteCRMHelper.GetUserId() == crmItem.GetValueAsString("assigned_user_id"))
            {
                DateTime?date_start = null;
                DateTime?date_due   = null;

                string time_start = "--:--", time_due = "--:--";

                if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("date_start")))
                {
                    Log.Warn("\tSET date_start = dResult.date_start");
                    date_start = DateTime.ParseExact(crmItem.GetValueAsString("date_start"), "yyyy-MM-dd HH:mm:ss", null);

                    date_start = date_start.Value.Add(new DateTimeOffset(DateTime.Now).Offset);
                    time_start =
                        TimeSpan.FromHours(date_start.Value.Hour)
                        .Add(TimeSpan.FromMinutes(date_start.Value.Minute))
                        .ToString(@"hh\:mm");
                }

                if (date_start != null && date_start >= GetStartDate())
                {
                    if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("date_due")))
                    {
                        date_due = DateTime.ParseExact(crmItem.GetValueAsString("date_due"), "yyyy-MM-dd HH:mm:ss", null);
                        date_due = date_due.Value.Add(new DateTimeOffset(DateTime.Now).Offset);
                        time_due =
                            TimeSpan.FromHours(date_due.Value.Hour).Add(TimeSpan.FromMinutes(date_due.Value.Minute)).ToString(@"hh\:mm");
                        ;
                    }

                    var oItem = ItemsSyncState.FirstOrDefault(a => a.CrmEntryId == crmItem.GetValueAsString("id"));

                    if (oItem == null)
                    {
                        result = AddNewItemFromCrmToOutlook(tasksFolder, crmItem, date_start, date_due, time_start, time_due);
                    }
                    else
                    {
                        result = UpdateExistingOutlookItemFromCrm(crmItem, date_start, date_due, time_start, time_due, oItem);
                    }
                }
            }

            return(result);
        }
        /// <summary>
        /// Get a sync state for this item, creating it if necessary.
        /// </summary>
        /// <remarks>Outlook items are not true objects and don't have a common superclass,
        /// so we have to use this rather clumsy despatch.</remarks>
        /// <param name="item">the item.</param>
        /// <returns>an appropriate sync state.</returns>
        /// <exception cref="UnexpectedSyncStateClassException">if the sync state found is not of the expected class (shouldn't happen).</exception>
        public SyncState <ItemType> GetOrCreateSyncState <ItemType>(ItemType item)
            where ItemType : class
        {
            lock (this.creationLock)
            {
                SyncState <ItemType> result = this.GetExistingSyncState(item);

                if (result == null)
                {
                    result = CreateSyncStateForItem(item);
                }

                return(result);
            }
        }
Example #17
0
 /// <summary>
 /// Delete this Outlook item from CRM, and tidy up afterwards.
 /// </summary>
 /// <param name="olItem">The Outlook item to delete.</param>
 private void DeleteFromCrm(Outlook.AppointmentItem olItem)
 {
     if (olItem != null)
     {
         /* Remove the magic properties */
         RemoveSynchronisationPropertiesFromOutlookItem(olItem);
         SyncState <Outlook.AppointmentItem> syncStateForItem = GetSyncStateForItem(olItem);
         if (syncStateForItem != null)
         {
             this.RemoveFromCrm(syncStateForItem);
             /* TODO: Not at all sure I should remove the sync state */
             RemoveItemSyncState(syncStateForItem);
         }
     }
 }
Example #18
0
        /// <summary>
        /// Add the Outlook item referenced by this sync state, which may not exist in CRM, to CRM.
        /// </summary>
        /// <param name="syncState">The sync state referencing the outlook item to add.</param>
        /// <param name="crmType">The CRM type ('module') to which it should be added</param>
        /// <param name="entryId">The id of this item in CRM, if known (in which case I should be doing
        /// an update, not an add).</param>
        /// <returns>The id of the entry added o</returns>
        internal virtual string AddOrUpdateItemFromOutlookToCrm(SyncState <OutlookItemType> syncState, string crmType, string entryId = "")
        {
            string result = entryId;

            if (this.ShouldAddOrUpdateItemFromOutlookToCrm(syncState.OutlookItem, crmType))
            {
                OutlookItemType outlookItem = syncState.OutlookItem;

                try
                {
                    lock (this.TransmissionLock)
                    {
                        LogItemAction(outlookItem, "Synchroniser.AddOrUpdateItemFromOutlookToCrm, Despatching");

                        if (syncState != null)
                        {
                            syncState.SetTransmitted();
                        }

                        result = ConstructAndDespatchCrmItem(outlookItem, crmType, entryId);
                        if (!string.IsNullOrEmpty(result))
                        {
                            var utcNow = DateTime.UtcNow;
                            EnsureSynchronisationPropertiesForOutlookItem(outlookItem, utcNow.ToString(), crmType, result);
                            this.SaveItem(outlookItem);

                            syncState.SetSynced(result);
                        }
                        else
                        {
                            Log.Warn("AppointmentSyncing.AddItemFromOutlookToCrm: Invalid CRM Id returned; item may not be stored.");
                            syncState.SetPending();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error("Synchroniser.AddOrUpdateItemFromOutlookToCrm", ex);
                    syncState.SetPending();
                }
                finally
                {
                    this.SaveItem(outlookItem);
                }
            }

            return(result);
        }
        /// <summary>
        /// Find the SyncState whose item is this item; if it does not already exist, construct and return it.
        /// </summary>
        /// <param name="oItem">The item to find.</param>
        /// <returns>the SyncState whose item is this item</returns>
        protected SyncState <OutlookItemType> AddOrGetSyncState(OutlookItemType oItem)
        {
            var existingState = GetExistingSyncState(oItem);

            if (existingState != null)
            {
                existingState.OutlookItem = oItem;
                return(existingState);
            }
            else
            {
                SyncState <OutlookItemType> newState = ConstructSyncState(oItem);
                ItemsSyncState.Add(newState);
                return(newState);
            }
        }
Example #20
0
 /// <summary>
 /// (Don't actually) remove the item implied by this sync state from CRM.
 /// </summary>
 /// <remarks>
 /// After considerable thought we've decided that contacts should never actually be deleted from CRM
 /// by the action of the plugin.
 /// </remarks>
 /// <param name="state">A sync state wrapping an item which has been deleted or marked private in Outlook.</param>
 protected override void RemoveFromCrm(SyncState state)
 {
     if (state is ContactSyncState)
     {
         /* which it most definitely should be */
         if (state.ExistedInCrm && (state.IsDeletedInOutlook || !state.IsPublic))
         {
             /* remove sync_contact relationship in CRM */
             EnsureSyncWithOutlookSetInCRM(state.CrmEntryId, null, false);
         }
     }
     else
     {
         base.RemoveFromCrm(state);
     }
 }
        /// <summary>
        /// Check whether there exists a sync state other than this state whose CRM id is
        /// this CRM id or the CRM id of this state.
        /// </summary>
        /// <param name="state">The sync state to be checked.</param>
        /// <param name="crmId">A candidate CRM id.</param>
        /// <returns>A better guess at the CRM id.</returns>
        /// <exception cref="DuplicateSyncStateException">If a duplicate is detected.</exception>
        private CrmId CheckForDuplicateSyncState(SyncState state, CrmId crmId)
        {
            CrmId result = CrmId.IsInvalid(crmId) && state != null ? state.CrmEntryId : crmId;

            if (result != null)
            {
                SyncState byCrmState = this.byCrmId.ContainsKey(crmId) ? this.byCrmId[crmId] : null;

                if (state != null && byCrmState != null && state != byCrmState)
                {
                    throw new DuplicateSyncStateException(state);
                }
            }

            return(result);
        }
Example #22
0
        /// <summary>
        /// Remove the item implied by this sync state from CRM.
        /// </summary>
        /// <param name="state">A sync state wrapping an item which has been deleted or marked private in Outlook.</param>
        protected virtual void RemoveFromCrm(SyncState state)
        {
            if (SyncDirection.AllowOutbound(Direction))
            {
                var crmEntryId = state.CrmEntryId;
                if (state.ExistedInCrm && this.permissionsCache.HasImportAccess(state.CrmType))
                {
                    eNameValue[] data = new eNameValue[2];
                    data[0] = clsSuiteCRMHelper.SetNameValuePair("id", crmEntryId);
                    data[1] = clsSuiteCRMHelper.SetNameValuePair("deleted", "1");
                    clsSuiteCRMHelper.SetEntryUnsafe(data, state.CrmType);
                }

                state.RemoveCrmLink();
            }
        }
        protected void RemoveFromCrm(SyncState state)
        {
            if (!SyncingEnabled)
            {
                return;
            }
            var crmEntryId = state.CrmEntryId;

            if (!string.IsNullOrEmpty(crmEntryId) && this.HasImportAccess(state.CrmType))
            {
                eNameValue[] data = new eNameValue[2];
                data[0] = clsSuiteCRMHelper.SetNameValuePair("id", crmEntryId);
                data[1] = clsSuiteCRMHelper.SetNameValuePair("deleted", "1");
                clsSuiteCRMHelper.SetEntryUnsafe(data, state.CrmType);
            }

            state.RemoveCrmLink();
        }
        /// <summary>
        /// Add the Outlook item referenced by this sync state, which may not exist in CRM, to CRM.
        /// </summary>
        /// <param name="syncState">The sync state referencing the outlook item to add.</param>
        /// <param name="crmType">The CRM type ('module') to which it should be added</param>
        /// <param name="entryId">The id of this item in CRM, if known (in which case I should be doing
        /// an update, not an add).</param>
        /// <returns>The id of the entry added o</returns>
        internal override string AddOrUpdateItemFromOutlookToCrm(SyncState <Outlook.ContactItem> syncState, string crmType, string entryId = "")
        {
            string result = entryId;
            var    olItem = syncState.OutlookItem;

            if (this.ShouldAddOrUpdateItemFromOutlookToCrm(olItem))
            {
                result = base.AddOrUpdateItemFromOutlookToCrm(syncState, crmType, entryId);

                Outlook.UserProperty syncProperty = olItem.UserProperties["SShouldSync"];
                string shouldSync = syncProperty == null?
                                    Boolean.TrueString.ToLower() :
                                        syncProperty.Value;

                EnsureSyncWithOutlookSetInCRM(result, syncProperty);
            }

            return(result);
        }
        // TODO: this is very horrible and should be reworked.
        protected override SyncState <Outlook.TaskItem> AddOrUpdateItemFromCrmToOutlook(Outlook.MAPIFolder tasksFolder, string crmType, EntryValue crmItem)
        {
            SyncState <Outlook.TaskItem> result = null;

            Log.Debug($"TaskSyncing.AddOrUpdateItemFromCrmToOutlook\n\tSubject: {crmItem.GetValueAsString("name")}\n\tCurrent user id {RestAPIWrapper.GetUserId()}\n\tAssigned user id: {crmItem.GetValueAsString("assigned_user_id")}");

            if (RestAPIWrapper.GetUserId() == crmItem.GetValueAsString("assigned_user_id"))
            {
                DateTime dateStart = crmItem.GetValueAsDateTime("newValue");
                DateTime dateDue   = crmItem.GetValueAsDateTime("dateDue");
                string   timeStart =
                    TimeSpan.FromHours(dateStart.Hour)
                    .Add(TimeSpan.FromMinutes(dateStart.Minute))
                    .ToString(@"hh\:mm");
                string timeDue = TimeSpan.FromHours(dateDue.Hour)
                                 .Add(TimeSpan.FromMinutes(dateDue.Minute))
                                 .ToString(@"hh\:mm");

                var syncState = this.GetExistingSyncState(crmItem);

                if (syncState == null)
                {
                    /* check for howlaround */
                    var matches = this.FindMatches(crmItem);

                    if (matches.Count == 0)
                    {
                        /* didn't find it, so add it to Outlook */
                        result = AddNewItemFromCrmToOutlook(tasksFolder, crmItem, dateStart, dateDue, timeStart, timeDue);
                    }
                    else
                    {
                        this.Log.Warn($"Howlaround detected? Task '{crmItem.GetValueAsString("name")}' offered with id {crmItem.GetValueAsString("id")}, expected {matches[0].CrmEntryId}, {matches.Count} duplicates");
                    }
                }
                else
                {
                    result = UpdateExistingOutlookItemFromCrm(crmItem, dateStart, dateDue, timeStart, timeDue, syncState);
                }
            }

            return(result);
        }
Example #26
0
        /// <summary>
        /// Add the Outlook item referenced by this sync state, which may not exist in CRM, to CRM.
        /// </summary>
        /// <param name="syncState">The sync state referencing the outlook item to add.</param>
        /// an update, not an add).</param>
        /// <returns>The id of the entry added o</returns>
        internal override CrmId AddOrUpdateItemFromOutlookToCrm(SyncState <Outlook.ContactItem> syncState)
        {
            CrmId result = CrmId.Empty;
            var   olItem = syncState.OutlookItem;

            if (this.ShouldAddOrUpdateItemFromOutlookToCrm(olItem))
            {
                result = base.AddOrUpdateItemFromOutlookToCrm(syncState);

                Outlook.UserProperty syncProperty = olItem.UserProperties["SShouldSync"];
                string shouldSync = syncProperty == null?
                                    Boolean.TrueString.ToLower() :
                                        syncProperty.Value;

                EnsureSyncWithOutlookSetInCRM(result, syncProperty);
            }

            return(result);
        }
Example #27
0
        internal override CrmId AddOrUpdateItemFromOutlookToCrm(SyncState <Outlook.AppointmentItem> syncState)
        {
            CrmId previousCrmId = syncState.CrmEntryId;
            CrmId result        = base.AddOrUpdateItemFromOutlookToCrm(syncState);

            if (CrmId.IsValid(result))
            {
                if (CrmId.IsInvalid(previousCrmId)) /* i.e., it's new */
                {
                    if (syncState.OutlookItem.Recipients != null)
                    {
                        AddMeetingRecipientsFromOutlookToCrm(syncState.OutlookItem, result);
                    }

                    this.AddOrUpdateMeetingAcceptanceFromOutlookToCRM(syncState.OutlookItem);
                }
            }

            return(result);
        }
        /// <summary>
        /// Update a single appointment in the specified Outlook folder with changes from CRM, but
        /// only if its start date is fewer than five days in the past.
        /// </summary>
        /// <param name="folder">The folder to synchronise into.</param>
        /// <param name="crmType">The CRM type of the candidate item.</param>
        /// <param name="crmItem">The candidate item from CRM.</param>
        /// <returns>The synchronisation state of the item updated (if it was updated).</returns>
        protected override SyncState <Outlook.AppointmentItem> AddOrUpdateItemFromCrmToOutlook(
            Outlook.MAPIFolder folder,
            string crmType,
            EntryValue crmItem)
        {
            SyncState <Outlook.AppointmentItem> result = null;
            DateTime dateStart = crmItem.GetValueAsDateTime("date_start");

            if (dateStart >= GetStartDate())
            {
                /* search for the item among the sync states I already know about */
                var syncState = this.GetExistingSyncState(crmItem);
                if (syncState == null)
                {
                    /* check for howlaround */
                    var matches = this.FindMatches(crmItem);

                    if (matches.Count == 0)
                    {
                        /* didn't find it, so add it to Outlook */
                        result = AddNewItemFromCrmToOutlook(folder, crmType, crmItem, dateStart);
                    }
                    else
                    {
                        this.Log.Warn($"Howlaround detected? Appointment '{crmItem.GetValueAsString("name")}' offered with id {crmItem.GetValueAsString("id")}, expected {matches[0].CrmEntryId}, {matches.Count} duplicates");
                    }
                }
                else
                {
                    /* found it, so update it from the CRM item */
                    result = UpdateExistingOutlookItemFromCrm(crmType, crmItem, dateStart, syncState);
                }

                result?.OutlookItem.Save();

                // TODO TODO TODO TODO: pull and cache the recipients!
            }

            return(result);
        }
Example #29
0
        /// <summary>
        /// Entry point from event handler when an item is added in Outlook.
        /// </summary>
        /// <remarks>Should always run in the 'VSTA_main' thread.</remarks>
        /// <param name="olItem">The item that has been added.</param>
        protected virtual void OutlookItemAdded(OutlookItemType olItem)
        {
            LogItemAction(olItem, "Synchroniser.OutlookItemAdded");

            if (Globals.ThisAddIn.IsLicensed)
            {
                try
                {
                    if (olItem != null)
                    {
                        lock (enqueueingLock)
                        {
                            if (IsCurrentView && this.GetExistingSyncState(olItem) == null)
                            {
                                SyncState <OutlookItemType> state = this.ConstructAndAddSyncState(olItem);
                                DaemonWorker.Instance.AddTask(new TransmitNewAction <OutlookItemType>(this, state, this.DefaultCrmModule));
                            }
                            else
                            {
                                Log.Warn($"Synchroniser.OutlookItemAdded: item {this.GetOutlookEntryId(olItem)} had already been added");
                            }
                        }
                    }
                }
                finally
                {
                    if (olItem != null)
                    {
                        SaveItem(olItem);
                    }
                }
            }
            else
            {
                Log.Warn($"Synchroniser.OutlookItemAdded: item {this.GetOutlookEntryId(olItem)} not added because not licensed");
            }
        }
 /// <summary>
 /// Remove all references to this sync state, if I hold any.
 /// </summary>
 /// <param name="state">The state to remove.</param>
 internal void RemoveSyncState(SyncState state)
 {
     lock (this.creationLock)
     {
         SyncState ignore;
         try
         {
             if (this.byOutlookId[state.OutlookItemEntryId] == state)
             {
                 this.byOutlookId.TryRemove(state.OutlookItemEntryId, out ignore);
             }
         }
         catch (KeyNotFoundException) { }
         catch (COMException) { }
         try
         {
             if (CrmId.IsValid(state.CrmEntryId) && this.byCrmId[state.CrmEntryId] == state)
             {
                 this.byCrmId.TryRemove(state.CrmEntryId, out ignore);
             }
         }
         catch (KeyNotFoundException) { }
     }
 }