diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..1ff0c423
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/Doxyfile b/Doxyfile
index 65dc588f..634366a0 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = "SuiteCRM Outlook Add-in"
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 3.0.16.5
+PROJECT_NUMBER = 3.0.16.51
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -51,7 +51,7 @@ PROJECT_BRIEF = "An outlook add-in which allows synchronisation with Su
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
-PROJECT_LOGO = ../SuiteCRMAddIn/Images/SuiteCRM.png
+PROJECT_LOGO = Images/SuiteCRM.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
diff --git a/README.md b/README.md
index 8a264ed4..e912e750 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
### What's in this repository
-SuiteCRM Outlook Plug-In v 3.0.16.5
+SuiteCRM Outlook Plug-In v 3.0.16.51
This repository has been created to allow community members to collaborate and contribute to the project.
diff --git a/SuiteCRMAddIn/BusinessLogic/AppointmentsSynchroniser.cs b/SuiteCRMAddIn/BusinessLogic/AppointmentsSynchroniser.cs
index 7e705437..973b55e2 100644
--- a/SuiteCRMAddIn/BusinessLogic/AppointmentsSynchroniser.cs
+++ b/SuiteCRMAddIn/BusinessLogic/AppointmentsSynchroniser.cs
@@ -22,42 +22,53 @@
*/
+#region
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.Office.Interop.Outlook;
+using SuiteCRMAddIn.Exceptions;
+using SuiteCRMAddIn.Extensions;
+using SuiteCRMAddIn.Properties;
+using SuiteCRMAddIn.ProtoItems;
+using SuiteCRMClient;
+using SuiteCRMClient.Logging;
+using SuiteCRMClient.RESTObjects;
+using Exception = System.Exception;
+
+#endregion
+
namespace SuiteCRMAddIn.BusinessLogic
{
- using Exceptions;
- using Extensions;
- using ProtoItems;
- using SuiteCRMClient;
- using SuiteCRMClient.Logging;
- using SuiteCRMClient.RESTObjects;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text;
- using Outlook = Microsoft.Office.Interop.Outlook;
-
///
- /// Handles the synchronisation of appointments between Outlook and CMS.
+ /// Handles the synchronisation of appointments between Outlook and CMS.
///
- public abstract class AppointmentsSynchroniser : Synchroniser
- where SyncStateType : SyncState
+ public abstract class AppointmentsSynchroniser : Synchroniser
+ where SyncStateType : SyncState
{
///
- /// The name of the organiser synchronisation property
+ /// The name of the organiser synchronisation property
///
public const string OrganiserPropertyName = "SOrganiser";
///
- /// Microsoft Conferencing Add-in creates temporary items whose names begin
- /// 'PLEASE IGNORE'. We should not sync these.
+ /// Microsoft Conferencing Add-in creates temporary items whose names begin
+ /// 'PLEASE IGNORE'. We should not sync these.
///
public const string MSConfTmpSubjectPrefix = "PLEASE IGNORE";
///
- /// A cache of email addresses to CRM modules and identities
+ /// Prefix for meetings which have been canceled.
///
- protected Dictionary> meetingRecipientsCache =
+ private const string CanceledPrefix = "CANCELED";
+
+ ///
+ /// A cache of email addresses to CRM modules and identities
+ ///
+ protected Dictionary> meetingRecipientsCache =
new Dictionary>();
@@ -65,134 +76,131 @@ public AppointmentsSynchroniser(string name, SyncContext context)
: base(name, context)
{
// TODO: Also need to fetch appointments to which the current user is invited.
- this.fetchQueryPrefix = new StringBuilder("assigned_user_id = '{0}'")
- .Append($" and date_start > '{string.Format("{0:yyyy-MM-dd HH:mm:ss}", GetStartDate())}' ") .ToString();
+ fetchQueryPrefix = new StringBuilder("assigned_user_id = '{0}'")
+ .Append($" and date_start > '{string.Format("{0:yyyy-MM-dd HH:mm:ss}", GetStartDate())}' ").ToString();
}
///
- /// Get the id of the record with the specified `smtpAddress` in the module with the specified `moduleName`.
+ /// Get the id of the record with the specified `smtpAddress` in the module with the specified `moduleName`.
///
/// The SMTP email address to be sought.
/// The name of the module in which to seek it.
/// The corresponding id, if present, else the empty string.
public CrmId GetInviteeIdBySmtpAddress(string smtpAddress, string moduleName)
{
- StringBuilder bob = new StringBuilder( $"({moduleName.ToLower()}.id in ")
- .Append( $"(select eabr.bean_id from email_addr_bean_rel eabr ")
- .Append( $"INNER JOIN email_addresses ea on eabr.email_address_id = ea.id ")
- .Append( $"where eabr.bean_module = '{moduleName}' ")
- .Append( $"and ea.email_address LIKE '%{RestAPIWrapper.MySqlEscape(smtpAddress)}%'))");
+ var bob = new StringBuilder($"({moduleName.ToLower()}.id in ")
+ .Append($"(select eabr.bean_id from email_addr_bean_rel eabr ")
+ .Append($"INNER JOIN email_addresses ea on eabr.email_address_id = ea.id ")
+ .Append($"where eabr.bean_module = '{moduleName}' ")
+ .Append($"and ea.email_address LIKE '%{RestAPIWrapper.MySqlEscape(smtpAddress)}%'))");
- string query = bob.ToString();
+ var query = bob.ToString();
Log.Debug($"AppointmentSyncing.GetID: query = `{query}`");
- string[] fields = { "id" };
- EntryList entries = RestAPIWrapper.GetEntryList(moduleName, query, Properties.Settings.Default.SyncMaxRecords, "date_entered DESC", 0, false, fields);
+ string[] fields = {"id"};
+ var entries = RestAPIWrapper.GetEntryList(moduleName, query, Settings.Default.SyncMaxRecords,
+ "date_entered DESC", 0, false, fields);
- return entries.result_count > 0 ?
- CrmId.Get(RestAPIWrapper.GetValueByKey(entries.entry_list[0], "id")) :
- CrmId.Empty;
+ return entries.result_count > 0
+ ? CrmId.Get(RestAPIWrapper.GetValueByKey(entries.entry_list[0], "id"))
+ : CrmId.Empty;
}
- public override Outlook.MAPIFolder GetDefaultFolder()
+ public override MAPIFolder GetDefaultFolder()
{
- return Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
+ return Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
}
///
- /// #2246: Discriminate between calls and meetings when adding and updating.
+ /// #2246: Discriminate between calls and meetings when adding and updating.
///
- protected override void OutlookItemAdded(Outlook.AppointmentItem olItem)
+ protected override void OutlookItemAdded(AppointmentItem olItem)
{
if (Globals.ThisAddIn.IsLicensed)
- {
try
{
var crmId = olItem.GetCrmId();
if (CrmId.IsValid(crmId))
{
- AppointmentSyncState existing =
+ var existing =
SyncStateManager.Instance.GetExistingSyncState(string.Empty, crmId) as AppointmentSyncState;
/* we have an existing item with the same CRM id: suspicious */
if (existing != null && existing.OutlookItem.GetVCalId() != crmId.ToString())
{
/* OK, its GlobalAppointmentId is wrong, it must have come via sync. Delete it. */
- Log.Debug($"Apparent case of item synced from CRM and then received via email/vCal. CRM id is {crmId}. Deleting bad copy.");
- this.RemoveItemAndSyncState(existing);
+ Log.Debug(
+ $"Apparent case of item synced from CRM and then received via email/vCal. CRM id is {crmId}. Deleting bad copy.");
+ RemoveItemAndSyncState(existing);
}
}
- Log.Debug($"OutlookItemAdded, CRM id = {crmId}; Outlook ID = {olItem.EntryID}");
+ Log.Debug($"OutlookItemAdded: entry, CRM id = {crmId}; Outlook ID = {olItem.EntryID}");
if (olItem.IsCall())
- {
- base.OutlookItemAdded(olItem, Globals.ThisAddIn.CallsSynchroniser);
- }
+ base.OutlookItemAdded(olItem, Globals.ThisAddIn.CallsSynchroniser);
else
- {
- base.OutlookItemAdded(olItem, Globals.ThisAddIn.MeetingsSynchroniser);
- }
+ base.OutlookItemAdded(olItem, Globals.ThisAddIn.MeetingsSynchroniser);
+ Log.Debug($"OutlookItemAdded: exit, CRM id = {crmId}; Outlook ID = {olItem.EntryID}");
}
finally
{
SaveItem(olItem);
}
- }
else
- {
- Log.Warn($"Synchroniser.OutlookItemAdded: item {this.GetOutlookEntryId(olItem)} not added because not licensed");
- }
+ Log.Warn(
+ $"Synchroniser.OutlookItemAdded: item {GetOutlookEntryId(olItem)} not added because not licensed");
}
///
- /// #2246: Discriminate between calls and meetings when adding and updating.
+ /// #2246: Discriminate between calls and meetings when adding and updating.
///
- protected override void OutlookItemChanged(Outlook.AppointmentItem olItem)
+ protected override void OutlookItemChanged(AppointmentItem olItem)
{
if (Globals.ThisAddIn.IsLicensed)
- {
try
{
var crmId = olItem.GetCrmId();
- Log.Debug($"OutlookItemChanged, CRM id = {crmId}; Outlook ID = {olItem.EntryID}");
+ Log.Debug($"OutlookItemChanged: entry, CRM id = {crmId}; Outlook ID = {olItem.EntryID}");
if (olItem.IsCall())
- {
- base.OutlookItemChanged(olItem, Globals.ThisAddIn.CallsSynchroniser);
- }
+ base.OutlookItemChanged(olItem, Globals.ThisAddIn.CallsSynchroniser);
else
- {
- base.OutlookItemChanged(olItem, Globals.ThisAddIn.MeetingsSynchroniser);
- }
+ base.OutlookItemChanged(olItem, Globals.ThisAddIn.MeetingsSynchroniser);
+
+ Log.Debug($"OutlookItemChanged: exit, CRM id = {crmId}; Outlook ID = {olItem.EntryID}");
}
catch (BadStateTransition bst)
{
if (bst.To != TransmissionState.Transmitted)
- {
Log.Warn("Bad state transition in OutlookItemChanged", bst);
- }
}
finally
{
- this.SaveItem(olItem);
+ SaveItem(olItem);
}
- }
else
- {
- Log.Warn($"Synchroniser.OutlookItemAdded: item {this.GetOutlookEntryId(olItem)} not updated because not licensed");
- }
+ Log.Warn(
+ $"Synchroniser.OutlookItemAdded: item {GetOutlookEntryId(olItem)} not updated because not licensed");
}
- protected override void SaveItem(Outlook.AppointmentItem olItem)
+ protected override void SaveItem(AppointmentItem olItem)
{
try
{
olItem.Save();
- LogItemAction(olItem, "AppointmentSyncing.SaveItem, saved item");
+ try
+ {
+ LogItemAction(olItem, "AppointmentSyncing.SaveItem, saved item");
+ }
+ catch (InvalidCrmIdException)
+ {
+ Log.Debug(
+ $"AppointmentSyncing.SaveItem, saved item '{olItem.Subject}' {olItem.EntryID} (no valid CRM id)");
+ }
}
- catch (System.Exception any)
+ catch (Exception any)
{
try
{
@@ -200,31 +208,28 @@ protected override void SaveItem(Outlook.AppointmentItem olItem)
}
catch (COMException comx)
{
- ErrorHandler.Handle("Failure while trying to save appointment, appointment has probably been deleted.", comx);
+ ErrorHandler.Handle(
+ "Failure while trying to save appointment, appointment has probably been deleted.", comx);
}
}
}
- ///
- /// Prefix for meetings which have been canceled.
- ///
- private const string CanceledPrefix = "CANCELED";
-
///
- /// Ensure that this Outlook item has a property of this name with this value.
+ /// Ensure that this Outlook item has a property of this name with this value.
///
/// The Outlook item.
/// The name.
/// The value.
- protected override void EnsureSynchronisationPropertyForOutlookItem(Outlook.AppointmentItem olItem, string name, string value)
+ protected override void EnsureSynchronisationPropertyForOutlookItem(AppointmentItem olItem, string name,
+ string value)
{
try
{
- Outlook.UserProperty olProperty = olItem.UserProperties[name] ?? olItem.UserProperties.Add(name, Outlook.OlUserPropertyType.olText);
+ var olProperty = olItem.UserProperties[name] ??
+ olItem.UserProperties.Add(name, OlUserPropertyType.olText);
if (!olProperty.Value.Equals(value))
- {
try
{
if (string.IsNullOrEmpty(value))
@@ -234,18 +239,19 @@ protected override void EnsureSynchronisationPropertyForOutlookItem(Outlook.Appo
else
{
olProperty.Value = value;
- Log.Debug($"AppointmentSyncing.EnsureSynchronisationPropertyForOutlookItem: Set property {name} to value {value} on item {olItem.Subject}");
+ Log.Debug(
+ $"AppointmentSyncing.EnsureSynchronisationPropertyForOutlookItem: Set property {name} to value {value} on item {olItem.Subject}");
}
}
catch (Exception any)
{
- ErrorHandler.Handle($"Failed to set property {name} to value {value} on item {olItem.Subject}", any);
+ ErrorHandler.Handle($"Failed to set property {name} to value {value} on item {olItem.Subject}",
+ any);
}
finally
{
- this.SaveItem(olItem);
+ SaveItem(olItem);
}
- }
}
catch (Exception any)
{
@@ -255,57 +261,57 @@ protected override void EnsureSynchronisationPropertyForOutlookItem(Outlook.Appo
///
- /// If a meeting was created in another Outlook we should NOT sync it with CRM because if we do we'll create
- /// duplicates. Only the Outlook which created it should sync it.
+ /// If a meeting was created in another Outlook we should NOT sync it with CRM because if we do we'll create
+ /// duplicates. Only the Outlook which created it should sync it.
///
/// The folder to synchronise into.
/// The CRM type of the candidate item.
/// The candidate item from CRM.
/// True if it's offered to us by CRM with its Outlook ID already populated.
- protected override bool ShouldAddOrUpdateItemFromCrmToOutlook(Outlook.MAPIFolder folder, string crmType, EntryValue crmItem)
+ protected override bool ShouldAddOrUpdateItemFromCrmToOutlook(MAPIFolder folder, string crmType,
+ EntryValue crmItem)
{
var outlookId = crmItem.GetValueAsString("outlook_id");
/* we're good if it's a meeting... */
- bool result = crmType == this.DefaultCrmModule;
+ var result = crmType == DefaultCrmModule;
/* provided it doesn't already have an Outlook id */
result &= string.IsNullOrWhiteSpace(outlookId);
/* and we're also good if we've already got it */
- result |= (SyncStateManager.Instance.GetExistingSyncState(crmItem) != null);
+ result |= SyncStateManager.Instance.GetExistingSyncState(crmItem) != null;
if (!result)
- {
- Log.Debug($"ShouldAddOrUpdateItemFromCrmToOutlook: not syncing meeting `{crmItem.GetValueAsString("name")}` as it appears to originate from another Outlook instance.");
- }
+ Log.Debug(
+ $"ShouldAddOrUpdateItemFromCrmToOutlook: not syncing meeting `{crmItem.GetValueAsString("name")}` as it appears to originate from another Outlook instance.");
return result;
}
///
- /// Add an item existing in CRM but not found in Outlook to Outlook.
+ /// Add an item existing in CRM but not found in Outlook to Outlook.
///
///
- /// This method is disconcertingly different from equivalent methods in other synchronisers;
- /// TODO: the differences ought to be thought about.
+ /// This method is disconcertingly different from equivalent methods in other synchronisers;
+ /// TODO: the differences ought to be thought about.
///
- ///
+ ///
/// The Outlook folder in which the item should be stored.
/// The CRM type of the item from which values are to be taken.
/// The CRM item from which values are to be taken.
/// The state date/time of the item, adjusted for timezone.
/// A sync state object for the new item.
protected virtual SyncStateType AddNewItemFromCrmToOutlook(
- Outlook.MAPIFolder appointmentsFolder,
+ MAPIFolder appointmentsFolder,
string crmType,
EntryValue crmItem,
DateTime dateStart)
{
SyncStateType newState = null;
- Outlook.AppointmentItem olItem = null;
+ AppointmentItem olItem = null;
Log.Debug(
- (string)string.Format(
- $"{this.GetType().Name}.AddNewItemFromCrmToOutlook, entry id is '{crmItem.GetValueAsString("id")}', creating in Outlook."));
+ string.Format(
+ $"{GetType().Name}.AddNewItemFromCrmToOutlook, entry id is '{crmItem.GetValueAsString("id")}', creating in Outlook."));
try
{
@@ -318,7 +324,7 @@ protected virtual SyncStateType AddNewItemFromCrmToOutlook(
*/
lock (enqueueingLock)
{
- olItem = appointmentsFolder.Items.Add(Outlook.OlItemType.olAppointmentItem);
+ olItem = appointmentsFolder.Items.Add(OlItemType.olAppointmentItem);
olItem.Subject = crmItem.GetValueAsString("name");
olItem.Body = crmItem.GetValueAsString("description");
@@ -353,12 +359,12 @@ protected virtual SyncStateType AddNewItemFromCrmToOutlook(
///
- /// Set this outlook item's duration, but also end time and location, from this CRM item.
+ /// Set this outlook item's duration, but also end time and location, from this CRM item.
///
/// The type of the CRM item.
/// The CRM item.
/// The Outlook item.
- protected void SetOutlookItemDuration(string crmType, EntryValue crmItem, Outlook.AppointmentItem olItem)
+ protected void SetOutlookItemDuration(string crmType, EntryValue crmItem, AppointmentItem olItem)
{
try
{
@@ -370,63 +376,58 @@ protected void SetOutlookItemDuration(string crmType, EntryValue crmItem, Outloo
}
finally
{
- this.SaveItem(olItem);
+ SaveItem(olItem);
}
}
///
- /// Set this outlook item's duration from this CRM item.
+ /// Set this outlook item's duration from this CRM item.
///
/// The CRM item.
/// The Outlook item.
- protected virtual void SetOutlookItemDuration(EntryValue crmItem, Outlook.AppointmentItem olItem)
+ protected virtual void SetOutlookItemDuration(EntryValue crmItem, AppointmentItem olItem)
{
int minutes = 0, hours = 0;
if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("duration_minutes")))
- {
minutes = int.Parse(crmItem.GetValueAsString("duration_minutes"));
- }
if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("duration_hours")))
- {
hours = int.Parse(crmItem.GetValueAsString("duration_hours"));
- }
- int durationMinutes = minutes + hours * 60;
+ var durationMinutes = minutes + hours * 60;
olItem.Duration = durationMinutes;
}
///
- /// Specialisation: in addition to the standard properties, meetings also require an organiser property.
+ /// Specialisation: in addition to the standard properties, meetings also require an organiser property.
///
/// The Outlook item.
/// The CRM item.
/// The value for the SType property (CRM module name).
- protected override void EnsureSynchronisationPropertiesForOutlookItem(Outlook.AppointmentItem olItem, EntryValue crmItem, string type)
+ protected override void EnsureSynchronisationPropertiesForOutlookItem(AppointmentItem olItem,
+ EntryValue crmItem, string type)
{
base.EnsureSynchronisationPropertiesForOutlookItem(olItem, crmItem, type);
- if (this.DefaultCrmModule.Equals(type))
- {
- this.EnsureSynchronisationPropertyForOutlookItem(olItem, OrganiserPropertyName, crmItem.GetValueAsString("assigned_user_id"));
- }
+ if (DefaultCrmModule.Equals(type))
+ EnsureSynchronisationPropertyForOutlookItem(olItem, OrganiserPropertyName,
+ crmItem.GetValueAsString("assigned_user_id"));
}
///
- /// Add the item implied by this SyncState, which may not exist in CRM, to CRM.
+ /// Add the item implied by this SyncState, which may not exist in CRM, to CRM.
///
/// The sync state.
/// The id of the entry added or updated.
- internal override CrmId AddOrUpdateItemFromOutlookToCrm(SyncState syncState)
+ internal override CrmId AddOrUpdateItemFromOutlookToCrm(SyncState syncState)
{
- Outlook.AppointmentItem olItem = syncState.OutlookItem;
+ var olItem = syncState.OutlookItem;
try
{
- CrmId result = CrmId.Empty;
+ var result = CrmId.Empty;
- if (this.ShouldAddOrUpdateItemFromOutlookToCrm(olItem))
- {
+ if (ShouldAddOrUpdateItemFromOutlookToCrm(olItem))
if (ShouldDeleteFromCrm(olItem))
{
LogItemAction(olItem, "AppointmentSyncing.AddOrUpdateItemFromOutlookToCrm: Deleting");
@@ -438,141 +439,124 @@ internal override CrmId AddOrUpdateItemFromOutlookToCrm(SyncState
- /// Construct a JSON packet representing this Outlook item, and despatch it to CRM.
+ /// Construct a JSON packet representing this Outlook item, and despatch it to CRM.
///
/// The Outlook item.
/// The CRM id of the object created or modified.
- protected override CrmId ConstructAndDespatchCrmItem(Outlook.AppointmentItem olItem)
+ protected override CrmId ConstructAndDespatchCrmItem(AppointmentItem olItem)
{
- return CrmId.Get(RestAPIWrapper.SetEntry(new ProtoAppointment(olItem).AsNameValues(), this.DefaultCrmModule));
+ return CrmId.Get(RestAPIWrapper.SetEntry(new ProtoAppointment(olItem).AsNameValues(),
+ DefaultCrmModule));
}
///
- /// Delete this Outlook item from CRM, and tidy up afterwards.
+ /// Delete this Outlook item from CRM, and tidy up afterwards.
///
/// The Outlook item to delete.
- private void DeleteFromCrm(Outlook.AppointmentItem olItem)
+ private void DeleteFromCrm(AppointmentItem olItem)
{
if (olItem != null)
{
/* Remove the magic properties */
RemoveSynchronisationPropertiesFromOutlookItem(olItem);
- SyncState syncStateForItem = SyncStateManager.Instance.GetExistingSyncState(olItem);
+ var syncStateForItem = SyncStateManager.Instance.GetExistingSyncState(olItem);
if (syncStateForItem != null)
{
- this.RemoveFromCrm(syncStateForItem);
- this.RemoveItemSyncState(syncStateForItem);
+ RemoveFromCrm(syncStateForItem);
+ RemoveItemSyncState(syncStateForItem);
}
}
}
///
- /// Get all items in this appointments folder. Should be called just once (per folder?)
- /// when the add-in starts up; initialises the SyncState list.
+ /// Get all items in this appointments folder. Should be called just once (per folder?)
+ /// when the add-in starts up; initialises the SyncState list.
///
/// The folder to scan.
- protected override void GetOutlookItems(Outlook.MAPIFolder appointmentsFolder)
+ protected override void LinkOutlookItems(MAPIFolder appointmentsFolder)
{
try
{
- List deletionCandidates = new List();
- foreach (Outlook.AppointmentItem olItem in appointmentsFolder.Items)
- {
+ var deletionCandidates = new List();
+ foreach (AppointmentItem olItem in appointmentsFolder.Items)
try
{
- if (olItem.Start >= this.GetStartDate())
+ if (olItem.Start >= GetStartDate())
{
- Outlook.UserProperty olPropertyModified = olItem.UserProperties[SyncStateManager.ModifiedDatePropertyName];
- Outlook.UserProperty olPropertyType = olItem.UserProperties[SyncStateManager.TypePropertyName];
- Outlook.UserProperty olPropertyEntryId = olItem.UserProperties[SyncStateManager.CrmIdPropertyName];
+ var olPropertyModified = olItem.UserProperties[SyncStateManager.ModifiedDatePropertyName];
+ var olPropertyType = olItem.UserProperties[SyncStateManager.TypePropertyName];
+ var olPropertyEntryId = olItem.UserProperties[SyncStateManager.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");
- }
+ LogItemAction(olItem,
+ "AppointmentSyncing.LinkOutlookItems: Adding known item to queue");
else
- {
- LogItemAction(olItem, "AppointmentSyncing.GetOutlookItems: Adding unknown item to queue");
- }
+ LogItemAction(olItem,
+ "AppointmentSyncing.LinkOutlookItems: Adding unknown item to queue");
SyncStateManager.Instance.GetOrCreateSyncState(olItem).SetPresentAtStartup();
}
}
- catch (ProbableDuplicateItemException)
+ catch (ProbableDuplicateItemException)
{
deletionCandidates.Add(olItem);
}
- }
-
+
foreach (var toDelete in deletionCandidates)
- {
toDelete.Delete();
- }
}
catch (Exception ex)
{
- ErrorHandler.Handle($"Failed while trying to index {this.DefaultCrmModule}", ex);
+ ErrorHandler.Handle($"Failed while trying to index {DefaultCrmModule}", ex);
}
}
///
- /// Log a message regarding this Outlook appointment.
+ /// Log a message regarding this Outlook appointment.
///
/// The outlook item.
/// The message to be logged.
- internal override void LogItemAction(Outlook.AppointmentItem olItem, string message)
+ internal override void LogItemAction(AppointmentItem olItem, string message)
{
try
{
- CrmId crmId = olItem.GetCrmId();
- if (CrmId.IsInvalid(crmId)) { crmId = CrmId.Empty; }
+ var crmId = IsEnabled() ? olItem.GetCrmId() : CrmId.Empty;
+ if (CrmId.IsInvalid(crmId)) crmId = CrmId.Empty;
- StringBuilder bob = new StringBuilder();
+ var bob = new StringBuilder();
bob.Append($"{message}:\n\tOutlook Id : {olItem.EntryID}")
.Append($"\n\tGlobal Id : {olItem.GlobalAppointmentID}")
- .Append($"\n\tCRM Id : {crmId}")
+ .Append(this.IsEnabled() ? $"\n\tCRM Id : {crmId}" : string.Empty)
.Append($"\n\tSubject : '{olItem.Subject}'")
.Append($"\n\tSensitivity : {olItem.Sensitivity}")
.Append($"\n\tStatus : {olItem.MeetingStatus}")
@@ -582,10 +566,9 @@ internal override void LogItemAction(Outlook.AppointmentItem olItem, string mess
.Append($"\n\tTxState : {SyncStateManager.Instance.GetExistingSyncState(olItem)?.TxState}")
.Append($"\n\tRecipients :\n");
- foreach (Outlook.Recipient recipient in olItem.Recipients)
- {
- bob.Append($"\t\t{recipient.Name}: {recipient.GetSmtpAddress()} - ({recipient.MeetingResponseStatus})\n");
- }
+ foreach (Recipient recipient in olItem.Recipients)
+ bob.Append(
+ $"\t\t{recipient.Name}: {recipient.GetSmtpAddress()} - ({recipient.MeetingResponseStatus})\n");
Log.Info(bob.ToString());
}
catch (COMException)
@@ -596,22 +579,22 @@ internal override void LogItemAction(Outlook.AppointmentItem olItem, string mess
///
- /// 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.
+ /// 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.
///
/// The folder to synchronise into.
/// The CRM type of the candidate item.
/// The candidate item from CRM.
/// The synchronisation state of the item updated (if it was updated).
- protected override SyncState AddOrUpdateItemFromCrmToOutlook(
- Outlook.MAPIFolder folder,
+ protected override SyncState AddOrUpdateItemFromCrmToOutlook(
+ MAPIFolder folder,
string crmType,
EntryValue crmItem)
{
- SyncState existing = SyncStateManager.Instance.GetExistingSyncState(crmItem);
- SyncStateType result = existing as SyncStateType;
+ var existing = SyncStateManager.Instance.GetExistingSyncState(crmItem);
+ var result = existing as SyncStateType;
- DateTime dateStart = crmItem.GetValueAsDateTime("date_start");
+ var dateStart = crmItem.GetValueAsDateTime("date_start");
if (dateStart >= GetStartDate())
{
@@ -619,7 +602,7 @@ internal override void LogItemAction(Outlook.AppointmentItem olItem, string mess
if (existing == null)
{
/* check for howlaround */
- var matches = this.FindMatches(crmItem);
+ var matches = FindMatches(crmItem);
if (matches.Count == 0)
{
@@ -637,13 +620,14 @@ internal override void LogItemAction(Outlook.AppointmentItem olItem, string mess
{
result.CrmEntryId = crmId;
result.OutlookItem.SetCrmId(crmId);
- this.UpdateExistingOutlookItemFromCrm(crmType, crmItem, dateStart, result);
+ UpdateExistingOutlookItemFromCrm(crmType, crmItem, dateStart, result);
}
}
else
{
result = matches.ElementAt(0) as SyncStateType;
- this.Log.Warn($"Howlaround detected? Appointment '{crmItem.GetValueAsString("name")}' offered with id {crmId}, expected {matches[0].CrmEntryId}, {matches.Count} duplicates");
+ Log.Warn(
+ $"Howlaround detected? Appointment '{crmItem.GetValueAsString("name")}' offered with id {crmId}, expected {matches[0].CrmEntryId}, {matches.Count} duplicates");
}
}
}
@@ -654,7 +638,7 @@ internal override void LogItemAction(Outlook.AppointmentItem olItem, string mess
}
else
{
- throw new UnexpectedSyncStateClassException($"{this.GetType().Name}", existing);
+ throw new UnexpectedSyncStateClassException($"{GetType().Name}", existing);
}
existing?.SaveItem();
@@ -663,152 +647,152 @@ internal override void LogItemAction(Outlook.AppointmentItem olItem, string mess
return result;
}
- internal override void HandleItemMissingFromOutlook(SyncState syncState)
+ internal override void HandleItemMissingFromOutlook(SyncState syncState)
{
if (syncState.CrmType == MeetingsSynchroniser.CrmModule)
{
/* typically, when this method is called, the Outlook Item will already be invalid, and if it is not,
* it may become invalid during the execution of this method. So this method CANNOT depend on any
* values taken from the Outlook item. */
- EntryList entries = RestAPIWrapper.GetEntryList(
+ var entries = RestAPIWrapper.GetEntryList(
syncState.CrmType, $"id = {syncState.CrmEntryId}",
- Properties.Settings.Default.SyncMaxRecords,
+ Settings.Default.SyncMaxRecords,
"date_entered DESC", 0, false, null);
if (entries.entry_list.Any())
- {
- this.HandleItemMissingFromOutlook(entries.entry_list[0], syncState, syncState.CrmType);
- }
+ HandleItemMissingFromOutlook(entries.entry_list[0], syncState, syncState.CrmType);
}
}
-
///
- /// Sets up a CRM relationship to mimic an Outlook relationship
+ /// Sets up a CRM relationship to mimic an Outlook relationship
///
/// The synchroniser tp forward to.
/// The ID of the appointment.
/// The outlook recipient representing the person to link with.
/// the name of the module we're seeking to link with.
/// True if a relationship was created.
- protected CrmId SetCrmRelationshipFromOutlook(Synchroniser sync, CrmId meetingId, Outlook.Recipient recipient, string foreignModule)
+ protected CrmId SetCrmRelationshipFromOutlook(Synchroniser sync, CrmId meetingId,
+ Recipient recipient, string foreignModule)
where T : class
where S : SyncState
{
- CrmId foreignId = GetInviteeIdBySmtpAddress(recipient.GetSmtpAddress(), foreignModule);
+ var foreignId = GetInviteeIdBySmtpAddress(recipient.GetSmtpAddress(), foreignModule);
return CrmId.IsValid(foreignId) &&
- SetCrmRelationshipFromOutlook(sync, meetingId, foreignModule, foreignId) ?
- foreignId :
- CrmId.Empty;
+ SetCrmRelationshipFromOutlook(sync, meetingId, foreignModule, foreignId)
+ ? foreignId
+ : CrmId.Empty;
}
///
- /// Sets up a CRM relationship to mimic an Outlook relationship
+ /// Sets up a CRM relationship to mimic an Outlook relationship
///
/// the synchroniser to despatch to
/// The meeting id.
/// Address resolution data from the cache.
/// True if a relationship was created.
- protected bool SetCrmRelationshipFromOutlook(Synchroniser sync, CrmId meetingId, AddressResolutionData resolution)
+ protected bool SetCrmRelationshipFromOutlook(Synchroniser sync, CrmId meetingId,
+ AddressResolutionData resolution)
where T : class
where S : SyncState
{
- return this.SetCrmRelationshipFromOutlook(sync, meetingId, resolution.ModuleName, resolution.ModuleId);
+ return SetCrmRelationshipFromOutlook(sync, meetingId, resolution.ModuleName, resolution.ModuleId);
}
///
- /// Sets up a CRM relationship to mimic an Outlook relationship
+ /// Sets up a CRM relationship to mimic an Outlook relationship
///
/// the synchroniser to despatch to.
/// The ID of the meeting
/// the name of the module we're seeking to link with.
/// The id in the foreign module of the record we're linking to.
/// True if a relationship was created.
- protected bool SetCrmRelationshipFromOutlook(Synchroniser sync, CrmId meetingId, string foreignModule, CrmId foreignId)
+ protected bool SetCrmRelationshipFromOutlook(Synchroniser sync, CrmId meetingId,
+ string foreignModule, CrmId foreignId)
where T : class
where S : SyncState
{
return CrmId.IsValid(foreignId) &&
- RestAPIWrapper.SetRelationshipUnsafe(new SetRelationshipParams
- {
- module2 = sync.DefaultCrmModule,
- module2_id = meetingId.ToString(),
- module1 = foreignModule,
- module1_id = foreignId.ToString()
- });
+ RestAPIWrapper.SetRelationshipUnsafe(new SetRelationshipParams
+ {
+ module2 = sync.DefaultCrmModule,
+ module2_id = meetingId.ToString(),
+ module1 = foreignModule,
+ module1_id = foreignId.ToString()
+ });
}
///
- /// 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.
+ /// 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.
///
///
protected override void RemoveFromCrm(SyncState state)
{
if (state.CrmType == MeetingsSynchroniser.CrmModule)
- {
- this.AddOrUpdateItemFromOutlookToCrm((SyncState)state);
- }
+ AddOrUpdateItemFromOutlookToCrm((SyncState) state);
else
- {
base.RemoveFromCrm(state);
- }
}
///
- /// Typically, when handling an item missing from outlook, the outlook item is missing and so can't
- /// be relied on; treat this record as representing the current, known state of the item.
+ /// Typically, when handling an item missing from outlook, the outlook item is missing and so can't
+ /// be relied on; treat this record as representing the current, known state of the item.
///
/// A record fetched from CRM representing the current state of the item.
/// The sync state representing the item.
/// The name/key of the CRM module in which the item exists.
- private void HandleItemMissingFromOutlook(EntryValue record, SyncState syncState, string crmModule)
+ private void HandleItemMissingFromOutlook(EntryValue record, SyncState syncState,
+ string crmModule)
{
try
{
- if (record.GetValueAsDateTime("date_start") > DateTime.Now && crmModule == MeetingsSynchroniser.CrmModule)
+ if (record.GetValueAsDateTime("date_start") > DateTime.Now &&
+ crmModule == MeetingsSynchroniser.CrmModule)
{
/* meeting in the future: mark it as canceled, do not delete it */
record.GetBinding("status").value = "NotHeld";
- string description = record.GetValue("description").ToString();
- if (!description.StartsWith(AppointmentsSynchroniser.CanceledPrefix))
+ var description = record.GetValue("description").ToString();
+ if (!description.StartsWith(CanceledPrefix))
{
- record.GetBinding("description").value = $"{AppointmentsSynchroniser.CanceledPrefix}: {description}";
+ record.GetBinding("description").value = $"{CanceledPrefix}: {description}";
RestAPIWrapper.SetEntry(record.nameValueList, crmModule);
}
}
else
{
/* meeting in the past: just delete it */
- this.RemoveFromCrm(syncState);
- this.RemoveItemSyncState(syncState);
+ RemoveFromCrm(syncState);
+ RemoveItemSyncState(syncState);
}
}
catch (Exception any)
{
/* what could possibly go wrong? */
- ErrorHandler.Handle($"Failed while attempting to handle item missing from Outlook; CRM Id is {syncState.CrmEntryId}", any);
+ ErrorHandler.Handle(
+ $"Failed while attempting to handle item missing from Outlook; CRM Id is {syncState.CrmEntryId}",
+ any);
}
}
- protected override bool IsMatch(Outlook.AppointmentItem olItem, EntryValue crmItem)
+ protected override bool IsMatch(AppointmentItem olItem, EntryValue crmItem)
{
return olItem.Subject == crmItem.GetValueAsString("name") &&
crmItem.GetValueAsDateTime("date_start") == olItem.Start;
}
///
- /// Remove the synchronisation properties from this Outlook item.
+ /// Remove the synchronisation properties from this Outlook item.
///
/// The Outlook item.
- private static void RemoveSynchronisationPropertiesFromOutlookItem(Outlook.AppointmentItem olItem)
+ private static void RemoveSynchronisationPropertiesFromOutlookItem(AppointmentItem olItem)
{
RemoveSynchronisationPropertyFromOutlookItem(olItem, SyncStateManager.CrmIdPropertyName);
RemoveSynchronisationPropertyFromOutlookItem(olItem, SyncStateManager.TypePropertyName);
@@ -816,57 +800,54 @@ private static void RemoveSynchronisationPropertiesFromOutlookItem(Outlook.Appoi
}
///
- /// Ensure that this Outlook item does not have a property of this name.
+ /// Ensure that this Outlook item does not have a property of this name.
///
/// The Outlook item.
/// The name.
- private static void RemoveSynchronisationPropertyFromOutlookItem(Outlook.AppointmentItem olItem, string name)
+ private static void RemoveSynchronisationPropertyFromOutlookItem(AppointmentItem olItem, string name)
{
- int found = 0;
+ var found = 0;
/* typical Microsoft, you can only remove a user property by its 1-based number */
- for (int i = 1; i <= olItem.UserProperties.Count; i++)
- {
+ for (var i = 1; i <= olItem.UserProperties.Count; i++)
if (olItem.UserProperties[i].Name == name)
{
found = i;
break;
}
- }
if (found > 0)
- {
try
{
olItem.UserProperties.Remove(found);
}
catch (Exception any)
{
- Globals.ThisAddIn.Log.Warn($"Unexpected error in RemoveSynchronisationPropertyFromOutlookItem", any);
+ Globals.ThisAddIn.Log.Warn($"Unexpected error in RemoveSynchronisationPropertyFromOutlookItem",
+ any);
}
finally
{
olItem.Save();
}
- }
}
///
- /// Set the meeting status of this `olItem` from this `crmItem`.
+ /// Set the meeting status of this `olItem` from this `crmItem`.
///
/// The Outlook item to update.
/// The CRM item to use as source.
- protected abstract void SetMeetingStatus(Outlook.AppointmentItem olItem, EntryValue crmItem);
+ protected abstract void SetMeetingStatus(AppointmentItem olItem, EntryValue crmItem);
///
- /// We should delete an item from CRM if it already exists in CRM, but it is now private.
+ /// We should delete an item from CRM if it already exists in CRM, but it is now private.
///
/// The Outlook item
/// true if the Outlook item should be deleted from CRM.
- private bool ShouldDeleteFromCrm(Outlook.AppointmentItem olItem)
+ private bool ShouldDeleteFromCrm(AppointmentItem olItem)
{
- bool result = (CrmId.IsValid(olItem.GetCrmId()) && olItem.Sensitivity != Outlook.OlSensitivity.olNormal);
+ var result = CrmId.IsValid(olItem.GetCrmId()) && olItem.Sensitivity != OlSensitivity.olNormal;
LogItemAction(olItem, $"ShouldDeleteFromCrm returning {result}");
@@ -874,109 +855,106 @@ private bool ShouldDeleteFromCrm(Outlook.AppointmentItem olItem)
}
///
- /// True if we should despatch this item to CRM, else false.
+ /// True if we should despatch this item to CRM, else false.
///
///
/// true iff settings.SyncCalendar is true, the item is not null, and it is not private (normal sensitivity)
- private bool ShouldDespatchToCrm(Outlook.AppointmentItem olItem)
+ private bool ShouldDespatchToCrm(AppointmentItem olItem)
{
var syncConfigured = SyncDirection.AllowOutbound(Direction);
- string organiser = olItem.Organizer;
+ var organiser = olItem.Organizer;
var currentUser = Application.Session.CurrentUser;
var exchangeUser = currentUser.AddressEntry.GetExchangeUser();
- var currentUserName = exchangeUser == null ?
- Application.Session.CurrentUser.Name:
- exchangeUser.Name;
-
- return syncConfigured &&
- olItem.Sensitivity == Outlook.OlSensitivity.olNormal &&
- /* If there is a valid crmId it's arrived via CRM and is therefore safe to save to CRM;
- * if the current user is the organiser, AND there's no valid CRM id, then it's a new one
- * that the current user made, and we should save it to CRM. */
- (CrmId.IsInvalid(olItem.GetCrmId()) || currentUserName == organiser) &&
- /* Microsoft Conferencing Add-in creates temporary items with names which start
- * 'PLEASE IGNORE' - we should not sync these. */
- !olItem.Subject.StartsWith(MSConfTmpSubjectPrefix);
+ var currentUserName = exchangeUser == null ? Application.Session.CurrentUser.Name : exchangeUser.Name;
+
+ return syncConfigured &&
+ olItem.Sensitivity == OlSensitivity.olNormal &&
+ /* If there is a valid crmId it's arrived via CRM and is therefore safe to save to CRM;
+ * if the current user is the organiser, AND there's no valid CRM id, then it's a new one
+ * that the current user made, and we should save it to CRM. */
+ (CrmId.IsInvalid(olItem.GetCrmId()) || currentUserName == organiser) &&
+ /* Microsoft Conferencing Add-in creates temporary items with names which start
+ * 'PLEASE IGNORE' - we should not sync these. */
+ !olItem.Subject.StartsWith(MSConfTmpSubjectPrefix);
}
///
- /// Synchronise items in the specified folder with the specified SuiteCRM module.
+ /// Synchronise items in the specified folder with the specified SuiteCRM module.
///
///
- /// TODO: candidate for refactoring upwards, in concert with ContactSyncing.SyncFolder.
+ /// TODO: candidate for refactoring upwards, in concert with ContactSyncing.SyncFolder.
///
/// The folder.
/// The module.
- protected override void SyncFolder(Outlook.MAPIFolder folder, string crmModule)
+ protected override void SyncFolder(MAPIFolder folder, string crmModule)
{
- Log.Debug($"{this.GetType().Name}.SyncFolder: '{crmModule}'");
+ Log.Debug($"{GetType().Name}.SyncFolder: '{crmModule}'");
try
{
/* this.ItemsSyncState already contains items to be synced. */
- var untouched = new HashSet>(SyncStateManager.Instance.GetSynchronisedItems());
- IList records = MergeRecordsFromCrm(folder, crmModule, untouched);
+ var untouched =
+ new HashSet>(SyncStateManager.Instance
+ .GetSynchronisedItems());
+ var records = MergeRecordsFromCrm(folder, crmModule, untouched);
AddOrUpdateItemsFromCrmToOutlook(records, folder, untouched, crmModule);
- EntryValue[] invited = RestAPIWrapper.GetRelationships("Users",
+ var invited = RestAPIWrapper.GetRelationships("Users",
RestAPIWrapper.GetUserId(), crmModule.ToLower(),
RestAPIWrapper.GetSugarFields(crmModule));
if (invited != null)
- {
AddOrUpdateItemsFromCrmToOutlook(invited, folder, untouched, crmModule);
- }
try
{
- this.ResolveUnmatchedItems(untouched);
+ ResolveUnmatchedItems(untouched);
}
catch (Exception ex)
{
- ErrorHandler.Handle($"Failed while synchronising {this.DefaultCrmModule}", ex);
+ ErrorHandler.Handle($"Failed while synchronising {DefaultCrmModule}", ex);
}
}
catch (Exception ex)
{
- ErrorHandler.Handle($"Failed while synchronising {this.DefaultCrmModule}", ex);
+ ErrorHandler.Handle($"Failed while synchronising {DefaultCrmModule}", ex);
}
}
///
- /// Update an existing Outlook item with values taken from a corresponding CRM item. Note that
- /// this just overwrites all values in the Outlook item.
+ /// Update an existing Outlook item with values taken from a corresponding CRM item. Note that
+ /// this just overwrites all values in the Outlook item.
///
/// The CRM type of the item from which values are to be taken.
/// The CRM item from which values are to be taken.
/// The state date/time of the item, adjusted for timezone.
/// The outlook item assumed to correspond with the CRM item.
/// An appropriate sync state.
- private SyncState UpdateExistingOutlookItemFromCrm(
- string crmType,
- EntryValue crmItem,
- DateTime dateStart,
- SyncState syncState)
+ private SyncState UpdateExistingOutlookItemFromCrm(
+ string crmType,
+ EntryValue crmItem,
+ DateTime dateStart,
+ SyncState syncState)
{
LogItemAction(syncState.OutlookItem, "AppointmentSyncing.UpdateExistingOutlookItemFromCrm");
if (!syncState.IsDeletedInOutlook)
{
- Outlook.AppointmentItem olItem = syncState.OutlookItem;
- Outlook.UserProperty olPropertyModifiedDate = olItem.UserProperties[SyncStateManager.ModifiedDatePropertyName];
+ var olItem = syncState.OutlookItem;
+ var olPropertyModifiedDate = olItem.UserProperties[SyncStateManager.ModifiedDatePropertyName];
- if (olPropertyModifiedDate == null || olPropertyModifiedDate.Value != crmItem.GetValueAsString("date_modified"))
- {
+ if (olPropertyModifiedDate == null || olPropertyModifiedDate.Value !=
+ crmItem.GetValueAsString("date_modified"))
try
{
olItem.Subject = crmItem.GetValueAsString("name");
olItem.Body = crmItem.GetValueAsString("description");
if (!string.IsNullOrWhiteSpace(crmItem.GetValueAsString("date_start")))
- {
UpdateOutlookDetails(crmType, crmItem, dateStart, olItem);
- }
EnsureSynchronisationPropertiesForOutlookItem(olItem, crmItem, crmType);
- LogItemAction(syncState.OutlookItem, "AppointmentSyncing.UpdateExistingOutlookItemFromCrm, item saved");
+ LogItemAction(syncState.OutlookItem,
+ "AppointmentSyncing.UpdateExistingOutlookItemFromCrm, item saved");
}
catch (Exception any)
{
@@ -984,23 +962,24 @@ protected override void SyncFolder(Outlook.MAPIFolder folder, string crmModule)
}
finally
{
- this.SaveItem(olItem);
+ SaveItem(olItem);
}
- }
- syncState.OModifiedDate = DateTime.ParseExact(crmItem.GetValueAsString("date_modified"), "yyyy-MM-dd HH:mm:ss", null);
+ syncState.OModifiedDate =
+ DateTime.ParseExact(crmItem.GetValueAsString("date_modified"), "yyyy-MM-dd HH:mm:ss", null);
}
return syncState;
}
///
- /// Update this Outlook appointment's start and duration from this CRM object.
+ /// Update this Outlook appointment's start and duration from this CRM object.
///
/// The CRM type of the item from which values are to be taken.
/// The CRM item from which values are to be taken.
/// The state date/time of the item, adjusted for timezone.
/// The outlook item assumed to correspond with the CRM item.
- protected virtual void UpdateOutlookDetails(string crmType, EntryValue crmItem, DateTime date_start, Outlook.AppointmentItem olItem)
+ protected virtual void UpdateOutlookDetails(string crmType, EntryValue crmItem, DateTime date_start,
+ AppointmentItem olItem)
{
try
{
@@ -1008,161 +987,163 @@ protected virtual void UpdateOutlookDetails(string crmType, EntryValue crmItem,
var minutesString = crmItem.GetValueAsString("duration_minutes");
var hoursString = crmItem.GetValueAsString("duration_hours");
- int minutes = string.IsNullOrWhiteSpace(minutesString) ? 0 : int.Parse(minutesString);
- int hours = string.IsNullOrWhiteSpace(hoursString) ? 0 : int.Parse(hoursString);
+ var minutes = string.IsNullOrWhiteSpace(minutesString) ? 0 : int.Parse(minutesString);
+ var hours = string.IsNullOrWhiteSpace(hoursString) ? 0 : int.Parse(hoursString);
olItem.Duration = minutes + hours * 60;
}
finally
{
- this.SaveItem(olItem);
+ SaveItem(olItem);
}
}
- internal override string GetOutlookEntryId(Outlook.AppointmentItem olItem)
+ internal override string GetOutlookEntryId(AppointmentItem olItem)
{
return olItem.EntryID;
}
- protected override CrmId GetCrmEntryId(Outlook.AppointmentItem olItem)
+ protected override CrmId GetCrmEntryId(AppointmentItem olItem)
{
return olItem.GetCrmId();
}
///
- /// Return the sensitivity of this outlook item.
+ /// Return the sensitivity of this outlook item.
///
///
- /// Outlook item classes do not inherit from a common base class, so generic client code cannot refer to 'OutlookItem.Sensitivity'.
+ /// Outlook item classes do not inherit from a common base class, so generic client code cannot refer to
+ /// 'OutlookItem.Sensitivity'.
///
/// The outlook item whose sensitivity is required.
/// the sensitivity of the item.
- internal override Outlook.OlSensitivity GetSensitivity(Outlook.AppointmentItem item)
+ internal override OlSensitivity GetSensitivity(AppointmentItem item)
{
return item.Sensitivity;
}
///
- /// Add an address resolution composed from this module name and record to the cache.
+ /// Add an address resolution composed from this module name and record to the cache.
///
/// The name of the module in which the record was found
/// The record.
protected void CacheAddressResolutionData(string moduleName, LinkRecord record)
{
CacheAddressResolutionData(
- new AddressResolutionData(moduleName,
+ new AddressResolutionData(moduleName,
record.data.AsDictionary()));
}
///
- /// Add this resolution to the cache.
+ /// Add this resolution to the cache.
///
/// The resolution to add.
protected void CacheAddressResolutionData(AddressResolutionData resolution)
{
List resolutions;
- if (this.meetingRecipientsCache.ContainsKey(resolution.EmailAddress))
+ if (meetingRecipientsCache.ContainsKey(resolution.EmailAddress))
{
- resolutions = this.meetingRecipientsCache[resolution.EmailAddress];
+ resolutions = meetingRecipientsCache[resolution.EmailAddress];
}
else
{
resolutions = new List();
- this.meetingRecipientsCache[resolution.EmailAddress] = resolutions;
+ meetingRecipientsCache[resolution.EmailAddress] = resolutions;
}
if (!resolutions.Any(x => x.ModuleId == resolution.ModuleId && x.ModuleName == resolution.ModuleName))
- {
resolutions.Add(resolution);
- }
- Log.Debug($"Successfully cached recipient {resolution.EmailAddress} => {resolution.ModuleName}, {resolution.ModuleId}.");
+ Log.Debug(
+ $"Successfully cached recipient {resolution.EmailAddress} => {resolution.ModuleName}, {resolution.ModuleId}.");
}
protected void CacheAddressResolutionData(EntryValue crmItem)
{
foreach (var list in crmItem.relationships.link_list)
+ foreach (var record in list.records)
{
- foreach (var record in list.records)
+ var data = record.data.AsDictionary();
+ try
{
- var data = record.data.AsDictionary();
- try
- {
- this.CacheAddressResolutionData(list.name, record);
- }
- catch (TypeInitializationException tix)
- {
- ErrorHandler.Handle("Probable invalid CRM ID", tix);
- }
- catch (KeyNotFoundException kex)
- {
- ErrorHandler.Handle($"Email address '{record.data.GetValueAsString(AddressResolutionData.EmailAddressFieldName)}' not recognised while caching meeting recipients.", kex);
- }
+ CacheAddressResolutionData(list.name, record);
+ }
+ catch (TypeInitializationException tix)
+ {
+ ErrorHandler.Handle("Probable invalid CRM ID", tix);
+ }
+ catch (KeyNotFoundException kex)
+ {
+ ErrorHandler.Handle(
+ $"Email address '{record.data.GetValueAsString(AddressResolutionData.EmailAddressFieldName)}' not recognised while caching meeting recipients.",
+ kex);
}
}
}
///
- /// Used for caching data for resolving email addresses to CRM records.
+ /// Used for caching data for resolving email addresses to CRM records.
///
protected class AddressResolutionData
{
///
- /// Expected name in the input map of the email address field.
+ /// Expected name in the input map of the email address field.
///
public const string EmailAddressFieldName = "email1";
///
- /// Expected name in the input map of the field containing the id in
- /// the specified module.
+ /// Expected name in the input map of the field containing the id in
+ /// the specified module.
///
public const string ModuleIdFieldName = "id";
///
- /// Expected name in the input map of the field containing an associated id in
- /// the `Accounts` module, if any.
+ /// Expected name in the input map of the field containing an associated id in
+ /// the `Accounts` module, if any.
///
public const string AccountIdFieldName = "account_id";
///
- /// The email address resolved by this data.
+ /// The id within the `Accounts` module of a related record, if any.
///
- public readonly string EmailAddress;
+ private readonly object accountId;
+
///
- /// The name of the CRM module to which it resolves.
+ /// The email address resolved by this data.
///
- public readonly string ModuleName;
+ public readonly string EmailAddress;
+
///
- /// The id within that module of the record to which it resolves.
+ /// The id within that module of the record to which it resolves.
///
public readonly CrmId ModuleId;
///
- /// The id within the `Accounts` module of a related record, if any.
+ /// The name of the CRM module to which it resolves.
///
- private readonly object accountId;
+ public readonly string ModuleName;
public AddressResolutionData(string moduleName, CrmId moduleId, string emailAddress)
{
- this.ModuleName = moduleName;
- this.ModuleId = moduleId;
- this.EmailAddress = emailAddress;
+ ModuleName = moduleName;
+ ModuleId = moduleId;
+ EmailAddress = emailAddress;
}
public AddressResolutionData(string moduleName, Dictionary data)
{
- this.ModuleName = moduleName;
- this.ModuleId = CrmId.Get(data[ModuleIdFieldName]);
- this.EmailAddress = data[EmailAddressFieldName]?.ToString();
+ ModuleName = moduleName;
+ ModuleId = CrmId.Get(data[ModuleIdFieldName]);
+ EmailAddress = data[EmailAddressFieldName]?.ToString();
try
{
- this.accountId = data[AccountIdFieldName]?.ToString();
+ accountId = data[AccountIdFieldName]?.ToString();
}
catch (KeyNotFoundException)
{
@@ -1171,4 +1152,4 @@ public AddressResolutionData(string moduleName, Dictionary data)
}
}
}
-}
+}
\ No newline at end of file
diff --git a/SuiteCRMAddIn/BusinessLogic/CRMPermissionsCache.cs b/SuiteCRMAddIn/BusinessLogic/CRMPermissionsCache.cs
index 33d6b8ac..ac77d629 100644
--- a/SuiteCRMAddIn/BusinessLogic/CRMPermissionsCache.cs
+++ b/SuiteCRMAddIn/BusinessLogic/CRMPermissionsCache.cs
@@ -383,6 +383,7 @@ internal override void PerformIteration()
///
/// The type of outlook item for which I manage
/// permissions (may be stored in more than one module).
+ /// The appropriate SyncState type for that Outlook item type.
public class CRMPermissionsCache : CRMPermissionsCache
where OutlookItemType : class
where SyncStateType : SyncState
diff --git a/SuiteCRMAddIn/BusinessLogic/ContactSynchroniser.cs b/SuiteCRMAddIn/BusinessLogic/ContactSynchroniser.cs
index b006babb..331f897a 100644
--- a/SuiteCRMAddIn/BusinessLogic/ContactSynchroniser.cs
+++ b/SuiteCRMAddIn/BusinessLogic/ContactSynchroniser.cs
@@ -241,12 +241,12 @@ internal override void LogItemAction(Outlook.ContactItem olItem, string message)
{
try
{
- CrmId crmId = olItem.GetCrmId();
+ CrmId crmId = this.IsEnabled() ? olItem.GetCrmId() : CrmId.Empty;
if (CrmId.IsInvalid(crmId)) { crmId = CrmId.Empty; }
StringBuilder bob = new StringBuilder();
bob.Append($"{message}:\n\tOutlook Id : {olItem.EntryID}")
- .Append($"\n\tCRM Id : {crmId}")
+ .Append(this.IsEnabled() ? $"\n\tCRM Id : {crmId}" : string.Empty)
.Append($"\n\tFull name : '{olItem.FullName}'")
.Append($"\n\tSensitivity : {olItem.Sensitivity}")
.Append($"\n\tTxState : {SyncStateManager.Instance.GetExistingSyncState(olItem)?.TxState}");
@@ -417,7 +417,7 @@ protected override void EnsureSynchronisationPropertyForOutlookItem(Outlook.Cont
}
- protected override void GetOutlookItems(Outlook.MAPIFolder taskFolder)
+ protected override void LinkOutlookItems(Outlook.MAPIFolder taskFolder)
{
try
{
diff --git a/SuiteCRMAddIn/BusinessLogic/CrmId.cs b/SuiteCRMAddIn/BusinessLogic/CrmId.cs
index 7890150f..c741a8cb 100644
--- a/SuiteCRMAddIn/BusinessLogic/CrmId.cs
+++ b/SuiteCRMAddIn/BusinessLogic/CrmId.cs
@@ -20,13 +20,15 @@
*
* @author SalesAgility
*/
+
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using SuiteCRMAddIn.Exceptions;
+using SuiteCRMAddIn.Properties;
+
namespace SuiteCRMAddIn.BusinessLogic
{
- using System;
- using System.Collections.Generic;
- using System.Runtime.CompilerServices;
- using System.Text.RegularExpressions;
-
///
/// A validated CRM id.
///
@@ -35,7 +37,7 @@ public class CrmId : IComparable
public static readonly CrmId Empty = new CrmId();
private static readonly Regex Validator =
- CrmIdValidationPolicy.GetValidationPattern(Properties.Settings.Default.CrmIdValidationPolicy);
+ CrmIdValidationPolicy.GetValidationPattern(Settings.Default.CrmIdValidationPolicy);
private static readonly Dictionary Issued = new Dictionary();
@@ -53,11 +55,11 @@ private CrmId()
}
///
- /// Create a new instance of a CrmId with this id.
+ /// Create a new instance of a CrmId with this id.
///
///
- /// This has to be public so that the JSON deserialiser can use it - but don't use it
- /// otherwise
+ /// This has to be public so that the JSON deserialiser can use it - but don't use it
+ /// otherwise
///
///
public CrmId(string id)
@@ -69,8 +71,8 @@ public CrmId(string id)
}
else
{
- throw new TypeInitializationException(this.GetType().FullName,
- new Exception($"'{id}' does not appear to be a valid CRM id."));
+ throw new TypeInitializationException(GetType().FullName,
+ new InvalidCrmIdException($"'{id}' does not appear to be a valid CRM id."));
}
}
@@ -123,13 +125,13 @@ public bool IsValid()
}
///
- /// True if is false of this id.
+ /// True if is false of this id.
///
/// The object which may or may not be a valid CRM id.
- /// True if is false of this id.
+ /// True if is false of this id.
public static bool IsInvalid(CrmId id)
{
- return !CrmId.IsValid(id);
+ return !IsValid(id);
}
public override bool Equals(object obj)
@@ -143,29 +145,25 @@ public override int GetHashCode()
}
///
- /// Get the single CrmId instance for this value.
+ /// Get the single CrmId instance for this value.
///
/// The value to seek.
/// A CrmId instance
/// if `value` does not appear to be a valid CRM id.
public static CrmId Get(string value)
{
- return string.IsNullOrEmpty(value) ?
- CrmId.Empty :
- CrmId.Issued.ContainsKey(value) ?
- CrmId.Issued[value] :
- new CrmId(value);
+ return string.IsNullOrEmpty(value) ? Empty : Issued.ContainsKey(value) ? Issued[value] : new CrmId(value);
}
///
- /// Get the single CrmId instance for this value.
+ /// Get the single CrmId instance for this value.
///
/// The value to seek.
/// A CrmId instance
/// if `value` does not appear to be a valid CRM id.
public static CrmId Get(object value)
{
- return value == null ? CrmId.Empty : CrmId.Get(value.ToString());
+ return value == null ? Empty : Get(value.ToString());
}
}
}
\ No newline at end of file
diff --git a/SuiteCRMAddIn/BusinessLogic/SyncDirection.cs b/SuiteCRMAddIn/BusinessLogic/SyncDirection.cs
index a908f0da..baacf8b2 100644
--- a/SuiteCRMAddIn/BusinessLogic/SyncDirection.cs
+++ b/SuiteCRMAddIn/BusinessLogic/SyncDirection.cs
@@ -89,6 +89,5 @@ public static bool AllowOutbound(Direction direction)
{
return (direction == Direction.Import || direction == Direction.BiDirectional);
}
-
}
}
diff --git a/SuiteCRMAddIn/BusinessLogic/Synchroniser.cs b/SuiteCRMAddIn/BusinessLogic/Synchroniser.cs
index f42e2735..2fe3ab37 100644
--- a/SuiteCRMAddIn/BusinessLogic/Synchroniser.cs
+++ b/SuiteCRMAddIn/BusinessLogic/Synchroniser.cs
@@ -21,125 +21,136 @@
* @author SalesAgility
*/
+#region
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using Microsoft.Office.Interop.Outlook;
+using Newtonsoft.Json;
+using SuiteCRMAddIn.Daemon;
+using SuiteCRMAddIn.Exceptions;
+using SuiteCRMAddIn.Properties;
+using SuiteCRMClient;
+using SuiteCRMClient.Logging;
+using SuiteCRMClient.RESTObjects;
+using Exception = System.Exception;
+
+#endregion
+
namespace SuiteCRMAddIn.BusinessLogic
{
- using Daemon;
- using Exceptions;
- using Newtonsoft.Json;
- using SuiteCRMClient;
- using SuiteCRMClient.Logging;
- using SuiteCRMClient.RESTObjects;
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using Outlook = Microsoft.Office.Interop.Outlook;
-
public abstract class Synchroniser : RepeatingProcess
{
public Synchroniser(string name, SyncContext context) : base(name, context.Log)
{
- this.Context = context;
+ Context = context;
}
- protected Outlook.Application Application => Context.Application;
+ protected Application Application => Context.Application;
///
- /// The name of the default CRM module (record type) that this synchroniser synchronises.
+ /// The name of the default CRM module (record type) that this synchroniser synchronises.
///
- public abstract string DefaultCrmModule
- {
- get;
- }
+ public abstract string DefaultCrmModule { get; }
///
- /// The direction(s) in which I sync
+ /// The direction(s) in which I sync
///
public abstract SyncDirection.Direction Direction { get; }
///
- /// The synchronisation context in which I operate.
+ /// The synchronisation context in which I operate.
///
- protected SyncContext Context { get; private set; }
+ protected SyncContext Context { get; }
///
- /// Get the Outlook folder in which my items are stored.
+ /// Get the Outlook folder in which my items are stored.
///
- ///
- public abstract Outlook.MAPIFolder GetDefaultFolder();
+ /// the Outlook folder in which my items are stored
+ public abstract MAPIFolder GetDefaultFolder();
///
- /// Specialisation: get my Outlook items.
+ /// Specialisation: get my Outlook items.
///
public override void PerformStartup()
{
- this.GetOutlookItems(this.GetDefaultFolder());
+ LinkOutlookItems(GetDefaultFolder());
}
- protected abstract void GetOutlookItems(Outlook.MAPIFolder folder);
+ ///
+ /// Links the outlook items in the specified folder into the items whose synchronisation states I track.
+ ///
+ /// the Outlook folder from which items should be taken.
+ protected abstract void LinkOutlookItems(MAPIFolder folder);
+
- protected abstract void SyncFolder(Outlook.MAPIFolder folder, string crmModule);
+ ///
+ /// Synchronise items in the specified folder with the specified SuiteCRM module.
+ ///
+ protected abstract void SyncFolder(MAPIFolder folder, string crmModule);
}
///
- /// Synchronise items of the class for which I am responsible.
+ /// Synchronise items of the class for which I am responsible.
///
///
- /// It's arguable that specialisations of this class ought to be singletons, but currently they are not.
+ /// It's arguable that specialisations of this class ought to be singletons, but currently they are not.
///
/// The class of item that I am responsible for synchronising.
- /// An appropriate sync state type for my
+ /// An appropriate sync state type for my
public abstract class Synchroniser : Synchroniser, IDisposable
where OutlookItemType : class
where SyncStateType : SyncState
{
///
- /// A cache for CRM premissions to prevent continually asking for them.
+ /// A cache for CRM premissions to prevent continually asking for them.
///
protected readonly CRMPermissionsCache permissionsCache;
+ // Keep a reference to the COM object on which we have event handlers, otherwise
+ // when the reference is garbage-collected, the event-handlers are removed!
+ private Items _itemsCollection;
+
///
- /// A lock on the creation of new objects in Outlook.
+ /// A lock on the creation of new objects in Outlook.
///
protected object creationLock = new object();
///
- /// It appears that CRM sends us back strings HTML escaped.
+ /// It appears that CRM sends us back strings HTML escaped.
///
- protected JsonSerializerSettings deserialiseSettings = new JsonSerializerSettings()
+ protected JsonSerializerSettings DeserialiseSettings = new JsonSerializerSettings
{
StringEscapeHandling = StringEscapeHandling.EscapeHtml
};
///
- /// A lock to prevent enqueueing the same new object twice in different
- /// threads (unlikely, since it should always be in the VSTA_main thread,
- /// but let's be paranoid).
+ /// A lock to prevent enqueueing the same new object twice in different
+ /// threads (unlikely, since it should always be in the VSTA_main thread,
+ /// but let's be paranoid).
///
protected object enqueueingLock = new object();
///
- /// The prefix for the fetch query, used in FetchRecordsFromCrm, q.v.
+ /// The prefix for the fetch query, used in FetchRecordsFromCrm, q.v.
///
protected string fetchQueryPrefix;
private string folderName;
- // Keep a reference to the COM object on which we have event handlers, otherwise
- // when the reference is garbage-collected, the event-handlers are removed!
- private Outlook.Items _itemsCollection = null;
-
///
- /// Construct a new instance of a synchroniser with this thread name and context.
+ /// Construct a new instance of a synchroniser with this thread name and context.
///
/// The name of the thread I shall create.
/// The context in which I shall work.
- public Synchroniser(string threadName, SyncContext context) : base( threadName, context)
+ public Synchroniser(string threadName, SyncContext context) : base(threadName, context)
{
- this.InstallEventHandlers();
- this.AddSuiteCrmOutlookCategory();
- this.permissionsCache = new CRMPermissionsCache(this, context.Log);
+ InstallEventHandlers();
+ AddSuiteCrmOutlookCategory();
+ permissionsCache = new CRMPermissionsCache(this, context.Log);
}
public void Dispose()
@@ -148,63 +159,83 @@ public void Dispose()
}
///
- /// Get a date stamp for midnight five days ago (why?).
+ /// Am I enabled? I.e., am I able either to import or to export?
+ ///
+ /// True if this synchroniser is enabled.
+ public bool IsEnabled()
+ {
+ return Globals.ThisAddIn.HasCrmUserSession &&
+ (SyncDirection.AllowInbound(Direction) ||
+ SyncDirection.AllowOutbound(Direction));
+ }
+
+ ///
+ /// Get a date stamp for midnight five days ago (why?).
///
/// A date stamp for midnight five days ago.
public DateTime GetStartDate()
{
- DateTime dtRet = DateTime.Now.AddDays(-5);
+ var dtRet = DateTime.Now.AddDays(-5);
return new DateTime(dtRet.Year, dtRet.Month, dtRet.Day, 0, 0, 0);
}
+ ///
+ /// Return a SQL fragment based on my start date
+ ///
+ ///
public string GetStartDateString()
{
- return " AND [Start] >='" + GetStartDate().ToString("MM/dd/yyyy HH:mm") + "'";
+ return $" AND [Start] >='{GetStartDate().ToString("MM/dd/yyyy HH:mm")}'";
}
+ ///
+ /// Prepare me for shutdown by removing my event handlers.
+ ///
+ /// Always zero.
public override int PrepareShutdown()
{
- this.RemoveEventHandlers();
+ RemoveEventHandlers();
return 0;
}
///
- /// Run a single iteration of the synchronisation process for the items for which I am responsible.
+ /// Run a single iteration of the synchronisation process for the items for which I am responsible.
///
public virtual void SynchroniseAll()
{
- Log.Debug($"{this.GetType().Name} SynchroniseAll starting");
+ Log.Debug($"{GetType().Name} SynchroniseAll starting");
- if (this.permissionsCache.HasExportAccess())
+ if (permissionsCache.HasExportAccess())
{
- Outlook.MAPIFolder folder = GetDefaultFolder();
+ var folder = GetDefaultFolder();
- SyncFolder(folder, this.DefaultCrmModule);
+ SyncFolder(folder, DefaultCrmModule);
}
else
{
- Log.Debug($"{this.GetType().Name}.SynchroniseAll not synchronising {this.DefaultCrmModule} because export access is denied");
+ Log.Debug(
+ $"{GetType().Name}.SynchroniseAll not synchronising {DefaultCrmModule} because export access is denied");
}
- Log.Debug($"{this.GetType().Name} SynchroniseAll completed");
+ Log.Debug($"{GetType().Name} SynchroniseAll completed");
}
///
- /// Add the item implied by this SyncState, which may not exist in CRM, to CRM.
+ /// Add the item implied by this SyncState, which may not exist in CRM, to CRM.
///
/// The sync state.
/// The id of the entry added or updated.
internal virtual CrmId AddOrUpdateItemFromOutlookToCrm(SyncState syncState)
{
- CrmId result = CrmId.Empty;
+ var result = CrmId.Empty;
- if (this.ShouldAddOrUpdateItemFromOutlookToCrm(syncState.OutlookItem))
+ if (ShouldAddOrUpdateItemFromOutlookToCrm(syncState.OutlookItem))
{
- OutlookItemType olItem = syncState.OutlookItem;
+ var olItem = syncState.OutlookItem;
try
{
- lock (this.enqueueingLock)
+ lock (enqueueingLock)
{
LogItemAction(olItem, "Synchroniser.AddOrUpdateItemFromOutlookToCrm, Despatching");
@@ -216,13 +247,15 @@ internal virtual CrmId AddOrUpdateItemFromOutlookToCrm(SyncState
- /// Get the entry id of this Outlook item.
+ /// Get the entry id of this Outlook item.
///
+ ///
+ /// Outlook item classes do not inherit from a common base class, so generic client code cannot refer to
+ /// 'OutlookItem.EntryId'; hance this rather clumsy mechanism.
+ ///
/// The Outlook item from which the entry id should be taken.
/// the entry id of this Outlook item.
internal abstract string GetOutlookEntryId(OutlookItemType olItem);
///
- /// Return the sensitivity of this outlook item.
+ /// Return the sensitivity of this outlook item.
///
///
- /// Outlook item classes do not inherit from a common base class, so generic client code cannot refer to 'OutlookItem.Sensitivity'.
+ /// Outlook item classes do not inherit from a common base class, so generic client code cannot refer to
+ /// 'OutlookItem.Sensitivity'; hance this rather clumsy mechanism.
///
/// The outlook item whose sensitivity is required.
/// the sensitivity of the item.
- internal abstract Outlook.OlSensitivity GetSensitivity(OutlookItemType olItem);
+ internal abstract OlSensitivity GetSensitivity(OutlookItemType olItem);
+
internal IEnumerable GetSynchronisedItems()
{
- return SyncStateManager.Instance.GetSynchronisedItems(); ;
+ return IsEnabled()
+ ? SyncStateManager.Instance.GetSynchronisedItems()
+ : new List();
}
///
- /// Deal with an item which used to exist in Outlook but which no longer does.
- /// The default behaviour is to remove it from CRM.
+ /// Deal with an item which used to exist in Outlook but which no longer does.
+ /// The default behaviour is to remove it from CRM.
///
/// The dangling syncState of the missing item.
internal virtual void HandleItemMissingFromOutlook(SyncState syncState)
{
- this.RemoveFromCrm(syncState);
- this.RemoveItemSyncState(syncState);
+ RemoveFromCrm(syncState);
+ RemoveItemSyncState(syncState);
}
///
- /// Log a message regarding this Outlook item, with detail of the item.
+ /// Log a message regarding this Outlook item, with detail of the item.
///
/// The outlook item.
/// The message to be logged.
internal abstract void LogItemAction(OutlookItemType olItem, string message);
///
- /// If I am currently configured to do so, synchronise the items for which I am
- /// responsible once.
+ /// If I am currently configured to do so, synchronise the items for which I am
+ /// responsible once.
///
internal override void PerformIteration()
{
- if (Globals.ThisAddIn.HasCrmUserSession)
+ if (IsEnabled())
{
- if (SyncDirection.AllowInbound(this.Direction))
- {
- this.SynchroniseAll();
- }
+ if (SyncDirection.AllowInbound(Direction))
+ SynchroniseAll();
else
- {
- Log.Debug($"{this.GetType().Name}.SynchroniseAll not running because not enabled");
- }
+ Log.Debug($"{GetType().Name}.SynchroniseAll not running because not enabled");
- this.OtherIterationActions();
+ OtherIterationActions();
}
else
{
- Log.Debug($"{this.GetType().Name}.SynchroniseAll not running because no session");
+ Log.Debug($"{GetType().Name}.SynchroniseAll not running because no session");
}
}
///
- /// Update a single item in the specified Outlook folder with changes from CRM. If the item
- /// does not exist, create it.
+ /// Update a single item in the specified Outlook folder with changes from CRM. If the item
+ /// does not exist, create it.
///
/// The folder to synchronise into.
/// The CRM type of the candidate item.
/// The candidate item from CRM.
/// The synchronisation state of the item updated (if it was updated).
- protected abstract SyncState AddOrUpdateItemFromCrmToOutlook(Outlook.MAPIFolder folder, string crmType, EntryValue crmItem);
+ protected abstract SyncState AddOrUpdateItemFromCrmToOutlook(MAPIFolder folder, string crmType,
+ EntryValue crmItem);
///
- /// Update these items, which may or may not already exist in Outlook.
+ /// Update these items, which may or may not already exist in Outlook.
///
///
- /// TODO: It would be much better if, rather than taking `untouched` as a mutable argument,
- /// this method returned a list of items which weren't identified.
+ /// TODO: It would be much better if, rather than taking `untouched` as a mutable argument,
+ /// this method returned a list of items which weren't identified.
///
/// The items to be synchronised.
/// The outlook folder to synchronise into.
- /// A list of sync states of existing items which have
- /// not yet been synchronised; this list is modified (destructuvely changed)
- /// by the action of this method.
+ ///
+ /// A list of sync states of existing items which have
+ /// not yet been synchronised; this list is modified (destructuvely changed)
+ /// by the action of this method.
+ ///
/// The CRM record type ('module') to be fetched.
protected virtual void AddOrUpdateItemsFromCrmToOutlook(
IList crmItems,
- Outlook.MAPIFolder folder,
+ MAPIFolder folder,
HashSet> untouched,
string crmType)
{
foreach (var crmItem in crmItems)
- {
try
{
if (ShouldAddOrUpdateItemFromCrmToOutlook(folder, crmType, crmItem))
@@ -364,7 +401,8 @@ protected virtual void AddOrUpdateItemsFromCrmToOutlook(
* ideally not be sent, so we forcibly mark them as synced overriding the
* normal flow of the state transition engine. */
state.SetSynced(true);
- LogItemAction(state.OutlookItem, "Synchroniser.AddOrUpdateItemsFromCrmToOutlook, item removed from untouched");
+ LogItemAction(state.OutlookItem,
+ "Synchroniser.AddOrUpdateItemsFromCrmToOutlook, item removed from untouched");
}
}
else
@@ -375,44 +413,47 @@ protected virtual void AddOrUpdateItemsFromCrmToOutlook(
}
catch (Exception ex)
{
- ErrorHandler.Handle($"Failed while trying to add or update {this.DefaultCrmModule} from Outlook to CRM", ex);
+ ErrorHandler.Handle($"Failed while trying to add or update {DefaultCrmModule} from Outlook to CRM",
+ ex);
}
- }
}
///
- /// Construct a JSON packet representing this Outlook item, and despatch it to CRM.
+ /// Construct a JSON packet representing this Outlook item, and despatch it to CRM.
///
///
- /// You'd think that with normal object oriented programming you could just implement this
- /// method here, but because Outlook items are not really objects and don't have a common
- /// superclass you can't. So it has to be implemented in subclasses.
+ /// You'd think that with normal object oriented programming you could just implement this
+ /// method here, but because Outlook items are not really objects and don't have a common
+ /// superclass you can't. So it has to be implemented in subclasses.
///
/// The Outlook item.
/// The CRM id of the object created or modified.
protected abstract CrmId ConstructAndDespatchCrmItem(OutlookItemType olItem);
///
- /// Every Outlook item which is to be synchronised must have a property SOModifiedDate,
- /// a property SType, and a property SEntryId, referencing respectively the last time it
- /// was modified, the type of CRM item it is to be synchronised with, and the id of the
- /// CRM item it is to be synchronised with.
+ /// Every Outlook item which is to be synchronised must have a property SOModifiedDate,
+ /// a property SType, and a property SEntryId, referencing respectively the last time it
+ /// was modified, the type of CRM item it is to be synchronised with, and the id of the
+ /// CRM item it is to be synchronised with.
///
/// The Outlook item.
/// The value for the SOModifiedDate property.
/// The value for the SType property (CRM module name).
/// The value for the SEntryId property (CRM item id).
- protected void EnsureSynchronisationPropertiesForOutlookItem(OutlookItemType olItem, string modifiedDate, string type, CrmId entryId)
+ protected void EnsureSynchronisationPropertiesForOutlookItem(OutlookItemType olItem, string modifiedDate,
+ string type, CrmId entryId)
{
try
{
- EnsureSynchronisationPropertyForOutlookItem(olItem, SyncStateManager.ModifiedDatePropertyName, modifiedDate);
+ EnsureSynchronisationPropertyForOutlookItem(olItem, SyncStateManager.ModifiedDatePropertyName,
+ modifiedDate);
EnsureSynchronisationPropertyForOutlookItem(olItem, SyncStateManager.TypePropertyName, type);
if (CrmId.IsValid(entryId))
{
EnsureSynchronisationPropertyForOutlookItem(olItem, SyncStateManager.CrmIdPropertyName, entryId);
- SyncStateManager.Instance.SetByCrmId(entryId, SyncStateManager.Instance.GetOrCreateSyncState(olItem));
+ SyncStateManager.Instance.SetByCrmId(entryId,
+ SyncStateManager.Instance.GetOrCreateSyncState(olItem));
}
}
catch (Exception any)
@@ -426,27 +467,28 @@ protected void EnsureSynchronisationPropertiesForOutlookItem(OutlookItemType olI
}
///
- /// Set up synchronisation properties for this outlook item from this CRM item, assuming my default CRM module.
+ /// Set up synchronisation properties for this outlook item from this CRM item, assuming my default CRM module.
///
/// The Outlook item.
/// The CRM item.
protected virtual void EnsureSynchronisationPropertiesForOutlookItem(OutlookItemType olItem, EntryValue crmItem)
{
- this.EnsureSynchronisationPropertiesForOutlookItem(
+ EnsureSynchronisationPropertiesForOutlookItem(
olItem,
crmItem,
- this.DefaultCrmModule);
+ DefaultCrmModule);
}
///
- /// Set up synchronisation properties for this outlook item from this CRM item, assuming my default CRM module.
+ /// Set up synchronisation properties for this outlook item from this CRM item, assuming my default CRM module.
///
/// The Outlook item.
/// The CRM item.
/// The value for the SType property (CRM module name).
- protected virtual void EnsureSynchronisationPropertiesForOutlookItem(OutlookItemType olItem, EntryValue crmItem, string type)
+ protected virtual void EnsureSynchronisationPropertiesForOutlookItem(OutlookItemType olItem, EntryValue crmItem,
+ string type)
{
- this.EnsureSynchronisationPropertiesForOutlookItem(
+ EnsureSynchronisationPropertiesForOutlookItem(
olItem,
crmItem.GetValueAsString("date_modified"),
type,
@@ -454,35 +496,38 @@ protected virtual void EnsureSynchronisationPropertiesForOutlookItem(OutlookItem
}
///
- /// Every Outlook item which is to be synchronised must have a property SOModifiedDate,
- /// a property SType, and a property SEntryId, referencing respectively the last time it
- /// was modified, the type of CRM item it is to be synchronised with, and the id of the
- /// CRM item it is to be synchronised with.
+ /// Every Outlook item which is to be synchronised must have a property SOModifiedDate,
+ /// a property SType, and a property SEntryId, referencing respectively the last time it
+ /// was modified, the type of CRM item it is to be synchronised with, and the id of the
+ /// CRM item it is to be synchronised with.
///
/// The Outlook item.
/// The value for the SOModifiedDate property.
/// The value for the SType property.
/// The value for the SEntryId property.
- protected void EnsureSynchronisationPropertiesForOutlookItem(OutlookItemType olItem, DateTime modifiedDate, string type, CrmId entryId)
+ protected void EnsureSynchronisationPropertiesForOutlookItem(OutlookItemType olItem, DateTime modifiedDate,
+ string type, CrmId entryId)
{
- this.EnsureSynchronisationPropertiesForOutlookItem(olItem, modifiedDate.ToString("yyyy-MM-dd HH:mm:ss"), type, entryId);
+ EnsureSynchronisationPropertiesForOutlookItem(olItem, modifiedDate.ToString("yyyy-MM-dd HH:mm:ss"), type,
+ entryId);
}
///
- /// Ensure that this Outlook item has a property of this name with this value.
+ /// Ensure that this Outlook item has a property of this name with this value.
///
/// The Outlook item.
/// The name.
/// The value.
- protected abstract void EnsureSynchronisationPropertyForOutlookItem(OutlookItemType olItem, string name, string value);
+ protected abstract void EnsureSynchronisationPropertyForOutlookItem(OutlookItemType olItem, string name,
+ string value);
protected void EnsureSynchronisationPropertyForOutlookItem(OutlookItemType olItem, string name, CrmId value)
{
- this.EnsureSynchronisationPropertyForOutlookItem(olItem, name, value.ToString());
+ EnsureSynchronisationPropertyForOutlookItem(olItem, name, value.ToString());
}
///
- /// Find any existing Outlook items which appear to be identical to this CRM item.
+ /// Find any existing Outlook items which appear to be identical to this CRM item.
///
/// The CRM item to match.
/// A list of matching Outlook items.
@@ -492,8 +537,9 @@ protected List> FindMatches(EntryValue crmItem)
try
{
- result = SyncStateManager.Instance.GetSynchronisedItems>().Where(a => this.IsMatch(a.OutlookItem, crmItem))
- .ToList>();
+ result = SyncStateManager.Instance.GetSynchronisedItems>()
+ .Where(a => IsMatch(a.OutlookItem, crmItem))
+ .ToList();
}
catch (Exception any)
{
@@ -505,32 +551,32 @@ protected List> FindMatches(EntryValue crmItem)
}
///
- /// Get the CRM entry id of this item, if it has one and is known.
+ /// Get the CRM entry id of this item, if it has one and is known.
///
/// The item whose id is saught.
/// The id, or null if it is not known.
protected abstract CrmId GetCrmEntryId(OutlookItemType olItem);
///
- /// Fetch the page of entries from this module starting at this offset.
+ /// Fetch the page of entries from this module starting at this offset.
///
/// The offset into the resultset at which the page begins.
/// A set of entries.
protected virtual EntryList GetEntriesPage(int offset)
{
- return RestAPIWrapper.GetEntryList(this.DefaultCrmModule,
- String.Format(fetchQueryPrefix, RestAPIWrapper.GetUserId()),
- Properties.Settings.Default.SyncMaxRecords, "date_start DESC", offset, false,
- RestAPIWrapper.GetSugarFields(this.DefaultCrmModule));
+ return RestAPIWrapper.GetEntryList(DefaultCrmModule,
+ string.Format(fetchQueryPrefix, RestAPIWrapper.GetUserId()),
+ Settings.Default.SyncMaxRecords, "date_start DESC", offset, false,
+ RestAPIWrapper.GetSugarFields(DefaultCrmModule));
}
///
- /// Check whether this synchroniser is allowed import access for its default CRM module.
+ /// Check whether this synchroniser is allowed import access for its default CRM module.
///
/// true if this synchroniser is allowed import access for its default CRM module.
protected bool HasImportAccess()
{
- return this.permissionsCache.HasImportAccess(this.DefaultCrmModule);
+ return permissionsCache.HasImportAccess(DefaultCrmModule);
}
protected virtual void InstallEventHandlers()
@@ -548,10 +594,10 @@ protected virtual void InstallEventHandlers()
}
///
- /// Return true if this Outlook item appears to represent the same item as this CRM item.
+ /// Return true if this Outlook item appears to represent the same item as this CRM item.
///
///
- /// Intended to help block howlaround.
+ /// Intended to help block howlaround.
///
/// The Outlook item.
/// The CRM item.
@@ -586,7 +632,7 @@ protected void Items_ItemChange(object olItem)
protected void Items_ItemRemove()
{
- Log.Debug($"Outlook {folderName} ItemRemove");
+ Log.Debug($"Outlook {folderName} ItemRemove: entry");
try
{
RemoveDeletedItems();
@@ -595,19 +641,21 @@ protected void Items_ItemRemove()
{
ErrorHandler.Handle($"Failed to handle item(s) removed from {folderName}", problem);
}
+ Log.Debug($"Outlook {folderName} ItemRemove: exit");
}
///
- /// Fetch records in pages from CRM, and merge them into Outlook.
+ /// Fetch records in pages from CRM, and merge them into Outlook.
///
/// The folder to be synchronised.
/// The name of the CRM module to synchronise with.
/// A list of all known Outlook items, from which those modified by this method are removed.
- protected virtual IList MergeRecordsFromCrm(Outlook.MAPIFolder folder, string crmModule, HashSet> untouched)
+ protected virtual IList MergeRecordsFromCrm(MAPIFolder folder, string crmModule,
+ HashSet> untouched)
{
- int thisOffset = 0; // offset of current page of entries
- int nextOffset = 0; // offset of the next page of entries, if any.
- List result = new List();
+ var thisOffset = 0; // offset of current page of entries
+ var nextOffset = 0; // offset of the next page of entries, if any.
+ var result = new List();
/* get candidates for syncrhonisation from SuiteCRM one page at a time */
do
@@ -615,7 +663,7 @@ protected virtual IList MergeRecordsFromCrm(Outlook.MAPIFolder folde
/* update the offset to the offset of the next page */
thisOffset = nextOffset;
- EntryList entriesPage = GetEntriesPage(thisOffset);
+ var entriesPage = GetEntriesPage(thisOffset);
/* get the offset of the next page */
nextOffset = entriesPage.next_offset;
@@ -630,7 +678,7 @@ protected virtual IList MergeRecordsFromCrm(Outlook.MAPIFolder folde
}
///
- /// A hook to allow specialisations to do something additional to just syncing in their iterations.
+ /// A hook to allow specialisations to do something additional to just syncing in their iterations.
///
protected virtual void OtherIterationActions()
{
@@ -638,7 +686,7 @@ protected virtual void OtherIterationActions()
}
///
- /// Entry point from event handler when an item is added in Outlook.
+ /// Entry point from event handler when an item is added in Outlook.
///
/// Should always run in the 'VSTA_main' thread.
/// Shouldn't happen here.
@@ -646,10 +694,9 @@ protected virtual void OtherIterationActions()
protected virtual void OutlookItemAdded(OutlookItemType olItem)
{
if (Globals.ThisAddIn.IsLicensed)
- {
try
{
- OutlookItemAdded(olItem, this);
+ OutlookItemAdded(olItem, this);
}
catch (Exception any)
{
@@ -658,19 +705,15 @@ protected virtual void OutlookItemAdded(OutlookItemType olItem)
finally
{
if (olItem != null)
- {
SaveItem(olItem);
- }
}
- }
else
- {
- Log.Warn($"Synchroniser.OutlookItemAdded: item {this.GetOutlookEntryId(olItem)} not added because not licensed");
- }
+ Log.Warn(
+ $"Synchroniser.OutlookItemAdded: item {GetOutlookEntryId(olItem)} not added because not licensed");
}
///
- /// #2246: Nasty workaround for the fact that Outlook 'Appointments' and 'Meetings' are actually the same class.
+ /// #2246: Nasty workaround for the fact that Outlook 'Appointments' and 'Meetings' are actually the same class.
///
/// The type of sync state to use.
/// The Outlook item which has been added.
@@ -678,20 +721,19 @@ protected virtual void OutlookItemAdded(OutlookItemType olItem)
protected void OutlookItemAdded(OutlookItemType olItem, Synchroniser synchroniser)
where T : SyncState
{
- LogItemAction(olItem, $"{this.GetType().Name}.OutlookItemAdded: {this.GetOutlookEntryId(olItem)}");
+ LogItemAction(olItem, $"{GetType().Name}.OutlookItemAdded: {GetOutlookEntryId(olItem)}");
{
lock (enqueueingLock)
{
if (SyncStateManager.Instance.GetExistingSyncState(olItem) == null)
{
- T state = SyncStateManager.Instance.GetOrCreateSyncState(olItem) as T;
+ var state = SyncStateManager.Instance.GetOrCreateSyncState(olItem) as T;
if (state != null)
{
- if (olItem != null && this.ShouldAddOrUpdateItemFromOutlookToCrm(olItem))
- {
- DaemonWorker.Instance.AddTask(new TransmitNewAction(synchroniser, state));
- }
+ if (olItem != null && ShouldAddOrUpdateItemFromOutlookToCrm(olItem))
+ DaemonWorker.Instance.AddTask(
+ new TransmitNewAction(synchroniser, state));
}
else
{
@@ -700,46 +742,42 @@ protected void OutlookItemAdded(OutlookItemType olItem, Synchroniser
- /// Entry point from event handler, called when an Outlook item of class AppointmentItem
- /// is believed to have changed.
+ /// Entry point from event handler, called when an Outlook item of class AppointmentItem
+ /// is believed to have changed.
///
/// The item which has changed.
protected virtual void OutlookItemChanged(OutlookItemType olItem)
{
if (Globals.ThisAddIn.IsLicensed)
- {
try
{
- OutlookItemChanged(olItem, this);
+ OutlookItemChanged(olItem, this);
}
catch (BadStateTransition bst)
{
if (bst.From != TransmissionState.Transmitted)
- {
throw;
- }
/* couldn't set pending -> transmission is in progress */
}
finally
{
- this.SaveItem(olItem);
+ SaveItem(olItem);
}
- }
else
- {
- Log.Warn($"Synchroniser.OutlookItemAdded: item {this.GetOutlookEntryId(olItem)} not updated because not licensed");
- }
+ Log.Warn(
+ $"Synchroniser.OutlookItemAdded: item {GetOutlookEntryId(olItem)} not updated because not licensed");
}
///
- /// #2246: Nasty workaround for the fact that Outlook 'Appointments' and 'Meetings' are actually the same class.
+ /// #2246: Nasty workaround for the fact that Outlook 'Appointments' and 'Meetings' are actually the same class.
///
/// The type of sync state to use.
/// The Outlook item which has been changed.
@@ -747,49 +785,38 @@ protected virtual void OutlookItemChanged(OutlookItemType olItem)
protected void OutlookItemChanged(OutlookItemType olItem, Synchroniser synchroniser)
where T : SyncState
{
- LogItemAction(olItem, $"{this.GetType().Name}.OutlookItemChanged: {this.GetOutlookEntryId(olItem)}");
+ LogItemAction(olItem, $"{GetType().Name}.OutlookItemChanged: {GetOutlookEntryId(olItem)}");
SyncState state = SyncStateManager.Instance.GetExistingSyncState(olItem);
- T syncStateForItem = state as T;
+ var syncStateForItem = state as T;
if (syncStateForItem != null)
- {
try
{
syncStateForItem.SetPending();
- if (this.ShouldPerformSyncNow(syncStateForItem))
- {
- DaemonWorker.Instance.AddTask(new TransmitUpdateAction(synchroniser, syncStateForItem));
- }
+ if (ShouldPerformSyncNow(syncStateForItem))
+ DaemonWorker.Instance.AddTask(
+ new TransmitUpdateAction(synchroniser, syncStateForItem));
else if (!syncStateForItem.ShouldSyncWithCrm)
- {
- this.RemoveFromCrm(syncStateForItem);
- }
+ RemoveFromCrm(syncStateForItem);
}
catch (BadStateTransition bst)
{
if (bst.From != TransmissionState.Transmitted)
- {
throw;
- }
}
- }
else
- {
- /* we don't have a sync state for this item (presumably formerly private);
- * that's OK, treat it as new */
OutlookItemAdded(olItem);
- }
}
///
- /// Parse a date time object from a user property, assuming the ISO 8601 date-time
- /// format but ommitting the 'T'. (why? I don't know. TODO: possibly fix).
+ /// Parse a date time object from a user property, assuming the ISO 8601 date-time
+ /// format but ommitting the 'T'. (why? I don't know. TODO: possibly fix).
///
///
- /// If the expected format is not recognised, a second scan is attempted without a
- /// specific format; if this fails, it fails silently and the current time is returned.
+ /// If the expected format is not recognised, a second scan is attempted without a
+ /// specific format; if this fails, it fails silently and the current time is returned.
///
/// A property value believed to contain a date time string.
/// A date time object.
@@ -797,15 +824,14 @@ protected DateTime ParseDateTimeFromUserProperty(string propertyValue)
{
if (propertyValue == null) return default(DateTime);
var modDateTime = DateTime.UtcNow;
- if (!DateTime.TryParseExact(propertyValue, "yyyy-MM-dd HH:mm:ss", null, DateTimeStyles.None, out modDateTime))
- {
+ if (!DateTime.TryParseExact(propertyValue, "yyyy-MM-dd HH:mm:ss", null, DateTimeStyles.None,
+ out modDateTime))
DateTime.TryParse(propertyValue, out modDateTime);
- }
return modDateTime;
}
///
- /// Deal, in CRM, with items deleted in Outlook.
+ /// Deal, in CRM, with items deleted in Outlook.
///
protected void RemoveDeletedItems()
{
@@ -813,9 +839,11 @@ protected void RemoveDeletedItems()
var syncStatesCopy = SyncStateManager.Instance.GetSynchronisedItems();
foreach (var syncState in syncStatesCopy)
{
- var shouldDeleteFromCrm = syncState.IsDeletedInOutlook || !syncState.ShouldSyncWithCrm;
- if (shouldDeleteFromCrm) { RemoveFromCrm(syncState); }
- if (syncState.IsDeletedInOutlook) { SyncStateManager.Instance.RemoveSyncState(syncState); }
+ var shouldDeleteFromCrm = this.IsEnabled() &&
+ SyncDirection.AllowOutbound(this.Direction) &&
+ (syncState.IsDeletedInOutlook || !syncState.ShouldSyncWithCrm);
+ if (shouldDeleteFromCrm) RemoveFromCrm(syncState);
+ if (syncState.IsDeletedInOutlook) SyncStateManager.Instance.RemoveSyncState(syncState);
}
}
@@ -832,7 +860,7 @@ protected virtual void RemoveEventHandlers()
}
///
- /// Remove the item implied by this sync state from CRM.
+ /// Remove the item implied by this sync state from CRM.
///
/// A sync state wrapping an item which has been deleted or marked private in Outlook.
protected virtual void RemoveFromCrm(SyncState state)
@@ -840,9 +868,9 @@ protected virtual void RemoveFromCrm(SyncState state)
if (SyncDirection.AllowOutbound(Direction))
{
var crmEntryId = state.CrmEntryId;
- if (state.ExistedInCrm && this.permissionsCache.HasImportAccess(state.CrmType))
+ if (state.ExistedInCrm && permissionsCache.HasImportAccess(state.CrmType))
{
- NameValue[] data = new NameValue[2];
+ var data = new NameValue[2];
data[0] = RestAPIWrapper.SetNameValuePair("id", crmEntryId);
data[1] = RestAPIWrapper.SetNameValuePair("deleted", "1");
RestAPIWrapper.SetEntry(data, state.CrmType);
@@ -853,63 +881,57 @@ protected virtual void RemoveFromCrm(SyncState state)
}
///
- /// Remove an outlook item and its associated sync state.
+ /// Remove an outlook item and its associated sync state.
///
/// The sync state of the item to remove.
protected void RemoveItemAndSyncState(SyncState syncState)
{
- this.LogItemAction(syncState.OutlookItem, "Synchroniser.RemoveItemAndSyncState, deleting item");
+ LogItemAction(syncState.OutlookItem, "Synchroniser.RemoveItemAndSyncState, deleting item");
try
{
syncState.DeleteItem();
}
catch (Exception ex)
{
- ErrorHandler.Handle($"Failed while trying to delete a {this.DefaultCrmModule} item", ex);
+ ErrorHandler.Handle($"Failed while trying to delete a {DefaultCrmModule} item", ex);
}
- this.RemoveItemSyncState(syncState);
+ RemoveItemSyncState(syncState);
}
///
- /// Remove an item from ItemsSyncState.
+ /// Remove an item from ItemsSyncState.
///
/// The sync state of the item to remove.
protected void RemoveItemSyncState(SyncState item)
{
- this.LogItemAction(item.OutlookItem, "Synchroniser.RemoveItemSyncState, removed item from queue");
+ LogItemAction(item.OutlookItem, "Synchroniser.RemoveItemSyncState, removed item from queue");
SyncStateManager.Instance.RemoveSyncState(item);
}
///
- /// Given a list of items which exist in Outlook but are missing from CRM, resolve
- /// how to handle them.
+ /// Given a list of items which exist in Outlook but are missing from CRM, resolve
+ /// how to handle them.
///
/// The list of items to resolve.
protected virtual void ResolveUnmatchedItems(IEnumerable> itemsToResolve)
{
foreach (var unresolved in itemsToResolve)
- {
switch (unresolved.TxState)
{
case TransmissionState.PendingDeletion:
/* If it's to resolve and marked pending deletion, we delete it
* (unresolved on two successive iterations): */
- this.RemoveItemAndSyncState(unresolved);
+ RemoveItemAndSyncState(unresolved);
break;
case TransmissionState.Synced:
if (unresolved.ExistedInCrm)
- {
- /* if it's unresolved but it used to exist in CRM, it's probably been deleted from
- * CRM. Mark it pending deletion and check again next iteration. */
unresolved.SetPendingDeletion();
- }
break;
case TransmissionState.Pending:
case TransmissionState.PresentAtStartup:
if (unresolved.ShouldSyncWithCrm)
- {
try
{
/* if it's unresolved, pending, and should be synced send it. */
@@ -920,12 +942,10 @@ protected virtual void ResolveUnmatchedItems(IEnumerable()
- .Where(s => s.TxState == TransmissionState.PendingDeletion &&
- !itemsToResolve.Contains(s)))
- {
+ .Where(s => s.TxState == TransmissionState.PendingDeletion &&
+ !itemsToResolve.Contains(s)))
/* finally, if there exists an item which had been marked pending deletion, but it has
- * been found in CRM (i.e. not in unresolved), mark it as synced */
- ((SyncState)resolved).SetSynced();
- }
+ * been found in CRM (i.e. not in unresolved), mark it as synced */
+ ((SyncState) resolved).SetSynced();
}
///
- /// Save this item.
+ /// Save this item.
///
///
- /// Because Outlook items are not proper objects, you cannot call the Save method of
- /// an Outlook item without knowing its exact class explicitly. So there are what look
- /// like redundant specialisations of this method; they aren't.
+ ///
+ /// Because Outlook items are not proper objects, you cannot call the Save method of
+ /// an Outlook item without knowing its exact class explicitly. So there are what look
+ /// like redundant specialisations of this method; they aren't.
+ ///
+ /// Note that we must be able to save an item whether or not the synchroniser is enabled.
///
/// The item to save.
protected abstract void SaveItem(OutlookItemType olItem);
///
- /// Specialisations should return false if there's a good reason why we should
- /// NOT sync this item.
+ /// Specialisations should return false if there's a good reason why we should
+ /// NOT sync this item.
///
/// The folder to synchronise into.
/// The CRM type of the candidate item.
/// The candidate item from CRM.
/// true
- protected virtual bool ShouldAddOrUpdateItemFromCrmToOutlook(Outlook.MAPIFolder folder, string crmType, EntryValue crmItem)
+ protected virtual bool ShouldAddOrUpdateItemFromCrmToOutlook(MAPIFolder folder, string crmType,
+ EntryValue crmItem)
{
return true;
}
///
- /// Perform all the necessary checking before adding or updating an item on CRM.
+ /// Perform all the necessary checking before adding or updating an item on CRM.
///
///
- /// TODO TODO TODO: This does NOT actually do all the checking. Checking is also
- /// done in SyncState.ShouldSyncWithCRM, and possibly other places. Fix.
+ /// TODO TODO TODO: This does NOT actually do all the checking. Checking is also
+ /// done in SyncState.ShouldSyncWithCRM, and possibly other places. Fix.
///
- /// The item we may seek to add or update, presumed to be of
- /// my default item type.
+ ///
+ /// The item we may seek to add or update, presumed to be of
+ /// my default item type.
+ ///
/// true if we may attempt to add or update that item.
protected virtual bool ShouldAddOrUpdateItemFromOutlookToCrm(OutlookItemType olItem)
{
bool result;
- string prefix = "Synchoniser.ShouldAddOrUpdateItemFromOutlookToCrm";
+ var prefix = "Synchoniser.ShouldAddOrUpdateItemFromOutlookToCrm";
try
{
if (olItem == null)
{
- Log.Warn($"{prefix}: attempt to send null {this.DefaultCrmModule}?");
+ Log.Warn($"{prefix}: attempt to send null to {DefaultCrmModule}?");
result = false;
}
else
{
if (SyncDirection.AllowOutbound(Direction))
{
- if (this.permissionsCache.HasImportAccess(this.DefaultCrmModule))
+ if (permissionsCache.HasImportAccess(DefaultCrmModule))
{
- if (this.GetSensitivity(olItem) == Outlook.OlSensitivity.olNormal)
+ if (GetSensitivity(olItem) == OlSensitivity.olNormal)
{
result = true;
}
else
{
- Log.Info($"{prefix}: {this.DefaultCrmModule} not added to CRM because its sensitivity is not public.");
+ Log.Info(
+ $"{prefix}: {DefaultCrmModule} not added to CRM because its sensitivity is not public.");
result = false;
}
}
else
{
- Log.Info($"{prefix}: {this.DefaultCrmModule} not added to CRM because import access is not granted.");
+ Log.Info(
+ $"{prefix}: {DefaultCrmModule} not added to CRM because import access is not granted.");
result = false;
}
}
else
{
- Log.Info($"{prefix}: {this.DefaultCrmModule} not added to CRM because synchronisation is not enabled.");
+ Log.Info(
+ $"{prefix}: {DefaultCrmModule} not added to CRM because synchronisation is not enabled.");
result = false;
}
}
}
catch (Exception any)
{
- ErrorHandler.Handle($"Unexpected failure while checking {this.DefaultCrmModule}.", any);
+ ErrorHandler.Handle($"Unexpected failure while checking {DefaultCrmModule}.", any);
result = false;
}
@@ -1039,27 +1064,25 @@ protected virtual bool ShouldAddOrUpdateItemFromOutlookToCrm(OutlookItemType olI
}
///
- /// Should the item represented by this sync state be synchronised now?
+ /// Should the item represented by this sync state be synchronised now?
///
/// The sync state under consideration.
/// True if this synchroniser relates to the current tab and the timing logic is satisfied.
protected bool ShouldPerformSyncNow(SyncState syncState)
{
- return (syncState.ShouldPerformSyncNow());
+ return syncState.ShouldPerformSyncNow();
}
///
- /// Add the magic 'SuiteCRM' category to the Outlook mapi namespace, if it does not
- /// already exist.
+ /// Add the magic 'SuiteCRM' category to the Outlook mapi namespace, if it does not
+ /// already exist.
///
private void AddSuiteCrmOutlookCategory()
{
- Outlook.NameSpace oNS = this.Application.GetNamespace("mapi");
+ var oNS = Application.GetNamespace("mapi");
if (oNS.Categories["SuiteCRM"] == null)
- {
- oNS.Categories.Add("SuiteCRM", Outlook.OlCategoryColor.olCategoryColorGreen,
- Outlook.OlCategoryShortcutKey.olCategoryShortcutKeyNone);
- }
+ oNS.Categories.Add("SuiteCRM", OlCategoryColor.olCategoryColorGreen,
+ OlCategoryShortcutKey.olCategoryShortcutKeyNone);
}
}
-}
+}
\ No newline at end of file
diff --git a/SuiteCRMAddIn/BusinessLogic/TaskSynchroniser.cs b/SuiteCRMAddIn/BusinessLogic/TaskSynchroniser.cs
index bd846b5e..9c0e448a 100644
--- a/SuiteCRMAddIn/BusinessLogic/TaskSynchroniser.cs
+++ b/SuiteCRMAddIn/BusinessLogic/TaskSynchroniser.cs
@@ -146,12 +146,12 @@ internal override void LogItemAction(Outlook.TaskItem olItem, string message)
{
try
{
- CrmId crmId = olItem.GetCrmId();
+ CrmId crmId = this.IsEnabled() ? olItem.GetCrmId() : CrmId.Empty;
if (CrmId.IsInvalid(crmId)) { crmId = CrmId.Empty; }
StringBuilder bob = new StringBuilder();
bob.Append($"{message}:\n\tOutlook Id : {olItem.EntryID}")
- .Append($"\n\tCRM Id : {crmId}")
+ .Append(this.IsEnabled() ? $"\n\tCRM Id : {crmId}" : string.Empty)
.Append($"\n\tSubject : '{olItem.Subject}'")
.Append($"\n\tStatus : {olItem.Status}")
.Append($"\n\tSensitivity : {olItem.Sensitivity}")
@@ -351,7 +351,7 @@ protected override CrmId ConstructAndDespatchCrmItem(Outlook.TaskItem olItem)
}
- protected override void GetOutlookItems(Outlook.MAPIFolder taskFolder)
+ protected override void LinkOutlookItems(Outlook.MAPIFolder taskFolder)
{
try
{
diff --git a/SuiteCRMAddIn/Dialogs/ClearCrmIdsDialog.cs b/SuiteCRMAddIn/Dialogs/ClearCrmIdsDialog.cs
index 851164d1..5ef1e40b 100644
--- a/SuiteCRMAddIn/Dialogs/ClearCrmIdsDialog.cs
+++ b/SuiteCRMAddIn/Dialogs/ClearCrmIdsDialog.cs
@@ -20,7 +20,7 @@ public partial class ClearCrmIdsDialog : Form
///
static BackgroundWorker fred = new BackgroundWorker();
- private IEnumerable items = Globals.ThisAddIn.GetSynchronisableItems();
+ private readonly IEnumerable items = Globals.ThisAddIn.GetSynchronisableItems();
///
/// The total number of items which may have to be cleared.
diff --git a/SuiteCRMAddIn/Dialogs/SettingsDialog.Designer.cs b/SuiteCRMAddIn/Dialogs/SettingsDialog.Designer.cs
index d524ca10..05771143 100644
--- a/SuiteCRMAddIn/Dialogs/SettingsDialog.Designer.cs
+++ b/SuiteCRMAddIn/Dialogs/SettingsDialog.Designer.cs
@@ -117,6 +117,7 @@ private void InitializeComponent()
this.AddInTitleLabel = new System.Windows.Forms.Label();
this.btnCancel = new System.Windows.Forms.Button();
this.btnSave = new System.Windows.Forms.Button();
+ this.dotNetVersionLabel = new System.Windows.Forms.Label();
this.tabPage3.SuspendLayout();
this.EmailArchiveAccountTabs.SuspendLayout();
this.tabPage2.SuspendLayout();
@@ -614,6 +615,7 @@ private void InitializeComponent()
//
// InformationTabPage
//
+ this.InformationTabPage.Controls.Add(this.dotNetVersionLabel);
this.InformationTabPage.Controls.Add(this.AddInVersionLabel);
this.InformationTabPage.Controls.Add(this.groupBox4);
this.InformationTabPage.Controls.Add(this.AddInTitleLabel);
@@ -629,7 +631,7 @@ private void InitializeComponent()
this.AddInVersionLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.AddInVersionLabel.Location = new System.Drawing.Point(13, 61);
this.AddInVersionLabel.Name = "AddInVersionLabel";
- this.AddInVersionLabel.Size = new System.Drawing.Size(332, 25);
+ this.AddInVersionLabel.Size = new System.Drawing.Size(332, 16);
this.AddInVersionLabel.TabIndex = 6;
this.AddInVersionLabel.Text = "Version 0.0.0.0";
this.AddInVersionLabel.TextAlign = System.Drawing.ContentAlignment.TopCenter;
@@ -777,6 +779,16 @@ private void InitializeComponent()
this.btnSave.UseVisualStyleBackColor = true;
this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
//
+ // dotNetVersionLabel
+ //
+ this.dotNetVersionLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.dotNetVersionLabel.Location = new System.Drawing.Point(13, 77);
+ this.dotNetVersionLabel.Name = "dotNetVersionLabel";
+ this.dotNetVersionLabel.Size = new System.Drawing.Size(332, 16);
+ this.dotNetVersionLabel.TabIndex = 7;
+ this.dotNetVersionLabel.Text = ".Net version 0.0.0";
+ this.dotNetVersionLabel.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ //
// SettingsDialog
//
this.AcceptButton = this.btnSave;
@@ -894,5 +906,6 @@ private void InitializeComponent()
private System.Windows.Forms.ComboBox crmIdValidationSelector;
private System.Windows.Forms.Label crmIdValidationLabel;
private System.Windows.Forms.BindingSource policyBindingSource;
+ private System.Windows.Forms.Label dotNetVersionLabel;
}
}
diff --git a/SuiteCRMAddIn/Dialogs/SettingsDialog.cs b/SuiteCRMAddIn/Dialogs/SettingsDialog.cs
index d7abf6c6..3082e49a 100644
--- a/SuiteCRMAddIn/Dialogs/SettingsDialog.cs
+++ b/SuiteCRMAddIn/Dialogs/SettingsDialog.cs
@@ -24,6 +24,7 @@ namespace SuiteCRMAddIn.Dialogs
{
using BusinessLogic;
using Microsoft.Office.Interop.Outlook;
+ using Microsoft.Win32;
using SuiteCRMClient;
using SuiteCRMClient.Logging;
using System;
@@ -95,6 +96,7 @@ private void frmSettings_Load(object sender, EventArgs e)
{
AddInTitleLabel.Text = ThisAddIn.AddInTitle;
AddInVersionLabel.Text = "Version " + ThisAddIn.AddInVersion;
+ dotNetVersionLabel.Text = ".Net version " + CheckFor45DotVersion(Get45or451FromRegistry());
if (Globals.ThisAddIn.SuiteCRMUserSession == null)
{
@@ -115,6 +117,77 @@ private void frmSettings_Load(object sender, EventArgs e)
}
}
+ private static int Get45or451FromRegistry()
+ {
+ int result;
+ try
+ {
+ using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)
+ .OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\"))
+ {
+ result = Convert.ToInt32(ndpKey.GetValue("Release"));
+ }
+ }
+ catch (Exception)
+ {
+ result = 0;
+ }
+
+ return result;
+ }
+
+
+
+// Checking the version using >= will enable forward compatibility,
+// however you should always compile your code on newer versions of
+// the framework to ensure your app works the same.
+ private static string CheckFor45DotVersion(int releaseKey)
+ {
+ if (releaseKey >= 461808)
+ {
+ return "4.7.2";
+ }
+ if (releaseKey >= 461308)
+ {
+ return "4.7.1";
+ }
+ if (releaseKey >= 460798)
+ {
+ return "4.7";
+ }
+ if (releaseKey >= 394802)
+ {
+ return "4.6.2";
+ }
+ if (releaseKey >= 394254)
+ {
+ return "4.6.1";
+ }
+ if (releaseKey >= 393295)
+ {
+ return "4.6";
+ }
+ if (releaseKey >= 393273)
+ {
+ return "4.6 RC";
+ }
+ if ((releaseKey >= 379893))
+ {
+ return "4.5.2";
+ }
+ if ((releaseKey >= 378675))
+ {
+ return "4.5.1";
+ }
+ if ((releaseKey >= 378389))
+ {
+ return "4.5";
+ }
+ // This line should never execute. A non-null release key should mean
+ // that 4.5 is installed.
+ return "No 4.5 version detected";
+ }
+
private void LoadSettings()
{
if (Properties.Settings.Default.Host != string.Empty)
diff --git a/SuiteCRMAddIn/Exceptions/ActionDisabledException.cs b/SuiteCRMAddIn/Exceptions/ActionDisabledException.cs
index 9e7da309..aefc087f 100644
--- a/SuiteCRMAddIn/Exceptions/ActionDisabledException.cs
+++ b/SuiteCRMAddIn/Exceptions/ActionDisabledException.cs
@@ -1,16 +1,35 @@
-namespace SuiteCRMAddIn.Exceptions
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
+/**
+ * Outlook integration for SuiteCRM.
+ * @package Outlook integration for SuiteCRM
+ * @copyright SalesAgility Ltd http://www.salesagility.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU LESSER GENERAL PUBLIC LICENCE as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENCE
+ * along with this program; if not, see http://www.gnu.org/licenses
+ * or write to the Free Software Foundation,Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @author SalesAgility
+ */
+namespace SuiteCRMAddIn.Exceptions
+{
///
- /// A mechanism for temporarily disabling an action.
+ /// A mechanism for temporarily disabling an action.
///
public class ActionDisabledException : ActionFailedException
{
- public ActionDisabledException() : base("This action is dissabled") { }
+ public ActionDisabledException() : base("This action is dissabled")
+ {
+ }
}
-}
+}
\ No newline at end of file
diff --git a/SuiteCRMAddIn/Exceptions/DuplicateCrmIdException.cs b/SuiteCRMAddIn/Exceptions/DuplicateCrmIdException.cs
index 2c858449..13fd339a 100644
--- a/SuiteCRMAddIn/Exceptions/DuplicateCrmIdException.cs
+++ b/SuiteCRMAddIn/Exceptions/DuplicateCrmIdException.cs
@@ -1,14 +1,35 @@
-using SuiteCRMAddIn.BusinessLogic;
-using SuiteCRMClient;
-using System;
-using System.Runtime.Serialization;
+/**
+ * Outlook integration for SuiteCRM.
+ * @package Outlook integration for SuiteCRM
+ * @copyright SalesAgility Ltd http://www.salesagility.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU LESSER GENERAL PUBLIC LICENCE as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENCE
+ * along with this program; if not, see http://www.gnu.org/licenses
+ * or write to the Free Software Foundation,Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @author SalesAgility
+ */
namespace SuiteCRMAddIn.Exceptions
{
+ using System;
+ using System.Runtime.Serialization;
+ using SuiteCRMAddIn.BusinessLogic;
+
[Serializable]
internal class DuplicateCrmIdException : Exception
{
-
public DuplicateCrmIdException()
{
}
@@ -17,7 +38,8 @@ public DuplicateCrmIdException(string message) : base(message)
{
}
- public DuplicateCrmIdException(SyncState syncState, CrmId id) : base($"Shouldn't happen: more than one Outlook object with CRM id '{id}' ({syncState.Description})")
+ public DuplicateCrmIdException(SyncState syncState, CrmId id) : base(
+ $"Shouldn't happen: more than one Outlook object with CRM id '{id}' ({syncState.Description})")
{
}
diff --git a/SuiteCRMAddIn/Exceptions/InvalidCrmIdException.cs b/SuiteCRMAddIn/Exceptions/InvalidCrmIdException.cs
new file mode 100644
index 00000000..8b526cac
--- /dev/null
+++ b/SuiteCRMAddIn/Exceptions/InvalidCrmIdException.cs
@@ -0,0 +1,52 @@
+/**
+ * Outlook integration for SuiteCRM.
+ * @package Outlook integration for SuiteCRM
+ * @copyright SalesAgility Ltd http://www.salesagility.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU LESSER GENERAL PUBLIC LICENCE as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENCE
+ * along with this program; if not, see http://www.gnu.org/licenses
+ * or write to the Free Software Foundation,Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @author SalesAgility
+ */
+
+using System;
+using System.Runtime.Serialization;
+
+namespace SuiteCRMAddIn.Exceptions
+{
+ ///
+ /// An exception thrown if a supposed CRM id does not meet the expected pattern.
+ ///
+ ///
+ [Serializable]
+ internal class InvalidCrmIdException : Exception
+ {
+ public InvalidCrmIdException()
+ {
+ }
+
+ public InvalidCrmIdException(string message) : base(message)
+ {
+ }
+
+ public InvalidCrmIdException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected InvalidCrmIdException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/SuiteCRMAddIn/Exceptions/ProbableDuplicateItemException.cs b/SuiteCRMAddIn/Exceptions/ProbableDuplicateItemException.cs
index 8813864a..28898b43 100644
--- a/SuiteCRMAddIn/Exceptions/ProbableDuplicateItemException.cs
+++ b/SuiteCRMAddIn/Exceptions/ProbableDuplicateItemException.cs
@@ -1,4 +1,26 @@
-namespace SuiteCRMAddIn.Exceptions
+/**
+ * Outlook integration for SuiteCRM.
+ * @package Outlook integration for SuiteCRM
+ * @copyright SalesAgility Ltd http://www.salesagility.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU LESSER GENERAL PUBLIC LICENCE as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENCE
+ * along with this program; if not, see http://www.gnu.org/licenses
+ * or write to the Free Software Foundation,Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @author SalesAgility
+ */
+namespace SuiteCRMAddIn.Exceptions
{
using System;
using System.Runtime.Serialization;
diff --git a/SuiteCRMAddIn/Exceptions/UnexpectedSyncStateClassException.cs b/SuiteCRMAddIn/Exceptions/UnexpectedSyncStateClassException.cs
index 4306a201..67cc08e4 100644
--- a/SuiteCRMAddIn/Exceptions/UnexpectedSyncStateClassException.cs
+++ b/SuiteCRMAddIn/Exceptions/UnexpectedSyncStateClassException.cs
@@ -1,4 +1,26 @@
-namespace SuiteCRMAddIn.Exceptions
+/**
+ * Outlook integration for SuiteCRM.
+ * @package Outlook integration for SuiteCRM
+ * @copyright SalesAgility Ltd http://www.salesagility.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU LESSER GENERAL PUBLIC LICENCE as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENCE
+ * along with this program; if not, see http://www.gnu.org/licenses
+ * or write to the Free Software Foundation,Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @author SalesAgility
+ */
+namespace SuiteCRMAddIn.Exceptions
{
using BusinessLogic;
using System;
diff --git a/SuiteCRMAddIn/Log4NetLogger.cs b/SuiteCRMAddIn/Log4NetLogger.cs
index 2d57df95..1f64c07f 100644
--- a/SuiteCRMAddIn/Log4NetLogger.cs
+++ b/SuiteCRMAddIn/Log4NetLogger.cs
@@ -147,6 +147,10 @@ public static Log4NetLogger FromFilePath(string area, string filePath, Func
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
diff --git a/SuiteCRMAddIn/SuiteCRMAddIn.csproj b/SuiteCRMAddIn/SuiteCRMAddIn.csproj
index 36758ba9..8b657b57 100644
--- a/SuiteCRMAddIn/SuiteCRMAddIn.csproj
+++ b/SuiteCRMAddIn/SuiteCRMAddIn.csproj
@@ -1,6 +1,6 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
- ="10.0.30319" OR VSTORUNTIMEREDIST_R>="10.0.30319"]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ="10.0.30319" OR VSTORUNTIMEREDIST_R>="10.0.30319"]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SuiteCRMAddInWixSetup/SuiteCRMAddInWixSetup.wixproj b/SuiteCRMAddInWixSetup/SuiteCRMAddInWixSetup.wixproj
index c4ba3297..7ca598f1 100644
--- a/SuiteCRMAddInWixSetup/SuiteCRMAddInWixSetup.wixproj
+++ b/SuiteCRMAddInWixSetup/SuiteCRMAddInWixSetup.wixproj
@@ -1,61 +1,61 @@
-
-
-
- Debug
- x86
- 3.10
- 03906f90-2afd-411d-b1d5-be9a934baf74
- 2.0
- SuiteCRMAddInSetup
- Package
-
-
- bin\$(Configuration)\
- obj\$(Configuration)\
- Debug;AddinFiles=..\SuiteCRMAddIn\bin\$(Configuration)\;ClientFiles=..\SuiteCRMClient\bin\$(Configuration)\
-
-
- bin\$(Configuration)\
- obj\$(Configuration)\
- AddinFiles=..\SuiteCRMAddIn\bin\$(Configuration)\;ClientFiles=..\SuiteCRMClient\bin\$(Configuration)\
-
-
-
-
-
-
- $(WixExtDir)\WixUtilExtension.dll
- WixUtilExtension
-
-
- $(WixExtDir)\WixUIExtension.dll
- WixUIExtension
-
-
- $(WixExtDir)\WixNetFxExtension.dll
- WixNetFxExtension
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ Debug
+ x86
+ 3.10
+ 03906f90-2afd-411d-b1d5-be9a934baf74
+ 2.0
+ SuiteCRMAddIn
+ Package
+
+
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+ Debug;AddinFiles=..\SuiteCRMAddIn\bin\$(Configuration)\;ClientFiles=..\SuiteCRMClient\bin\$(Configuration)\
+
+
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+ AddinFiles=..\SuiteCRMAddIn\bin\$(Configuration)\;ClientFiles=..\SuiteCRMClient\bin\$(Configuration)\
+
+
+
+
+
+
+ $(WixExtDir)\WixUtilExtension.dll
+ WixUtilExtension
+
+
+ $(WixExtDir)\WixUIExtension.dll
+ WixUIExtension
+
+
+ $(WixExtDir)\WixNetFxExtension.dll
+ WixNetFxExtension
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SuiteCRMClient/LDAPAuthenticationHelper.cs b/SuiteCRMClient/LDAPAuthenticationHelper.cs
index 3569e788..2cc1bd19 100644
--- a/SuiteCRMClient/LDAPAuthenticationHelper.cs
+++ b/SuiteCRMClient/LDAPAuthenticationHelper.cs
@@ -82,8 +82,13 @@ public string Authenticate()
user_auth = new
{
user_name = username,
- password = EncryptPassword(this.password,
- ConstructEncryptionAlgorithm(this.key, this.initialisationVector)),
+ password = string.IsNullOrWhiteSpace(this.key) ?
+ this.password:
+ EncryptPassword(this.password,
+ ConstructEncryptionAlgorithm(this.key, this.initialisationVector)),
+ encryption = string.IsNullOrWhiteSpace(this.key) ?
+ "PLAIN" :
+ Boolean.TrueString,
application_name = this.applicationName
}
};
diff --git a/SuiteCRMClient/Properties/AssemblyInfo.cs b/SuiteCRMClient/Properties/AssemblyInfo.cs
index 79e0dfab..5277ca48 100644
--- a/SuiteCRMClient/Properties/AssemblyInfo.cs
+++ b/SuiteCRMClient/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("3.0.16.5")]
+[assembly: AssemblyVersion("3.0.16.51")]
[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/SuiteCRMClient/Properties/Settings.Designer.cs b/SuiteCRMClient/Properties/Settings.Designer.cs
index 88d12622..10419db3 100644
--- a/SuiteCRMClient/Properties/Settings.Designer.cs
+++ b/SuiteCRMClient/Properties/Settings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.18449
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,7 +12,7 @@ namespace SuiteCRMClient.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
diff --git a/SuiteCRMClient/SuiteCRMClient.csproj b/SuiteCRMClient/SuiteCRMClient.csproj
index 50513dff..2525ef76 100644
--- a/SuiteCRMClient/SuiteCRMClient.csproj
+++ b/SuiteCRMClient/SuiteCRMClient.csproj
@@ -1,5 +1,5 @@
-
+
Debug
@@ -9,10 +9,11 @@
Properties
SuiteCRMClient
SuiteCRMClient
- v4.5
+ v4.6.1
512
..\
true
+
true
@@ -42,8 +43,8 @@
..\packages\log4net.2.0.8\lib\net45-full\log4net.dll
True
-
- ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
+
+ ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll
True
diff --git a/SuiteCRMClient/app.config b/SuiteCRMClient/app.config
index 2bb9d1de..ea010057 100644
--- a/SuiteCRMClient/app.config
+++ b/SuiteCRMClient/app.config
@@ -1,24 +1,22 @@
-
+
-
-
+
+
-
+
http://localhost:8080/SuiteCRM/service/v2/soap.php
-
+
http://localhost:8080/SuiteCRM/service/v4_1/soap.php
-
-
+
+
-
\ No newline at end of file
+
diff --git a/SuiteCRMClient/packages.config b/SuiteCRMClient/packages.config
index 2404ab11..1bacc8cf 100644
--- a/SuiteCRMClient/packages.config
+++ b/SuiteCRMClient/packages.config
@@ -1,6 +1,6 @@
-
-
+
+
\ No newline at end of file