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; } } }
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 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; } } }