From 229d9eccecf13257e23455ba537101b201bee593 Mon Sep 17 00:00:00 2001 From: Bobbie Hodgetts Date: Wed, 5 Feb 2020 14:52:37 +0000 Subject: [PATCH] Xero invoice export feature Added Xero invoice export feature and other small improvements --- .../Form1.Designer.cs | 172 ++++++++---------- .../BealeEngineering.Accounts/Form1.cs | 56 +++++- .../BealeEngineering.Core.csproj | 6 + .../Data/Database/Sale/ReadInvoice.cs | 4 +- .../Data/Database/Sale/UpdateInvoice.cs | 26 ++- .../Data/Xero/ReadXeroInvoiceFlatFile.cs | 90 +-------- .../Logic/Adapter/Contact.cs | 33 ++++ .../Logic/Adapter/SaleInvoice.cs | 66 +++++++ .../Logic/Adapter/XeroInvoiceFlatFile.cs | 148 +++++++++++++++ .../Logic/Adapter/XeroInvoiceFlatFileDTO.cs | 100 ++++++++++ .../Logic/Export/XeroInvoiceFlatFile.cs | 53 ++++++ .../Logic/Import/XeroInvoiceFlatFile.cs | 114 +++--------- .../Model/Import/XeroInvoiceFlatFile.cs | 2 +- .../BealeEngineering.Core/Test/AUtoexec.cs | 6 +- .../Test/Export/FlatFile.cs | 27 +++ .../Test/Import/ImportFlatfile.cs | 2 +- 16 files changed, 628 insertions(+), 277 deletions(-) create mode 100644 BealeEngineering/BealeEngineering.Core/Logic/Adapter/Contact.cs create mode 100644 BealeEngineering/BealeEngineering.Core/Logic/Adapter/SaleInvoice.cs create mode 100644 BealeEngineering/BealeEngineering.Core/Logic/Adapter/XeroInvoiceFlatFile.cs create mode 100644 BealeEngineering/BealeEngineering.Core/Logic/Adapter/XeroInvoiceFlatFileDTO.cs create mode 100644 BealeEngineering/BealeEngineering.Core/Logic/Export/XeroInvoiceFlatFile.cs create mode 100644 BealeEngineering/BealeEngineering.Core/Test/Export/FlatFile.cs diff --git a/BealeEngineering/BealeEngineering.Accounts/Form1.Designer.cs b/BealeEngineering/BealeEngineering.Accounts/Form1.Designer.cs index eec3bab..4009c3a 100644 --- a/BealeEngineering/BealeEngineering.Accounts/Form1.Designer.cs +++ b/BealeEngineering/BealeEngineering.Accounts/Form1.Designer.cs @@ -33,7 +33,6 @@ System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle(); - this.purchaseOrderAllocationBindingSource = new System.Windows.Forms.BindingSource(this.components); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.splitContainer3 = new System.Windows.Forms.SplitContainer(); @@ -44,6 +43,14 @@ this.textBox1 = new System.Windows.Forms.TextBox(); this.txtUnallocatedCount = new System.Windows.Forms.TextBox(); this.dataGridView1 = new System.Windows.Forms.DataGridView(); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.xeroInvoiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.testToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.testItToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.xeroInvoiceToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.contactNameDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.projectTitleDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.purchaseOrderDateDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); @@ -57,15 +64,7 @@ this.purchaseOrderIsClosedDataGridViewCheckBoxColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn(); this.jobTitleDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.jobDescriptionDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.tabPage2 = new System.Windows.Forms.TabPage(); - this.splitContainer2 = new System.Windows.Forms.SplitContainer(); - this.menuStrip1 = new System.Windows.Forms.MenuStrip(); - this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.xeroInvoiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.testToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.testItToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - ((System.ComponentModel.ISupportInitialize)(this.purchaseOrderAllocationBindingSource)).BeginInit(); + this.purchaseOrderAllocationBindingSource = new System.Windows.Forms.BindingSource(this.components); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); @@ -73,21 +72,13 @@ this.splitContainer3.Panel2.SuspendLayout(); this.splitContainer3.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); - this.tabPage2.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); - this.splitContainer2.SuspendLayout(); this.menuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.purchaseOrderAllocationBindingSource)).BeginInit(); this.SuspendLayout(); // - // purchaseOrderAllocationBindingSource - // - this.purchaseOrderAllocationBindingSource.AllowNew = false; - this.purchaseOrderAllocationBindingSource.DataSource = typeof(BealeEngineering.Core.Model.Client.PurchaseOrderAllocation); - // // tabControl1 // this.tabControl1.Controls.Add(this.tabPage1); - this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControl1.Location = new System.Drawing.Point(0, 24); this.tabControl1.Name = "tabControl1"; @@ -221,6 +212,70 @@ this.dataGridView1.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellContentClick); this.dataGridView1.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellDoubleClick); // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.importToolStripMenuItem, + this.exportToolStripMenuItem, + this.testToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(1151, 24); + this.menuStrip1.TabIndex = 6; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Text = "File"; + // + // importToolStripMenuItem + // + this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.xeroInvoiceToolStripMenuItem}); + this.importToolStripMenuItem.Name = "importToolStripMenuItem"; + this.importToolStripMenuItem.Size = new System.Drawing.Size(55, 20); + this.importToolStripMenuItem.Text = "Import"; + // + // xeroInvoiceToolStripMenuItem + // + this.xeroInvoiceToolStripMenuItem.Name = "xeroInvoiceToolStripMenuItem"; + this.xeroInvoiceToolStripMenuItem.Size = new System.Drawing.Size(139, 22); + this.xeroInvoiceToolStripMenuItem.Text = "Xero Invoice"; + this.xeroInvoiceToolStripMenuItem.Click += new System.EventHandler(this.xeroInvoiceToolStripMenuItem_Click); + // + // testToolStripMenuItem + // + this.testToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.testItToolStripMenuItem}); + this.testToolStripMenuItem.Name = "testToolStripMenuItem"; + this.testToolStripMenuItem.Size = new System.Drawing.Size(39, 20); + this.testToolStripMenuItem.Text = "Test"; + // + // testItToolStripMenuItem + // + this.testItToolStripMenuItem.Name = "testItToolStripMenuItem"; + this.testItToolStripMenuItem.Size = new System.Drawing.Size(107, 22); + this.testItToolStripMenuItem.Text = "Test it!"; + this.testItToolStripMenuItem.Click += new System.EventHandler(this.testItToolStripMenuItem_Click); + // + // exportToolStripMenuItem + // + this.exportToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.xeroInvoiceToolStripMenuItem1}); + this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; + this.exportToolStripMenuItem.Size = new System.Drawing.Size(53, 20); + this.exportToolStripMenuItem.Text = "Export"; + // + // xeroInvoiceToolStripMenuItem1 + // + this.xeroInvoiceToolStripMenuItem1.Name = "xeroInvoiceToolStripMenuItem1"; + this.xeroInvoiceToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + this.xeroInvoiceToolStripMenuItem1.Text = "Xero Invoice"; + this.xeroInvoiceToolStripMenuItem1.Click += new System.EventHandler(this.xeroInvoiceToolStripMenuItem1_Click); + // // contactNameDataGridViewTextBoxColumn // this.contactNameDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; @@ -363,74 +418,10 @@ this.jobDescriptionDataGridViewTextBoxColumn.ReadOnly = true; this.jobDescriptionDataGridViewTextBoxColumn.Visible = false; // - // tabPage2 + // purchaseOrderAllocationBindingSource // - this.tabPage2.Controls.Add(this.splitContainer2); - this.tabPage2.Location = new System.Drawing.Point(4, 22); - this.tabPage2.Name = "tabPage2"; - this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(1143, 695); - this.tabPage2.TabIndex = 1; - this.tabPage2.Text = "tabPage2"; - this.tabPage2.UseVisualStyleBackColor = true; - // - // splitContainer2 - // - this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer2.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; - this.splitContainer2.Location = new System.Drawing.Point(3, 3); - this.splitContainer2.Name = "splitContainer2"; - this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; - this.splitContainer2.Size = new System.Drawing.Size(1137, 689); - this.splitContainer2.SplitterDistance = 100; - this.splitContainer2.TabIndex = 0; - // - // menuStrip1 - // - this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.fileToolStripMenuItem, - this.importToolStripMenuItem, - this.testToolStripMenuItem}); - this.menuStrip1.Location = new System.Drawing.Point(0, 0); - this.menuStrip1.Name = "menuStrip1"; - this.menuStrip1.Size = new System.Drawing.Size(1151, 24); - this.menuStrip1.TabIndex = 6; - this.menuStrip1.Text = "menuStrip1"; - // - // fileToolStripMenuItem - // - this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; - this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); - this.fileToolStripMenuItem.Text = "File"; - // - // importToolStripMenuItem - // - this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.xeroInvoiceToolStripMenuItem}); - this.importToolStripMenuItem.Name = "importToolStripMenuItem"; - this.importToolStripMenuItem.Size = new System.Drawing.Size(55, 20); - this.importToolStripMenuItem.Text = "Import"; - // - // xeroInvoiceToolStripMenuItem - // - this.xeroInvoiceToolStripMenuItem.Name = "xeroInvoiceToolStripMenuItem"; - this.xeroInvoiceToolStripMenuItem.Size = new System.Drawing.Size(139, 22); - this.xeroInvoiceToolStripMenuItem.Text = "Xero Invoice"; - // - // testToolStripMenuItem - // - this.testToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.testItToolStripMenuItem}); - this.testToolStripMenuItem.Name = "testToolStripMenuItem"; - this.testToolStripMenuItem.Size = new System.Drawing.Size(39, 20); - this.testToolStripMenuItem.Text = "Test"; - // - // testItToolStripMenuItem - // - this.testItToolStripMenuItem.Name = "testItToolStripMenuItem"; - this.testItToolStripMenuItem.Size = new System.Drawing.Size(107, 22); - this.testItToolStripMenuItem.Text = "Test it!"; - this.testItToolStripMenuItem.Click += new System.EventHandler(this.testItToolStripMenuItem_Click); + this.purchaseOrderAllocationBindingSource.AllowNew = false; + this.purchaseOrderAllocationBindingSource.DataSource = typeof(BealeEngineering.Core.Model.Client.PurchaseOrderAllocation); // // Form1 // @@ -443,7 +434,6 @@ this.Name = "Form1"; this.Text = "Form1"; this.Load += new System.EventHandler(this.Form1_Load); - ((System.ComponentModel.ISupportInitialize)(this.purchaseOrderAllocationBindingSource)).EndInit(); this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); this.splitContainer3.Panel1.ResumeLayout(false); @@ -452,11 +442,9 @@ ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); this.splitContainer3.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); - this.tabPage2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); - this.splitContainer2.ResumeLayout(false); this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.purchaseOrderAllocationBindingSource)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -474,8 +462,6 @@ private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.TextBox txtUnallocatedCount; private System.Windows.Forms.DataGridView dataGridView1; - private System.Windows.Forms.TabPage tabPage2; - private System.Windows.Forms.SplitContainer splitContainer2; private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem importToolStripMenuItem; @@ -495,6 +481,8 @@ private System.Windows.Forms.DataGridViewCheckBoxColumn purchaseOrderIsClosedDataGridViewCheckBoxColumn; private System.Windows.Forms.DataGridViewTextBoxColumn jobTitleDataGridViewTextBoxColumn; private System.Windows.Forms.DataGridViewTextBoxColumn jobDescriptionDataGridViewTextBoxColumn; + private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem xeroInvoiceToolStripMenuItem1; } } diff --git a/BealeEngineering/BealeEngineering.Accounts/Form1.cs b/BealeEngineering/BealeEngineering.Accounts/Form1.cs index 983c2ed..3fd3540 100644 --- a/BealeEngineering/BealeEngineering.Accounts/Form1.cs +++ b/BealeEngineering/BealeEngineering.Accounts/Form1.cs @@ -14,13 +14,14 @@ namespace BealeEngineering.Accounts { public partial class Form1 : Form { + private string sqlConnectionString; + public Form1() { InitializeComponent(); - SqlConnectionString = ConfigurationManager.ConnectionStrings["BealeEngSQLDb"].ToString(); + sqlConnectionString = ConfigurationManager.ConnectionStrings["BealeEngSQLDb"].ToString(); } - private string SqlConnectionString { get; set; } public List TableData { get; set; } private void Form1_Load(object sender, EventArgs e) @@ -36,7 +37,7 @@ namespace BealeEngineering.Accounts private void UpdateTable() { - var readData = new Core.Data.Database.Client.ReadPurchaseOrderAllocation(SqlConnectionString); + var readData = new Core.Data.Database.Client.ReadPurchaseOrderAllocation(sqlConnectionString); var data = readData.Read(); //dataGridView1.Rows.AddRange() @@ -101,7 +102,7 @@ namespace BealeEngineering.Accounts private void button2_Click(object sender, EventArgs e) { - var dataRead = new Core.Data.Database.Client.ReadSaleInvoiceAllocation(SqlConnectionString); + var dataRead = new Core.Data.Database.Client.ReadSaleInvoiceAllocation(sqlConnectionString); txtUnallocatedCount.Text = dataRead.GetUnallocatedInvoiceCount().ToString(); } @@ -117,7 +118,7 @@ namespace BealeEngineering.Accounts private void testItToolStripMenuItem_Click(object sender, EventArgs e) { - var inst = new Core.Test.Autoexec(SqlConnectionString); + var inst = new Core.Test.Autoexec(sqlConnectionString); } private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) @@ -129,5 +130,50 @@ namespace BealeEngineering.Accounts { } + + private void xeroInvoiceToolStripMenuItem_Click(object sender, EventArgs e) + { + string fileInputPath = + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + + @"\Dropbox\Beale Engineering Services Ltd\BE Accounts\Xero-Export-Invoices - Orig.csv"; + + string dialogText = "Importing file from location: " + Environment.NewLine + Environment.NewLine + fileInputPath; + + DialogResult dialogResult = MessageBox.Show(dialogText, "Import Xero Invoice flat-file", MessageBoxButtons.OKCancel); + if (dialogResult == DialogResult.OK) + { + var importXeroInvoice = new BealeEngineering.Core.Logic.Import.XeroInvoiceFlatFile(sqlConnectionString); + importXeroInvoice.ByFilePath(fileInputPath); + + dialogText = "Import complete." + Environment.NewLine + Environment.NewLine + + importXeroInvoice.InvoicesProcessed + " invoice(s) found" + Environment.NewLine + + importXeroInvoice.InvoicesCreated + " invoice(s) created" + Environment.NewLine + + importXeroInvoice.InvoicesUpdated + " invoice(s) updated" + Environment.NewLine; + + MessageBox.Show(dialogText); + } + } + + private void xeroInvoiceToolStripMenuItem1_Click(object sender, EventArgs e) + { + string filePath = + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + + @"\Dropbox\Beale Engineering Services Ltd\BE Accounts\Xero-Export-Invoices.csv"; + + string dialogText = "Exporting all sales invoices to location: " + Environment.NewLine + Environment.NewLine + filePath; + + DialogResult dialogResult = MessageBox.Show(dialogText, "Export Xero Invoice flat-file", MessageBoxButtons.OKCancel); + if (dialogResult == DialogResult.OK) + { + var exportXeroInvoice = new BealeEngineering.Core.Logic.Export.XeroInvoiceFlatFile(sqlConnectionString); + exportXeroInvoice.FileOutputPath = filePath; + exportXeroInvoice.Execute(); + + dialogText = "Export complete." + Environment.NewLine + Environment.NewLine + + exportXeroInvoice.InvoicesExported + " invoice(s) exported" + Environment.NewLine; + + MessageBox.Show(dialogText); + } + } } } diff --git a/BealeEngineering/BealeEngineering.Core/BealeEngineering.Core.csproj b/BealeEngineering/BealeEngineering.Core/BealeEngineering.Core.csproj index a150bed..8f1c218 100644 --- a/BealeEngineering/BealeEngineering.Core/BealeEngineering.Core.csproj +++ b/BealeEngineering/BealeEngineering.Core/BealeEngineering.Core.csproj @@ -67,6 +67,11 @@ + + + + + @@ -93,6 +98,7 @@ + diff --git a/BealeEngineering/BealeEngineering.Core/Data/Database/Sale/ReadInvoice.cs b/BealeEngineering/BealeEngineering.Core/Data/Database/Sale/ReadInvoice.cs index 5afe4f2..110b517 100644 --- a/BealeEngineering/BealeEngineering.Core/Data/Database/Sale/ReadInvoice.cs +++ b/BealeEngineering/BealeEngineering.Core/Data/Database/Sale/ReadInvoice.cs @@ -28,7 +28,7 @@ namespace BealeEngineering.Core.Data.Database.Sale SalesInvoiceIdList = invoiceIdList; try { - return GetByFilters(); + return Read(); } catch (Exception ex) { @@ -39,7 +39,7 @@ namespace BealeEngineering.Core.Data.Database.Sale SalesInvoiceIdList = null; } } - public new List GetByFilters() + public new List Read() { // build the sql string and dapper parameters var parameters = new DynamicParameters(); diff --git a/BealeEngineering/BealeEngineering.Core/Data/Database/Sale/UpdateInvoice.cs b/BealeEngineering/BealeEngineering.Core/Data/Database/Sale/UpdateInvoice.cs index 7c5c9a3..85a4a79 100644 --- a/BealeEngineering/BealeEngineering.Core/Data/Database/Sale/UpdateInvoice.cs +++ b/BealeEngineering/BealeEngineering.Core/Data/Database/Sale/UpdateInvoice.cs @@ -11,10 +11,17 @@ namespace BealeEngineering.Core.Data.Database.Sale { public class UpdateInvoice : Connection { + private int recordsCreated = 0; + private int recordsUpdated = 0; + private int invoicesProcessed = 0; + public UpdateInvoice(string sqlConnectionString) : base(sqlConnectionString) { } + public int RecordsCreated { get { return recordsCreated; } } + public int RecordsUpdated { get { return recordsUpdated; } } + public int InvoicesProcessed { get { return invoicesProcessed; } } public void ByInvoice(Model.Sale.Invoice invoice, bool insertNew = false) { var invoiceList = new List { invoice }; @@ -22,7 +29,14 @@ namespace BealeEngineering.Core.Data.Database.Sale } public void ByInvoiceList(List invoiceList, bool insertNew = false) { + recordsCreated = 0; + recordsUpdated = 0; + invoicesProcessed = 0; + // check the list + if (invoiceList == null || !invoiceList.Any()) { return; } + else { invoicesProcessed = invoiceList.Count(); } + CheckList(ref invoiceList); using (TransactionScope scope = new TransactionScope()) @@ -120,11 +134,13 @@ namespace BealeEngineering.Core.Data.Database.Sale if (saleInvoiceId == 0) { saleInvoiceId = (int)cmd.ExecuteScalar(); + recordsCreated += 1; } else { cmd.Parameters.AddWithValue("@saleInvoiceId", saleInvoiceId); int effected = cmd.ExecuteNonQuery(); + recordsUpdated += 1; } } @@ -182,7 +198,15 @@ namespace BealeEngineering.Core.Data.Database.Sale } } } - scope.Complete(); + if (InvoicesProcessed == (RecordsCreated + RecordsUpdated)) + { + scope.Complete(); + } + else + { + scope.Dispose(); + throw new Exception("Error updating invoices, DB transaction has been rolled back"); + } } } private void CheckList(ref List invoiceList) diff --git a/BealeEngineering/BealeEngineering.Core/Data/Xero/ReadXeroInvoiceFlatFile.cs b/BealeEngineering/BealeEngineering.Core/Data/Xero/ReadXeroInvoiceFlatFile.cs index a2c5926..2dbbf3f 100644 --- a/BealeEngineering/BealeEngineering.Core/Data/Xero/ReadXeroInvoiceFlatFile.cs +++ b/BealeEngineering/BealeEngineering.Core/Data/Xero/ReadXeroInvoiceFlatFile.cs @@ -64,95 +64,7 @@ namespace BealeEngineering.Core.Data.Xero.FlatFile dto = csv.GetRecords().ToList(); } - return ConvertFlatDTO(ref dto).Values.ToList(); - } - - private Dictionary ConvertFlatDTO(ref List flatData) - { - // ensure flat data is in invoice number order - var invDictionary = new Dictionary(); - string lastNumber = null; - foreach (var line in flatData) - { - if (line.InvoiceNumber != lastNumber) - { - lastNumber = line.InvoiceNumber; - if (invDictionary.ContainsKey(lastNumber)) - { - throw new Exception("Invoices are not grouped in CSV flatfile."); - } - else - { - invDictionary.Add(lastNumber, 0); - } - } - } - - // convert to one to many class data - var dictionaryList = new Dictionary(); - foreach (var line in flatData) - { - string invoiceNumber = line.InvoiceNumber; - - if (!dictionaryList.ContainsKey(invoiceNumber)) - { - var invoice = new Model.Import.XeroInvoiceFlatFile(); - - invoice.ContactName = line.ContactName; - invoice.Currency = line.Currency; - invoice.DueDate = line.DueDate; - invoice.EmailAddress = line.EmailAddress; - invoice.InvoiceAmountDue = line.InvoiceAmountDue; - invoice.InvoiceAmountPaid = line.InvoiceAmountPaid; - invoice.InvoiceDate = line.InvoiceDate; - invoice.InvoiceNumber = line.InvoiceNumber; - invoice.PlannedDate = line.PlannedDate; - invoice.POAddressLine1 = line.POAddressLine1; - invoice.POAddressLine2 = line.POAddressLine2; - invoice.POAddressLine3 = line.POAddressLine3; - invoice.POAddressLine4 = line.POAddressLine4; - invoice.POCity = line.POCity; - invoice.POCountry = line.POCountry; - invoice.POPostalCode = line.POPostalCode; - invoice.PORegion = line.PORegion; - invoice.Reference = line.Reference; - invoice.SAAddressLine1 = line.SAAddressLine1; - invoice.SAAddressLine2 = line.SAAddressLine2; - invoice.SAAddressLine3 = line.SAAddressLine3; - invoice.SAAddressLine4 = line.SAAddressLine4; - invoice.SACity = line.SACity; - invoice.SACountry = line.SACountry; - invoice.SAPostalCode = line.SAPostalCode; - invoice.SARegion = line.SARegion; - invoice.Sent = line.Sent; - invoice.Status = line.Status; - invoice.TaxTotal = line.TaxTotal; - invoice.Total = line.Total; - invoice.Type = line.Type; - - dictionaryList.Add(invoice.InvoiceNumber, invoice); - } - - var item = new Model.Import.XeroInvoiceFlatFile.LineItem(); - - item.AccountCode = line.AccountCode; - item.Description = line.Description; - item.Discount = line.Discount; - item.InventoryItemCode = line.InventoryItemCode; - item.LineAmount = line.LineAmount; - item.Quantity = line.Quantity; - item.TaxAmount = line.TaxAmount; - item.TaxType = line.TaxType; - item.TrackingName1 = line.TrackingName1; - item.TrackingName2 = line.TrackingName2; - item.TrackingOption1 = line.TrackingOption1; - item.TrackingOption2 = line.TrackingOption2; - item.UnitAmount = line.UnitAmount; - - dictionaryList[invoiceNumber].LineItems.Add(item); - } - - return dictionaryList; + return new Logic.Adapter.XeroInvoiceFlatFile().XeroInvoiceFlatFileDTO(dto); } } } diff --git a/BealeEngineering/BealeEngineering.Core/Logic/Adapter/Contact.cs b/BealeEngineering/BealeEngineering.Core/Logic/Adapter/Contact.cs new file mode 100644 index 0000000..a8d0858 --- /dev/null +++ b/BealeEngineering/BealeEngineering.Core/Logic/Adapter/Contact.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BealeEngineering.Core.Logic.Adapter +{ + public class Contact + { + public Model.Contact.Contact XeroInvoiceFlatFile(Model.Import.XeroInvoiceFlatFile xeroInvoice) + { + var contact = new Model.Contact.Contact(); + contact.ContactName = xeroInvoice.ContactName; + if (string.IsNullOrWhiteSpace(xeroInvoice.EmailAddress)) { contact.EmailAddress = null; } + else { contact.EmailAddress = xeroInvoice.EmailAddress; } + + var address = new Model.Contact.Address(); + address.AddressLine1 = xeroInvoice.POAddressLine1; + address.AddressLine2 = xeroInvoice.POAddressLine2; + address.AddressLine3 = xeroInvoice.POAddressLine3; + address.AddressLine4 = xeroInvoice.POAddressLine4; + address.City = xeroInvoice.POCity; + address.Country = xeroInvoice.POCountry; + address.PostalCode = xeroInvoice.POPostalCode; + address.Region = xeroInvoice.PORegion; + + if (address.IsValid()) { contact.PostalAddress = address; } + + return contact; + } + } +} diff --git a/BealeEngineering/BealeEngineering.Core/Logic/Adapter/SaleInvoice.cs b/BealeEngineering/BealeEngineering.Core/Logic/Adapter/SaleInvoice.cs new file mode 100644 index 0000000..d24ccae --- /dev/null +++ b/BealeEngineering/BealeEngineering.Core/Logic/Adapter/SaleInvoice.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BealeEngineering.Core.Logic.Adapter +{ + public class SaleInvoice + { + public Model.Sale.Invoice XeroInvoiceFlatFIle(Model.Import.XeroInvoiceFlatFile xeroInvoice) + { + var result = XeroInvoiceFlatFile(new List { xeroInvoice }); + if (result == null) { return null; } + else { return result[0]; } + } + + public List XeroInvoiceFlatFile(List xeroInvoiceList) + { + var dbInvoiceData = new List(); + for (var i = 0; i < xeroInvoiceList.Count; i++) + { + if (xeroInvoiceList[i] == null) { throw new NullReferenceException(); } + var invoice = new Model.Sale.Invoice(); + + invoice.ContactName = xeroInvoiceList[i].ContactName; + invoice.CurrencyCode = xeroInvoiceList[i].Currency; + invoice.DueDate = xeroInvoiceList[i].DueDate; + invoice.InvoiceDate = xeroInvoiceList[i].InvoiceDate; + invoice.InvoiceTotal = xeroInvoiceList[i].Total; + if (xeroInvoiceList[i].Type == "Sales invoice") { invoice.IsCreditNote = false; } + else if (xeroInvoiceList[i].Type == "Sales credit note") { invoice.IsCreditNote = true; } + else { throw new FormatException("Unknow value '" + xeroInvoiceList[i].Type + "' found in 'Type' field"); } + invoice.Reference = xeroInvoiceList[i].Reference; + invoice.SaleInvoiceNumber = xeroInvoiceList[i].InvoiceNumber; + invoice.TaxTotal = xeroInvoiceList[i].TaxTotal; + + invoice.InvoiceLineList = new List(); + for (int j = 0; j < xeroInvoiceList[i].LineItemList.Count; j++) + { + if (xeroInvoiceList[i].LineItemList[j] == null) { throw new NullReferenceException(); } + var invoiceLine = new Model.Sale.Invoice.InvoiceLine(); + + invoiceLine.LineNumber = j + 1; + invoiceLine.AccountCode = xeroInvoiceList[i].LineItemList[j].AccountCode; + invoiceLine.Description = xeroInvoiceList[i].LineItemList[j].Description; + invoiceLine.Discount = xeroInvoiceList[i].LineItemList[j].Discount; + invoiceLine.InventoryItemCode = xeroInvoiceList[i].LineItemList[j].InventoryItemCode; + invoiceLine.Quantity = xeroInvoiceList[i].LineItemList[j].Quantity; + invoiceLine.TaxAmount = xeroInvoiceList[i].LineItemList[j].TaxAmount; + invoiceLine.TaxType = xeroInvoiceList[i].LineItemList[j].TaxType; + invoiceLine.UnitAmount = xeroInvoiceList[i].LineItemList[j].UnitAmount; + + //check, as line amount is same as calculated in model + if (invoiceLine.LineAmount != xeroInvoiceList[i].LineItemList[j].LineAmount) + { + throw new Exception("Imported line total does not equal caluclated."); + } + invoice.InvoiceLineList.Add(invoiceLine); + } + dbInvoiceData.Add(invoice); + } + return dbInvoiceData; + } + } +} diff --git a/BealeEngineering/BealeEngineering.Core/Logic/Adapter/XeroInvoiceFlatFile.cs b/BealeEngineering/BealeEngineering.Core/Logic/Adapter/XeroInvoiceFlatFile.cs new file mode 100644 index 0000000..f1d685e --- /dev/null +++ b/BealeEngineering/BealeEngineering.Core/Logic/Adapter/XeroInvoiceFlatFile.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BealeEngineering.Core.Logic.Adapter +{ + public class XeroInvoiceFlatFile + { + public List SaleInvoice(List invoiceList) + { + if (invoiceList == null || !invoiceList.Any()) { return null; } + + var xeroInvoiceList = new List(); + for (int i = 0; i < invoiceList.Count(); i++) + { + var xeroInvoice = new Model.Import.XeroInvoiceFlatFile(); + + xeroInvoice.ContactName = invoiceList[i].ContactName; + xeroInvoice.Currency = invoiceList[i].CurrencyCode; + xeroInvoice.DueDate = invoiceList[i].DueDate; + xeroInvoice.InvoiceDate = invoiceList[i].InvoiceDate; + xeroInvoice.InvoiceNumber = invoiceList[i].SaleInvoiceNumber; + xeroInvoice.Reference = invoiceList[i].Reference; + xeroInvoice.TaxTotal = invoiceList[i].TaxTotal; + xeroInvoice.Total = invoiceList[i].InvoiceTotal; + if (invoiceList[i].IsCreditNote) { xeroInvoice.Type = "Sales credit note"; } + else { xeroInvoice.Type = "Sales invoice"; } + + // invoice lines + if (invoiceList[i].InvoiceLineListIsSet) + { + xeroInvoice.LineItemList = new List(); + for (int j = 0; j < invoiceList[i].InvoiceLineList.Count(); j++) + { + var line = new Model.Import.XeroInvoiceFlatFile.LineItem(); + line.AccountCode = invoiceList[i].InvoiceLineList[j].AccountCode; + line.Description = invoiceList[i].InvoiceLineList[j].Description; + line.Discount = invoiceList[i].InvoiceLineList[j].Discount; + line.InventoryItemCode = invoiceList[i].InvoiceLineList[j].InventoryItemCode; + line.LineAmount = invoiceList[i].InvoiceLineList[j].LineAmount; + line.Quantity = invoiceList[i].InvoiceLineList[j].Quantity; + line.TaxAmount = invoiceList[i].InvoiceLineList[j].TaxAmount; + line.TaxType = invoiceList[i].InvoiceLineList[j].TaxType; + line.UnitAmount = invoiceList[i].InvoiceLineList[j].UnitAmount; + + xeroInvoice.LineItemList.Add(line); + } + } + xeroInvoiceList.Add(xeroInvoice); + } + return xeroInvoiceList; + } + + public List XeroInvoiceFlatFileDTO(List flatData) + { + if (flatData == null || !flatData.Any()) { return null; } + + // ensure flat data is in invoice number order + var invDictionary = new Dictionary(); + string lastNumber = null; + foreach (var line in flatData) + { + if (line.InvoiceNumber != lastNumber) + { + lastNumber = line.InvoiceNumber; + if (invDictionary.ContainsKey(lastNumber)) + { + throw new Exception("Invoices are not grouped in CSV flatfile."); + } + else + { + invDictionary.Add(lastNumber, 0); + } + } + } + + // create the invoice list + var dictionaryList = new Dictionary(); + + for (int i = 0; i < flatData.Count(); i++) + //foreach (var line in flatData) + { + string invoiceNumber = flatData[i].InvoiceNumber; + + if (!dictionaryList.ContainsKey(invoiceNumber)) + { + var invoice = new Model.Import.XeroInvoiceFlatFile(); + + invoice.ContactName = flatData[i].ContactName; + invoice.Currency = flatData[i].Currency; + invoice.DueDate = flatData[i].DueDate; + invoice.EmailAddress = flatData[i].EmailAddress; + invoice.InvoiceAmountDue = flatData[i].InvoiceAmountDue; + invoice.InvoiceAmountPaid = flatData[i].InvoiceAmountPaid; + invoice.InvoiceDate = flatData[i].InvoiceDate; + invoice.InvoiceNumber = flatData[i].InvoiceNumber; + invoice.PlannedDate = flatData[i].PlannedDate; + invoice.POAddressLine1 = flatData[i].POAddressLine1; + invoice.POAddressLine2 = flatData[i].POAddressLine2; + invoice.POAddressLine3 = flatData[i].POAddressLine3; + invoice.POAddressLine4 = flatData[i].POAddressLine4; + invoice.POCity = flatData[i].POCity; + invoice.POCountry = flatData[i].POCountry; + invoice.POPostalCode = flatData[i].POPostalCode; + invoice.PORegion = flatData[i].PORegion; + invoice.Reference = flatData[i].Reference; + invoice.SAAddressLine1 = flatData[i].SAAddressLine1; + invoice.SAAddressLine2 = flatData[i].SAAddressLine2; + invoice.SAAddressLine3 = flatData[i].SAAddressLine3; + invoice.SAAddressLine4 = flatData[i].SAAddressLine4; + invoice.SACity = flatData[i].SACity; + invoice.SACountry = flatData[i].SACountry; + invoice.SAPostalCode = flatData[i].SAPostalCode; + invoice.SARegion = flatData[i].SARegion; + invoice.Sent = flatData[i].Sent; + invoice.Status = flatData[i].Status; + invoice.TaxTotal = flatData[i].TaxTotal; + invoice.Total = flatData[i].Total; + invoice.Type = flatData[i].Type; + + dictionaryList.Add(invoiceNumber, invoice); + } + + var item = new Model.Import.XeroInvoiceFlatFile.LineItem(); + + item.AccountCode = flatData[i].AccountCode; + item.Description = flatData[i].Description; + item.Discount = flatData[i].Discount; + item.InventoryItemCode = flatData[i].InventoryItemCode; + item.LineAmount = flatData[i].LineAmount; + item.Quantity = flatData[i].Quantity; + item.TaxAmount = flatData[i].TaxAmount; + item.TaxType = flatData[i].TaxType; + item.TrackingName1 = flatData[i].TrackingName1; + item.TrackingName2 = flatData[i].TrackingName2; + item.TrackingOption1 = flatData[i].TrackingOption1; + item.TrackingOption2 = flatData[i].TrackingOption2; + item.UnitAmount = flatData[i].UnitAmount; + + dictionaryList[invoiceNumber].LineItemList.Add(item); + } + + return dictionaryList.Values.ToList(); + } + } +} diff --git a/BealeEngineering/BealeEngineering.Core/Logic/Adapter/XeroInvoiceFlatFileDTO.cs b/BealeEngineering/BealeEngineering.Core/Logic/Adapter/XeroInvoiceFlatFileDTO.cs new file mode 100644 index 0000000..e597556 --- /dev/null +++ b/BealeEngineering/BealeEngineering.Core/Logic/Adapter/XeroInvoiceFlatFileDTO.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BealeEngineering.Core.Logic.Adapter +{ + class XeroInvoiceFlatFileDTO + { + public XeroInvoiceFlatFileDTO() + { + // ensure XeroInvoiceFlatFileDTO hasn't changed + int dtoPropertyCouny = new Model.Import.XeroInvoiceFlatFileDTO().GetType().GetProperties().Count(); + if (dtoPropertyCouny != 44) + { + throw new Exception("Model.Import.XeroInvoiceFlatFileDTO has changed, it's adapter class needs updating."); + } + } + public List XeroInvoiceFlatFile(List invoices) + { + //throw new NotImplementedException(); + if (invoices == null) { return null; } + + // create the invoice list + var result = new List(); + int i = 0; + int invoiceCount = invoices.Count(); + + while (i < invoiceCount) + { + int j = 0; + int invoiceLineCount = 0; + if (invoices[i].LineItemList != null) + { invoiceLineCount = invoices[i].LineItemList.Count(); } + + do + { + var dto = new Model.Import.XeroInvoiceFlatFileDTO(); + + dto.ContactName = invoices[i].ContactName; + dto.Currency = invoices[i].Currency; + dto.DueDate = invoices[i].DueDate; + dto.EmailAddress = invoices[i].EmailAddress; + dto.InvoiceAmountDue = invoices[i].InvoiceAmountDue; + dto.InvoiceAmountPaid = invoices[i].InvoiceAmountPaid; + dto.InvoiceDate = invoices[i].InvoiceDate; + dto.InvoiceNumber = invoices[i].InvoiceNumber; + dto.PlannedDate = invoices[i].PlannedDate; + dto.POAddressLine1 = invoices[i].POAddressLine1; + dto.POAddressLine2 = invoices[i].POAddressLine2; + dto.POAddressLine3 = invoices[i].POAddressLine3; + dto.POAddressLine4 = invoices[i].POAddressLine4; + dto.POCity = invoices[i].POCity; + dto.POCountry = invoices[i].POCountry; + dto.POPostalCode = invoices[i].POPostalCode; + dto.PORegion = invoices[i].PORegion; + dto.Reference = invoices[i].Reference; + dto.SAAddressLine1 = invoices[i].SAAddressLine1; + dto.SAAddressLine2 = invoices[i].SAAddressLine2; + dto.SAAddressLine3 = invoices[i].SAAddressLine3; + dto.SAAddressLine4 = invoices[i].SAAddressLine4; + dto.SACity = invoices[i].SACity; + dto.SACountry = invoices[i].SACountry; + dto.SAPostalCode = invoices[i].SAPostalCode; + dto.SARegion = invoices[i].SARegion; + dto.Sent = invoices[i].Sent; + dto.Status = invoices[i].Status; + dto.TaxTotal = invoices[i].TaxTotal; + dto.Total = invoices[i].Total; + dto.Type = invoices[i].Type; + + if (j < invoiceLineCount) + { + dto.AccountCode = invoices[i].LineItemList[j].AccountCode; + dto.Description = invoices[i].LineItemList[j].Description; + dto.Discount = invoices[i].LineItemList[j].Discount; + dto.InventoryItemCode = invoices[i].LineItemList[j].InventoryItemCode; + dto.LineAmount = invoices[i].LineItemList[j].LineAmount; + dto.Quantity = invoices[i].LineItemList[j].Quantity; + dto.TaxAmount = invoices[i].LineItemList[j].TaxAmount; + dto.TaxType = invoices[i].LineItemList[j].TaxType; + dto.TrackingName1 = invoices[i].LineItemList[j].TrackingName1; + dto.TrackingName2 = invoices[i].LineItemList[j].TrackingName2; + dto.TrackingOption1 = invoices[i].LineItemList[j].TrackingOption1; + dto.TrackingOption2 = invoices[i].LineItemList[j].TrackingOption2; + dto.UnitAmount = invoices[i].LineItemList[j].UnitAmount; + } + + result.Add(dto); + j++; + + } while (j < invoiceLineCount); + + i++; + } + return result; + } + } +} diff --git a/BealeEngineering/BealeEngineering.Core/Logic/Export/XeroInvoiceFlatFile.cs b/BealeEngineering/BealeEngineering.Core/Logic/Export/XeroInvoiceFlatFile.cs new file mode 100644 index 0000000..e5599dd --- /dev/null +++ b/BealeEngineering/BealeEngineering.Core/Logic/Export/XeroInvoiceFlatFile.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CsvHelper; + +namespace BealeEngineering.Core.Logic.Export +{ + public class XeroInvoiceFlatFile + { + string sqlConnectionString; + + public XeroInvoiceFlatFile(string sqlConnectionString) + { + this.sqlConnectionString = sqlConnectionString; + + FileOutputPath = + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + + @"\Dropbox\Beale Engineering Services Ltd\BE Accounts\Xero-Export-Invoices.csv"; + } + + public int InvoicesExported { get; private set; } = 0; + + public string FileOutputPath { get; set; } + + public void Execute() + { + if (string.IsNullOrWhiteSpace(FileOutputPath)) + { throw new Exception("File path not set"); } + + // read all invoice from db + var invoiceList = new Data.Database.Sale.ReadInvoice(sqlConnectionString).Read(); + + // map into xeroinvoice dto + var xeroInvoiceList = new Logic.Adapter.XeroInvoiceFlatFile().SaleInvoice(invoiceList); + if (xeroInvoiceList == null || !xeroInvoiceList.Any()) + { return; } + else { InvoicesExported = xeroInvoiceList.Count(); } + var xeroInvoiceDtoList = new Logic.Adapter.XeroInvoiceFlatFileDTO().XeroInvoiceFlatFile(xeroInvoiceList); + + // create flatfile from dto + using (var writer = new StreamWriter(FileOutputPath)) + using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) + { + csv.WriteRecords(xeroInvoiceDtoList); + //csv.WriteRecords(xeroInvoiceList); + } + } + } +} diff --git a/BealeEngineering/BealeEngineering.Core/Logic/Import/XeroInvoiceFlatFile.cs b/BealeEngineering/BealeEngineering.Core/Logic/Import/XeroInvoiceFlatFile.cs index 3f41b7b..6831ed3 100644 --- a/BealeEngineering/BealeEngineering.Core/Logic/Import/XeroInvoiceFlatFile.cs +++ b/BealeEngineering/BealeEngineering.Core/Logic/Import/XeroInvoiceFlatFile.cs @@ -1,24 +1,27 @@ -using CsvHelper; -using System; +using System; using System.Collections.Generic; -using System.Globalization; -using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.VisualBasic.FileIO; namespace BealeEngineering.Core.Logic.Import { public class XeroInvoiceFlatFile { - private List XeroInvoiceData { get; set; } - private List DbInvoiceData { get; set; } + private string sqlConnectionString; + public XeroInvoiceFlatFile(string sqlConnectionString) { - SqlConnectionString = sqlConnectionString; + this.sqlConnectionString = sqlConnectionString; } - private string SqlConnectionString { get; set; } + + private List XeroInvoiceData { get; set; } + + public int InvoicesCreated { get; private set; } = 0; + + public int InvoicesUpdated { get; private set; } = 0; + + public int InvoicesProcessed { get; private set; } = 0; + + public void ByFilePath(string filePath, bool updateContacts = true) { // get xero data @@ -29,19 +32,26 @@ namespace BealeEngineering.Core.Logic.Import UpdateContacts(); // populate/map xero data to invoice model list - MapInvoiceDetails(); + var dbInvoiceData = new Logic.Adapter.SaleInvoice().XeroInvoiceFlatFile(XeroInvoiceData); //check - if (XeroInvoiceData.Count != DbInvoiceData.Count) + if (dbInvoiceData == null ||( XeroInvoiceData.Count != dbInvoiceData.Count)) { throw new Exception("Something went wrong while mapping the data."); } // send list to database (it will get validated in data layer) - if (DbInvoiceData.Any()) + if (dbInvoiceData.Any()) { - var updateInvoice = new Data.Database.Sale.UpdateInvoice(SqlConnectionString); - updateInvoice.ByInvoiceList(DbInvoiceData); + var updateInvoice = new Data.Database.Sale.UpdateInvoice(sqlConnectionString); + updateInvoice.ByInvoiceList(dbInvoiceData); + + InvoicesCreated = updateInvoice.RecordsCreated; + InvoicesUpdated = updateInvoice.RecordsUpdated; + InvoicesProcessed = updateInvoice.InvoicesProcessed; + + if (InvoicesProcessed != (InvoicesCreated + InvoicesUpdated)) + { throw new Exception("Error importing invoices"); } } } /// @@ -51,86 +61,20 @@ namespace BealeEngineering.Core.Logic.Import /// private void UpdateContacts() { + var contactAdapter = new Logic.Adapter.Contact(); var dicContacts = new Dictionary(); for (var i = 0; i < XeroInvoiceData.Count; i++) { if (!dicContacts.ContainsKey(XeroInvoiceData[0].ContactName)) { - dicContacts.Add(XeroInvoiceData[0].ContactName, MapContactDetails(XeroInvoiceData[0])); + dicContacts.Add(XeroInvoiceData[0].ContactName, contactAdapter.XeroInvoiceFlatFile(XeroInvoiceData[0])); } } if (dicContacts.Any()) { - var updateContact = new Data.Database.Contact.UpdateContact(SqlConnectionString); + var updateContact = new Data.Database.Contact.UpdateContact(sqlConnectionString); updateContact.ByContactList(dicContacts.Values.ToList()); } } - private Model.Contact.Contact MapContactDetails(Model.Import.XeroInvoiceFlatFile xeroData) - { - var contact = new Model.Contact.Contact(); - contact.ContactName = xeroData.ContactName; - if (string.IsNullOrWhiteSpace(xeroData.EmailAddress)) { contact.EmailAddress = null; } - else { contact.EmailAddress = xeroData.EmailAddress; } - - var address = new Model.Contact.Address(); - address.AddressLine1 = xeroData.POAddressLine1; - address.AddressLine2 = xeroData.POAddressLine2; - address.AddressLine3 = xeroData.POAddressLine3; - address.AddressLine4 = xeroData.POAddressLine4; - address.City = xeroData.POCity; - address.Country = xeroData.POCountry; - address.PostalCode = xeroData.POPostalCode; - address.Region = xeroData.PORegion; - - if (address.IsValid()) { contact.PostalAddress = address; } - - return contact; - } - private void MapInvoiceDetails() - { - DbInvoiceData = new List(); - for (var i = 0; i < XeroInvoiceData.Count; i++) - { - if (XeroInvoiceData[i] == null) { throw new NullReferenceException(); } - var invoice = new Model.Sale.Invoice(); - - invoice.ContactName = XeroInvoiceData[i].ContactName; - invoice.CurrencyCode = XeroInvoiceData[i].Currency; - invoice.DueDate = XeroInvoiceData[i].DueDate; - invoice.InvoiceDate = XeroInvoiceData[i].InvoiceDate; - invoice.InvoiceTotal = XeroInvoiceData[i].Total; - if (XeroInvoiceData[i].Type == "Sales invoice") { invoice.IsCreditNote = false; } - else if (XeroInvoiceData[i].Type == "Sales credit note") { invoice.IsCreditNote = true; } - else { throw new FormatException("Unknow value '" + XeroInvoiceData[i].Type + "' found in 'Type' field"); } - invoice.Reference = XeroInvoiceData[i].Reference; - invoice.SaleInvoiceNumber = XeroInvoiceData[i].InvoiceNumber; - invoice.TaxTotal = XeroInvoiceData[i].TaxTotal; - - invoice.InvoiceLineList = new List(); - for (int j = 0; j < XeroInvoiceData[i].LineItems.Count; j++) - { - if (XeroInvoiceData[i].LineItems[j] == null) { throw new NullReferenceException(); } - var invoiceLine = new Model.Sale.Invoice.InvoiceLine(); - - invoiceLine.LineNumber = j + 1; - invoiceLine.AccountCode = XeroInvoiceData[i].LineItems[j].AccountCode; - invoiceLine.Description = XeroInvoiceData[i].LineItems[j].Description; - invoiceLine.Discount = XeroInvoiceData[i].LineItems[j].Discount; - invoiceLine.InventoryItemCode = XeroInvoiceData[i].LineItems[j].InventoryItemCode; - invoiceLine.Quantity = XeroInvoiceData[i].LineItems[j].Quantity; - invoiceLine.TaxAmount = XeroInvoiceData[i].LineItems[j].TaxAmount; - invoiceLine.TaxType = XeroInvoiceData[i].LineItems[j].TaxType; - invoiceLine.UnitAmount = XeroInvoiceData[i].LineItems[j].UnitAmount; - - //check, as line amount is same as calculated in model - if (invoiceLine.LineAmount != XeroInvoiceData[i].LineItems[j].LineAmount) - { - throw new Exception("Imported line total does not equal caluclated."); - } - invoice.InvoiceLineList.Add(invoiceLine); - } - DbInvoiceData.Add(invoice); - } - } } } diff --git a/BealeEngineering/BealeEngineering.Core/Model/Import/XeroInvoiceFlatFile.cs b/BealeEngineering/BealeEngineering.Core/Model/Import/XeroInvoiceFlatFile.cs index 5509ed6..2cb7759 100644 --- a/BealeEngineering/BealeEngineering.Core/Model/Import/XeroInvoiceFlatFile.cs +++ b/BealeEngineering/BealeEngineering.Core/Model/Import/XeroInvoiceFlatFile.cs @@ -32,7 +32,7 @@ namespace BealeEngineering.Core.Model.Import public decimal TaxTotal { get; set; } public decimal InvoiceAmountPaid { get; set; } public decimal InvoiceAmountDue { get; set; } - public List LineItems { get; set; } = new List(); + public List LineItemList { get; set; } = new List(); public class LineItem { public string InventoryItemCode { get; set; } diff --git a/BealeEngineering/BealeEngineering.Core/Test/AUtoexec.cs b/BealeEngineering/BealeEngineering.Core/Test/AUtoexec.cs index 1b78a8b..a16cc84 100644 --- a/BealeEngineering/BealeEngineering.Core/Test/AUtoexec.cs +++ b/BealeEngineering/BealeEngineering.Core/Test/AUtoexec.cs @@ -13,7 +13,7 @@ namespace BealeEngineering.Core.Test SqlConnectionString = sqlConnectionString; // enter method to start here - ClientPurchaseOrder(); + Export(); } private string SqlConnectionString { get; set; } public void ClientPurchaseOrder() @@ -24,6 +24,10 @@ namespace BealeEngineering.Core.Test { var inst = new Test.Contact.Contact(SqlConnectionString); } + public void Export() + { + new Test.Export.FlatFile(SqlConnectionString); + } public void Import() { var inst = new Test.Import.ImportFlatfile(SqlConnectionString); diff --git a/BealeEngineering/BealeEngineering.Core/Test/Export/FlatFile.cs b/BealeEngineering/BealeEngineering.Core/Test/Export/FlatFile.cs new file mode 100644 index 0000000..5d9f97f --- /dev/null +++ b/BealeEngineering/BealeEngineering.Core/Test/Export/FlatFile.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BealeEngineering.Core.Test.Export +{ + public class FlatFile + { + string sqlConnectionString; + + public FlatFile(string sqlConnectionString) + { + this.sqlConnectionString = sqlConnectionString; + + // put method to run here + XeroInvoice(); + + } + + public void XeroInvoice() + { + new Logic.Export.XeroInvoiceFlatFile(sqlConnectionString).Execute(); + } + } +} diff --git a/BealeEngineering/BealeEngineering.Core/Test/Import/ImportFlatfile.cs b/BealeEngineering/BealeEngineering.Core/Test/Import/ImportFlatfile.cs index dc86503..1390c1a 100644 --- a/BealeEngineering/BealeEngineering.Core/Test/Import/ImportFlatfile.cs +++ b/BealeEngineering/BealeEngineering.Core/Test/Import/ImportFlatfile.cs @@ -16,7 +16,7 @@ namespace BealeEngineering.Core.Test.Import { string fileInputPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) - + @"\Dropbox\Beale Engineering Services Ltd\BE Accounts\Xero-Export-Invoices.csv"; + + @"\Dropbox\Beale Engineering Services Ltd\BE Accounts\Xero-Export-Invoices - Orig.csv"; var inst = new Logic.Import.XeroInvoiceFlatFile(sqlConnectionString); inst.ByFilePath(fileInputPath);