diff --git a/AyaNovaQBI/util.cs b/AyaNovaQBI/util.cs index 74903e3..45f32d7 100644 --- a/AyaNovaQBI/util.cs +++ b/AyaNovaQBI/util.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json.Linq; using Interop.QBFC15; using System.Text.RegularExpressions; using System.Windows.Forms; +using System.Data; namespace AyaNovaQBI { @@ -891,6 +892,1528 @@ namespace AyaNovaQBI #endregion qb specific utils + #region QB API helper methods/ attributes/cached lists + /// + /// Populate or repopulate the list of + /// + public static void PopulateQBListCache() + { + //Get the cached QB data + Waiting w = new Waiting(); + w.Show(); + w.Ops = "Reading from QuickBooks..."; + + + + w.Step = "Classes"; + PopulateQBClassCache(); + + w.Step = "Vendors"; + PopulateQBVendorCache(); + + w.Step = "Customers"; + PopulateQBClientCache(); + + w.Step = "Items"; + PopulateQBItemCache(); + + if (!(QVersion < 3))//qbXML 3.0 or higher (QB 2004 any country or newer) + { + w.Step = "Invoice templates"; + PopulateQBInvoiceTemplates(); + } + + //case 632 + w.Step = "Accounts"; + PopulateQBAccountCache(); + + //case 519 + w.Step = "Terms"; + PopulateQBTermsCache(); + + w.Close(); + } + + #region QuickBooks "items" + public enum qbitemtype + { + Inventory, + NonInventory, + Service, + OtherCharge, + Assembly + + } + + private static DataTable _dtQBItems = null; + + /// + /// qb items + /// + public static DataTable QBItems + { + get + { + return _dtQBItems; + } + } + + + /// + /// Given a QB Item ID, return the + /// AyaNova Vendor ID linked to that items + /// QB preferred Vendor ID or + /// Guid empty on any problem or not found + /// + /// + /// + public static Guid AyaVendorForQBItem(string QBItemID) + { + if (QBItemID == null || QBItemID == "") return Guid.Empty; + DataRow dr = _dtQBItems.Rows.Find(QBItemID); + if (dr == null || dr["VendorID"] == null || dr["VendorID"].ToString() == "") return Guid.Empty; + + DataRow drVendor = _dtQBVendors.Rows.Find(dr["VendorID"].ToString()); + if (drVendor == null) return Guid.Empty; + + if (!QBI.Maps.Contains(drVendor["ID"].ToString(), RootObjectTypes.Vendor)) return Guid.Empty; + + //Ok we have a matching vendor in the list, return the guid of it + return QBI.Maps[drVendor["ID"].ToString(), RootObjectTypes.Vendor].RootObjectID; + } + + + /// + /// Populate the cached qb data + /// billable + /// + private static void PopulateQBItemCache() + { + if (_dtQBItems == null) + { + _dtQBItems = new DataTable("QBItems"); + //setup the columns + _dtQBItems.Columns.Add("ID", typeof(string)); + _dtQBItems.Columns.Add("FullName", typeof(string)); + _dtQBItems.Columns.Add("Type", typeof(qbitemtype)); + _dtQBItems.Columns.Add("Modified", typeof(DateTime)); + _dtQBItems.Columns.Add("Price", typeof(decimal)); + + _dtQBItems.Columns.Add("Cost", typeof(decimal)); + _dtQBItems.Columns.Add("SalesDesc", typeof(string)); + _dtQBItems.Columns.Add("ReorderPoint", typeof(decimal)); + _dtQBItems.Columns.Add("VendorID", typeof(string)); + + + + _dtQBItems.PrimaryKey = new DataColumn[] { _dtQBItems.Columns[0] }; + + //Case 237 + _dtQBItems.DefaultView.Sort = "FullName asc"; + } + else + _dtQBItems.Clear(); + + //Connect to QB and fill + // IY: Create the session manager object using QBFC + QBSessionManager sessionManager = new QBSessionManager(); + + // IY: We want to know if we begun a session so we can end it if an + // error happens + bool booSessionBegun = false; + + try + { + // IY: Get the RequestMsgSet based on the correct QB Version + IMsgSetRequest requestSet = getLatestMsgSetRequest(sessionManager); + + // IY: Initialize the message set request object + requestSet.Attributes.OnError = ENRqOnError.roeStop; + + // IY: Add the request to the message set request object + IItemQuery ItemQ = requestSet.AppendItemQueryRq(); + + //Active items only + ItemQ.ORListQuery.ListFilter.ActiveStatus.SetValue(ENActiveStatus.asActiveOnly); + + + //This is intended to be called after already sucessfully connected + //to get version info so no special safety checks here + sessionManager.OpenConnection2("", "AyaNova QBI", ENConnectionType.ctLocalQBDLaunchUI); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + booSessionBegun = true; + + // IY: Do the request and get the response message set object + IMsgSetResponse responseSet = sessionManager.DoRequests(requestSet); + + // Uncomment the following to view and save the request and response XML + //string requestXML = requestSet.ToXMLString(); + //MessageBox.Show(requestXML); + // SaveXML(requestXML); + //string responseXML = responseSet.ToXMLString(); + //MessageBox.Show(responseXML); + // SaveXML(responseXML); + + IResponse response = responseSet.ResponseList.GetAt(0); + + //Added: 21-June-2006 nonzero status codes 500 and higher are serious errors, less than 500 could just mean no matching items in list + if (response.StatusCode > 499) + { + throw new ApplicationException(response.StatusMessage + " Code: " + response.StatusCode); + + } + + //Added: 21-June-2006 outer if to avoid crash on no match response (code 1) + if (response.StatusCode == 0) + { + + IORItemRetList orItemRetList = response.Detail as IORItemRetList; + + if (!(orItemRetList.Count == 0)) + { + for (int ndx = 0; ndx <= (orItemRetList.Count - 1); ndx++) + { + IORItemRet orItemRet = orItemRetList.GetAt(ndx); + + // IY: The ortype property returns an enum + // of the elements that can be contained in the OR object + switch (orItemRet.ortype) + { + case ENORItemRet.orirItemServiceRet: + { + // orir prefix comes from OR + Item + Ret + IItemServiceRet ItemServiceRet = orItemRet.ItemServiceRet; + + IORSalesPurchase sp = ItemServiceRet.ORSalesPurchase; + _dtQBItems.Rows.Add(new object[] { + ItemServiceRet.ListID.GetValue(), + ItemServiceRet.FullName.GetValue(), + qbitemtype.Service, + ItemServiceRet.TimeModified.GetValue(), + PriceGrabber(sp), + CostGrabber(sp), + SalesDescGrabber(sp), + 0, + PrefVendorGrabber(sp) + + }); + + + + + } + break; + case ENORItemRet.orirItemInventoryRet: + { + IItemInventoryRet ItemInventoryRet = orItemRet.ItemInventoryRet; + _dtQBItems.Rows.Add(new object[] { + ItemInventoryRet.ListID.GetValue(), + ItemInventoryRet.FullName.GetValue(), + qbitemtype.Inventory, + ItemInventoryRet.TimeModified.GetValue(), + PriceGrabber(ItemInventoryRet.SalesPrice), + PriceGrabber(ItemInventoryRet.PurchaseCost), + ProcessQBString(ItemInventoryRet.SalesDesc), + QuanGrabber(ItemInventoryRet.ReorderPoint), + BaseRefIDGrabber(ItemInventoryRet.PrefVendorRef) + + + + }); + } + break; + case ENORItemRet.orirItemNonInventoryRet: + { + IItemNonInventoryRet ItemNonInventoryRet = orItemRet.ItemNonInventoryRet; + _dtQBItems.Rows.Add(new object[] { + ItemNonInventoryRet.ListID.GetValue(), + ItemNonInventoryRet.FullName.GetValue(), + qbitemtype.NonInventory, + ItemNonInventoryRet.TimeModified.GetValue(), + PriceGrabber(ItemNonInventoryRet.ORSalesPurchase), + CostGrabber(ItemNonInventoryRet.ORSalesPurchase), + SalesDescGrabber(ItemNonInventoryRet.ORSalesPurchase), + 0, + PrefVendorGrabber(ItemNonInventoryRet.ORSalesPurchase) + + }); + } + break; + case ENORItemRet.orirItemOtherChargeRet: + { + IItemOtherChargeRet ItemOtherChargeRet = orItemRet.ItemOtherChargeRet; + _dtQBItems.Rows.Add(new object[] { + ItemOtherChargeRet.ListID.GetValue(), + ItemOtherChargeRet.FullName.GetValue(), + qbitemtype.OtherCharge, + ItemOtherChargeRet.TimeModified.GetValue(), + PriceGrabber(ItemOtherChargeRet.ORSalesPurchase), + CostGrabber(ItemOtherChargeRet.ORSalesPurchase), + SalesDescGrabber(ItemOtherChargeRet.ORSalesPurchase), + 0, + PrefVendorGrabber(ItemOtherChargeRet.ORSalesPurchase) + + }); + } + break; + case ENORItemRet.orirItemInventoryAssemblyRet: + { + IItemInventoryAssemblyRet ItemInventoryAssemblyRet = orItemRet.ItemInventoryAssemblyRet; + _dtQBItems.Rows.Add(new object[] { + ItemInventoryAssemblyRet.ListID.GetValue(), + ItemInventoryAssemblyRet.FullName.GetValue(), + qbitemtype.Assembly, + ItemInventoryAssemblyRet.TimeModified.GetValue(), + PriceGrabber(ItemInventoryAssemblyRet.SalesPrice), + PriceGrabber(ItemInventoryAssemblyRet.PurchaseCost), + ProcessQBString(ItemInventoryAssemblyRet.SalesDesc), + QuanGrabber(ItemInventoryAssemblyRet.BuildPoint), + BaseRefIDGrabber(ItemInventoryAssemblyRet.PrefVendorRef) + + }); + } + break; + } + } // for loop + } // if + + } + // IY: Close the session and connection with QuickBooks + sessionManager.EndSession(); + booSessionBegun = false; + sessionManager.CloseConnection(); + + + } + catch (Exception ex) + { + await IntegrationLog( "PopulateQBItems: Failed with exception:" + ex.Message); + if (booSessionBegun) + { + sessionManager.EndSession(); + sessionManager.CloseConnection(); + } + throw; + } + + } + + + /// + /// Given a qb BaseRef object + /// return the ListID or empty string if null + /// + /// + /// + private static string BaseRefIDGrabber(IQBBaseRef b) + { + + + if (b != null && b.ListID != null) + { + return b.ListID.GetValue(); + } + return ""; + + + + } + + /// + /// Given a qb Pricetype object + /// return the price or zero on any issue + /// + /// + /// + private static decimal PriceGrabber(IQBPriceType p) + { + decimal d = 0;//default + + if (p != null) + { + d = System.Convert.ToDecimal(p.GetValue()); + } + + + return d; + } + /// + /// Given a qb IQBQuanType object + /// return the value as decimal or zero on any issue + /// + /// + /// + private static decimal QuanGrabber(IQBQuanType p) + { + decimal d = 0;//default + + if (p != null) + { + d = System.Convert.ToDecimal(p.GetValue()); + } + + + return d; + } + /// + /// Given a qb salespurchase object + /// return the price + /// + /// + /// + private static decimal PriceGrabber(IORSalesPurchase sp) + { + decimal d = 0;//default + decimal d1 = 0; + decimal d2 = 0; + if (sp != null) + { + if (sp.SalesOrPurchase != null && sp.SalesOrPurchase.ORPrice != null && sp.SalesOrPurchase.ORPrice.Price != null) + { + d1 = System.Convert.ToDecimal(sp.SalesOrPurchase.ORPrice.Price.GetValue()); + } + + if (sp.SalesAndPurchase != null && sp.SalesAndPurchase.SalesPrice != null) + { + d2 = System.Convert.ToDecimal(sp.SalesAndPurchase.SalesPrice.GetValue()); + } + + //get the highest price of the two + + if (d1 > d2) + d = d1; + else + d = d2; + } + + + return d; + } + + + /// + /// Given a qb salespurchase object + /// return the purchase cose + /// + /// + /// + private static decimal CostGrabber(IORSalesPurchase sp) + { + decimal d = 0;//default + + if (sp != null) + { + + if (sp.SalesAndPurchase != null && sp.SalesAndPurchase.PurchaseCost != null) + { + d = System.Convert.ToDecimal(sp.SalesAndPurchase.PurchaseCost.GetValue()); + } + + + } + + + return d; + } + + /// + /// return the sales description if available + /// + /// + /// + private static string SalesDescGrabber(IORSalesPurchase sp) + { + string str = ""; + + if (sp != null) + { + + if (sp.SalesOrPurchase != null && sp.SalesOrPurchase.Desc != null) + { + str = sp.SalesOrPurchase.Desc.GetValue(); + } + + + if (sp.SalesAndPurchase != null && sp.SalesAndPurchase.SalesDesc != null) + { + str = sp.SalesAndPurchase.SalesDesc.GetValue(); + } + + + } + + + return str; + } + + /// + /// return the preferred vendor if available + /// + /// + /// + private static string PrefVendorGrabber(IORSalesPurchase sp) + { + string str = ""; + + if (sp != null) + { + + if (sp.SalesAndPurchase != null && sp.SalesAndPurchase.PrefVendorRef != null && sp.SalesAndPurchase.PrefVendorRef.ListID != null) + { + str = sp.SalesAndPurchase.PrefVendorRef.ListID.GetValue(); + } + + + } + + + return str; + } + #endregion quickbooks items + + #region QuickBooks "Transactionclasses" + + + private static DataTable _dtQBClasses = null; + + /// + /// QB Transaction Classes + /// + public static DataTable QBClasses + { + get + { + return _dtQBClasses; + } + } + + + + + /// + /// Populate the cached qb data + /// billable + /// + private static void PopulateQBClassCache() + { + if (_dtQBClasses == null) + { + _dtQBClasses = new DataTable("QBClasses"); + //setup the columns + _dtQBClasses.Columns.Add("ID", typeof(string)); + _dtQBClasses.Columns.Add("FullName", typeof(string)); + + + _dtQBClasses.PrimaryKey = new DataColumn[] { _dtQBClasses.Columns[0] }; + //Case 237 + _dtQBClasses.DefaultView.Sort = "FullName asc"; + } + else + _dtQBClasses.Clear(); + + //case 3268 + _dtQBClasses.Rows.Add(new object[] { TRANSACTION_CLASS_NO_CLASS_SELECTED, "< Do not use classes >" }); + + //Connect to QB and fill + // IY: Create the session manager object using QBFC + QBSessionManager sessionManager = new QBSessionManager(); + + // IY: We want to know if we begun a session so we can end it if an + // error happens + bool booSessionBegun = false; + + try + { + // IY: Get the RequestMsgSet based on the correct QB Version + IMsgSetRequest requestSet = getLatestMsgSetRequest(sessionManager); + + // IY: Initialize the message set request object + requestSet.Attributes.OnError = ENRqOnError.roeStop; + + // IY: Add the request to the message set request object + IClassQuery cq = requestSet.AppendClassQueryRq(); + + //transactions + cq.ORListQuery.ListFilter.ActiveStatus.SetValue(ENActiveStatus.asActiveOnly); + + + + //This is intended to be called in a secondary thread immediately after already sucessfully connected + //to get version info so no special safety checks here + sessionManager.OpenConnection2("", "AyaNova QBI", ENConnectionType.ctLocalQBDLaunchUI); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + booSessionBegun = true; + + // IY: Do the request and get the response message set object + IMsgSetResponse responseSet = sessionManager.DoRequests(requestSet); + + // Uncomment the following to view and save the request and response XML + //string requestXML = requestSet.ToXMLString(); + //MessageBox.Show(requestXML); + // SaveXML(requestXML); + //string responseXML = responseSet.ToXMLString(); + //MessageBox.Show(responseXML); + // SaveXML(responseXML); + + IResponse response = responseSet.ResponseList.GetAt(0); + //nonzero indicates an error, likely no classes defined + if (response.StatusCode == 0) + { + + //int statusCode = response.StatusCode; + //string statusMessage = response.StatusMessage; + //string statusSeverity = response.StatusSeverity; + //MessageBox.Show("Status:\nCode = " + statusCode + "\nMessage = " + statusMessage + "\nSeverity = " + statusSeverity); + IClassRetList cl = response.Detail as IClassRetList; + + if (!(cl.Count == 0)) + { + for (int ndx = 0; ndx <= (cl.Count - 1); ndx++) + { + IClassRet clitem = cl.GetAt(ndx); + if (clitem != null && clitem.FullName != null && clitem.ListID != null) + { + //add a record to the datatable + _dtQBClasses.Rows.Add(new object[] { clitem.ListID.GetValue(), clitem.FullName.GetValue() }); + } + } // for loop + } // if + }//if status ==0 nonzero means some error, probably no classes defined + + // IY: Close the session and connection with QuickBooks + sessionManager.EndSession(); + booSessionBegun = false; + sessionManager.CloseConnection(); + + + } + catch (Exception ex) + { + await IntegrationLog( "PopulateQBClasses: Failed with exception:" + ex.Message); + if (booSessionBegun) + { + sessionManager.EndSession(); + sessionManager.CloseConnection(); + } + throw; + } + + } + + + + #endregion quickbooks transaction classes + + #region QuickBooks Invoice Templates + + + private static DataTable _dtQBInvoiceTemplates = null; + + /// + /// QB Transaction Templates + /// + public static DataTable QBInvoiceTemplates + { + get + { + return _dtQBInvoiceTemplates; + } + } + + + + + /// + /// Populate the cached qb data + /// Invoice templates + /// + private static void PopulateQBInvoiceTemplates() + { + if (_dtQBInvoiceTemplates == null) + { + _dtQBInvoiceTemplates = new DataTable("QBInvoiceTemplates"); + //setup the columns + _dtQBInvoiceTemplates.Columns.Add("ID", typeof(string)); + _dtQBInvoiceTemplates.Columns.Add("FullName", typeof(string)); + _dtQBInvoiceTemplates.PrimaryKey = new DataColumn[] { _dtQBInvoiceTemplates.Columns[0] }; + + //Case 237 + _dtQBInvoiceTemplates.DefaultView.Sort = "FullName asc"; + } + else + _dtQBInvoiceTemplates.Clear(); + + _dtQBInvoiceTemplates.Rows.Add(new object[] { "", "< Use default >" }); + + //Connect to QB and fill + // IY: Create the session manager object using QBFC + QBSessionManager sessionManager = new QBSessionManager(); + + // IY: We want to know if we begun a session so we can end it if an + // error happens + bool booSessionBegun = false; + + try + { + // IY: Get the RequestMsgSet based on the correct QB Version + IMsgSetRequest requestSet = getLatestMsgSetRequest(sessionManager); + + // IY: Initialize the message set request object + requestSet.Attributes.OnError = ENRqOnError.roeStop; + + // IY: Add the request to the message set request object + ITemplateQuery cq = requestSet.AppendTemplateQueryRq(); + + + //This is intended to be called in a secondary thread immediately after already sucessfully connected + //to get version info so no special safety checks here + sessionManager.OpenConnection2("", "AyaNova QBI", ENConnectionType.ctLocalQBDLaunchUI); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + booSessionBegun = true; + + // IY: Do the request and get the response message set object + IMsgSetResponse responseSet = sessionManager.DoRequests(requestSet); + + // Uncomment the following to view and save the request and response XML + //sLastRequestXML = requestSet.ToXMLString(); + //MessageBox.Show(requestXML); + // SaveXML(requestXML); + //string responseXML = responseSet.ToXMLString(); + //MessageBox.Show(responseXML); + // SaveXML(responseXML); + + IResponse response = responseSet.ResponseList.GetAt(0); + //nonzero indicates an error, likely no templates defined + if (response.StatusCode == 0) + { + + //int statusCode = response.StatusCode; + //string statusMessage = response.StatusMessage; + //string statusSeverity = response.StatusSeverity; + //MessageBox.Show("Status:\nCode = " + statusCode + "\nMessage = " + statusMessage + "\nSeverity = " + statusSeverity); + ITemplateRetList cl = response.Detail as ITemplateRetList; + + if (!(cl.Count == 0)) + { + for (int ndx = 0; ndx <= (cl.Count - 1); ndx++) + { + try + { + + ITemplateRet clitem = cl.GetAt(ndx); + bool b = clitem.IsActive.GetValue(); + b = clitem.TemplateType == null; + if (clitem != null && + clitem.Name != null && + clitem.ListID != null && + clitem.TemplateType.IsSet() && + clitem.TemplateType.GetValue() == ENTemplateType.tttInvoice) + { + //add a record to the datatable + _dtQBInvoiceTemplates.Rows.Add(new object[] { clitem.ListID.GetValue(), clitem.Name.GetValue() }); + } + } + catch (System.Runtime.InteropServices.COMException ex)//QBFC7 - throwing this exception here on last item in list can't pin it down + { + string s = ex.ToString(); + } + + } // for loop + } // if + }//if status ==0 nonzero means some error, probably no classes defined + + // IY: Close the session and connection with QuickBooks + sessionManager.EndSession(); + booSessionBegun = false; + sessionManager.CloseConnection(); + + + } + catch (Exception ex) + { + + await IntegrationLog( "PopulateQBInvoiceTemplates: Failed with exception:" + ex.Message); + if (booSessionBegun) + { + sessionManager.EndSession(); + sessionManager.CloseConnection(); + } + throw; + } + + } + + + + #endregion quickbooks Templates + + #region QuickBooks "Customers" + + private static string GetQBCustomerEditSequence(string customerid) + { + + string strEditSequence = ""; + + //Connect to QB and fill + // IY: Create the session manager object using QBFC + QBSessionManager sessionManager = new QBSessionManager(); + + // IY: We want to know if we begun a session so we can end it if an + // error happens + bool booSessionBegun = false; + + try + { + // IY: Get the RequestMsgSet based on the correct QB Version + IMsgSetRequest requestSet = getLatestMsgSetRequest(sessionManager); + + // IY: Initialize the message set request object + requestSet.Attributes.OnError = ENRqOnError.roeStop; + + // IY: Add the request to the message set request object + ICustomerQuery cq = requestSet.AppendCustomerQueryRq(); + cq.IncludeRetElementList.Add("EditSequence"); + cq.ORCustomerListQuery.ListIDList.Add(customerid); + + + sessionManager.OpenConnection2("", "AyaNova QBI", ENConnectionType.ctLocalQBDLaunchUI); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + booSessionBegun = true; + + // IY: Do the request and get the response message set object + IMsgSetResponse responseSet = sessionManager.DoRequests(requestSet); + + // Uncomment the following to view and save the request and response XML + //string requestXML = requestSet.ToXMLString(); + //MessageBox.Show(requestXML); + // SaveXML(requestXML); + //string responseXML = responseSet.ToXMLString(); + //MessageBox.Show(responseXML); + // SaveXML(responseXML); + + IResponse response = responseSet.ResponseList.GetAt(0); + //nonzero indicates an error this is unrecoverable + //so throw an exception + + //Changed: 21-June-2006 nonzero status codes 500 and higher are serious errors, less than 500 could just mean no matching items in list + if (response.StatusCode > 499) + { + throw new ApplicationException(response.StatusMessage + " Code: " + response.StatusCode); + + } + + //Added: 21-June-2006 outer if to avoid crash on no match response (code 1) + if (response.StatusCode == 0) + { + ICustomerRetList cl = response.Detail as ICustomerRetList; + if (!(cl.Count == 0)) + { + ICustomerRet clitem = cl.GetAt(0); + if (clitem != null) + strEditSequence = clitem.EditSequence.GetValue(); + } + + } + // IY: Close the session and connection with QuickBooks + sessionManager.EndSession(); + booSessionBegun = false; + sessionManager.CloseConnection(); + + + } + catch (Exception ex) + { + await IntegrationLog( "GetClientEditSequence: Failed with exception:" + ex.Message); + if (booSessionBegun) + { + sessionManager.EndSession(); + sessionManager.CloseConnection(); + } + throw; + + } + + return strEditSequence; + } + + private static DataTable _dtQBClients = null; + + /// + /// QB Transaction Clients + /// + public static DataTable QBClients + { + get + { + return _dtQBClients; + } + } + + #region Address structure + /// + /// Address properties + /// + public struct Address + { + + public string DeliveryAddress; + public string City; + public string StateProv; + public string Country; + public string Postal; + } + + #endregion + /// + /// Populate the cached qb data + /// of customers / clients + /// + private static void PopulateQBClientCache() + { + if (_dtQBClients == null) + { + _dtQBClients = new DataTable("QBClients"); + + //setup the columns + _dtQBClients.Columns.Add("ID", typeof(string)); + _dtQBClients.Columns.Add("FullName", typeof(string)); + _dtQBClients.Columns.Add("MailAddress", typeof(Address)); + _dtQBClients.Columns.Add("StreetAddress", typeof(Address)); + _dtQBClients.Columns.Add("Phone", typeof(string)); + _dtQBClients.Columns.Add("Fax", typeof(string)); + _dtQBClients.Columns.Add("AltPhone", typeof(string)); + _dtQBClients.Columns.Add("Email", typeof(string)); + _dtQBClients.Columns.Add("Contact", typeof(string)); + _dtQBClients.Columns.Add("Created", typeof(DateTime)); + _dtQBClients.Columns.Add("Modified", typeof(DateTime)); + _dtQBClients.Columns.Add("Account", typeof(string)); + + _dtQBClients.PrimaryKey = new DataColumn[] { _dtQBClients.Columns[0] }; + + //Case 237 + _dtQBClients.DefaultView.Sort = "FullName asc"; + } + else + _dtQBClients.Clear(); + + + + //Connect to QB and fill + // IY: Create the session manager object using QBFC + QBSessionManager sessionManager = new QBSessionManager(); + + // IY: We want to know if we begun a session so we can end it if an + // error happens + bool booSessionBegun = false; + + try + { + // IY: Get the RequestMsgSet based on the correct QB Version + IMsgSetRequest requestSet = getLatestMsgSetRequest(sessionManager); + + // IY: Initialize the message set request object + requestSet.Attributes.OnError = ENRqOnError.roeStop; + + // IY: Add the request to the message set request object + ICustomerQuery cq = requestSet.AppendCustomerQueryRq(); + + //Active Customers only + cq.ORCustomerListQuery.CustomerListFilter.ActiveStatus.SetValue(ENActiveStatus.asActiveOnly); + + //case 1664 + //not sure why these were ever in here to be honest + + //whups, it's *necessary* see case 1100 + //there is a bug in qbfc7 which blows if there are "special" characters + //it was fixed later but we use qbfc7 currently + + cq.ORCustomerListQuery.CustomerListFilter.ORNameFilter.NameRangeFilter.FromName.SetValue("0"); + cq.ORCustomerListQuery.CustomerListFilter.ORNameFilter.NameRangeFilter.ToName.SetValue("ZZ"); + + + sessionManager.OpenConnection2("", "AyaNova QBI", ENConnectionType.ctLocalQBDLaunchUI); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + booSessionBegun = true; + + // IY: Do the request and get the response message set object + IMsgSetResponse responseSet = sessionManager.DoRequests(requestSet); + + // Uncomment the following to view and save the request and response XML + // string requestXML = requestSet.ToXMLString(); + // MessageBox.Show(requestXML); + // SaveXML(requestXML); + //string responseXML = responseSet.ToXMLString(); + // MessageBox.Show(responseXML); + // SaveXML(responseXML); + + IResponse response = responseSet.ResponseList.GetAt(0); + //nonzero indicates an error this is unrecoverable + //so throw an exception + + //Changed: 21-June-2006 nonzero status codes 500 and higher are serious errors, less than 500 could just mean no matching items in list + if (response.StatusCode > 499) + { + throw new ApplicationException(response.StatusMessage + " Code: " + response.StatusCode); + + } + + //Added: 21-June-2006 outer if to avoid crash on no match response (code 1) + if (response.StatusCode == 0) + { + //int statusCode = response.StatusCode; + //string statusMessage = response.StatusMessage; + //string statusSeverity = response.StatusSeverity; + //MessageBox.Show("Status:\nCode = " + statusCode + "\nMessage = " + statusMessage + "\nSeverity = " + statusSeverity); + ICustomerRetList cl = response.Detail as ICustomerRetList; + + if (!(cl.Count == 0)) + { + for (int ndx = 0; ndx <= (cl.Count - 1); ndx++) + { + ICustomerRet clitem = cl.GetAt(ndx); + if (clitem != null) + { + //add a record to the datatable + + + DataRow dr = _dtQBClients.Rows.Add( + new object[]{ + clitem.ListID.GetValue(), + clitem.FullName.GetValue(), + ProcessAddress(clitem.BillAddress), + ProcessAddress(clitem.ShipAddress), + ProcessQBString(clitem.Phone), + ProcessQBString(clitem.Fax), + ProcessQBString(clitem.AltPhone), + ProcessQBString(clitem.Email), + ProcessQBString(clitem.Contact), + clitem.TimeCreated.GetValue(), + clitem.TimeModified.GetValue(), + ProcessQBString(clitem.AccountNumber), + + }); + } + } // for loop + } // if + + } + // IY: Close the session and connection with QuickBooks + sessionManager.EndSession(); + booSessionBegun = false; + sessionManager.CloseConnection(); + + + } + catch (Exception ex) + { + await IntegrationLog( "PopulateQBClients: Failed with exception:" + ex.Message); + if (booSessionBegun) + { + sessionManager.EndSession(); + sessionManager.CloseConnection(); + } + throw; + + } + + } + + /// + /// Take a qb address and return an AyaNova friendly + /// address structure + /// + /// + /// + private static Address ProcessAddress(IAddress a) + { + Address b = new Address(); + b.City = ""; + b.Country = ""; + b.DeliveryAddress = ""; + b.Postal = ""; + b.StateProv = ""; + if (a == null) return b; + //Append each line of the address, add cr/lf for each line if present after + //the first line + //Assumption: First line always has *something* in it + b.DeliveryAddress = ProcessQBString(a.Addr1); + b.DeliveryAddress += AyaBizUtils.SS("\r\n", ProcessQBString(a.Addr2), ""); + b.DeliveryAddress += AyaBizUtils.SS("\r\n", ProcessQBString(a.Addr3), ""); + + //Address line 4 is a qbxml 2 or higher feature + if (QVersion > 1.1) + b.DeliveryAddress += AyaBizUtils.SS("\r\n", ProcessQBString(a.Addr4), ""); + + //Country specific: + b.City = ProcessQBString(a.City); + + //QBFC7 unifies county and province to "state" + b.StateProv = ProcessQBString(a.State); + + //switch(QCountry) + //{ + // case "CA": + // b.StateProv=ProcessQBString(a.Province); + // break; + // case "UK": + // b.StateProv=ProcessQBString(a.County); + // break; + // default: + // b.StateProv=ProcessQBString(a.State); + // break; + + //} + + b.Country = ProcessQBString(a.Country); + + b.Postal = ProcessQBString(a.PostalCode); + + + + return b; + } + + /// + /// Handle null qb string types with "aplomb" :) + /// + /// + /// + private static string ProcessQBString(IQBStringType qs) + { + if (qs == null) return ""; + return qs.GetValue(); + } + + #endregion quickbooks transaction Clients + + #region QuickBooks "Vendors" + + + private static DataTable _dtQBVendors = null; + + /// + /// QB Vendors + /// + public static DataTable QBVendors + { + get + { + return _dtQBVendors; + } + } + + + /// + /// Populate the cached qb data + /// of Vendors + /// + private static void PopulateQBVendorCache() + { + if (_dtQBVendors == null) + { + _dtQBVendors = new DataTable("QBVendors"); + + //setup the columns + _dtQBVendors.Columns.Add("ID", typeof(string)); + _dtQBVendors.Columns.Add("FullName", typeof(string)); + _dtQBVendors.Columns.Add("MailAddress", typeof(Address)); + _dtQBVendors.Columns.Add("StreetAddress", typeof(Address)); + _dtQBVendors.Columns.Add("Phone", typeof(string)); + _dtQBVendors.Columns.Add("Fax", typeof(string)); + _dtQBVendors.Columns.Add("AltPhone", typeof(string)); + _dtQBVendors.Columns.Add("Email", typeof(string)); + _dtQBVendors.Columns.Add("Contact", typeof(string)); + _dtQBVendors.Columns.Add("Created", typeof(DateTime)); + _dtQBVendors.Columns.Add("Modified", typeof(DateTime)); + _dtQBVendors.Columns.Add("Account", typeof(string)); + + _dtQBVendors.PrimaryKey = new DataColumn[] { _dtQBVendors.Columns[0] }; + + //Case 237 + _dtQBVendors.DefaultView.Sort = "FullName asc"; + } + else + _dtQBVendors.Clear(); + + + + //Connect to QB and fill + // IY: Create the session manager object using QBFC + QBSessionManager sessionManager = new QBSessionManager(); + + // IY: We want to know if we begun a session so we can end it if an + // error happens + bool booSessionBegun = false; + + try + { + // IY: Get the RequestMsgSet based on the correct QB Version + IMsgSetRequest requestSet = getLatestMsgSetRequest(sessionManager); + + // IY: Initialize the message set request object + requestSet.Attributes.OnError = ENRqOnError.roeStop; + + // IY: Add the request to the message set request object + IVendorQuery cq = requestSet.AppendVendorQueryRq(); + + //Active Vendors only + cq.ORVendorListQuery.VendorListFilter.ActiveStatus.SetValue(ENActiveStatus.asActiveOnly); + + sessionManager.OpenConnection2("", "AyaNova QBI", ENConnectionType.ctLocalQBDLaunchUI); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + booSessionBegun = true; + + // IY: Do the request and get the response message set object + IMsgSetResponse responseSet = sessionManager.DoRequests(requestSet); + + // Uncomment the following to view and save the request and response XML + //string requestXML = requestSet.ToXMLString(); + //MessageBox.Show(requestXML); + // SaveXML(requestXML); + //string responseXML = responseSet.ToXMLString(); + //MessageBox.Show(responseXML); + // SaveXML(responseXML); + + IResponse response = responseSet.ResponseList.GetAt(0); + //nonzero indicates an error; this is unrecoverable + //so throw an exception + + //Changed: 21-June-2006 nonzero status codes 500 and higher are serious errors, less than 500 could just mean no matching items in list + if (response.StatusCode > 499) + { + throw new ApplicationException(response.StatusMessage + " Code: " + response.StatusCode); + + } + //Added: 21-June-2006 outer if to avoid crash on no match response (code 1) + if (response.StatusCode == 0) + { + //int statusCode = response.StatusCode; + //string statusMessage = response.StatusMessage; + //string statusSeverity = response.StatusSeverity; + //MessageBox.Show("Status:\nCode = " + statusCode + "\nMessage = " + statusMessage + "\nSeverity = " + statusSeverity); + IVendorRetList cl = response.Detail as IVendorRetList; + + if (!(cl.Count == 0)) + { + for (int ndx = 0; ndx <= (cl.Count - 1); ndx++) + { + IVendorRet clitem = cl.GetAt(ndx); + if (clitem != null) + { + //add a record to the datatable + + + DataRow dr = _dtQBVendors.Rows.Add( + new object[] +{ + clitem.ListID.GetValue(), + clitem.Name.GetValue(), + ProcessAddress(clitem.VendorAddress), + ProcessAddress(clitem.VendorAddress), + ProcessQBString(clitem.Phone), + ProcessQBString(clitem.Fax), + ProcessQBString(clitem.AltPhone), + ProcessQBString(clitem.Email), + ProcessQBString(clitem.Contact), + clitem.TimeCreated.GetValue(), + clitem.TimeModified.GetValue(), + ProcessQBString(clitem.AccountNumber) +}); + } + } // for loop + } // if + + } + + + // IY: Close the session and connection with QuickBooks + sessionManager.EndSession(); + booSessionBegun = false; + sessionManager.CloseConnection(); + + + } + catch (Exception ex) + { + await IntegrationLog( "PopulateQBVendors: Failed with exception:" + ex.Message); + if (booSessionBegun) + { + sessionManager.EndSession(); + sessionManager.CloseConnection(); + } + throw; + } + + } + + + + #endregion quickbooks Vendors + + + + #region QuickBooks "accounts" + + + private static DataTable _dtQBAccounts = null; + + /// + /// QB Transaction Classes + /// + public static DataTable QBAccounts + { + get + { + return _dtQBAccounts; + } + } + + + + + /// + /// Populate the cached qb account list data + /// + private static void PopulateQBAccountCache() + { + if (_dtQBAccounts == null) + { + _dtQBAccounts = new DataTable("QBAccounts"); + //setup the columns + _dtQBAccounts.Columns.Add("ID", typeof(string)); + _dtQBAccounts.Columns.Add("FullName", typeof(string)); + _dtQBAccounts.Columns.Add("Type", typeof(string)); + + _dtQBAccounts.PrimaryKey = new DataColumn[] { _dtQBAccounts.Columns[0] }; + //Case 237 + _dtQBAccounts.DefaultView.Sort = "FullName asc"; + } + else + _dtQBAccounts.Clear(); + + + + //Connect to QB and fill + // IY: Create the session manager object using QBFC + QBSessionManager sessionManager = new QBSessionManager(); + + // IY: We want to know if we begun a session so we can end it if an + // error happens + bool booSessionBegun = false; + + try + { + // IY: Get the RequestMsgSet based on the correct QB Version + IMsgSetRequest requestSet = getLatestMsgSetRequest(sessionManager); + + // IY: Initialize the message set request object + requestSet.Attributes.OnError = ENRqOnError.roeStop; + + // IY: Add the request to the message set request object + IAccountQuery cq = requestSet.AppendAccountQueryRq(); + + //accounts (active ones only) + cq.ORAccountListQuery.AccountListFilter.ActiveStatus.SetValue(ENActiveStatus.asActiveOnly); + + + + //This is intended to be called in a secondary thread immediately after already sucessfully connected + //to get version info so no special safety checks here + sessionManager.OpenConnection2("", "AyaNova QBI", ENConnectionType.ctLocalQBDLaunchUI); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + booSessionBegun = true; + + // IY: Do the request and get the response message set object + IMsgSetResponse responseSet = sessionManager.DoRequests(requestSet); + + // Uncomment the following to view and save the request and response XML + //string requestXML = requestSet.ToXMLString(); + //MessageBox.Show(requestXML); + // SaveXML(requestXML); + //string responseXML = responseSet.ToXMLString(); + //MessageBox.Show(responseXML); + // SaveXML(responseXML); + + IResponse response = responseSet.ResponseList.GetAt(0); + //nonzero indicates an error, likely no classes defined + if (response.StatusCode == 0) + { + + //int statusCode = response.StatusCode; + //string statusMessage = response.StatusMessage; + //string statusSeverity = response.StatusSeverity; + //MessageBox.Show("Status:\nCode = " + statusCode + "\nMessage = " + statusMessage + "\nSeverity = " + statusSeverity); + IAccountRetList cl = response.Detail as IAccountRetList; + + if (!(cl.Count == 0)) + { + for (int ndx = 0; ndx <= (cl.Count - 1); ndx++) + { + IAccountRet clitem = cl.GetAt(ndx); + if (clitem != null && clitem.FullName != null && clitem.ListID != null) + { + //add a record to the datatable + _dtQBAccounts.Rows.Add(new object[] { clitem.ListID.GetValue(), clitem.AccountType.GetAsString() + " - " + clitem.FullName.GetValue(), clitem.AccountType.GetAsString() }); + } + } // for loop + } // if + }//if status ==0 nonzero means some error, probably no classes defined + + // IY: Close the session and connection with QuickBooks + sessionManager.EndSession(); + booSessionBegun = false; + sessionManager.CloseConnection(); + + + } + catch (Exception ex) + { + await IntegrationLog( "PopulateQBAccounts: Failed with exception:" + ex.Message); + if (booSessionBegun) + { + sessionManager.EndSession(); + sessionManager.CloseConnection(); + } + throw; + } + + } + + + + #endregion quickbooks accounts + + #region QuickBooks "Terms" + + + private static DataTable _dtQBTerms = null; + + /// + /// QB Transaction Classes + /// + public static DataTable QBTerms + { + get + { + return _dtQBTerms; + } + } + + + + + /// + /// Populate the cached qb terms list data + /// + private async static void PopulateQBTermsCache() + { + if (_dtQBTerms == null) + { + _dtQBTerms = new DataTable("QBTerms"); + //setup the columns + _dtQBTerms.Columns.Add("ID", typeof(string)); + _dtQBTerms.Columns.Add("FullName", typeof(string)); + + _dtQBTerms.PrimaryKey = new DataColumn[] { _dtQBTerms.Columns[0] }; + //Case 237 + _dtQBTerms.DefaultView.Sort = "FullName asc"; + } + else + _dtQBTerms.Clear(); + + + + //Connect to QB and fill + // IY: Create the session manager object using QBFC + QBSessionManager sessionManager = new QBSessionManager(); + + // IY: We want to know if we begun a session so we can end it if an + // error happens + bool booSessionBegun = false; + + try + { + // IY: Get the RequestMsgSet based on the correct QB Version + IMsgSetRequest requestSet = getLatestMsgSetRequest(sessionManager); + + // IY: Initialize the message set request object + requestSet.Attributes.OnError = ENRqOnError.roeStop; + + // IY: Add the request to the message set request object + ITermsQuery cq = requestSet.AppendTermsQueryRq(); + + + //This is intended to be called in a secondary thread immediately after already sucessfully connected + //to get version info so no special safety checks here + sessionManager.OpenConnection2("", "AyaNova QBI", ENConnectionType.ctLocalQBDLaunchUI); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + booSessionBegun = true; + + // IY: Do the request and get the response message set object + IMsgSetResponse responseSet = sessionManager.DoRequests(requestSet); + + // Uncomment the following to view and save the request and response XML + //string requestXML = requestSet.ToXMLString(); + //MessageBox.Show(requestXML); + // SaveXML(requestXML); + //string responseXML = responseSet.ToXMLString(); + //MessageBox.Show(responseXML); + // SaveXML(responseXML); + + IResponse response = responseSet.ResponseList.GetAt(0); + //nonzero indicates an error, likely no classes defined + if (response.StatusCode == 0) + { + + //int statusCode = response.StatusCode; + //string statusMessage = response.StatusMessage; + //string statusSeverity = response.StatusSeverity; + //MessageBox.Show("Status:\nCode = " + statusCode + "\nMessage = " + statusMessage + "\nSeverity = " + statusSeverity); + IORTermsRetList cl = response.Detail as IORTermsRetList; + + if (!(cl.Count == 0)) + { + for (int ndx = 0; ndx <= (cl.Count - 1); ndx++) + { + IORTermsRet clitem = cl.GetAt(ndx); + if (clitem != null) + { + //add a record to the datatable + if (clitem.StandardTermsRet != null && clitem.StandardTermsRet.ListID.IsSet()) + _dtQBTerms.Rows.Add(new object[] { clitem.StandardTermsRet.ListID.GetValue(), clitem.StandardTermsRet.Name.GetValue() }); + else + _dtQBTerms.Rows.Add(new object[] { clitem.DateDrivenTermsRet.ListID.GetValue(), clitem.DateDrivenTermsRet.Name.GetValue() }); + + } + } // for loop + } // if + }//if status ==0 nonzero means some error, probably no classes defined + + // IY: Close the session and connection with QuickBooks + sessionManager.EndSession(); + booSessionBegun = false; + sessionManager.CloseConnection(); + + + } + catch (Exception ex) + { + await IntegrationLog( "PopulateQBTerms: Failed with exception:" + ex.Message); + if (booSessionBegun) + { + sessionManager.EndSession(); + sessionManager.CloseConnection(); + } + throw; + } + + } + + + + #endregion quickbooks Terms + + #endregion