public static string DoRequest(XmlDocument doc) { RequestProcessor2 rp = null; string ticket = null; string response = null; bool errorOccurred = false; int maxTries = 1; int tries = 0; do { try { tries++; rp = new RequestProcessor2(); rp.OpenConnection("QBMT1", "QBMigrationTool"); ticket = rp.BeginSession("", QBFileMode.qbFileOpenDoNotCare); CheckIfBuildTypeAndQuickBooksFileMatch(rp.GetCurrentCompanyFileName(ticket)); response = rp.ProcessRequest(ticket, doc.OuterXml); if (errorOccurred) { Logging.RototrackErrorLog("QBMigrationTool: " + RototrackConfig.GetBuildType() + ": " + "DoRequest Retry succeeded."); errorOccurred = false; } } catch (System.Runtime.InteropServices.COMException e) { Logging.RototrackErrorLog("QBMigrationTool: " + RototrackConfig.GetBuildType() + ": " + "Error in DoRequest. Retrying. Details: " + e.ToString()); //MessageBox.Show("Outer: " + doc.OuterXml); errorOccurred = true; } catch (Exception e) { Logging.RototrackErrorLog("QBMigrationTool: " + RototrackConfig.GetBuildType() + ": " + "Error in DoRequest. Retrying. Details: " + e.ToString()); break; } finally { if (ticket != null) { rp.EndSession(ticket); } if (rp != null) { rp.CloseConnection(); } } } while (errorOccurred && tries <= maxTries); return response; }
public void Reverse() { // Disable the buttons. IsExitEnabled = false; IsTryEnabled = false; IsStartOverEnabled = false; OnPropertyChanged("IsExitEnabled"); OnPropertyChanged("IsTryEnabled"); OnPropertyChanged("IsStartOverEnabled"); // Reset error count. SaveErrorCount = 0; StatusText = string.Format("{0} - Starting.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); var service = new QuickBooksService(); StatusText += string.Format("{0} - Connecting to QuickBooks.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // QBXML request processor must always be closed after use. var req = new RequestProcessor2(); try { req.OpenConnection2("", "BRIZBEE Integration Utility", QBXMLRPConnectionType.localQBD); var ticket = req.BeginSession("", QBFileMode.qbFileOpenDoNotCare); var companyFileName = req.GetCurrentCompanyFileName(ticket); StatusText += string.Format("{0} - Reversing.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // ------------------------------------------------------------ // Collect the QuickBooks host details. // ------------------------------------------------------------ // Prepare a new QBXML document. var hostQBXML = service.MakeQBXMLDocument(); var hostDocument = hostQBXML.Item1; var hostElement = hostQBXML.Item2; service.BuildHostQueryRq(hostDocument, hostElement); // Make the request. var hostResponse = req.ProcessRequest(ticket, hostDocument.OuterXml); // Then walk the response. var hostWalkResponse = service.WalkHostQueryRsAndParseHostDetails(hostResponse); var hostDetails = hostWalkResponse.Item3; // ------------------------------------------------------------ // Prepare the reverse request. // ------------------------------------------------------------ string reverseTransactionType = Application.Current.Properties["ReverseTransactionType"] as string; string transactionType = ""; string[] selectedTxnIds = new string[] { }; string syncId = ""; if (reverseTransactionType == "Punches") { var selectedSync = Application.Current.Properties["SelectedSync"] as QuickBooksDesktopExport; selectedTxnIds = selectedSync.TxnIDs.Split(','); transactionType = "TimeTracking"; syncId = selectedSync.Id.ToString(); } else if (reverseTransactionType == "Consumption") { var selectedSync = Application.Current.Properties["SelectedSync"] as QBDInventoryConsumptionSync; if (Path.GetFileName(companyFileName) != selectedSync.HostCompanyFileName) { throw new Exception("The open company file in QuickBooks is not the same as the one that was synced."); } selectedTxnIds = selectedSync.TxnIDs.Split(','); transactionType = selectedSync.RecordingMethod; // InventoryAdjustment, SalesReceipt, or Bill syncId = selectedSync.Id.ToString(); } // ------------------------------------------------------------ // Reverse the transaction. // ------------------------------------------------------------ foreach (var txnId in selectedTxnIds) { // Prepare a new QBXML document. var delQBXML = service.MakeQBXMLDocument(); var delDocument = delQBXML.Item1; var delElement = delQBXML.Item2; service.BuildTxnDelRq(delDocument, delElement, transactionType, txnId); // InventoryAdjustment, SalesReceipt, TimeTracking, or Bill // Make the request. Logger.Debug(delDocument.OuterXml); var delResponse = req.ProcessRequest(ticket, delDocument.OuterXml); Logger.Debug(delResponse); // Then walk the response. var delWalkResponse = service.WalkTxnDelRs(delResponse); } // ------------------------------------------------------------ // Send the request to the server. // ------------------------------------------------------------ // Build the request. if (reverseTransactionType == "Consumption") { var syncHttpRequest = new RestRequest("api/QBDInventoryConsumptionSyncs/Reverse", Method.POST); syncHttpRequest.AddQueryParameter("id", syncId); // Execute request. var syncHttpResponse = client.Execute(syncHttpRequest); if ((syncHttpResponse.ResponseStatus == ResponseStatus.Completed) && (syncHttpResponse.StatusCode == System.Net.HttpStatusCode.OK)) { StatusText += string.Format("{0} - Reversed Successfully.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } else { StatusText += $"{DateTime.Now} - {syncHttpResponse.Content}"; StatusText += string.Format("{0} - Reverse failed.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } } else { StatusText += string.Format("{0} - Reversed Successfully.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } // Close the QuickBooks connection. req.EndSession(ticket); req.CloseConnection(); req = null; } catch (COMException cex) { Logger.Error(cex.ToString()); if ((uint)cex.ErrorCode == 0x80040408) { StatusText += string.Format("{0} - Reverse failed. QuickBooks Desktop is not open.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } else { StatusText += string.Format("{0} - Reverse failed. {1}\r\n", DateTime.Now.ToString(), cex.Message); OnPropertyChanged("StatusText"); } } catch (Exception ex) { Logger.Error(ex.ToString()); StatusText += string.Format("{0} - Reverse failed. {1}\r\n", DateTime.Now.ToString(), ex.Message); OnPropertyChanged("StatusText"); } finally { // Enable the buttons. IsExitEnabled = true; IsTryEnabled = true; IsStartOverEnabled = true; OnPropertyChanged("IsExitEnabled"); OnPropertyChanged("IsTryEnabled"); OnPropertyChanged("IsStartOverEnabled"); // Try to close the QuickBooks connection if it is still open. if (req != null) { req.CloseConnection(); req = null; } } }
public static string DoRequestRaw(string rawXML) { RequestProcessor2 rp = null; string ticket = null; string response = null; try { rp = new RequestProcessor2(); rp.OpenConnection("QBMT1", "QBMigrationTool"); ticket = rp.BeginSession("", QBFileMode.qbFileOpenDoNotCare); CheckIfBuildTypeAndQuickBooksFileMatch(rp.GetCurrentCompanyFileName(ticket)); response = rp.ProcessRequest(ticket, rawXML); return response; } catch (System.Runtime.InteropServices.COMException ex) { MessageBox.Show("COM Error Description = " + ex.Message, "COM error"); return ex.Message; } catch (Exception e) { MessageBox.Show("QBMigrationTool: " + RototrackConfig.GetBuildType() + ": " + "Error in DoRequestRaw. Details: " + e.ToString(), "Exception"); return e.Message; } finally { if (ticket != null) { rp.EndSession(ticket); } if (rp != null) { rp.CloseConnection(); } } }
public void Sync() { // Disable the buttons. IsExitEnabled = false; IsTryEnabled = false; IsStartOverEnabled = false; OnPropertyChanged("IsExitEnabled"); OnPropertyChanged("IsTryEnabled"); OnPropertyChanged("IsStartOverEnabled"); // Reset error count. ValidationErrorCount = 0; SaveErrorCount = 0; StatusText = string.Format("{0} - Starting.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // Open the offset mapping file first, but only if one has been specified. List <OffsetMapping> offsetMappings = new List <OffsetMapping>(0); if (!string.IsNullOrEmpty(offsetFileName)) { try { Logger.Debug($"Opening offset mapping file at {offsetFileName}"); using (var reader = new StreamReader(offsetFileName)) using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { offsetMappings = csv.GetRecords <OffsetMapping>().ToList(); } Logger.Debug($"There are {offsetMappings.Count} mappings"); } catch (Exception ex) { Logger.Error(ex.ToString()); StatusText += string.Format("{0} - Sync failed. {1}\r\n", DateTime.Now.ToString(), ex.Message); OnPropertyChanged("StatusText"); return; } } var service = new QuickBooksService(); StatusText += string.Format("{0} - Connecting to QuickBooks.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // QBXML request processor must always be closed after use. var req = new RequestProcessor2(); try { req.OpenConnection2("", "BRIZBEE Integration Utility", QBXMLRPConnectionType.localQBD); var ticket = req.BeginSession("", QBFileMode.qbFileOpenDoNotCare); var companyFileName = req.GetCurrentCompanyFileName(ticket); StatusText += string.Format("{0} - Syncing.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // ------------------------------------------------------------ // Collect the QuickBooks host details. // ------------------------------------------------------------ // Prepare a new QBXML document. var hostQBXML = service.MakeQBXMLDocument(); var hostDocument = hostQBXML.Item1; var hostElement = hostQBXML.Item2; service.BuildHostQueryRq(hostDocument, hostElement); // Make the request. var hostResponse = req.ProcessRequest(ticket, hostDocument.OuterXml); // Then walk the response. var hostWalkResponse = service.WalkHostQueryRsAndParseHostDetails(hostResponse); var hostDetails = hostWalkResponse.Item3; // ------------------------------------------------------------ // Collect the inventory items. // ------------------------------------------------------------ var items = new List <QBDInventoryItem>(); StatusText += string.Format("{0} - Collecting inventory items.\r\n", DateTime.Now.ToString()); items = SyncInventoryItems(service, ticket, req); // Cannot continue to sync if there are no items. if (items.Count == 0) { throw new Exception("There are no inventory items to sync."); } // Apply the offset items. foreach (var item in items) { var found = offsetMappings .Where(o => o.InventoryItemFullName == item.FullName) .FirstOrDefault(); if (found != null) { item.OffsetItemFullName = found.OffsetItemFullName; } } // ------------------------------------------------------------ // Collect the inventory sites. // ------------------------------------------------------------ var sites = new List <QBDInventorySite>(); // Attempt to sync sites even if they are not enabled or available. StatusText += string.Format("{0} - Collecting inventory sites.\r\n", DateTime.Now.ToString()); sites = SyncInventorySites(service, ticket, req); // ------------------------------------------------------------ // Collect the units of measure. // ------------------------------------------------------------ var units = new List <QBDUnitOfMeasureSet>(); // Attempt to sync sites even if they are not enabled or available. StatusText += string.Format("{0} - Collecting unit of measure sets.\r\n", DateTime.Now.ToString()); units = SyncUnitOfMeasureSets(service, ticket, req); // ------------------------------------------------------------ // Send the items to the server. // ------------------------------------------------------------ // Build the payload. var payload = new { InventoryItems = items ?? new List <QBDInventoryItem>(), InventorySites = sites ?? new List <QBDInventorySite>(), UnitOfMeasureSets = units ?? new List <QBDUnitOfMeasureSet>() }; // Build the request to send the sync details. var syncHttpRequest = new RestRequest("api/QBDInventoryItems/Sync", Method.POST); syncHttpRequest.AddJsonBody(payload); syncHttpRequest.AddQueryParameter("productName", hostDetails.QBProductName); syncHttpRequest.AddQueryParameter("majorVersion", hostDetails.QBMajorVersion); syncHttpRequest.AddQueryParameter("minorVersion", hostDetails.QBMinorVersion); syncHttpRequest.AddQueryParameter("country", hostDetails.QBCountry); syncHttpRequest.AddQueryParameter("supportedQBXMLVersion", hostDetails.QBSupportedQBXMLVersions); syncHttpRequest.AddQueryParameter("hostname", Environment.MachineName); syncHttpRequest.AddQueryParameter("companyFilePath", companyFileName); // Execute request. var syncHttpResponse = client.Execute(syncHttpRequest); if ((syncHttpResponse.ResponseStatus == ResponseStatus.Completed) && (syncHttpResponse.StatusCode == System.Net.HttpStatusCode.OK)) { StatusText += string.Format("{0} - Synced Successfully.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } else { StatusText += $"{DateTime.Now} - {syncHttpResponse.Content}"; StatusText += string.Format("{0} - Sync failed.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } // Close the QuickBooks connection. req.EndSession(ticket); req.CloseConnection(); req = null; } catch (COMException cex) { Logger.Error(cex.ToString()); if ((uint)cex.ErrorCode == 0x80040408) { StatusText += string.Format("{0} - Sync failed. QuickBooks Desktop is not open.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } else { StatusText += string.Format("{0} - Sync failed. {1}\r\n", DateTime.Now.ToString(), cex.Message); OnPropertyChanged("StatusText"); } } catch (Exception ex) { Logger.Error(ex.ToString()); StatusText += string.Format("{0} - Sync failed. {1}\r\n", DateTime.Now.ToString(), ex.Message); OnPropertyChanged("StatusText"); } finally { // Enable the buttons. IsExitEnabled = true; IsTryEnabled = true; IsStartOverEnabled = true; OnPropertyChanged("IsExitEnabled"); OnPropertyChanged("IsTryEnabled"); OnPropertyChanged("IsStartOverEnabled"); // Try to close the QuickBooks connection if it is still open. if (req != null) { req.CloseConnection(); req = null; } } }
private void btnImport_Click(object sender, EventArgs e) { try { _Rp = new RequestProcessor2(); _Rp.OpenConnection("", "Apex Interface"); _Ticket = _Rp.BeginSession("", Interop.QBXMLRP2.QBFileMode.qbFileOpenDoNotCare); _QBCompanyName = Path.GetFileName(_Rp.GetCurrentCompanyFileName(_Ticket)); _ApexTargetCompany = GetApexTargetCompany(_QBCompanyName); if (_ApexTargetCompany == "*") //invalid company open { Application.Exit(); return; } lblApexCompany.Text = "Quickbooks Company: " + Path.GetFileName(_QBCompanyName); lblApexCompany.Visible = true; lblApexCompany.Refresh(); //For efficiency we are creating these items once and reusing them for each QuickBooks transfer XmlSerializer serializer = new XmlSerializer(typeof(QBXML)); XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); var qbxml = new QBXML(); qbxml.ItemsElementName = new ItemsChoiceType99[1] { ItemsChoiceType99.QBXMLMsgsRq }; qbxml.Items = new object[1]; var qbMsgsRq = new QBXMLMsgsRq(); qbMsgsRq.Items = new object[1]; qbMsgsRq.onError = QBXMLMsgsRqOnError.stopOnError; Cursor.Current = Cursors.WaitCursor; try { StatusLabel.Text = "Receiving jobs..."; TransferJobs(serializer, ns, qbxml, qbMsgsRq); StatusLabel.Text = "Receiving vendors..."; TransferVendors(serializer, ns, qbxml, qbMsgsRq); StatusLabel.Text = "Receiving terms..."; TransferTerms(serializer, ns, qbxml, qbMsgsRq); if (DEBUGMODE) { StatusLabel.Text = "Receiving accounts..."; TransferAccounts(serializer, ns, qbxml, qbMsgsRq); StatusLabel.Text = "Receiving classes..."; TransferClasses(serializer, ns, qbxml, qbMsgsRq); } } finally { StatusLabel.Text = ""; Cursor.Current = Cursors.Default; } MessageBox.Show("QuickBooks data has been imported", "Importing complete"); } catch (System.Runtime.InteropServices.COMException ex) { MessageBox.Show("COM Error Description = " + ex.Message, "COM error"); return; } finally { StatusLabel.Text = ""; if (_Ticket != null) { _Rp.EndSession(_Ticket); } if (_Rp != null) { _Rp.CloseConnection(); } }; }
protected void SendApexInvoices() { using (ApexDataDataContext apexData = new ApexDataDataContext(_SqlConnBuilder.ConnectionString)) { try { _Rp = new RequestProcessor2(); _Rp.OpenConnection("", "Apex Interface"); _Ticket = _Rp.BeginSession("", Interop.QBXMLRP2.QBFileMode.qbFileOpenDoNotCare); _QBCompanyName = Path.GetFileName(_Rp.GetCurrentCompanyFileName(_Ticket)); _ApexTargetCompany = GetApexTargetCompany(_QBCompanyName); if (_ApexTargetCompany == "*") //invalid company open { Application.Exit(); return; } lblApexCompany.Text = "Quickbooks Company: " + Path.GetFileName(_QBCompanyName); lblApexCompany.Visible = true; lblApexCompany.Refresh(); _StatusLines.Clear(); List <VendIvc> apexInvoiceList = (from ivc in apexData.VendIvcs join po in apexData.POs on ivc.PO equals po.Po1 where ivc.IvcStatus == "A" && po.Company == _ApexTargetCompany select ivc).ToList(); if (apexInvoiceList.Count == 0) { MessageBox.Show("There are no invoices to send."); } else { _InvoicesSent = true; //We have a valid invoice to send so present the interface status report when complete try { GLAcctUtility.GLAcctList = GLAcctUtility.BuildGLAcctList(apexData); } catch (Exception ex) { MessageBox.Show(ex.Message, "G/L Setup Error"); return; } foreach (VendIvc invoice in apexInvoiceList) { decimal ponet = apexData.POs.Where(s => s.Po1 == invoice.PO).Select(s => s.PoNet).SingleOrDefault() ?? 0; decimal totalInvoiced = apexData.VendIvcs.Where(s => s.PO == invoice.PO).Sum(s => s.IvcAmt) ?? 0; if (apexData.QBInvoices.Where(s => s.Invoice == invoice.Invoice && s.PO == invoice.PO).Any()) { _StatusLines.Add(new StatusLine { Invoice = invoice.Invoice, PO = invoice.PO.Trim(), Message = "Duplicate invoice" }); } else { if (totalInvoiced != 0 && (totalInvoiced - ponet > _MaxDiffAmt)) { _StatusLines.Add(new StatusLine { Invoice = invoice.Invoice, PO = invoice.PO.Trim(), Message = $"The total invoiced {totalInvoiced:c} exceeds the P/O Net amount {ponet:c} by over {_MaxDiffAmt:c}" }); } else { decimal ivcTotal = 0; decimal poTaxableAmt = 0; foreach (VendIvcL ivcLine in invoice.VendIvcLs) { ivcTotal += ivcLine.AmtIvc ?? 0; POLine poline = apexData.POLines.Where(s => s.Po == ivcLine.PO && s.PoLine1 == ivcLine.POLine).SingleOrDefault(); if (poline?.Taxable == "Y") { poTaxableAmt += ivcLine.AmtIvc ?? 0; } } double poTaxRate = apexData.POs.Where(s => s.Po1 == invoice.PO).Select(s => s.TaxRate).SingleOrDefault() ?? 0; ivcTotal += poTaxableAmt * ((decimal)(poTaxRate * 0.01)); decimal invoiceDiff = Math.Abs((invoice.IvcAmt ?? 0) - ivcTotal); if (ivcTotal != 0 && ((double)((invoiceDiff / ivcTotal)) > (_MaxDiffPct * 0.01) || invoiceDiff > _MaxDiffAmt)) { //This enforces a business rule set by the client regarding tolerances when reconciling a vendor invoice _StatusLines.Add(new StatusLine { Invoice = invoice.Invoice, PO = invoice.PO.Trim(), Message = $"The P/O lines invoiced {ivcTotal:c} are more than {_MaxDiffAmt:c} or {_MaxDiffPct}% different from the invoice amount {invoice.IvcAmt:c}" }); } else { //Initial audits passed; process invoice ProcessInvoice(invoice, apexData); } } } } } } catch (System.Runtime.InteropServices.COMException ex) { MessageBox.Show("COM Error Description = " + ex.Message, "COM error"); return; } finally { if (_Ticket != null) { _Rp.EndSession(_Ticket); } if (_Rp != null) { _Rp.CloseConnection(); } UpdateStatus("Export complete"); } }; }
public void Sync() { // Disable the buttons. IsExitEnabled = false; IsTryEnabled = false; IsStartOverEnabled = false; OnPropertyChanged("IsExitEnabled"); OnPropertyChanged("IsTryEnabled"); OnPropertyChanged("IsStartOverEnabled"); // Reset error count. ValidationErrorCount = 0; SaveErrorCount = 0; StatusText = string.Format("{0} - Starting.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // ------------------------------------------------------------ // Ensure the vendor name is specified. // ------------------------------------------------------------ if (string.IsNullOrEmpty(vendorFullName)) { StatusText = string.Format("{0} - Must specify the InventoryConsumptionVendorName in the configuration.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // Enable the buttons. IsExitEnabled = true; IsTryEnabled = true; IsStartOverEnabled = true; OnPropertyChanged("IsExitEnabled"); OnPropertyChanged("IsTryEnabled"); OnPropertyChanged("IsStartOverEnabled"); return; } // ------------------------------------------------------------ // Prepare the QuickBooks connection. // ------------------------------------------------------------ var service = new QuickBooksService(); StatusText += string.Format("{0} - Connecting to QuickBooks.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // QBXML request processor must always be closed after use. var req = new RequestProcessor2(); try { req.OpenConnection2("", "BRIZBEE Integration Utility", QBXMLRPConnectionType.localQBD); var ticket = req.BeginSession("", QBFileMode.qbFileOpenDoNotCare); var companyFileName = req.GetCurrentCompanyFileName(ticket); StatusText += string.Format("{0} - Syncing.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); // Determine the method of recording consumption. if (selectedMethod == "Inventory Adjustment") { StatusText += string.Format("{0} - Using {1} method.\r\n", DateTime.Now.ToString(), selectedMethod); OnPropertyChanged("StatusText"); } else if (selectedMethod == "Sales Receipt") { StatusText += string.Format("{0} - Using {1} method and {2} value.\r\n", DateTime.Now.ToString(), selectedMethod, selectedValue); OnPropertyChanged("StatusText"); } else if (selectedMethod == "Bill") { StatusText += string.Format("{0} - Using {1} method and {2} value with {3} vendor.\r\n", DateTime.Now.ToString(), selectedMethod, selectedValue, vendorFullName); OnPropertyChanged("StatusText"); } // ------------------------------------------------------------ // Collect the QuickBooks host details. // ------------------------------------------------------------ // Prepare a new QBXML document. var hostQBXML = service.MakeQBXMLDocument(); var hostDocument = hostQBXML.Item1; var hostElement = hostQBXML.Item2; service.BuildHostQueryRq(hostDocument, hostElement); // Make the request. Logger.Debug(hostDocument.OuterXml); var hostResponse = req.ProcessRequest(ticket, hostDocument.OuterXml); Logger.Debug(hostResponse); // Then walk the response. var hostWalkResponse = service.WalkHostQueryRsAndParseHostDetails(hostResponse); var hostDetails = hostWalkResponse.Item3; // ------------------------------------------------------------ // Collect any unsynced consumption. // ------------------------------------------------------------ var consumptions = GetConsumption(); var txnIds = new List <string>(consumptions.Count); if (consumptions.Count == 0) { StatusText += string.Format("{0} - There is no inventory consumption to sync.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } else { // ------------------------------------------------------------ // Record the unsynced consumptions. // ------------------------------------------------------------ // Build the request to store consumptions. if (selectedMethod == "Sales Receipt") { // Prepare a new QBXML document. var consQBXML = service.MakeQBXMLDocument(); var consDocument = consQBXML.Item1; var consElement = consQBXML.Item2; service.BuildSalesReceiptAddRq(consDocument, consElement, consumptions, selectedValue.ToUpperInvariant()); // Make the request. Logger.Debug(consDocument.OuterXml); var consResponse = req.ProcessRequest(ticket, consDocument.OuterXml); Logger.Debug(consResponse); // Then walk the response. var walkReponse = service.WalkSalesReceiptAddRs(consResponse); txnIds = walkReponse.Item3; } else if (selectedMethod == "Bill") { foreach (var consumption in consumptions) { // Prepare a new QBXML document. var consQBXML = service.MakeQBXMLDocument(); var consDocument = consQBXML.Item1; var consElement = consQBXML.Item2; service.BuildBillAddRq(consDocument, consElement, consumption, vendorFullName, refNumber, selectedValue.ToUpperInvariant()); // Make the request. Logger.Debug(consDocument.OuterXml); var consResponse = req.ProcessRequest(ticket, consDocument.OuterXml); Logger.Debug(consResponse); // Then walk the response. var walkReponse = service.WalkBillAddRs(consResponse); txnIds = txnIds.Concat(walkReponse.Item3).ToList(); } } else if (selectedMethod == "Inventory Adjustment") { // Prepare a new QBXML document. var consQBXML = service.MakeQBXMLDocument(); var consDocument = consQBXML.Item1; var consElement = consQBXML.Item2; service.BuildInventoryAdjustmentAddRq(consDocument, consElement, consumptions, selectedValue.ToUpperInvariant()); // Make the request. Logger.Debug(consDocument.OuterXml); var consResponse = req.ProcessRequest(ticket, consDocument.OuterXml); Logger.Debug(consResponse); // Then walk the response. var walkReponse = service.WalkInventoryAdjustmentAddRs(consResponse); txnIds = walkReponse.Item3; } if (SaveErrorCount > 0) { StatusText += string.Format("{0} - Sync failed. Please correct the {1} errors first.\r\n", DateTime.Now.ToString(), SaveErrorCount); OnPropertyChanged("StatusText"); var transactionType = ""; switch (selectedMethod) { case "Sales Receipt": transactionType = "SalesReceipt"; break; case "Bill": transactionType = "Bill"; break; case "Inventory Adjustment": transactionType = "InventoryAdjustment"; break; } // Reverse the transactions. foreach (var txnId in txnIds) { // Prepare a new QBXML document. var delQBXML = service.MakeQBXMLDocument(); var delDocument = delQBXML.Item1; var delElement = delQBXML.Item2; service.BuildTxnDelRq(delDocument, delElement, transactionType, txnId); // InventoryAdjustment, SalesReceipt, or Bill // Make the request. Logger.Debug(delDocument.OuterXml); var delResponse = req.ProcessRequest(ticket, delDocument.OuterXml); Logger.Debug(delResponse); // Then walk the response. var delWalkResponse = service.WalkTxnDelRs(delResponse); } } else { // Build the payload. var payload = new { TxnIDs = txnIds, Ids = consumptions.Select(c => c.Id).ToArray() }; // Build the request to send the sync details. var syncHttpRequest = new RestRequest("api/QBDInventoryConsumptions/Sync", Method.POST); syncHttpRequest.AddJsonBody(payload); syncHttpRequest.AddQueryParameter("recordingMethod", selectedMethod); syncHttpRequest.AddQueryParameter("valueMethod", selectedValue); syncHttpRequest.AddQueryParameter("productName", hostDetails.QBProductName); syncHttpRequest.AddQueryParameter("majorVersion", hostDetails.QBMajorVersion); syncHttpRequest.AddQueryParameter("minorVersion", hostDetails.QBMinorVersion); syncHttpRequest.AddQueryParameter("country", hostDetails.QBCountry); syncHttpRequest.AddQueryParameter("supportedQBXMLVersion", hostDetails.QBSupportedQBXMLVersions); syncHttpRequest.AddQueryParameter("hostname", Environment.MachineName); syncHttpRequest.AddQueryParameter("companyFilePath", companyFileName); // Execute request. var syncHttpResponse = client.Execute(syncHttpRequest); if ((syncHttpResponse.ResponseStatus == ResponseStatus.Completed) && (syncHttpResponse.StatusCode == System.Net.HttpStatusCode.OK)) { StatusText += string.Format("{0} - Synced Successfully.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } else { StatusText += $"{DateTime.Now} - {syncHttpResponse.Content}"; StatusText += string.Format("{0} - Sync failed.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } } } // Close the QuickBooks connection. req.EndSession(ticket); req.CloseConnection(); req = null; } catch (DownloadFailedException) { StatusText += string.Format("{0} - Sync failed. Could not download consumption from the server.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } catch (COMException cex) { Logger.Error(cex.ToString()); if ((uint)cex.ErrorCode == 0x80040408) { StatusText += string.Format("{0} - Sync failed. QuickBooks Desktop is not open.\r\n", DateTime.Now.ToString()); OnPropertyChanged("StatusText"); } else { StatusText += string.Format("{0} - Sync failed. {1}\r\n", DateTime.Now.ToString(), cex.Message); OnPropertyChanged("StatusText"); } } catch (Exception ex) { Logger.Error(ex.ToString()); StatusText += string.Format("{0} - Sync failed. {1}\r\n", DateTime.Now.ToString(), ex.Message); OnPropertyChanged("StatusText"); } finally { // Enable the buttons. IsExitEnabled = true; IsTryEnabled = true; IsStartOverEnabled = true; OnPropertyChanged("IsExitEnabled"); OnPropertyChanged("IsTryEnabled"); OnPropertyChanged("IsStartOverEnabled"); // Try to close the QuickBooks connection if it is still open. if (req != null) { req.CloseConnection(); req = null; } } }