730 lines
31 KiB
C#
730 lines
31 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using GZTW.AyaNova.BLL;
|
|
using Outlook = Microsoft.Office.Interop.Outlook;
|
|
using Office = Microsoft.Office.Core;
|
|
using System.Reflection;
|
|
using System.ComponentModel;
|
|
using System.Security.Cryptography;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Forms;
|
|
|
|
namespace AyaNovaOL
|
|
{
|
|
class ImportSchedule
|
|
{
|
|
#region Globals
|
|
private Outlook.Application moutApp = null;
|
|
//Holds the current logged in user's localized text
|
|
//lookup object
|
|
private LocalizedTextTable mLocaleText = null;
|
|
public ImportSchedule(Outlook.Application outapp, LocalizedTextTable localeText)
|
|
{
|
|
moutApp = outapp;
|
|
mLocaleText = localeText;
|
|
}
|
|
|
|
public LocalizedTextTable LocaleText
|
|
{
|
|
get
|
|
{
|
|
return mLocaleText;
|
|
}
|
|
}
|
|
#endregion globals
|
|
|
|
#region Outlook api globals and util methods
|
|
|
|
#region Outlook application object
|
|
|
|
public Outlook.Application outApp
|
|
{
|
|
get
|
|
{
|
|
|
|
return moutApp;
|
|
}
|
|
|
|
}
|
|
#endregion outlook app object
|
|
|
|
#region AyaNova calendar folder
|
|
Outlook.MAPIFolder mAyaCalendar = null;
|
|
/// <summary>
|
|
/// Get the AyaNova calendar
|
|
/// create it if required
|
|
/// </summary>
|
|
public Outlook.MAPIFolder AyaCalendar
|
|
{
|
|
get
|
|
{
|
|
if (mAyaCalendar == null)
|
|
{
|
|
if (bdiag) d("Check for existing AyaNovaSchedule calendar...");
|
|
//see if there is one already, if not create it
|
|
mAyaCalendar = GetFolder(Outlook.OlDefaultFolders.olFolderCalendar, "AyaNovaSchedule");
|
|
if (mAyaCalendar == null)
|
|
{
|
|
if (bdiag) d("Calendar AyaNovaSchedule not found in Outlook. Creating it...");
|
|
//get required objects to do the op
|
|
Outlook.NameSpace ns = outApp.GetNamespace("MAPI");
|
|
Outlook.MAPIFolder fldDefault = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
|
|
Outlook.Folders fldDefaultFolders = fldDefault.Folders;
|
|
|
|
//create it
|
|
mAyaCalendar = fldDefaultFolders.Add("AyaNovaSchedule", Outlook.OlDefaultFolders.olFolderCalendar);
|
|
mAyaCalendar.Description = "AyaNova OLI exported items";
|
|
|
|
//release required objects
|
|
Marshal.ReleaseComObject(fldDefaultFolders);
|
|
fldDefaultFolders = null;
|
|
Marshal.ReleaseComObject(fldDefault);
|
|
fldDefault = null;
|
|
Marshal.ReleaseComObject(ns);
|
|
ns = null;
|
|
}
|
|
}
|
|
return mAyaCalendar;
|
|
}
|
|
}
|
|
#endregion ayanova calendar folder
|
|
|
|
#region Remove AyaNova generated appointment from Outlook
|
|
public void RemoveOutlookAppointment(TypeAndID tid)
|
|
{
|
|
// d("Remove outlook appointment top...");
|
|
Outlook.AppointmentItem oaiToDelete = null;
|
|
Outlook.Items ayCalItems = AyaCalendar.Items;
|
|
bool bFoundIt = false;
|
|
for (int x = 0; x < ayCalItems.Count; x++)
|
|
{
|
|
//d("fetching outlook appointment for comparison...");
|
|
Outlook.AppointmentItem oai = (Outlook.AppointmentItem)ayCalItems[x + 1];
|
|
//d("examining outlook appointment user properties...");
|
|
Outlook.UserProperties props = null;
|
|
if (oai.UserProperties != null)
|
|
props = oai.UserProperties;
|
|
if (props != null && props.Count > 0)
|
|
{
|
|
Outlook.UserProperty prop = props["AyaNovaTypeAndID"];
|
|
if (prop != null)
|
|
{
|
|
//d("prop.value to string:" + prop.Value.ToString());
|
|
//d("Tid to string:" + tid.ToString());//bugbug tid is null here
|
|
if (prop.Value.ToString() == tid.ToString())
|
|
{
|
|
//d("Have a match!");
|
|
oaiToDelete = oai;
|
|
bFoundIt = true;
|
|
}
|
|
Marshal.ReleaseComObject(prop); prop = null;
|
|
}
|
|
Marshal.ReleaseComObject(props); props = null;
|
|
}
|
|
|
|
//d("Found? - " + bFoundIt.ToString());
|
|
if (bFoundIt)
|
|
break;
|
|
else
|
|
Marshal.ReleaseComObject(oai); oai = null;
|
|
}
|
|
Marshal.ReleaseComObject(ayCalItems); ayCalItems = null;
|
|
//d("Finished in loop");
|
|
//Remove from Outlook
|
|
if (oaiToDelete != null)
|
|
{
|
|
//d("Deleteing outlook appointment " + oaiToDelete.Subject + " ...");
|
|
oaiToDelete.Delete();
|
|
if (oaiToDelete != null)
|
|
{
|
|
Marshal.ReleaseComObject(oaiToDelete); oaiToDelete = null;
|
|
}
|
|
}
|
|
else
|
|
throw new System.ApplicationException("Outlook schedule plugin: Error RemoveOutlookAppointment: appointment matching [" + tid.ToString() + "] not found in Outlook");
|
|
|
|
//d("Remove outlook appointment bottom.");
|
|
}
|
|
#endregion
|
|
|
|
#region Insert Shadow appointment into Outlook
|
|
public void InsertShadowAppointment(ShadowAppointment sa)
|
|
{
|
|
Outlook.Items ayCalItems = AyaCalendar.Items;
|
|
Outlook.AppointmentItem oa = (Outlook.AppointmentItem)ayCalItems.Add(Outlook.OlItemType.olAppointmentItem);
|
|
Outlook.UserProperties props = oa.UserProperties;
|
|
Outlook.UserProperty prop = props.Add("AyaNovaTypeAndID", Microsoft.Office.Interop.Outlook.OlUserPropertyType.olText, false, null);
|
|
prop.Value = sa.AyaNovaTypeAndID.ToString();
|
|
oa.Subject = sa.Subject;
|
|
oa.Location = sa.Location;
|
|
oa.Start = sa.Start;
|
|
oa.End = sa.End;
|
|
oa.Body = sa.BodyText;
|
|
if (sa.ShowTimeAsBusy)
|
|
oa.BusyStatus = Microsoft.Office.Interop.Outlook.OlBusyStatus.olBusy;
|
|
else
|
|
oa.BusyStatus = Microsoft.Office.Interop.Outlook.OlBusyStatus.olTentative;
|
|
oa.ReminderSet = false;
|
|
oa.Save();
|
|
Marshal.ReleaseComObject(prop); prop = null;
|
|
Marshal.ReleaseComObject(props); props = null;
|
|
Marshal.ReleaseComObject(oa); oa = null;
|
|
Marshal.ReleaseComObject(ayCalItems); ayCalItems = null;
|
|
}
|
|
#endregion insert shadow appt.
|
|
|
|
#region Localized text stuff
|
|
string mSchedUserLocalizedText = null;
|
|
string mSchedMarkerLocalizedText = null;
|
|
public string SchedMarkerLocalizedText
|
|
{
|
|
get
|
|
{
|
|
if (mSchedMarkerLocalizedText == null)
|
|
mSchedMarkerLocalizedText = LocaleText.GetLocalizedText("O.ScheduleMarker");
|
|
return mSchedMarkerLocalizedText;
|
|
}
|
|
}
|
|
|
|
public string SchedUserLocalizedText
|
|
{
|
|
get
|
|
{
|
|
if (mSchedUserLocalizedText == null)
|
|
mSchedUserLocalizedText = LocaleText.GetLocalizedText("O.WorkorderItemScheduledUser");
|
|
return mSchedUserLocalizedText;
|
|
}
|
|
}
|
|
#endregion LocalizedTextstuff
|
|
|
|
#region Client contact cache
|
|
Dictionary<Guid, string> clientInfoCache = null;
|
|
/// <summary>
|
|
/// Get client info
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <returns></returns>
|
|
public string GetClientInfoDisplay(Guid id)
|
|
{
|
|
//check in cache first
|
|
if (clientInfoCache == null)
|
|
clientInfoCache = new Dictionary<Guid, string>();
|
|
|
|
if (!clientInfoCache.ContainsKey(id))
|
|
{
|
|
//retrieve the client record
|
|
Client c = Client.GetItemNoMRU(id);
|
|
StringBuilder b = new StringBuilder();
|
|
b.Append(c.Name);
|
|
b.Append("\r\n");
|
|
b.Append(c.GoToAddress.FullAddress);
|
|
b.Append("\r\n");
|
|
b.Append(c.GetPrimaryContactDefaultContactInfo());
|
|
//if (c.TechNotes != "")
|
|
//{
|
|
// b.Append(LocaleText.GetLocalizedText("Client.Label.TechNotes"));
|
|
// b.Append(":\r\n");
|
|
// b.Append(c.TechNotes);
|
|
//}
|
|
clientInfoCache.Add(id, b.ToString());
|
|
}
|
|
return clientInfoCache[id];
|
|
}
|
|
#endregion client contact cache
|
|
|
|
#region utils
|
|
|
|
#region ShadowAppointmentStuff
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="i"></param>
|
|
/// <returns></returns>
|
|
public ShadowAppointment GetShadowAppointment(AppointmentList.AppointmentListInfo i)
|
|
{
|
|
ShadowAppointment a = new ShadowAppointment();
|
|
if (i.SourceObjectType == RootObjectTypes.ScheduleMarker)
|
|
{
|
|
ScheduleMarker sm = ScheduleMarker.GetItem(i.SourceObjectID);
|
|
a.Subject = sm.Name;
|
|
a.Location = SchedMarkerLocalizedText;
|
|
a.Start = i.StartDateTime;
|
|
a.End = i.EndDateTime;
|
|
a.ShowTimeAsBusy = false;
|
|
string sFollowUpText = "";
|
|
if (sm.FollowID != Guid.Empty)
|
|
sFollowUpText = NameFetcher.GetItem(new TypeAndID(sm.FollowType, sm.FollowID)).RecordName + "\r\n";
|
|
a.BodyText = sFollowUpText + sm.Notes;
|
|
a.AyaNovaTypeAndID = new TypeAndID(RootObjectTypes.ScheduleMarker, i.SourceObjectID);
|
|
|
|
}
|
|
else//workorderitemscheduleuser
|
|
{
|
|
WorkorderServiceList.WorkorderServiceListInfo woinfo = WorkorderServiceList.GetListForSingleItem(i.WorkorderID)[0];
|
|
|
|
a.Subject = i.ServiceNumber.ToString() + " " + woinfo.LT_O_Client.Display;
|
|
a.Location = SchedUserLocalizedText;
|
|
a.Start = i.StartDateTime;
|
|
a.End = i.EndDateTime;
|
|
a.ShowTimeAsBusy = true;
|
|
a.BodyText = i.Subject + "\r\n------------------------------------\r\n" + GetClientInfoDisplay(woinfo.LT_O_Client.Value);
|
|
a.AyaNovaTypeAndID = new TypeAndID(i.SourceObjectType, i.SourceObjectID);
|
|
}
|
|
|
|
System.Text.StringBuilder sb = new StringBuilder();
|
|
sb.Append(a.Subject);
|
|
sb.Append(a.Location);
|
|
sb.Append(a.Start.ToString("yyyyMMddHHmm"));
|
|
sb.Append(a.End.ToString("yyyyMMddHHmm"));
|
|
sb.Append(a.BodyText);
|
|
a.CheckSum = GetHash(sb.ToString());
|
|
|
|
//if (i.SourceObjectType == RootObjectTypes.ScheduleMarker)
|
|
// d("Shadow appt. checksum:" + a.CheckSum + "\r\nData was:\r\n" + sb.ToString());
|
|
return a;
|
|
}
|
|
|
|
#endregion shadowappointmentstuff
|
|
|
|
#region Outlook folder stuff
|
|
/// <summary>
|
|
/// Iterates all folders of type specified and returns the one with the name specified
|
|
/// Caller MUST release folder returned
|
|
/// </summary>
|
|
/// <param name="sNameContains"></param>
|
|
/// <returns></returns>
|
|
public Outlook.MAPIFolder GetFolder(Outlook.OlDefaultFolders folderType, string sNameContains)
|
|
{
|
|
//d("Top of GetFolder...");
|
|
//get required objects to do the op
|
|
Outlook.NameSpace ns = outApp.GetNamespace("MAPI");
|
|
Outlook.MAPIFolder f = GetCalendar(ns.GetDefaultFolder(folderType), sNameContains);
|
|
// d("Got folder, releasing objects...");
|
|
if (ns != null)
|
|
{
|
|
Marshal.ReleaseComObject(ns);
|
|
ns = null;
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recursive method to iterate folders and return one that contains the name specified
|
|
/// </summary>
|
|
/// <param name="mf"></param>
|
|
/// <param name="sNameContains"></param>
|
|
/// <returns></returns>
|
|
public Outlook.MAPIFolder GetCalendar(Outlook.MAPIFolder mf, string sNameContains)
|
|
{
|
|
//d("Top of GetCalendar " + mf.FolderPath + ", " + sNameContains);
|
|
if (mf.FolderPath.Contains(sNameContains))
|
|
{
|
|
//d("GetCalendar: Found it, returning.");
|
|
return mf;
|
|
}
|
|
Outlook.Folders fldrs = mf.Folders;
|
|
for (int x = 0; x < fldrs.Count; x++)
|
|
{
|
|
//d("GetCalendar: Checking calendar " + x.ToString() + " of " + mf.Folders.Count.ToString());
|
|
Outlook.MAPIFolder f = mf.Folders[x + 1];
|
|
if (GetCalendar(f, sNameContains) != null)
|
|
{
|
|
Marshal.ReleaseComObject(fldrs); fldrs = null;
|
|
return f;
|
|
}
|
|
else
|
|
{
|
|
Marshal.ReleaseComObject(f); f = null;
|
|
}
|
|
}
|
|
//d("GetCalendar: Not here, returning.");
|
|
Marshal.ReleaseComObject(fldrs); fldrs = null;
|
|
return null;
|
|
}
|
|
#endregion Outlook folder stuff
|
|
|
|
#region Checksum stuff
|
|
private aptOut GetOutlookAppointmentChecksum(Outlook.AppointmentItem oai)
|
|
{
|
|
//d("top of GetOutlookAppointmentChecksum(" + oai.Subject + ")");
|
|
aptOut a;
|
|
a.CheckSum = "";
|
|
a.AyaNovaTypeAndID = new TypeAndID(RootObjectTypes.Nothing, Guid.Empty);
|
|
if (oai == null) return a;
|
|
if (string.IsNullOrEmpty(oai.EntryID)) return a;
|
|
Outlook.UserProperties props = oai.UserProperties;
|
|
Outlook.UserProperty prop = props["AyaNovaTypeAndID"];
|
|
a.AyaNovaTypeAndID = TypeAndID.Parse(prop.Value.ToString());
|
|
Marshal.ReleaseComObject(prop); prop = null;
|
|
Marshal.ReleaseComObject(props); props = null;
|
|
System.Text.StringBuilder sb = new StringBuilder();
|
|
sb.Append(oai.Subject);
|
|
sb.Append(oai.Location);
|
|
sb.Append(oai.Start.ToString("yyyyMMddHHmm"));
|
|
sb.Append(oai.End.ToString("yyyyMMddHHmm"));
|
|
sb.Append(oai.Body);
|
|
a.CheckSum = GetHash(sb.ToString());
|
|
//if(a.CheckSum.StartsWith("92C"))
|
|
// d("Outlook appt. checksum:"+a.CheckSum+"\r\nData was:\r\n" + sb.ToString());
|
|
return a;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Get a reliable hash value
|
|
/// </summary>
|
|
/// <param name="s"></param>
|
|
/// <returns></returns>
|
|
private string GetHash(string s)
|
|
{
|
|
//TODO: FIPS
|
|
SHA256 shaM = new SHA256Managed();
|
|
UTF8Encoding enc = new UTF8Encoding();
|
|
return BitConverter.ToString(shaM.ComputeHash(enc.GetBytes(s))).Replace("-", "");
|
|
}
|
|
|
|
#endregion checksum stuff
|
|
|
|
#endregion utils
|
|
|
|
#endregion outlook api globals and util methods
|
|
|
|
#region Diagnostic messages
|
|
/// <summary>
|
|
/// Diagnostics messages
|
|
/// </summary>
|
|
/// <param name="s"></param>
|
|
private void d(string s)
|
|
{
|
|
if (bdiag)
|
|
MessageBox.Show(s);
|
|
}
|
|
|
|
private bool bdiag = false;
|
|
#endregion diags
|
|
|
|
#region DoImport
|
|
/// <summary>
|
|
/// Do the import
|
|
/// </summary>
|
|
public void Import(bool DiagnosticMode)
|
|
{
|
|
bdiag = DiagnosticMode;
|
|
|
|
DateTime dtStarted = DateTime.Now.AddMinutes(-1);
|
|
if (bdiag) d("Starting export of items between " + dtStarted.ToString() + " and " + dtStarted.AddYears(1) + "...");
|
|
List<aptOut> lsaptOut = new List<aptOut>();
|
|
List<ShadowAppointment> lsShadowApt = new List<ShadowAppointment>();
|
|
AppointmentList apl = null;
|
|
|
|
try
|
|
{
|
|
|
|
#region Build checksum list of appointments in Outlook
|
|
if (bdiag) d("Inspecting existing AyaNovaSchedule items in Outlook ...");
|
|
Outlook.Items ayCalItems = AyaCalendar.Items;
|
|
// d("Raw AyaCalendar.Items.Count=" + ayCalItems.Count);
|
|
for (int x = 0; x < ayCalItems.Count; x++)
|
|
{
|
|
//d("Fetching existing item " + x.ToString()+" ...");
|
|
Outlook.AppointmentItem oai = (Outlook.AppointmentItem)ayCalItems[x + 1];
|
|
if (oai.Start > dtStarted || oai.End > dtStarted)//appointments that start after now or end after now
|
|
{
|
|
Outlook.UserProperties props = oai.UserProperties;
|
|
if (props != null && props.Count > 0)
|
|
{
|
|
Outlook.UserProperty prop = props["AyaNovaTypeAndID"];
|
|
if (prop != null)
|
|
{
|
|
lsaptOut.Add(GetOutlookAppointmentChecksum(oai));
|
|
|
|
Marshal.ReleaseComObject(prop); prop = null;
|
|
}
|
|
Marshal.ReleaseComObject(props); props = null;
|
|
}
|
|
}
|
|
Marshal.ReleaseComObject(oai); oai = null;
|
|
}
|
|
Marshal.ReleaseComObject(ayCalItems); ayCalItems = null;
|
|
|
|
if (bdiag) d(lsaptOut.Count.ToString() + " existing relevant AyaNovaSchedule Outlook calendar items found in Outlook.");
|
|
#endregion build checksum list
|
|
|
|
#region Build shadow appointment list
|
|
if (bdiag) d("Fetching any existing open AyaNova schedule items in the next year for current logged in user...");
|
|
apl = AppointmentList.GetList(dtStarted, dtStarted.AddYears(1), User.CurrentThreadUserID);
|
|
UserListScheduleable uls = UserListScheduleable.GetList();
|
|
foreach (AppointmentList.AppointmentListInfo i in apl)
|
|
{
|
|
switch (i.SourceObjectType)
|
|
{
|
|
case RootObjectTypes.WorkorderItemScheduledUser:
|
|
{
|
|
lsShadowApt.Add(GetShadowAppointment(i));
|
|
}
|
|
break;
|
|
case RootObjectTypes.ScheduleMarker:
|
|
{
|
|
#region schedmarkers
|
|
|
|
////Could be a bunch by region , global , dispatchzone, schedusergroup
|
|
////or could be a single by one user ID
|
|
switch (i.AppliesToObjectType)
|
|
{
|
|
case RootObjectTypes.User:
|
|
if (i.AppliesToObjectID == User.CurrentThreadUserID)
|
|
lsShadowApt.Add(GetShadowAppointment(i));
|
|
break;
|
|
case RootObjectTypes.Region:
|
|
{
|
|
//Loop through all active scheduleable users
|
|
//if the region ID matches the marker region ID then
|
|
//add a marker on the calendar for it
|
|
foreach (UserListScheduleable.UserListScheduleableInfo ui in uls)
|
|
{
|
|
if (ui.ID == User.CurrentThreadUserID)
|
|
{
|
|
//case 58
|
|
if (i.AppliesToObjectID == GZTW.AyaNova.BLL.Region.DefaultRegionID)//SM is for default region? Then applies to everyone
|
|
lsShadowApt.Add(GetShadowAppointment(i));
|
|
else if (ui.RegionID == GZTW.AyaNova.BLL.Region.DefaultRegionID)//User is in default region? Then applies to them
|
|
lsShadowApt.Add(GetShadowAppointment(i));
|
|
else if (ui.RegionID == i.AppliesToObjectID)//SM and User in same non default region
|
|
lsShadowApt.Add(GetShadowAppointment(i));
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RootObjectTypes.DispatchZone:
|
|
{
|
|
//Loop through all active scheduleable users
|
|
//if the Dispatch zone ID matches the marker zone ID then
|
|
//add a marker on the calendar for it
|
|
foreach (UserListScheduleable.UserListScheduleableInfo ui in uls)
|
|
if (ui.ID == User.CurrentThreadUserID)
|
|
{
|
|
if (ui.DispatchZoneID == i.AppliesToObjectID)
|
|
lsShadowApt.Add(GetShadowAppointment(i));
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case RootObjectTypes.ScheduleableUserGroup:
|
|
{
|
|
ScheduleableUserGroupUsersList ScheduleMarkerGroup = ScheduleableUserGroupUsersList.GetList(i.AppliesToObjectID);
|
|
//Loop through all active scheduleable users
|
|
//if they are in the ScheduleableUserGroup then
|
|
//add a marker on the calendar for it
|
|
foreach (UserListScheduleable.UserListScheduleableInfo ui in uls)
|
|
if (ui.ID == User.CurrentThreadUserID)
|
|
{
|
|
if (ScheduleMarkerGroup.Contains(ui.ID))
|
|
lsShadowApt.Add(GetShadowAppointment(i));
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RootObjectTypes.Global:
|
|
{
|
|
lsShadowApt.Add(GetShadowAppointment(i));
|
|
|
|
}
|
|
break;
|
|
}
|
|
#endregion schedmarkers
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
if (bdiag) d(lsShadowApt.Count.ToString() + " existing AyaNova schedule items found in AyaNova.");
|
|
#endregion build shadow appointment list
|
|
|
|
//Do Export:
|
|
|
|
#region step 1 remove stale outlook appointments
|
|
if (bdiag) d("Removing existing AyaNovaSchedule Outlook calendar items that are changed since last export ...");
|
|
//iterate outlook appointments list, for each AyaNova generated one
|
|
//that has no matching checksum in shadow, delete it from outlook then from outlist
|
|
int nlsaptOutCount = lsaptOut.Count;
|
|
int nTotalStaleCount = 0;
|
|
|
|
#region mismatch Diagnostics stuff
|
|
if (bdiag)
|
|
{
|
|
System.Text.StringBuilder sbdiag = new StringBuilder();
|
|
sbdiag.Append("Shadowlist:\r\n");
|
|
foreach (ShadowAppointment sa in lsShadowApt)
|
|
{
|
|
sbdiag.Append(sa.Subject);
|
|
sbdiag.Append(" ck:");
|
|
sbdiag.Append(sa.CheckSum);
|
|
sbdiag.Append("\r\n");
|
|
}
|
|
d(sbdiag.ToString());
|
|
|
|
sbdiag.Length = 0;
|
|
sbdiag.Append("Outlist:\r\n");
|
|
foreach (aptOut sa in lsaptOut)
|
|
{
|
|
sbdiag.Append(sa.AyaNovaTypeAndID.ToString());
|
|
sbdiag.Append(" ck:");
|
|
sbdiag.Append(sa.CheckSum);
|
|
sbdiag.Append("\r\n");
|
|
}
|
|
d(sbdiag.ToString());
|
|
}
|
|
#endregion mismatch diags
|
|
|
|
//iterate the outlook appointments list
|
|
for (int x = 0; x < nlsaptOutCount; x++)
|
|
{
|
|
//d("x=" + x.ToString() + ", nlsaptOutCount=" + nlsaptOutCount.ToString() + ", lsaptOut.Count=" + lsaptOut.Count.ToString() + ", lsShadowApt.count=" + lsShadowApt.Count.ToString());
|
|
bool bExists = false;
|
|
|
|
//if outlook appointment checksum not in shadow list delete it
|
|
aptOut ThisapOut = lsaptOut[x];
|
|
foreach (ShadowAppointment sa in lsShadowApt)
|
|
{
|
|
|
|
//System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(sa.CheckSum));
|
|
//d("Comparing outlook checksum:\r\n " + ThisapOut.CheckSum + "\r\nTo shadow checksum:\r\n" + sa.CheckSum);
|
|
if (sa.CheckSum == ThisapOut.CheckSum)
|
|
{
|
|
//d("Identical match: " + sa.CheckSum);
|
|
bExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!bExists)
|
|
{
|
|
//d("Unmatched outlook checksum:\r\n " + ThisapOut.CheckSum );
|
|
//remove from outlook
|
|
RemoveOutlookAppointment(ThisapOut.AyaNovaTypeAndID);
|
|
//remove from the working list
|
|
lsaptOut.RemoveAt(x);
|
|
x--;
|
|
nlsaptOutCount--;
|
|
nTotalStaleCount++;
|
|
}
|
|
}
|
|
|
|
if (bdiag) d(nTotalStaleCount.ToString() + " stale items removed from Outlook.");
|
|
#endregion step 1
|
|
|
|
#region Step 2 Remove unchanged appointments from shadow appointment list
|
|
if (bdiag) d("Identifying AyaNova items that already exist identically in Outlook and do not need to be exported...");
|
|
//Iterate through shadow appointments, for each one that has matching checksum in outlook apts remove it from shadow list
|
|
int nShadowListCount = lsShadowApt.Count;
|
|
int nTotalUnchangedShadowItems = 0;
|
|
for (int x = 0; x < nShadowListCount; x++)
|
|
{
|
|
bool bExists = false;
|
|
ShadowAppointment sa = lsShadowApt[x];
|
|
foreach (aptOut ao in lsaptOut)
|
|
{
|
|
if (ao.CheckSum == sa.CheckSum)
|
|
{
|
|
bExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bExists)
|
|
{
|
|
//remove from shadowlist
|
|
lsShadowApt.RemoveAt(x);
|
|
x--;
|
|
nShadowListCount--;
|
|
nTotalUnchangedShadowItems++;
|
|
}
|
|
}
|
|
if (bdiag) d(nTotalUnchangedShadowItems.ToString() + " items in AyaNova already exist unchanged in Outlook and won't be exported.");
|
|
#endregion Step 2
|
|
|
|
#region Step 3 Insert remaining shadow appointments in Outlook
|
|
if (bdiag)
|
|
{
|
|
if (lsShadowApt.Count > 0)
|
|
d("Exporting " + lsShadowApt.Count.ToString() + " new / updated AyaNova schedule items to Outlook...");
|
|
else
|
|
d("No items found to export to Outlook.");
|
|
}
|
|
foreach (ShadowAppointment sa in lsShadowApt)
|
|
{
|
|
InsertShadowAppointment(sa);
|
|
}
|
|
|
|
#endregion step 3
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
throw (ex);
|
|
}
|
|
finally
|
|
{
|
|
|
|
#region Step 4 release objects
|
|
if (bdiag) d("Releasing calendar object...");
|
|
if (mAyaCalendar != null)
|
|
{
|
|
Marshal.ReleaseComObject(mAyaCalendar); mAyaCalendar = null;
|
|
}
|
|
//if (bdiag) d("Releasing app object...");
|
|
//if (moutApp != null)
|
|
//{
|
|
// Marshal.ReleaseComObject(moutApp); moutApp = null;
|
|
//}
|
|
|
|
//clear the client cache
|
|
if (clientInfoCache != null)
|
|
{
|
|
if (bdiag) d("Clearing client cache...");
|
|
clientInfoCache.Clear();
|
|
clientInfoCache = null;
|
|
}
|
|
if (bdiag) d("All done!");
|
|
#endregion step 4
|
|
}
|
|
}
|
|
#endregion doimport
|
|
|
|
#region Appointment and comparison structs
|
|
public struct aptOut
|
|
{
|
|
public TypeAndID AyaNovaTypeAndID;
|
|
public string CheckSum;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// contains all the data that will go into an Outlook appointment
|
|
/// </summary>
|
|
public struct ShadowAppointment
|
|
{
|
|
public string Subject;
|
|
public string Location;
|
|
public DateTime Start;
|
|
public DateTime End;
|
|
public bool ShowTimeAsBusy;
|
|
public string BodyText;
|
|
public TypeAndID AyaNovaTypeAndID;
|
|
public string CheckSum;
|
|
|
|
}
|
|
#endregion appt comparison structs
|
|
|
|
}//end of class
|
|
|
|
|
|
|
|
}
|