diff --git a/src/bnhtrade.Core/Data/Database/Account/CreateInvoiceLineItem.cs b/src/bnhtrade.Core/Data/Database/Account/CreateInvoiceLineItem.cs deleted file mode 100644 index 67eb118..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/CreateInvoiceLineItem.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -//using System.Data.SqlClient; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Data.Database.Account -{ - public class CreateInvoiceLineItem : Connection - { - public CreateInvoiceLineItem() - { - } - - public int CreateDefault(string itemCode) - { - using (var conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(@" - INSERT INTO tblAccountInvoiceLineItem ( ItemName, ItemCode ) - OUTPUT INSERTED.AccountInvoiceLineItemID - VALUES ( @itemName, @itemCode ) - ", conn)) - { - cmd.Parameters.AddWithValue("@itemName", itemCode); - cmd.Parameters.AddWithValue("@itemCode", itemCode); - - object obj = cmd.ExecuteScalar(); - - if (obj == null || obj == DBNull.Value) - { - throw new Exception("Error inserting new defalt invoice line item into database"); - } - - return (int)obj; - } - } - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/DeleteJournal.cs b/src/bnhtrade.Core/Data/Database/Account/DeleteJournal.cs deleted file mode 100644 index ce03164..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/DeleteJournal.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Transactions; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class DeleteJournal : Connection - { - /// - /// Old code needs sorting - /// - public bool AccountJournalDelete(int accountJournalId) - { - // check if journal entry is locked - using (TransactionScope scope = new TransactionScope()) - { - bool IsLocked = new Data.Database.Account.ReadJournal().EntryIsLocked(accountJournalId); - if (IsLocked == true) - { - return false; - } - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - // make the delete - using (SqlCommand cmd = new SqlCommand(@" - DELETE FROM tblAccountJournalPost - WHERE AccountJournalID=@accountJournalId; - ", conn)) - { - cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId); - - int rows = cmd.ExecuteNonQuery(); - - if (rows == 0) - { - throw new Exception("Journal entry and/or entry posts do not exist for AccountJournalId=" + accountJournalId); - } - } - - using (SqlCommand cmd = new SqlCommand(@" - DELETE FROM tblAccountJournal - WHERE AccountJournalID=@accountJournalId; - ", conn)) - { - cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId); - - cmd.ExecuteNonQuery(); - } - - scope.Complete(); - return true; - } - } - } - - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs b/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs deleted file mode 100644 index 4d808f3..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Data.Database.Account -{ - public class ReadAccountCode : Connection - { - private Data.Database.SqlWhereBuilder sqlWhere = new SqlWhereBuilder(); - - public ReadAccountCode() - { - } - - /// - /// Gets the full chart of accounts - /// - /// Dictionary where the database record id is the key - public Dictionary All() - { - Innit(); - var list = Execute(null, null); - var dictionary = new Dictionary(); - foreach (var item in list) - { - dictionary.Add(item.Value.Id, item.Value); - } - return dictionary; - } - - public Dictionary ByAccountId(List accountIdList) - { - Innit(); - var resultDict = new Dictionary(); - - if (accountIdList == null || !accountIdList.Any()) - { - return resultDict; - } - - sqlWhere.In("tblAccountChartOf.AccountChartOfID", accountIdList, " WHERE "); - resultDict = Execute(sqlWhere.SqlWhereString, sqlWhere.ParameterList); - return resultDict; - } - - public Dictionary ByAccountCode(List accountCodeList) - { - Innit(); - var resultDict = new Dictionary(); - - if (accountCodeList == null || !accountCodeList.Any()) - { - return resultDict; - } - - sqlWhere.In("tblAccountChartOf.AccountCode", accountCodeList, " WHERE "); - resultDict = Execute(sqlWhere.SqlWhereString, sqlWhere.ParameterList); - return resultDict; - } - - private Dictionary Execute(string sqlWhere, Dictionary parameters) - { - var resultDict = new Dictionary(); - - //build sql query - string sqlString = @" - SELECT tblAccountChartOf.AccountChartOfID - ,tblAccountChartOf.AccountCode - ,tblAccountChartOf.AccountName - ,tblAccountChartOf.Description - ,tblAccountChartOfType.AccountChartOfType - ,tblAccountChartOfType.BasicType - ,tblAccountChartOfType.Multiplier - FROM tblAccountChartOf - INNER JOIN tblAccountChartOfType ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID - " + sqlWhere; - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sqlString, conn)) - { - if (parameters != null) - { - foreach (var parameter in parameters) - { - cmd.Parameters.AddWithValue(parameter.Key, parameter.Value); - } - } - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.HasRows) - { - while (reader.Read()) - { - - uint tablePk = (uint)reader.GetInt32(0); - uint accountCode = (uint)reader.GetInt32(1); - string title = reader.GetString(2); - string description = null; - if (!reader.IsDBNull(3)) { description = reader.GetString(3); } - string type = reader.GetString(4); - string basicType = reader.GetString(5); - int multiplier = reader.GetInt32(6); - - var result = new Model.Account.Account(tablePk, accountCode, title, description, type, basicType, multiplier); - resultDict.Add(tablePk, result); - } - } - } - } - } - return resultDict; - } - - private void Innit() - { - sqlWhere.Init(); - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItem.cs b/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItem.cs deleted file mode 100644 index 9164335..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItem.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Transactions; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class ReadInvoiceLineItem : Connection - { - public ReadInvoiceLineItem() - { - } - - /// - /// Reads all invoice line items from the database. - /// - /// dictionary where key=id, value=object - internal Dictionary All() - { - return Execute(); - } - - /// - /// Read list of invoice line items by item code. - /// - /// List of item coeds to query db against - /// dictionary where key=id, value=object - /// - internal Dictionary ByItemCode(List itemCodes) - { - if (itemCodes == null || !itemCodes.Any()) - { - throw new ArgumentException("Item codes list cannot be null or empty."); - } - - var sqlwhere = new SqlWhereBuilder(); - sqlwhere.In("ItemCode", itemCodes, "AND"); - return Execute(sqlwhere); - } - - private Dictionary Execute(SqlWhereBuilder sqlwhere = null) - { - var resultList = new Dictionary(); - var accountCodeIdList = new Dictionary(); // key=LineItemID, value=AccountChartOfID - var taxCodeIdList = new Dictionary(); // key=LineItemID, value=AccountTaxCodeID - - string sql = @" - SELECT [AccountInvoiceLineItemID] - ,[ItemName] - ,[ItemCode] - ,[ItemDescription] - ,[IsNewReviewRequired] - ,[InvoiceLineEntryEnable] - ,[AccountChartOfID_Default] - ,[AccountTaxCodeID_Default] - FROM [e2A].[dbo].[tblAccountInvoiceLineItem] - WHERE 1=1 "; - - if (sqlwhere != null) - { - sql += sqlwhere.SqlWhereString; - } - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - if (sqlwhere != null) - { - sqlwhere.AddParametersToSqlCommand(cmd); - } - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - var lineItem = new Model.Account.InvoiceLineItem(); - - int lineItemId = reader.GetInt32(0); - lineItem.Name = reader.GetString(1); - lineItem.ItemCode = reader.GetString(2); - if (!reader.IsDBNull(3)) { lineItem.Description = reader.GetString(3); } - lineItem.IsNewReviewRequired = reader.GetBoolean(4); - lineItem.InvoiceLineEntryEnabled = reader.GetBoolean(5); - - if (!reader.IsDBNull(6)) - { - accountCodeIdList.Add(lineItemId, (uint)reader.GetInt32(6)); - } - if (!reader.IsDBNull(7)) - { - taxCodeIdList.Add(lineItemId, reader.GetInt32(7)); - } - - resultList.Add(lineItemId, lineItem); - } - } - } - - // get account codes and add to result list - var accountCodeDictionary = new Data.Database.Account.ReadAccountCode().ByAccountId(accountCodeIdList.Values.ToList()); - foreach (var accountCode in accountCodeIdList) - { - resultList[accountCode.Key].DefaultAccountCode = accountCodeDictionary[accountCode.Value]; - } - - // get tax codes - var taxCodeDictionary = new Data.Database.Account.ReadTaxCode().GetByTaxCodeId(taxCodeIdList.Values.ToList()); - foreach (var taxCode in taxCodeIdList) - { - resultList[taxCode.Key].DefaultTaxCode = taxCodeDictionary[taxCode.Value]; - } - - return resultList; - } - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadJournal.cs b/src/bnhtrade.Core/Data/Database/Account/ReadJournal.cs deleted file mode 100644 index a91897d..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadJournal.cs +++ /dev/null @@ -1,242 +0,0 @@ -using FikaAmazonAPI.AmazonSpApiSDK.Models.CatalogItems; -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Runtime.InteropServices.Marshalling; -using System.Text; -using System.Threading.Tasks; -using static System.ComponentModel.Design.ObjectSelectorEditor; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class ReadJournal : Connection - { - private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder; - - /// - /// Filter the read results - /// - public List AccountJournalId { get; set; } - - public ReadJournal() - { - Init(); - } - - public void Init() - { - sqlBuilder = new SqlWhereBuilder(); - AccountJournalId = new List(); - } - - /// - /// - /// - /// Dictionary were key is the table primary key - public Dictionary Read() - { - sqlBuilder.Init(); - - //build sql query - string sql = @" - SELECT tblAccountJournal.AccountJournalID - ,tblAccountJournal.AccountJournalTypeID - ,tblAccountJournal.EntryDate - ,tblAccountJournal.PostDate - ,tblAccountJournal.LastModified - ,tblAccountJournal.IsLocked - ,tblAccountJournalPost.AccountJournalPostID - ,tblAccountJournalPost.AccountChartOfID - ,tblAccountJournalPost.AmountGbp - FROM tblAccountJournal - INNER JOIN tblAccountJournalPost ON tblAccountJournal.AccountJournalID = tblAccountJournalPost.AccountJournalID - WHERE 1 = 1 "; - - // build the where statments - if (AccountJournalId.Any()) - { - sqlBuilder.In("tblAccountJournal.AccountJournalID", AccountJournalId, "AND"); - } - - // append where string to the sql - if (sqlBuilder.IsSetSqlWhereString) - { - sql = sql + sqlBuilder.SqlWhereString; - } - - // build tuple list - var dbJournalList = new List<( - uint AccountJournalId - , uint AccountJournalTypeId - , DateTime EntryDate - , DateTime PostDate - , DateTime LastModified - , bool IsLocked - )>(); - - var dbJournalPostList = new List<( - uint AccountJournalId - , uint AccountJournalPostId - , uint AccountChartOfId - , decimal AmountGbp - )>(); - - - bool hasRows = false; - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - sqlBuilder.AddParametersToSqlCommand(cmd); - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.HasRows) - { - hasRows = true; - uint lastJournalId = 0; - while (reader.Read()) - { - // read journal header - uint journalId = (uint)reader.GetInt32(0); - if (journalId != lastJournalId) - { - lastJournalId = journalId; - - (uint AccountJournalId - , uint AccountJournalTypeId - , DateTime EntryDate - , DateTime PostDate - , DateTime LastModified - , bool IsLocked - ) - journal = - ( journalId - , (uint)reader.GetInt32(1) - , DateTime.SpecifyKind(reader.GetDateTime(2), DateTimeKind.Utc) - , DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc) - , DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc) - , reader.GetBoolean(5) - ); - - dbJournalList.Add(journal); - } - - // read journal posts - (uint AccountJournalId - , uint AccountJournalPostId - , uint AccountChartOfId - , decimal AmountGbp - ) - journalPost = - ( journalId - , (uint)reader.GetInt32(6) - , (uint)reader.GetInt32(7) - , reader.GetDecimal(8) - ); - - dbJournalPostList.Add(journalPost); - } - } - } - } - } - - var returnList = new Dictionary(); - if (hasRows) - { - // build lists to filter db results by - var journalTypeIdList = new List(); - var accountIdList = new List(); - foreach (var item in dbJournalList) - { - journalTypeIdList.Add(item.AccountJournalTypeId); - } - foreach (var item in dbJournalPostList) - { - accountIdList.Add(item.AccountChartOfId); - } - - // get journalTypes from db - var dbJournalType = new Data.Database.Account.ReadJournalType(); - dbJournalType.IdList = journalTypeIdList; - var journalTypeDict = dbJournalType.Read(); - - // get accounts from db - var dbAccount = new Data.Database.Account.ReadAccountCode(); - var accountDict = dbAccount.ByAccountId(accountIdList); - - // build final return dictionary - foreach (var dbJournal in dbJournalList) - { - // build posts - var newPosts = new List(); - foreach (var dbJournalPost in dbJournalPostList) - { - if (dbJournalPost.AccountJournalId == dbJournal.AccountJournalId) - { - var newPost = new Core.Model.Account.Journal.Post( - dbJournalPost.AccountJournalPostId - , accountDict[dbJournalPost.AccountChartOfId] - , dbJournalPost.AmountGbp); - - newPosts.Add(newPost); - } - } - - // create the journal - var newJournal = new Core.Model.Account.Journal( - dbJournal.AccountJournalId - , journalTypeDict[dbJournal.AccountJournalTypeId] - , newPosts - , dbJournal.EntryDate - , dbJournal.PostDate - , dbJournal.LastModified - , dbJournal.IsLocked); - - returnList.Add(dbJournal.AccountJournalId, newJournal); - } - } - // all done, return the list herevar - return returnList; - } - - /// - /// Test for locked journal entry - /// - /// False on locked journal entry - public bool EntryIsLocked(int journalId) - { - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - using (SqlCommand cmd = new SqlCommand(@" - SELECT - tblAccountJournal.IsLocked - FROM - tblAccountJournal - WHERE - tblAccountJournal.AccountJournalID=@accountJournalId; - ", conn)) - { - cmd.Parameters.AddWithValue("@accountJournalId", journalId); - - object obj = cmd.ExecuteScalar(); - if (obj == null) - { - throw new Exception("Journal entry not found for AccountJournalID=" + journalId); - } - else - { - return (bool)obj; - } - } - } - } - - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadJournalType.cs b/src/bnhtrade.Core/Data/Database/Account/ReadJournalType.cs deleted file mode 100644 index 3835422..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadJournalType.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class ReadJournalType : Connection - { - private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder; - - /// - /// Results filter - /// - public List IdList { get; set; } - - /// - /// Searches for the specificed phases within the item description. Uses the LIKE AND sql function - /// - public List TitleList { get; set; } - - public ReadJournalType() - { - Init(); - } - - public void Init() - { - sqlBuilder = new SqlWhereBuilder(); - IdList = new List(); - TitleList = new List(); - } - - /// - /// - /// - /// Dictionary where key is the table primary key - public Dictionary Read() - { - // create the return (emptyP list) here - var returnList = new Dictionary(); - sqlBuilder.Init(); - - //build sql query - string sql = @" - SELECT [AccountJournalTypeID] - ,[TypeTitle] - ,[ChartOfAccountID_Debit] - ,[ChartOfAccountID_Credit] - FROM [e2A].[dbo].[tblAccountJournalType] - WHERE 1 = 1 "; - - // build the where statments - if (IdList.Any()) - { - sqlBuilder.In("AccountJournalTypeID", IdList, "AND"); - } - if (TitleList.Any()) - { - sqlBuilder.In("TypeTitle", TitleList, "AND"); - } - - // append where string to the sql - if (sqlBuilder.IsSetSqlWhereString) - { - sql = sql + sqlBuilder.SqlWhereString; - } - - // create dictionary to add credit/debit accounts on after db read - var creditDict = new Dictionary(); - var debitDict = new Dictionary(); - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - sqlBuilder.AddParametersToSqlCommand(cmd); - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.HasRows) - { - while (reader.Read()) - { - // read from db and create object - uint journalTypeId = (uint)reader.GetInt32(0); - string title = reader.GetString(1); - int? debitAccountId = null; - if (!reader.IsDBNull(2)) { debitAccountId = reader.GetInt32(2); } - int? creditAccountId = null; - if (!reader.IsDBNull(3)) { creditAccountId = reader.GetInt32(3); } - - // build return list - var item = new Model.Account.JournalType(journalTypeId, title); - returnList.Add(journalTypeId, item); - - // build dictionaries - if (debitAccountId != null) - { - debitDict.Add(journalTypeId, (uint)debitAccountId); - } - if (creditAccountId != null) - { - creditDict.Add(journalTypeId, (uint)creditAccountId); - } - } - } - } - } - } - // get account objects from db - var accountIdList = debitDict.Values.ToList(); - accountIdList.AddRange(creditDict.Values.ToList()); - var dbaccount = new Data.Database.Account.ReadAccountCode(); - var dbDict = dbaccount.ByAccountId(accountIdList); - - // add to the returnlist - foreach (var account in returnList.Values) - { - Model.Account.Account debitAccount = null; - if (debitDict.ContainsKey(account.JournalTypeId)) - { - debitAccount = dbDict[debitDict[account.JournalTypeId]]; - } - - Model.Account.Account creditAccount = null; - if (creditDict.ContainsKey(account.JournalTypeId)) - { - creditAccount = dbDict[creditDict[account.JournalTypeId]]; // key of 59 needed - } - - account.AddDefaultAccounts(creditAccount, debitAccount); - } - - // all done, return the list here - return returnList; - } - } -} - diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoice.cs b/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoice.cs deleted file mode 100644 index 97b608a..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoice.cs +++ /dev/null @@ -1,178 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static System.ComponentModel.Design.ObjectSelectorEditor; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class ReadPurchaseInvoice : Connection - { - private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder; - - public IEnumerable PurchaseInvoiceIdList { get; set; } - - public ReadPurchaseInvoice() - { - Init(); - } - - public void Init() - { - sqlBuilder = new SqlWhereBuilder(); - PurchaseInvoiceIdList = new List(); - } - - public Dictionary Read() - { - var returnList = new Dictionary(); - sqlBuilder.Init(); - - //build sql query - string sql = @" - SELECT tblPurchase.PurchaseID - ,tblPurchase.PurchaseNumber - ,tblPurchase.RecordID - ,tblPurchase.PurchaseDate - ,tblPurchase.ContactID - ,tblPurchase.SupplierRef - ,tblPurchase.PurchaseTotalAmount - ,tblPurchase.VatInclusiveAmounts - ,tblPurchase.RecordCreated - ,tblPurchase.RecordModified - ,tblPurchase.IsActive - ,tblAccountCurrency.CurrencyCode - ,tblPurchaseChannel.PurchaseChannelName - ,tblPurchaseStatus.PurchaseStatus - FROM tblPurchase - LEFT OUTER JOIN tblAccountCurrency ON tblPurchase.AccountCurrencyID = tblAccountCurrency.AccountCurrencyID - LEFT OUTER JOIN tblPurchaseStatus ON tblPurchase.PurchaseStatusID = tblPurchaseStatus.PurchaseStatusID - LEFT OUTER JOIN tblPurchaseChannel ON tblPurchase.PurchaseChannelID = tblPurchaseChannel.PurchaseChannelID - WHERE 1 = 1 - "; - - // build the where statments - if (PurchaseInvoiceIdList.Any()) - { - sqlBuilder.In("[PurchaseID]", PurchaseInvoiceIdList, "AND"); - } - - // append where string to the sql - if (sqlBuilder.IsSetSqlWhereString) - { - sql = sql + sqlBuilder.SqlWhereString; - } - - // dictionary so we can fill in details afterwards - var invoiceContactDict = new Dictionary(); - var purchaseIdList = new List(); - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - sqlBuilder.AddParametersToSqlCommand(cmd); - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.HasRows) - { - while (reader.Read()) - { - - - int purchaseID = reader.GetInt32(0); - int purchaseNumber = reader.GetInt32(1); - int? recordID = null; - if (!reader.IsDBNull(2)) { recordID = reader.GetInt32(2); } - DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc); - int? contactID = null; - if (!reader.IsDBNull(4)) { contactID = reader.GetInt32(4);} - string supplierRef = null; - if (!reader.IsDBNull(5)) { supplierRef = reader.GetString(5);} - decimal? purchaseTotalAmount = null; - if (!reader.IsDBNull(6)) { purchaseTotalAmount = reader.GetDecimal(6);} - bool vatInclusiveAmounts = reader.GetBoolean(7); - DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc); - DateTime recordModified = DateTime.SpecifyKind(reader.GetDateTime(9), DateTimeKind.Utc); - bool isActive = reader.GetBoolean(10); - string currencyCode = reader.GetString(11); - string purchaseChannelName = reader.GetString(12); - string purchaseStatus = null; - if (!reader.IsDBNull(13)) { purchaseStatus = reader.GetString(13);} - - var invoice = new Model.Account.PurchaseInvoice(); - invoice.PurchaseID = purchaseID; - invoice.PurchaseNumber = purchaseNumber; - invoice.RecordID = recordID; - invoice.PurchaseDate = purchaseDate; - invoice.SupplierRef = supplierRef; - //invoice.PurchaseTotalAmount = purchaseTotalAmount; - invoice.VatInclusiveAmounts = vatInclusiveAmounts; - invoice.RecordCreated = recordCreated; - invoice.RecordModified = recordModified; - invoice.IsActive = isActive; - invoice.CurrencyCode = currencyCode; - invoice.PurchaseChannel = purchaseChannelName; - - // is there contact info that needs to be added? - if (contactID != null) - { - invoiceContactDict.Add(purchaseID, (int)contactID); - } - - purchaseIdList.Add(purchaseID); - - returnList.Add(purchaseID, invoice); - } - } - } - } - } - // add contact info - if (invoiceContactDict.Any()) - { - var readContact = new Data.Database.Account.ReadContact(); - readContact.ContactIdList = invoiceContactDict.Values.ToList(); - var contactDict = readContact.Read(); - - if (contactDict.Any()) - { - foreach ( var invoice in returnList) - { - if (invoiceContactDict.ContainsKey(invoice.Value.PurchaseID)) - { - int contactId = invoiceContactDict[invoice.Value.PurchaseID]; - invoice.Value.Contact = contactDict[contactId]; - } - } - } - } - - // add invoice lines - var readLines = new Data.Database.Account.ReadPurchaseInvoiceLine(); - readLines.InvoiceIdList = purchaseIdList; - var lines = readLines.Read(); - foreach(var invoice in returnList.Values) - { - foreach(var line in lines.Values) - { - if (line.PurchaseId == invoice.PurchaseID) - { - if (invoice.InvoiceLines == null) - { - invoice.InvoiceLines = new List(); - } - invoice.InvoiceLines.Add(line); - } - } - } - - return returnList; - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLine.cs b/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLine.cs deleted file mode 100644 index 4642f28..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLine.cs +++ /dev/null @@ -1,212 +0,0 @@ -using Amazon.Runtime.Internal.Transform; -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static System.ComponentModel.Design.ObjectSelectorEditor; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class ReadPurchaseInvoiceLine : Connection - { - private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder; - - /// - /// Results filter - /// - public List InvoiceIdList { get; set; } - - /// - /// Results filter - /// - public List InvoiceLineIdList { get; set; } - - /// - /// Results filter - /// - public List StatusList { get; set; } - - /// - /// Searches for the specificed phases within the item description. Uses the LIKE AND sql function - /// - public List ItemDescription { get; set; } - - public ReadPurchaseInvoiceLine() - { - Init(); - } - - public void Init() - { - sqlBuilder = new SqlWhereBuilder(); - InvoiceIdList = new List(); - InvoiceLineIdList = new List(); - StatusList = new List(); - ItemDescription = new List(); - } - - public Dictionary Read() - { - var returnList = new Dictionary(); - sqlBuilder.Init(); - - //build sql query - string sql = @" - SELECT tblPurchaseLine.PurchaseLineID - ,tblPurchaseLine.PurchaseID - ,tblPurchaseLineStatus.PurchaseLineStatus - ,tblPurchaseLine.SupplierRef - ,tblPurchaseLine.CheckedIn - ,tblPurchaseLine.ItemDescription - ,tblPurchaseLine.ItemQuantity - ,tblPurchaseLine.ItemGross - ,tblPurchaseLine.ItemTax - ,tblPurchaseLine.ShippingGross - ,tblPurchaseLine.ShippingTax - ,tblPurchaseLine.OtherGross - ,tblPurchaseLine.OtherTax - ,tblPurchaseLine.AccountTaxCodeID - ,tblPurchaseLine.Tax_AccountTransactionID - ,tblPurchaseLine.Net_AccountChartOfID - ,tblPurchaseLine.Net_AccountTransactionID - ,tblPurchaseLine.RecordCreated - ,tblPurchaseLine.RecordModified - ,tblPurchaseLine.IsActive - ,tblAccountTaxCode.TaxCode - FROM tblPurchaseLine - INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID - LEFT OUTER JOIN tblAccountTaxCode ON tblPurchaseLine.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID - WHERE 1 = 1 "; - - // build the where statments - if (InvoiceIdList.Any()) - { - sqlBuilder.In("PurchaseID", InvoiceLineIdList, "AND"); - } - if (InvoiceLineIdList.Any()) - { - sqlBuilder.In("PurchaseLineID", InvoiceLineIdList, "AND"); - } - if (StatusList.Any()) - { - sqlBuilder.In("PurchaseLineStatus", InvoiceLineIdList, "AND"); - } - if (ItemDescription.Any()) - { - sqlBuilder.LikeAnd("ItemDescription", ItemDescription, "AND"); - } - - - // append where string to the sql - if (sqlBuilder.IsSetSqlWhereString) - { - sql = sql + sqlBuilder.SqlWhereString; - } - - // catch taxcode to add in after db read - var lineTaxCodeDict = new Dictionary(); - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - sqlBuilder.AddParametersToSqlCommand(cmd); - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.HasRows) - { - while (reader.Read()) - { - int purchaseLineID = reader.GetInt32(0); - int purchaseID = reader.GetInt32(1); - string purchaseLineStatus = reader.GetString(2); - string supplierRef = null; - if (!reader.IsDBNull(3)) { supplierRef = reader.GetString(3); } - DateTime? checkedIn = null; - if (!reader.IsDBNull(4)) { checkedIn = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc); } - string itemDescription = null; - if (!reader.IsDBNull(5)) { itemDescription = reader.GetString(5); } - int itemQuantity = reader.GetInt32(6); - decimal itemGross = 0; - if (!reader.IsDBNull(7)) { itemGross = reader.GetDecimal(7); } - decimal itemTax = 0; - if (!reader.IsDBNull(8)) { itemTax = reader.GetDecimal(8); } - decimal shippingGross = 0; - if (!reader.IsDBNull(9)) { shippingGross = reader.GetDecimal(9); } - decimal shippingTax = 0; - if (!reader.IsDBNull(10)) { shippingTax = reader.GetDecimal(10); } - decimal otherGross = 0; - if (!reader.IsDBNull(11)) { otherGross = reader.GetDecimal(11); } - decimal otherTax = 0; - if (!reader.IsDBNull(12)) { otherTax = reader.GetDecimal(12); } - int accountTaxCodeID = reader.GetInt32(13); - int? tax_AccountTransactionID = null; - if (!reader.IsDBNull(14)) { tax_AccountTransactionID = reader.GetInt32(14); } - int net_AccountChartOfID = reader.GetInt32(15); - int? net_AccountTransactionID = null; - if (!reader.IsDBNull(16)) { net_AccountTransactionID = reader.GetInt32(16); } - DateTime recordModified; - DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(17), DateTimeKind.Utc); - if (reader.IsDBNull(18)) { recordModified = recordCreated; } - else { recordModified = DateTime.SpecifyKind(reader.GetDateTime(18), DateTimeKind.Utc); } - bool isActive = reader.GetBoolean(19); - string accountTaxCode = reader.GetString(20); - - var line = new Model.Account.PurchaseInvoice.Line(); - line.PurchaseLineId = purchaseLineID; - line.PurchaseId = purchaseID; - line.Status = purchaseLineStatus; - line.SupplierRef = supplierRef; - line.CheckedIn = checkedIn; - line.ItemDescription = itemDescription; - line.ItemQuantity = itemQuantity; - line.ItemGross = itemGross; - line.ItemTax = itemTax; - line.ShippingGross = shippingGross; - line.ShippingTax = shippingTax; - line.OtherGross = otherGross; - line.OtherTax = otherTax; - line.Tax_AccountTransactionId = tax_AccountTransactionID; - line.Net_AccountChartOfId = net_AccountChartOfID; - line.Net_AccountTransactionId = net_AccountTransactionID; - line.RecordModified = recordModified; - line.RecordCreated = recordCreated; - line.IsActive = isActive; - - returnList.Add(purchaseLineID, line); - - lineTaxCodeDict.Add(purchaseLineID, accountTaxCode); - } - } - } - } - } - // read tax codes form db and add to return object - var taxcodeList = new Data.Database.Account.ReadTaxCode().GetByTaxCode(lineTaxCodeDict.Values.ToList()); - - foreach (var line in returnList.Values) - { - foreach(var taxcode in taxcodeList) - { - if (taxcode.TaxCode == lineTaxCodeDict[line.PurchaseLineId]) - { - line.AccountTaxCode = taxcode; - break; - } - } - if (line.AccountTaxCode == null) - { - throw new Exception("Fail safe, this really shouodn't happen"); - } - } - - // all done - return returnList; - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLineStatus.cs b/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLineStatus.cs deleted file mode 100644 index d15e0c9..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLineStatus.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class ReadPurchaseInvoiceLineStatus : Connection - { - public Dictionary Read() - { - var returnList = new Dictionary(); - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(@" - SELECT [PurchaseLineStatusID] - ,[PurchaseLineStatus] - ,[ListSort] - ,[TimeStamp] - FROM [e2A].[dbo].[tblPurchaseLineStatus] - ORDER BY [ListSort] - ", conn)) - { - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (!reader.HasRows) - { - // do something - } - else - { - while (reader.Read()) - { - int id = reader.GetInt32(0); - string name = reader.GetString(1); - int lineSort = reader.GetInt32(2); - - var returnItem = new Model.Account.PurchaseInvoiceLineStatus(id, name,lineSort); - returnList.Add(id, returnItem ); - } - } - } - } - } - return returnList; - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLineSummary.cs b/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLineSummary.cs deleted file mode 100644 index da2bc15..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadPurchaseInvoiceLineSummary.cs +++ /dev/null @@ -1,91 +0,0 @@ -using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductFees; -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static System.ComponentModel.Design.ObjectSelectorEditor; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class ReadPurchaseInvoiceLineSummary : Connection - { - public List Read(DateTime periodTo, string lineStatus, List descriptionSearch) - { - var returnList = new List(); - var sqlBuilder = new bnhtrade.Core.Data.Database.SqlWhereBuilder(); - - //build sql query - string sql = @" - SELECT tblPurchase.PurchaseDate - ,tblPurchase.PurchaseID - ,tblPurchase.PurchaseNumber - ,tblPurchaseLine.PurchaseLineID - ,tblPurchaseLine.ItemDescription - ,tblPurchaseLineStatus.PurchaseLineStatus - FROM tblPurchase - INNER JOIN tblPurchaseLine ON tblPurchase.PurchaseID = tblPurchaseLine.PurchaseID - INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID - WHERE tblPurchase.PurchaseDate <= @purchaseDate - "; - - if (lineStatus != null) - { - sql = sql + " AND PurchaseLineStatus = @purchaseLineStatus "; - } - - // build the where statments - if (descriptionSearch.Any()) - { - sqlBuilder.LikeAnd("ItemDescription", descriptionSearch, "AND"); - } - - // append where string to the sql - if (sqlBuilder.IsSetSqlWhereString) - { - sql = sql + sqlBuilder.SqlWhereString; - } - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.AddWithValue("@purchaseDate", periodTo); - if (lineStatus != null) - { - cmd.Parameters.AddWithValue("@purchaseLineStatus", lineStatus); - } - - sqlBuilder.AddParametersToSqlCommand(cmd); - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc); - int purchaseID = reader.GetInt32(1); - int purchaseNumber = reader.GetInt32(2); - int purchaseLineID = reader.GetInt32(3); - string itemDescription = reader.GetString(4); - string purchaseLineStatus = reader.GetString(5); - - var item = new Model.Account.PurchaseInvoiceLineSummary(); - item.PurchaseDate = purchaseDate; - item.PurchaseId = purchaseID; - item.PurchaseNumber = purchaseNumber; - item.PurchaseLineId = purchaseLineID; - item.ItemDescription = itemDescription; - item.LineStatus = purchaseLineStatus; - - returnList.Add(item); - } - } - } - } - return returnList; - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs b/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs deleted file mode 100644 index cd9f031..0000000 --- a/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs +++ /dev/null @@ -1,242 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Data.Database.Account -{ - internal class ReadTaxCode : Connection - { - private Data.Database.SqlWhereBuilder whereBuilder = new SqlWhereBuilder(); - - public ReadTaxCode() - { - } - - private Dictionary Execute(string sqlWhere, Dictionary parameters) - { - var resultList = new Dictionary(); - - //build sql query - string sqlString = @" - SELECT - AccountTaxCodeID - ,TaxCode - ,TaxCodeName - ,TaxCodeDescription - ,TaxRatePercent - ,IsMarginScheme - ,IsValidOnExpense - ,IsVailidOnIncome - ,IsActive - ,TaxType - FROM tblAccountTaxCode"; - - sqlString += sqlWhere; - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sqlString, conn)) - { - foreach (var paramter in parameters) - { - cmd.Parameters.AddWithValue(paramter.Key, paramter.Value); - } - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.HasRows) - { - while (reader.Read()) - { - int taxCodeId = reader.GetByte(0); - string taxCode = reader.GetString(1); - string name = reader.GetString(2); - string description = null; - if (!reader.IsDBNull(3)) { description = reader.GetString(3); } - decimal rate = reader.GetDecimal(4); - bool isMargin = reader.GetBoolean(5); - bool isValidOnExpense = reader.GetBoolean(6); - bool isValidOnIncome = reader.GetBoolean(7); - bool isActive = reader.GetBoolean(8); - string taxType = reader.GetString(9); - - var result = new Model.Account.TaxCodeInfo( - taxCode, - name, - description, - rate, - isMargin, - isValidOnExpense, - isValidOnIncome, - taxType, - isActive); - - resultList.Add(taxCodeId, result); - } - } - } - } - } - return resultList; - } - - public List GetByTaxCode(List taxcodeList) - { - var resultList = new List(); - - if (taxcodeList == null || !taxcodeList.Any()) - { - return resultList; - } - - taxcodeList = taxcodeList.Distinct().ToList(); - - whereBuilder.Init(); - whereBuilder.In("TaxCode", taxcodeList, "WHERE"); - - var dic = Execute(whereBuilder.SqlWhereString, whereBuilder.ParameterList); - return dic.Values.ToList(); - } - - public Dictionary GetByTaxCodeId(List taxcodeIdList) - { - var resultList = new Dictionary(); - - if (taxcodeIdList == null || !taxcodeIdList.Any()) - { - return resultList; - } - - taxcodeIdList = taxcodeIdList.Distinct().ToList(); - - whereBuilder.Init(); - whereBuilder.In("AccountTaxCodeID", taxcodeIdList, "WHERE"); - - return Execute(whereBuilder.SqlWhereString, whereBuilder.ParameterList); - } - - - /// - /// Gets all active Tax Code objects - /// - /// Dictionary where database record ID is the key - public Dictionary GetAllActive() - { - string sqlWhere = @" - WHERE IsActive=@isActive;"; - var parameters = new Dictionary(); - parameters.Add("@isActive", true); - - return Execute(sqlWhere, parameters); - } - - public Dictionary GetTaxCodeBySkuNumber(List skuNumberList) - { - var resultList = new Dictionary(); - - if (skuNumberList == null || !skuNumberList.Any()) - { - return resultList; - } - - skuNumberList = skuNumberList.Distinct().ToList(); - - string sql = @" - SELECT tblSku.skuSkuNumber - ,tblAccountTaxCode.TaxCode - FROM tblSku - INNER JOIN tblAccountTaxCode ON tblSku.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID "; - - whereBuilder.Init(); - whereBuilder.In("tblSku.skuSkuNumber", skuNumberList, "WHERE"); - - sql += whereBuilder.SqlWhereString; - - using (var conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (var cmd = new SqlCommand(sql, conn)) - { - foreach (var param in whereBuilder.ParameterList) - { - cmd.Parameters.AddWithValue(param.Key, param.Value); - } - - using (var reader = cmd.ExecuteReader()) - { - if (!reader.HasRows) - { - return resultList; - } - - while (reader.Read()) - { - resultList.Add(reader.GetString(0), reader.GetString(1)); - } - } - } - } - - return resultList; - } - - public Dictionary GetTaxCodeByInvoiceLineItemCode(List lineItemCode) - { - var resultList = new Dictionary(); - - if (lineItemCode == null || !lineItemCode.Any()) - { - return resultList; - } - - lineItemCode = lineItemCode.Distinct().ToList(); - - string sql = @" - SELECT tblAccountInvoiceLineItem.ItemCode - ,tblAccountTaxCode.TaxCode - FROM tblAccountInvoiceLineItem - LEFT OUTER JOIN tblAccountTaxCode ON tblAccountInvoiceLineItem.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID - "; - - whereBuilder.Init(); - whereBuilder.In("tblAccountInvoiceLineItem.ItemCode", lineItemCode, "WHERE"); - - sql += whereBuilder.SqlWhereString; - - using (var conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (var cmd = new SqlCommand(sql, conn)) - { - foreach (var param in whereBuilder.ParameterList) - { - cmd.Parameters.AddWithValue(param.Key, param.Value); - } - - using (var reader = cmd.ExecuteReader()) - { - if (!reader.HasRows) - { - return resultList; - } - - while (reader.Read()) - { - if (reader.IsDBNull(1)) { resultList.Add(reader.GetString(0), null); } - else { resultList.Add(reader.GetString(0), reader.GetString(1)); } - } - } - } - } - - return resultList; - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/AccountCodeRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/AccountCodeRepository.cs new file mode 100644 index 0000000..389b527 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/AccountCodeRepository.cs @@ -0,0 +1,82 @@ +using bnhtrade.Core.Data.Database._BoilerPlate; +using bnhtrade.Core.Data.Database.Repository.Interface; +using Microsoft.Data.SqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Implementation +{ + internal class AccountCodeRepository : _Base, IAccountCodeRepository + { + public AccountCodeRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) + { + } + + public Dictionary ReadAccountCode(List accountIdList = null, List accountCodeList = null) + { + var resultDict = new Dictionary(); + var sqlWhere = new SqlWhereBuilder(); + + //build sql query + string sqlString = @" + SELECT tblAccountChartOf.AccountChartOfID + ,tblAccountChartOf.AccountCode + ,tblAccountChartOf.AccountName + ,tblAccountChartOf.Description + ,tblAccountChartOfType.AccountChartOfType + ,tblAccountChartOfType.BasicType + ,tblAccountChartOfType.Multiplier + FROM tblAccountChartOf + INNER JOIN tblAccountChartOfType ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID + WHERE 1=1 "; + + if (accountIdList != null && accountIdList.Any()) + { + sqlWhere.In("tblAccountChartOf.AccountChartOfID", accountIdList, " AND "); + } + if (accountCodeList != null && accountCodeList.Any()) + { + sqlWhere.In("tblAccountChartOf.AccountCode", accountCodeList, " AND "); + } + if (sqlWhere.IsSetSqlWhereString) + { + sqlString = sqlString + sqlWhere.SqlWhereString; + } + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sqlString; + cmd.Transaction = _transaction as SqlTransaction; + + if (sqlWhere.ParameterListIsSet) + { + sqlWhere.AddParametersToSqlCommand(cmd); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + + int tablePk = reader.GetInt32(0); + int accountCode = reader.GetInt32(1); + string title = reader.GetString(2); + string description = null; + if (!reader.IsDBNull(3)) { description = reader.GetString(3); } + string type = reader.GetString(4); + string basicType = reader.GetString(5); + int multiplier = reader.GetInt32(6); + + var result = new Model.Account.Account(tablePk, accountCode, title, description, type, basicType, multiplier); + resultDict.Add(tablePk, result); + } + } + } + return resultDict; + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/AccountTaxRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/AccountTaxRepository.cs new file mode 100644 index 0000000..638221b --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/AccountTaxRepository.cs @@ -0,0 +1,201 @@ +using bnhtrade.Core.Data.Database._BoilerPlate; +using bnhtrade.Core.Data.Database.Repository.Interface; +using Microsoft.Data.SqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Implementation +{ + internal class AccountTaxRepository : _Base, IAccountTaxRepository + { + public AccountTaxRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) + { + } + + public Dictionary ReadTaxCodeInfo(bool? IsActive = null, List taxcodeList = null, List taxcodeIdList = null) + { + var resultList = new Dictionary(); + Data.Database.SqlWhereBuilder whereBuilder = new SqlWhereBuilder(); + + //build sql query + string sqlString = @" + SELECT + AccountTaxCodeID + ,TaxCode + ,TaxCodeName + ,TaxCodeDescription + ,TaxRatePercent + ,IsMarginScheme + ,IsValidOnExpense + ,IsVailidOnIncome + ,IsActive + ,TaxType + FROM tblAccountTaxCode + WHERE 1=1 "; + + // add where clauses + if (IsActive.HasValue) + { + whereBuilder.IsEqualTo("IsActive", IsActive.Value, "AND"); + } + if (taxcodeList != null && taxcodeList.Count > 0) + { + whereBuilder.In("TaxCode", taxcodeList, "AND"); + } + if (taxcodeIdList != null && taxcodeIdList.Count > 0) + { + whereBuilder.In("AccountTaxCodeID", taxcodeIdList, "AND"); + } + + if (whereBuilder.IsSetSqlWhereString) + { + sqlString = sqlString + whereBuilder.SqlWhereString; + } + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sqlString; + cmd.Transaction = _transaction as SqlTransaction; + + if (whereBuilder.ParameterListIsSet) + { + whereBuilder.AddParametersToSqlCommand(cmd); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int taxCodeId = reader.GetByte(0); + string taxCode = reader.GetString(1); + string name = reader.GetString(2); + string description = null; + if (!reader.IsDBNull(3)) { description = reader.GetString(3); } + decimal rate = reader.GetDecimal(4); + bool isMargin = reader.GetBoolean(5); + bool isValidOnExpense = reader.GetBoolean(6); + bool isValidOnIncome = reader.GetBoolean(7); + bool isActive = reader.GetBoolean(8); + string taxType = reader.GetString(9); + + var result = new Model.Account.TaxCodeInfo( + taxCode, + name, + description, + rate, + isMargin, + isValidOnExpense, + isValidOnIncome, + taxType, + isActive); + + resultList.Add(taxCodeId, result); + } + } + } + return resultList; + } + + public Dictionary GetTaxCodeBySkuNumber(List skuNumberList) + { + var resultList = new Dictionary(); + + if (skuNumberList == null || !skuNumberList.Any()) + { + return resultList; + } + + skuNumberList = skuNumberList.Distinct().ToList(); + + string sql = @" + SELECT tblSku.skuSkuNumber + ,tblAccountTaxCode.TaxCode + FROM tblSku + INNER JOIN tblAccountTaxCode ON tblSku.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID "; + + var whereBuilder = new Data.Database.SqlWhereBuilder(); + whereBuilder.In("tblSku.skuSkuNumber", skuNumberList, "WHERE"); + + sql += whereBuilder.SqlWhereString; + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + if (whereBuilder.ParameterListIsSet) + { + whereBuilder.AddParametersToSqlCommand(cmd); + } + + using (var reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + return resultList; + } + + while (reader.Read()) + { + resultList.Add(reader.GetString(0), reader.GetString(1)); + } + } + } + return resultList; + } + + public Dictionary ReadTaxCodeByInvoiceLineItemCode(List lineItemCode) + { + var resultList = new Dictionary(); + + if (lineItemCode == null || !lineItemCode.Any()) + { + return resultList; + } + + lineItemCode = lineItemCode.Distinct().ToList(); + + string sql = @" + SELECT tblAccountInvoiceLineItem.ItemCode + ,tblAccountTaxCode.TaxCode + FROM tblAccountInvoiceLineItem + LEFT OUTER JOIN tblAccountTaxCode ON tblAccountInvoiceLineItem.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID + "; + + var whereBuilder = new Data.Database.SqlWhereBuilder(); + whereBuilder.In("tblAccountInvoiceLineItem.ItemCode", lineItemCode, "WHERE"); + + sql += whereBuilder.SqlWhereString; + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + if (whereBuilder.ParameterListIsSet) + { + whereBuilder.AddParametersToSqlCommand(cmd); + } + + using (var reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + return resultList; + } + + while (reader.Read()) + { + if (reader.IsDBNull(1)) { resultList.Add(reader.GetString(0), null); } + else { resultList.Add(reader.GetString(0), reader.GetString(1)); } + } + } + } + return resultList; + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/ImportAmazonRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/AmazonSettlementRepository.cs similarity index 95% rename from src/bnhtrade.Core/Data/Database/Repository/Implementation/ImportAmazonRepository.cs rename to src/bnhtrade.Core/Data/Database/Repository/Implementation/AmazonSettlementRepository.cs index e122a63..ccfe64a 100644 --- a/src/bnhtrade.Core/Data/Database/Repository/Implementation/ImportAmazonRepository.cs +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/AmazonSettlementRepository.cs @@ -14,11 +14,11 @@ using System.Transactions; namespace bnhtrade.Core.Data.Database.Repository.Implementation { - internal class ImportAmazonRepository : _Base, IImportAmazonRepository + internal class AmazonSettlementRepository : _Base, IAmazonSettlementRepository { Logic.Log.LogEvent _log = new Logic.Log.LogEvent(); - public ImportAmazonRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) + public AmazonSettlementRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) { } @@ -368,13 +368,39 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation // Update Amazon Settlement Report // + /// + /// Update the settlement report marketplace name by settlement Id (not table id) + /// + /// Settlement id (not table/record id) of the settlement to update + /// marketplace name + /// + /// + public bool UpdateAmazonSettlementMarketPlaceName (string settlementId, Model.Amazon.MarketPlaceEnum marketPlace) + { + if (string.IsNullOrWhiteSpace(settlementId) || marketPlace == null) + { + throw new Exception("Settlement id or market place is invalid."); + } + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = @" + UPDATE tblImportAmazonSettlementReport + SET [marketplace-name] = @marketPlaceName + WHERE [settlement-id] = @settlementId;"; + cmd.Parameters.AddWithValue("@marketPlaceName", marketPlace.GetMarketplaceUrl()); + cmd.Parameters.AddWithValue("@settlementId", settlementId); + cmd.Transaction = _transaction as SqlTransaction; + return cmd.ExecuteNonQuery() > 0; + } + } + /// /// Set the IsProcessed flag to true or false for the specified settlement Ids. /// /// List of settlement id (not table id) /// value to set the isProcessed to /// Number of rows effected - public int SetAmazonSettlementIsProcessed(List settlementIdList, bool isProcessed) + public int UpdateAmazonSettlementIsProcessed(List settlementIdList, bool isProcessed) { if (settlementIdList == null || !settlementIdList.Any()) { diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/ExportInvoiceRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/ExportInvoiceRepository.cs index b8846d0..626639c 100644 --- a/src/bnhtrade.Core/Data/Database/Repository/Implementation/ExportInvoiceRepository.cs +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/ExportInvoiceRepository.cs @@ -1,4 +1,5 @@ using bnhtrade.Core.Data.Database.Repository.Interface; +using bnhtrade.Core.Logic.Account; using bnhtrade.Core.Logic.Validate; using Microsoft.Data.SqlClient; using System; @@ -164,7 +165,7 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation // /// - /// Returns list of invoice numbers that have not yet been exported (i.e. IsComplete=True) + /// Returns list of invoice numbers that have not yet been exported (i.e. IsComplete=True), in InvoiceNumber asending order. /// /// Sales or Purchase /// Dictionary where key=ExportAccountInvoiceID, value=InvoiceNumber @@ -176,7 +177,8 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation SELECT tblExportAccountInvoice.ExportAccountInvoiceID, [InvoiceNumber] FROM tblExportAccountInvoice WHERE (tblExportAccountInvoice.IsComplete = 0) - AND (tblExportAccountInvoice.ExportAccountInvoiceTypeID = @invoiceType);"; + AND (tblExportAccountInvoice.ExportAccountInvoiceTypeID = @invoiceType) + ORDER BY [InvoiceNumber];"; using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) { @@ -211,35 +213,35 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation } // get the account and tax code objects - var taxcode = new Data.Database.Account.ReadTaxCode().GetAllActive(); - var account = new Data.Database.Account.ReadAccountCode().All(); + //var taxcode = new Data.Database.Account.ReadTaxCode().GetAllActive(); + //var account = new Data.Database.Account.ReadAccountCode().All(); + var taxcodeIds = new Dictionary(); + var accountIds = new Dictionary(); + var lineItemIds = new Dictionary(); // build sql string string sql = @" - SELECT tblExportAccountInvoice.ExportAccountInvoiceID - , tblExportAccountInvoice.ExportAccountInvoiceTypeID - , tblExportAccountInvoice.Contact - , tblExportAccountInvoice.InvoiceNumber - , tblExportAccountInvoice.InvoiceDate - , tblExportAccountInvoice.InvoiceDueDate - , tblExportAccountInvoice.Reference - , tblExportAccountInvoice.CurrencyCode - , tblExportAccountInvoice.InvoiceAmount - , tblExportAccountInvoice.IsComplete - , tblExportAccountInvoiceLine.ExportAccountInvoiceLineID - , tblAccountInvoiceLineItem.ItemName - , tblExportAccountInvoiceLine.AccountChartOfID - , tblExportAccountInvoiceLine.NetAmount - , tblExportAccountInvoiceLine.AccountTaxCodeID - , tblExportAccountInvoiceLine.TaxAmount - , tblExportAccountInvoice.LineUnitAmountIsTaxExclusive - FROM tblExportAccountInvoice - INNER JOIN - tblExportAccountInvoiceLine - ON tblExportAccountInvoice.ExportAccountInvoiceID = tblExportAccountInvoiceLine.ExportAccountInvoiceID - INNER JOIN - tblAccountInvoiceLineItem - ON tblExportAccountInvoiceLine.AccountInvoiceLineItemID = tblAccountInvoiceLineItem.AccountInvoiceLineItemID + SELECT tblExportAccountInvoice.ExportAccountInvoiceID, + tblExportAccountInvoice.ExportAccountInvoiceTypeID, + tblExportAccountInvoice.Contact, + tblExportAccountInvoice.InvoiceNumber, + tblExportAccountInvoice.InvoiceDate, + tblExportAccountInvoice.InvoiceDueDate, + tblExportAccountInvoice.Reference, + tblExportAccountInvoice.CurrencyCode, + tblExportAccountInvoice.InvoiceAmount, + tblExportAccountInvoice.IsComplete, + tblExportAccountInvoiceLine.ExportAccountInvoiceLineID, + tblExportAccountInvoiceLine.AccountInvoiceLineItemID, + tblExportAccountInvoiceLine.AccountChartOfID, + tblExportAccountInvoiceLine.NetAmount, + tblExportAccountInvoiceLine.AccountTaxCodeID, + tblExportAccountInvoiceLine.TaxAmount, + tblExportAccountInvoice.LineUnitAmountIsTaxExclusive + FROM tblExportAccountInvoice + INNER JOIN + tblExportAccountInvoiceLine + ON tblExportAccountInvoice.ExportAccountInvoiceID = tblExportAccountInvoiceLine.ExportAccountInvoiceID "; var sqlWhere = new Data.Database.SqlWhereBuilder(); @@ -247,6 +249,7 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation sql = sql + sqlWhere.SqlWhereString + " ORDER BY tblExportAccountInvoice.ExportAccountInvoiceID, tblExportAccountInvoiceLine.ExportAccountInvoiceLineID; "; + int i = 0; using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) { cmd.CommandText = sql; @@ -265,8 +268,10 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation int? previousInvoiceId = null; Model.Account.SalesInvoice invoice = null; + i = -1; while (reader.Read()) { + i++; invoiceId = reader.GetInt32(0); // test for first/next invoice @@ -301,11 +306,11 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation // add line info var invoiceLine = new Model.Account.SalesInvoice.InvoiceLine(invoice); int lineId = reader.GetInt32(10); - invoiceLine.ItemCode = reader.GetString(11); - invoiceLine.Account = account[Convert.ToUInt32(reader.GetInt32(12))]; + lineItemIds.Add(i, reader.GetInt32(11)); + accountIds.Add(i, reader.GetInt32(12)); invoiceLine.UnitAmount = reader.GetDecimal(13); invoiceLine.Quantity = 1; - invoiceLine.TaxCode = taxcode[reader.GetByte(14)]; + taxcodeIds.Add(i, reader.GetByte(14)); invoiceLine.SetTaxAdjustmentByTaxTotal(reader.GetDecimal(15)); invoice.InvoiceLineList.Add(invoiceLine); @@ -316,6 +321,30 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation returnList.Add(invoiceId.Value, invoice); } } + + // get and add account/tax/item objects to invoice + var dbTaxCodes = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, null, taxcodeIds.Values.ToList()); + var dbAccountCodes = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIds.Values.ToList()); + var dbLineItems = new InvoiceRepository(_connection, _transaction).GetInvoiceLineItem(lineItemIds.Values.ToList()); + + i = -1; + foreach (var invoice in returnList.Values) + { + foreach (var line in invoice.InvoiceLineList) + { + i++; + line.TaxCode = dbTaxCodes[taxcodeIds[i]]; + line.Account = dbAccountCodes[accountIds[i]]; + + // fill in missing data for line item, if required + var invoiceLineItem = dbLineItems[lineItemIds[i]]; + line.ItemCode = invoiceLineItem.ItemCode; + if (string.IsNullOrEmpty(line.Description)) + { + line.Description = invoiceLineItem.Name; + } + } + } return returnList; } @@ -323,57 +352,36 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation // invoice update methods // - /// - /// Update the 'IsComplete' field by invoice id - /// - /// key=ExportAccountInvoiceTypeID, value=IsComplete - /// Number of row effected - public int SetInvoiceIsCompleteValue(Dictionary updateDictionary) + public int UpdateInvoiceHeaderDetail(int invoiceId, string invoiceNumber = null, bool? isComplete = null) { - int returnCount = 0; - - foreach (var item in updateDictionary) + if (invoiceNumber == null && isComplete == null) { - string sql = @" - UPDATE - tblExportAccountInvoice - SET - IsComplete = @isComplete - WHERE - ExportAccountInvoiceID = @id - "; - - using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) - { - cmd.CommandText = sql; - cmd.Transaction = _transaction as SqlTransaction; - - cmd.Parameters.AddWithValue("@id", item.Key); - cmd.Parameters.AddWithValue("@isComplete", item.Value); - - returnCount = returnCount + cmd.ExecuteNonQuery(); - } + throw new ArgumentException("At least one of the parameters must be set to update invoice header details."); + } + + // build the statement with my helper + var sqlupdate = new Core.Data.Database.SqlUpdateBuilder(); + sqlupdate.SetTableName("tblExportAccountInvoice"); + if (invoiceNumber != null) + sqlupdate.AddUpdateArugment("InvoiceNumber", invoiceNumber); + if (isComplete.HasValue) + sqlupdate.AddUpdateArugment("IsComplete", isComplete); + sqlupdate.AddWhereArugment("ExportAccountInvoiceID", invoiceId); + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.Transaction = _transaction as SqlTransaction; + cmd.CommandText = sqlupdate.GetSqlString(); + sqlupdate.AddParametersToSqlCommand(cmd); + + return cmd.ExecuteNonQuery(); } - return returnCount; } // // Invoice Delete Methods // - public int DeleteInvoiceLine(int invoiceLineId) - { - // only being able to delete one line at a time is a design/safety decision - // otherwise, delete whole invoice - if (invoiceLineId <= 0) - { - throw new ArgumentException("InvoiceLineId must be greater than zero."); - } - Core.Data.Database.SqlWhereBuilder sqlWhereBuilder = new Core.Data.Database.SqlWhereBuilder(); - sqlWhereBuilder.In("ExportAccountInvoiceLineID", new List { invoiceLineId }); - return DeleteInvoiceExecuteInvoiceLine(sqlWhereBuilder); - } - public int DeleteInvoice(IEnumerable invoiceIdList) { if (invoiceIdList == null || invoiceIdList.Count() == 0) @@ -406,6 +414,19 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation } } + public int DeleteInvoiceLine(int invoiceLineId) + { + // only being able to delete one line at a time is a design/safety decision + // otherwise, delete whole invoice + if (invoiceLineId <= 0) + { + throw new ArgumentException("InvoiceLineId must be greater than zero."); + } + Core.Data.Database.SqlWhereBuilder sqlWhereBuilder = new Core.Data.Database.SqlWhereBuilder(); + sqlWhereBuilder.In("ExportAccountInvoiceLineID", new List { invoiceLineId }); + return DeleteInvoiceExecuteInvoiceLine(sqlWhereBuilder); + } + /// /// Helper method Only intended for use with ExecuteInvoice() or ExecuteInvoiceLine() /// diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/InvoiceRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/InvoiceRepository.cs new file mode 100644 index 0000000..d9d1d59 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/InvoiceRepository.cs @@ -0,0 +1,585 @@ +using bnhtrade.Core.Data.Database.Repository.Interface; +using FikaAmazonAPI.AmazonSpApiSDK.Models.EasyShip20220323; +using Microsoft.Data.SqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Implementation +{ + internal class InvoiceRepository : _Base, IInvoiceRepository + { + public InvoiceRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) + { + } + + public int CreateDefaultInvoiceLineItem(string itemCode) + { + string sql = @" + INSERT INTO tblAccountInvoiceLineItem ( ItemName, ItemCode ) + OUTPUT INSERTED.AccountInvoiceLineItemID + VALUES ( @itemName, @itemCode ) + "; + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + cmd.Parameters.AddWithValue("@itemName", itemCode); + cmd.Parameters.AddWithValue("@itemCode", itemCode); + + object obj = cmd.ExecuteScalar(); + + if (obj == null || obj == DBNull.Value) + { + throw new Exception("Error inserting new defalt invoice line item into database"); + } + + return (int)obj; + } + } + + /// + /// Retrieves a collection of invoice line items, optionally including account and tax information. + /// + /// This method queries the database to retrieve invoice line items. If or is set to , + /// additional queries are performed to fetch the corresponding account and tax information, which may impact + /// performance. + /// An optional collection of item codes to filter the results. If or empty, all invoice + /// line items are retrieved. + /// A value indicating whether to include account information for each invoice line item. If , the default account code is populated for each item. Defaults to . + /// A value indicating whether to include tax information for each invoice line item. If , the default tax code is populated for each item. Defaults to . + /// A dictionary where the key is the table record id of the invoice line item, and the value is the + /// corresponding object. The dictionary will be empty if no + /// matching items are found. + public Dictionary GetInvoiceLineItem( + IEnumerable itemIds = null, IEnumerable itemCodes = null, bool includeAccountInfo = true, bool includeTaxInfo = true + ) + { + var sqlwhere = new SqlWhereBuilder(); + var returnList = new Dictionary(); + var accountCodeIdList = new Dictionary(); // key=LineItemID, value=AccountChartOfID + var taxCodeIdList = new Dictionary(); // key=LineItemID, value=AccountTaxCodeID + + string sql = @" + SELECT [AccountInvoiceLineItemID] + ,[ItemName] + ,[ItemCode] + ,[ItemDescription] + ,[IsNewReviewRequired] + ,[InvoiceLineEntryEnable] + ,[AccountChartOfID_Default] + ,[AccountTaxCodeID_Default] + FROM [e2A].[dbo].[tblAccountInvoiceLineItem] + WHERE 1=1 "; + + if (itemCodes != null && itemCodes.Any()) + { + sqlwhere.In("ItemCode", itemCodes, "AND"); + sql += sqlwhere.SqlWhereString; + } + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + sqlwhere.AddParametersToSqlCommand(cmd); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + var lineItem = new Model.Account.InvoiceLineItem(); + + int recordId = reader.GetInt32(0); + lineItem.Name = reader.GetString(1); + lineItem.ItemCode = reader.GetString(2); + if (!reader.IsDBNull(3)) { lineItem.Description = reader.GetString(3); } + lineItem.IsNewReviewRequired = reader.GetBoolean(4); + lineItem.InvoiceLineEntryEnabled = reader.GetBoolean(5); + + if (!reader.IsDBNull(6)) + { + accountCodeIdList.Add(recordId, reader.GetInt32(6)); + } + if (!reader.IsDBNull(7)) + { + taxCodeIdList.Add(recordId, reader.GetInt32(7)); + } + + returnList.Add(recordId, lineItem); + } + } + } + + // get account codes and add to result list + if (includeAccountInfo) + { + var accountCodeDictionary = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountCodeIdList.Values.ToList()); + foreach (var accountCode in accountCodeIdList) + { + returnList[accountCode.Key].DefaultAccountCode = accountCodeDictionary[accountCode.Value]; + } + } + + // get tax codes + if (includeTaxInfo) + { + var taxCodeDictionary = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, null, taxCodeIdList.Values.ToList()); + foreach (var taxCode in taxCodeIdList) + { + returnList[taxCode.Key].DefaultTaxCode = taxCodeDictionary[taxCode.Value]; + } + } + + return returnList; + } + + + public Dictionary ReadPurchaseInvoice(IEnumerable purchaseInvoiceIdList) + { + var returnList = new Dictionary(); + SqlWhereBuilder sqlBuilder = new SqlWhereBuilder(); + + //build sql query + string sql = @" + SELECT tblPurchase.PurchaseID + ,tblPurchase.PurchaseNumber + ,tblPurchase.RecordID + ,tblPurchase.PurchaseDate + ,tblPurchase.ContactID + ,tblPurchase.SupplierRef + ,tblPurchase.PurchaseTotalAmount + ,tblPurchase.VatInclusiveAmounts + ,tblPurchase.RecordCreated + ,tblPurchase.RecordModified + ,tblPurchase.IsActive + ,tblAccountCurrency.CurrencyCode + ,tblPurchaseChannel.PurchaseChannelName + ,tblPurchaseStatus.PurchaseStatus + FROM tblPurchase + LEFT OUTER JOIN tblAccountCurrency ON tblPurchase.AccountCurrencyID = tblAccountCurrency.AccountCurrencyID + LEFT OUTER JOIN tblPurchaseStatus ON tblPurchase.PurchaseStatusID = tblPurchaseStatus.PurchaseStatusID + LEFT OUTER JOIN tblPurchaseChannel ON tblPurchase.PurchaseChannelID = tblPurchaseChannel.PurchaseChannelID + WHERE 1 = 1 + "; + + // build the where statments + if (purchaseInvoiceIdList.Any()) + { + sqlBuilder.In("[PurchaseID]", purchaseInvoiceIdList, "AND"); + } + + // append where string to the sql + if (sqlBuilder.IsSetSqlWhereString) + { + sql = sql + sqlBuilder.SqlWhereString; + } + + // dictionary so we can fill in details afterwards + var invoiceContactDict = new Dictionary(); + var purchaseIdList = new List(); + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + sqlBuilder.AddParametersToSqlCommand(cmd); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.HasRows) + { + while (reader.Read()) + { + + + int purchaseID = reader.GetInt32(0); + int purchaseNumber = reader.GetInt32(1); + int? recordID = null; + if (!reader.IsDBNull(2)) { recordID = reader.GetInt32(2); } + DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc); + int? contactID = null; + if (!reader.IsDBNull(4)) { contactID = reader.GetInt32(4); } + string supplierRef = null; + if (!reader.IsDBNull(5)) { supplierRef = reader.GetString(5); } + decimal? purchaseTotalAmount = null; + if (!reader.IsDBNull(6)) { purchaseTotalAmount = reader.GetDecimal(6); } + bool vatInclusiveAmounts = reader.GetBoolean(7); + DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc); + DateTime recordModified = DateTime.SpecifyKind(reader.GetDateTime(9), DateTimeKind.Utc); + bool isActive = reader.GetBoolean(10); + string currencyCode = reader.GetString(11); + string purchaseChannelName = reader.GetString(12); + string purchaseStatus = null; + if (!reader.IsDBNull(13)) { purchaseStatus = reader.GetString(13); } + + var invoice = new Model.Account.PurchaseInvoice(); + invoice.PurchaseID = purchaseID; + invoice.PurchaseNumber = purchaseNumber; + invoice.RecordID = recordID; + invoice.PurchaseDate = purchaseDate; + invoice.SupplierRef = supplierRef; + //invoice.PurchaseTotalAmount = purchaseTotalAmount; + invoice.VatInclusiveAmounts = vatInclusiveAmounts; + invoice.RecordCreated = recordCreated; + invoice.RecordModified = recordModified; + invoice.IsActive = isActive; + invoice.CurrencyCode = currencyCode; + invoice.PurchaseChannel = purchaseChannelName; + + // is there contact info that needs to be added? + if (contactID != null) + { + invoiceContactDict.Add(purchaseID, (int)contactID); + } + + purchaseIdList.Add(purchaseID); + + returnList.Add(purchaseID, invoice); + } + } + } + } + // add contact info + if (invoiceContactDict.Any()) + { + var readContact = new Data.Database.Account.ReadContact(); + readContact.ContactIdList = invoiceContactDict.Values.ToList(); + var contactDict = readContact.Read(); + + if (contactDict.Any()) + { + foreach (var invoice in returnList) + { + if (invoiceContactDict.ContainsKey(invoice.Value.PurchaseID)) + { + int contactId = invoiceContactDict[invoice.Value.PurchaseID]; + invoice.Value.Contact = contactDict[contactId]; + } + } + } + } + + // add invoice lines + var lines = ReadPurchaseInvoiceLine(purchaseIdList); + foreach (var invoice in returnList.Values) + { + foreach (var line in lines.Values) + { + if (line.PurchaseId == invoice.PurchaseID) + { + if (invoice.InvoiceLines == null) + { + invoice.InvoiceLines = new List(); + } + invoice.InvoiceLines.Add(line); + } + } + } + + return returnList; + } + + /// + /// Retrieves purchase invoice lines based on specified filters. + /// + /// This method queries the database to retrieve purchase invoice line details that match + /// the provided filters. The filters include invoice IDs, invoice line IDs, statuses, and item descriptions. + /// The returned dictionary maps the purchase line ID to its corresponding object. + /// A list of purchase invoice IDs to filter the results. If empty, no filtering is applied. + /// A list of purchase invoice line IDs to filter the results. If empty, no filtering is applied. + /// A list of statuses to filter the results. If empty, no filtering is applied. + /// Searches for the specificed phases within the item description. Uses the LIKE AND sql function. Partial matches are supported. If empty, no filtering is + /// applied. + /// A dictionary where the key is the purchase line ID and the value is the corresponding + /// Model.Account.PurchaseInvoice.Line object containing detailed information about the purchase invoice line. + /// Thrown if a fail-safe condition is triggered, indicating an unexpected issue with tax code assignment. + public Dictionary ReadPurchaseInvoiceLine + (List invoiceIdList = null, List invoiceLineIdList = null, List statusList = null, List itemDescriptionList = null) + { + var returnList = new Dictionary(); + var sqlBuilder = new SqlWhereBuilder(); + + //build sql query + string sql = @" + SELECT tblPurchaseLine.PurchaseLineID + ,tblPurchaseLine.PurchaseID + ,tblPurchaseLineStatus.PurchaseLineStatus + ,tblPurchaseLine.SupplierRef + ,tblPurchaseLine.CheckedIn + ,tblPurchaseLine.ItemDescription + ,tblPurchaseLine.ItemQuantity + ,tblPurchaseLine.ItemGross + ,tblPurchaseLine.ItemTax + ,tblPurchaseLine.ShippingGross + ,tblPurchaseLine.ShippingTax + ,tblPurchaseLine.OtherGross + ,tblPurchaseLine.OtherTax + ,tblPurchaseLine.AccountTaxCodeID + ,tblPurchaseLine.Tax_AccountTransactionID + ,tblPurchaseLine.Net_AccountChartOfID + ,tblPurchaseLine.Net_AccountTransactionID + ,tblPurchaseLine.RecordCreated + ,tblPurchaseLine.RecordModified + ,tblPurchaseLine.IsActive + ,tblAccountTaxCode.TaxCode + FROM tblPurchaseLine + INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID + LEFT OUTER JOIN tblAccountTaxCode ON tblPurchaseLine.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID + WHERE 1 = 1 "; + + // build the where statments + if (invoiceIdList != null || invoiceIdList.Any()) + { + sqlBuilder.In("PurchaseID", invoiceLineIdList, "AND"); + } + if (invoiceLineIdList != null || invoiceLineIdList.Any()) + { + sqlBuilder.In("PurchaseLineID", invoiceLineIdList, "AND"); + } + if (statusList != null || statusList.Any()) + { + sqlBuilder.In("PurchaseLineStatus", invoiceLineIdList, "AND"); + } + if (itemDescriptionList != null || itemDescriptionList.Any()) + { + sqlBuilder.LikeAnd("ItemDescription", itemDescriptionList, "AND"); + } + + + // append where string to the sql + if (sqlBuilder.IsSetSqlWhereString) + { + sql = sql + sqlBuilder.SqlWhereString; + } + + // catch taxcode to add in after db read + var lineTaxCodeDict = new Dictionary(); + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + sqlBuilder.AddParametersToSqlCommand(cmd); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.HasRows) + { + while (reader.Read()) + { + int purchaseLineID = reader.GetInt32(0); + int purchaseID = reader.GetInt32(1); + string purchaseLineStatus = reader.GetString(2); + string supplierRef = null; + if (!reader.IsDBNull(3)) { supplierRef = reader.GetString(3); } + DateTime? checkedIn = null; + if (!reader.IsDBNull(4)) { checkedIn = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc); } + string itemDescription = null; + if (!reader.IsDBNull(5)) { itemDescription = reader.GetString(5); } + int itemQuantity = reader.GetInt32(6); + decimal itemGross = 0; + if (!reader.IsDBNull(7)) { itemGross = reader.GetDecimal(7); } + decimal itemTax = 0; + if (!reader.IsDBNull(8)) { itemTax = reader.GetDecimal(8); } + decimal shippingGross = 0; + if (!reader.IsDBNull(9)) { shippingGross = reader.GetDecimal(9); } + decimal shippingTax = 0; + if (!reader.IsDBNull(10)) { shippingTax = reader.GetDecimal(10); } + decimal otherGross = 0; + if (!reader.IsDBNull(11)) { otherGross = reader.GetDecimal(11); } + decimal otherTax = 0; + if (!reader.IsDBNull(12)) { otherTax = reader.GetDecimal(12); } + int accountTaxCodeID = reader.GetInt32(13); + int? tax_AccountTransactionID = null; + if (!reader.IsDBNull(14)) { tax_AccountTransactionID = reader.GetInt32(14); } + int net_AccountChartOfID = reader.GetInt32(15); + int? net_AccountTransactionID = null; + if (!reader.IsDBNull(16)) { net_AccountTransactionID = reader.GetInt32(16); } + DateTime recordModified; + DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(17), DateTimeKind.Utc); + if (reader.IsDBNull(18)) { recordModified = recordCreated; } + else { recordModified = DateTime.SpecifyKind(reader.GetDateTime(18), DateTimeKind.Utc); } + bool isActive = reader.GetBoolean(19); + string accountTaxCode = reader.GetString(20); + + var line = new Model.Account.PurchaseInvoice.Line(); + line.PurchaseLineId = purchaseLineID; + line.PurchaseId = purchaseID; + line.Status = purchaseLineStatus; + line.SupplierRef = supplierRef; + line.CheckedIn = checkedIn; + line.ItemDescription = itemDescription; + line.ItemQuantity = itemQuantity; + line.ItemGross = itemGross; + line.ItemTax = itemTax; + line.ShippingGross = shippingGross; + line.ShippingTax = shippingTax; + line.OtherGross = otherGross; + line.OtherTax = otherTax; + line.Tax_AccountTransactionId = tax_AccountTransactionID; + line.Net_AccountChartOfId = net_AccountChartOfID; + line.Net_AccountTransactionId = net_AccountTransactionID; + line.RecordModified = recordModified; + line.RecordCreated = recordCreated; + line.IsActive = isActive; + + returnList.Add(purchaseLineID, line); + + lineTaxCodeDict.Add(purchaseLineID, accountTaxCode); + } + } + } + } + // read tax codes form db and add to return object + var taxcodeList = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, lineTaxCodeDict.Values.ToList()).Values.ToList(); + + foreach (var line in returnList.Values) + { + foreach (var taxcode in taxcodeList) + { + if (taxcode.TaxCode == lineTaxCodeDict[line.PurchaseLineId]) + { + line.AccountTaxCode = taxcode; + break; + } + } + if (line.AccountTaxCode == null) + { + throw new Exception("Fail safe, this really shouodn't happen"); + } + } + + // all done + return returnList; + } + + public Dictionary ReadPurchaseInvoiceLineStatus() + { + var returnList = new Dictionary(); + + string sql = @" + SELECT [PurchaseLineStatusID] + ,[PurchaseLineStatus] + ,[ListSort] + ,[TimeStamp] + FROM [e2A].[dbo].[tblPurchaseLineStatus] + ORDER BY [ListSort]"; + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + // do something + } + else + { + while (reader.Read()) + { + int id = reader.GetInt32(0); + string name = reader.GetString(1); + int lineSort = reader.GetInt32(2); + + var returnItem = new Model.Account.PurchaseInvoiceLineStatus(id, name, lineSort); + returnList.Add(id, returnItem); + } + } + } + } + return returnList; + } + + public List ReadPurchaseInvoiceLineSummary(DateTime periodTo, string lineStatus, List descriptionSearch) + { + var returnList = new List(); + var sqlBuilder = new bnhtrade.Core.Data.Database.SqlWhereBuilder(); + + //build sql query + string sql = @" + SELECT tblPurchase.PurchaseDate + ,tblPurchase.PurchaseID + ,tblPurchase.PurchaseNumber + ,tblPurchaseLine.PurchaseLineID + ,tblPurchaseLine.ItemDescription + ,tblPurchaseLineStatus.PurchaseLineStatus + FROM tblPurchase + INNER JOIN tblPurchaseLine ON tblPurchase.PurchaseID = tblPurchaseLine.PurchaseID + INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID + WHERE tblPurchase.PurchaseDate <= @purchaseDate + "; + + if (lineStatus != null) + { + sql = sql + " AND PurchaseLineStatus = @purchaseLineStatus "; + } + + // build the where statments + if (descriptionSearch.Any()) + { + sqlBuilder.LikeAnd("ItemDescription", descriptionSearch, "AND"); + } + + // append where string to the sql + if (sqlBuilder.IsSetSqlWhereString) + { + sql = sql + sqlBuilder.SqlWhereString; + } + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + cmd.Parameters.AddWithValue("@purchaseDate", periodTo); + if (lineStatus != null) + { + cmd.Parameters.AddWithValue("@purchaseLineStatus", lineStatus); + } + + sqlBuilder.AddParametersToSqlCommand(cmd); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc); + int purchaseID = reader.GetInt32(1); + int purchaseNumber = reader.GetInt32(2); + int purchaseLineID = reader.GetInt32(3); + string itemDescription = reader.GetString(4); + string purchaseLineStatus = reader.GetString(5); + + var item = new Model.Account.PurchaseInvoiceLineSummary(); + item.PurchaseDate = purchaseDate; + item.PurchaseId = purchaseID; + item.PurchaseNumber = purchaseNumber; + item.PurchaseLineId = purchaseLineID; + item.ItemDescription = itemDescription; + item.LineStatus = purchaseLineStatus; + + returnList.Add(item); + } + } + } + + return returnList; + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/JournalRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/JournalRepository.cs new file mode 100644 index 0000000..7646118 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/JournalRepository.cs @@ -0,0 +1,372 @@ +using bnhtrade.Core.Data.Database._BoilerPlate; +using bnhtrade.Core.Data.Database.Repository.Interface; +using Microsoft.Data.SqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Transactions; + +namespace bnhtrade.Core.Data.Database.Repository.Implementation +{ + internal class JournalRepository : _Base, IJournalRepository + { + public JournalRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) + { + } + + public Dictionary ReadJournal(List journalIdList) + { + var sqlBuilder = new SqlWhereBuilder(); + + //build sql query + string sql = @" + SELECT tblAccountJournal.AccountJournalID + ,tblAccountJournal.AccountJournalTypeID + ,tblAccountJournal.EntryDate + ,tblAccountJournal.PostDate + ,tblAccountJournal.LastModified + ,tblAccountJournal.IsLocked + ,tblAccountJournalPost.AccountJournalPostID + ,tblAccountJournalPost.AccountChartOfID + ,tblAccountJournalPost.AmountGbp + FROM tblAccountJournal + INNER JOIN tblAccountJournalPost ON tblAccountJournal.AccountJournalID = tblAccountJournalPost.AccountJournalID + WHERE 1 = 1 "; + + // build the where statments + if (journalIdList.Any()) + { + sqlBuilder.In("tblAccountJournal.AccountJournalID", journalIdList, "AND"); + } + + // append where string to the sql + if (sqlBuilder.IsSetSqlWhereString) + { + sql = sql + sqlBuilder.SqlWhereString; + } + + // build tuple list + var dbJournalList = new List<( + int AccountJournalId + , int AccountJournalTypeId + , DateTime EntryDate + , DateTime PostDate + , DateTime LastModified + , bool IsLocked + )>(); + + var dbJournalPostList = new List<( + int AccountJournalId + , int AccountJournalPostId + , int AccountChartOfId + , decimal AmountGbp + )>(); + + + bool hasRows = false; + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + if (sqlBuilder.ParameterListIsSet) + { + sqlBuilder.AddParametersToSqlCommand(cmd); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.HasRows) + { + hasRows = true; + int lastJournalId = 0; + while (reader.Read()) + { + // read journal header + int journalId = reader.GetInt32(0); + if (journalId != lastJournalId) + { + lastJournalId = journalId; + + (int AccountJournalId + , int AccountJournalTypeId + , DateTime EntryDate + , DateTime PostDate + , DateTime LastModified + , bool IsLocked + ) + journal = + (journalId + , reader.GetInt32(1) + , DateTime.SpecifyKind(reader.GetDateTime(2), DateTimeKind.Utc) + , DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc) + , DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc) + , reader.GetBoolean(5) + ); + + dbJournalList.Add(journal); + } + + // read journal posts + (int AccountJournalId + , int AccountJournalPostId + , int AccountChartOfId + , decimal AmountGbp + ) + journalPost = + (journalId + , reader.GetInt32(6) + , reader.GetInt32(7) + , reader.GetDecimal(8) + ); + + dbJournalPostList.Add(journalPost); + } + } + } + } + + var returnList = new Dictionary(); + if (hasRows) + { + // build lists to filter db results by + var journalTypeIdList = new List(); + var accountIdList = new List(); + foreach (var item in dbJournalList) + { + journalTypeIdList.Add(item.AccountJournalTypeId); + } + foreach (var item in dbJournalPostList) + { + accountIdList.Add(item.AccountChartOfId); + } + + // get journalTypes from db + var journalTypeDict = new JournalRepository(_connection, _transaction).ReadJournalType(journalTypeIdList); + + // get accounts from db + var accountDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIdList); + + // build final return dictionary + foreach (var dbJournal in dbJournalList) + { + // build posts + var newPosts = new List(); + foreach (var dbJournalPost in dbJournalPostList) + { + if (dbJournalPost.AccountJournalId == dbJournal.AccountJournalId) + { + var newPost = new Core.Model.Account.Journal.Post( + dbJournalPost.AccountJournalPostId + , accountDict[dbJournalPost.AccountChartOfId] + , dbJournalPost.AmountGbp); + + newPosts.Add(newPost); + } + } + + // create the journal + var newJournal = new Core.Model.Account.Journal( + dbJournal.AccountJournalId + , journalTypeDict[dbJournal.AccountJournalTypeId] + , newPosts + , dbJournal.EntryDate + , dbJournal.PostDate + , dbJournal.LastModified + , dbJournal.IsLocked); + + returnList.Add(dbJournal.AccountJournalId, newJournal); + } + } + // all done, return the list herevar + return returnList; + } + + /// + /// Test for locked journal entry + /// + /// False on locked journal entry + public bool ReadJournalIsLocked(int journalId) + { + string sql = @" + SELECT + tblAccountJournal.IsLocked + FROM + tblAccountJournal + WHERE + tblAccountJournal.AccountJournalID=@accountJournalId;"; + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + cmd.Parameters.AddWithValue("@accountJournalId", journalId); + + object obj = cmd.ExecuteScalar(); + if (obj == null) + { + throw new Exception("Journal entry not found for AccountJournalID=" + journalId); + } + else + { + return (bool)obj; + } + } + } + + + public Dictionary ReadJournalType(List journalTypeIds = null, List typeTitles = null) + { + var sqlBuilder = new SqlWhereBuilder(); + + // create the return (emptyP list) here + var returnList = new Dictionary(); + sqlBuilder.Init(); + + //build sql query + string sql = @" + SELECT [AccountJournalTypeID] + ,[TypeTitle] + ,[ChartOfAccountID_Debit] + ,[ChartOfAccountID_Credit] + FROM [e2A].[dbo].[tblAccountJournalType] + WHERE 1 = 1 "; + + // build the where statments + if (journalTypeIds.Any()) + { + sqlBuilder.In("AccountJournalTypeID", journalTypeIds, "AND"); + } + if (typeTitles.Any()) + { + sqlBuilder.In("TypeTitle", typeTitles, "AND"); + } + + // append where string to the sql + if (sqlBuilder.IsSetSqlWhereString) + { + sql = sql + sqlBuilder.SqlWhereString; + } + + // create dictionary to add credit/debit accounts on after db read + var creditDict = new Dictionary(); + var debitDict = new Dictionary(); + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + if (sqlBuilder.ParameterListIsSet) + { + sqlBuilder.AddParametersToSqlCommand(cmd); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.HasRows) + { + while (reader.Read()) + { + // read from db and create object + int journalTypeId = reader.GetInt32(0); + string title = reader.GetString(1); + int? debitAccountId = null; + if (!reader.IsDBNull(2)) { debitAccountId = reader.GetInt32(2); } + int? creditAccountId = null; + if (!reader.IsDBNull(3)) { creditAccountId = reader.GetInt32(3); } + + // build return list + var item = new Model.Account.JournalType(journalTypeId, title); + returnList.Add(journalTypeId, item); + + // build dictionaries + if (debitAccountId != null) + { + debitDict.Add(journalTypeId, debitAccountId.Value); + } + if (creditAccountId != null) + { + creditDict.Add(journalTypeId, creditAccountId.Value); + } + } + } + } + } + // get account objects from db + var accountIdList = debitDict.Values.ToList(); + accountIdList.AddRange(creditDict.Values.ToList()); + var dbDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIdList); + + // add to the returnlist + foreach (var account in returnList.Values) + { + Model.Account.Account debitAccount = null; + if (debitDict.ContainsKey(account.JournalTypeId)) + { + debitAccount = dbDict[debitDict[account.JournalTypeId]]; + } + + Model.Account.Account creditAccount = null; + if (creditDict.ContainsKey(account.JournalTypeId)) + { + creditAccount = dbDict[creditDict[account.JournalTypeId]]; // key of 59 needed + } + + account.AddDefaultAccounts(creditAccount, debitAccount); + } + + // all done, return the list here + return returnList; + } + + /// + /// Old code needs sorting + /// + public bool DeleteJournal(int accountJournalId) + { + bool IsLocked = ReadJournalIsLocked(accountJournalId); + if (IsLocked == true) + { + return false; + } + + // make the delete + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = @" + DELETE FROM tblAccountJournalPost + WHERE AccountJournalID=@accountJournalId;"; + cmd.Transaction = _transaction as SqlTransaction; + + cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId); + + int rows = cmd.ExecuteNonQuery(); + + if (rows == 0) + { + throw new Exception("Journal entry and/or entry posts do not exist for AccountJournalId=" + accountJournalId); + } + } + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = @" + DELETE FROM tblAccountJournal + WHERE AccountJournalID=@accountJournalId;"; + cmd.Transaction = _transaction as SqlTransaction; + + cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId); + + cmd.ExecuteNonQuery(); + } + return true; + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/SkuRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/SkuRepository.cs new file mode 100644 index 0000000..c463385 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/SkuRepository.cs @@ -0,0 +1,117 @@ +using bnhtrade.Core.Data.Database._BoilerPlate; +using bnhtrade.Core.Data.Database.Repository.Interface; +using Microsoft.Data.SqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Transactions; + + +namespace bnhtrade.Core.Data.Database.Repository.Implementation +{ + internal class SkuRepository : _Base, ISkuRepository + { + public SkuRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) + { + } + + public int? ReadSkuId(int productId, int conditionId, int accountTaxCodeId) + { + int? returnId = null; + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = @" + SELECT + tblSku.skuSkuID + FROM + tblSku + WHERE + (((tblSku.skuProductID)=@productId) AND ((tblSku.skuSkuConditionID)=@conditionId) AND ((tblSku.AccountTaxCodeID)=@accountTaxCodeId)); + "; + cmd.Transaction = _transaction as SqlTransaction; + + cmd.Parameters.AddWithValue("@productId", productId); + cmd.Parameters.AddWithValue("@conditionId", conditionId); + cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId); + + object obj = cmd.ExecuteScalar(); + if (obj != null || obj == DBNull.Value) + { + returnId = (int)obj; + } + } + return returnId; + } + + public int InsertNewSku(int productId, int conditionId, int accountTaxCodeId) + { + // check tax code id is a valid for SKU + var taxCodeList = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, null, new List { accountTaxCodeId }); + + if (taxCodeList.ContainsKey(accountTaxCodeId) == false) + { + throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " doesn't exist!"); + } + else if (taxCodeList[accountTaxCodeId].IsValidOnIncome == false) + { + throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " is not a valid type for an SKU."); + } + + // get info to create sku number + int skuCount; + int skuSuffix; + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = "SELECT NEXT VALUE FOR SkuCountSequence;"; + cmd.Transaction = _transaction as SqlTransaction; + skuCount = (int)cmd.ExecuteScalar(); + } + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = @" + SELECT tblSkuCondition.scnSkuNumberSuffix + FROM tblSkuCondition + WHERE (((tblSkuCondition.scnSkuConditionID)=@conditionId));"; + cmd.Transaction = _transaction as SqlTransaction; + cmd.Parameters.AddWithValue("@conditionId", conditionId); + + try + { + skuSuffix = (int)cmd.ExecuteScalar(); + } + catch (Exception ex) + { + throw new Exception("Error retriving SKU number suffix for SkuConditionID=" + conditionId + "." + + System.Environment.NewLine + "Error Message: " + ex.Message); + } + } + string skuNumber = skuCount.ToString("D6") + "-" + skuSuffix.ToString("D2"); + + // insert new sku + int skuId; + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = @" + INSERT INTO tblSku + (skuSkuNumber, skuProductID, skuSkuConditionID, AccountTaxCodeID) + OUTPUT INSERTED.skuSkuID + VALUES + (@skuNumber, @productId, @conditionId, @accountTaxCodeId)"; + cmd.Transaction = _transaction as SqlTransaction; + + cmd.Parameters.AddWithValue("@skuNumber", skuNumber); + cmd.Parameters.AddWithValue("@productId", productId); + cmd.Parameters.AddWithValue("@conditionId", conditionId); + cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId); + + skuId = (int)cmd.ExecuteScalar(); + } + return skuId; + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/StockRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/StockRepository.cs new file mode 100644 index 0000000..1014ac8 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/StockRepository.cs @@ -0,0 +1,141 @@ +using bnhtrade.Core.Data.Database._BoilerPlate; +using bnhtrade.Core.Data.Database.Repository.Interface; +using Microsoft.Data.SqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Implementation +{ + internal class StockRepository : _Base, IStockRepository + { + public StockRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) + { + } + + public List ReadStatus(List statusIds = null, List statusTypeIds = null) + { + var sqlBuilder = new SqlWhereBuilder(); + var returnList = new List(); + + //build sql query + string sql = @" + SELECT [StockStatusID] + ,[StatusCode] + ,[StockStatus] + ,[StockStatusTypeID] + ,[Reference] + ,[ForeignKeyID] + ,[IsCreditOnly] + ,[IsClosed] + ,[RecordCreated] + FROM [e2A].[dbo].[tblStockStatus] + WHERE 1=1 "; + + // build the where statments + if (statusIds.Any()) + { + sqlBuilder.In("StockStatusID", statusIds, "AND"); + } + if (statusTypeIds.Any()) + { + sqlBuilder.In("StockStatusTypeID", statusTypeIds, "AND"); + } + + // append where string to the sql + if (sqlBuilder.IsSetSqlWhereString) + { + sql = sql + sqlBuilder.SqlWhereString; + } + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = sql; + cmd.Transaction = _transaction as SqlTransaction; + + if (sqlBuilder.ParameterListIsSet) + { + sqlBuilder.AddParametersToSqlCommand(cmd); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + var typeDict = new StockRepository(_connection, _transaction).ReadStatusType(); + + while (reader.Read()) + { + int statusId = reader.GetInt32(0); + int? statusCode = null; + if (!reader.IsDBNull(1)) { statusCode = reader.GetInt32(1); } + string stockStatus = reader.GetString(2); + int typeId = reader.GetInt32(3); + string reference = null; + if (!reader.IsDBNull(4)) { reference = reader.GetString(4); } + int? foreignKeyId = null; + if (!reader.IsDBNull(5)) { foreignKeyId = reader.GetInt32(5); } + bool isCreditOnly = reader.GetBoolean(6); + bool isClosed = reader.GetBoolean(7); + DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc); + + var newItem = new Model.Stock.Status(statusId + , statusCode + , stockStatus + , typeDict[typeId] + , reference + , foreignKeyId + , isCreditOnly + , isClosed + , recordCreated + ); + + returnList.Add(newItem); + } + } + } + return returnList; + } + + public Dictionary ReadStatusType() + { + var returnDict = new Dictionary(); + + // get all account info before we start + var accountDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(); + + using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) + { + cmd.CommandText = @" + SELECT [StockStatusTypeID] + ,[StatusTypeName] + ,[ForeignKeyType] + ,[ReferenceType] + ,[AccountChartOfID] + FROM [e2A].[dbo].[tblStockStatusType]"; + cmd.Transaction = _transaction as SqlTransaction; + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + var accountIdDict = new Dictionary(); + + while (reader.Read()) + { + int statusTypeId = reader.GetInt32(0); + string name = reader.GetString(1); + string foreignKey = null; + if (!reader.IsDBNull(2)) { foreignKey = reader.GetString(2); } + string reference = null; + if (!reader.IsDBNull(3)) { reference = reader.GetString(3); } + uint accountId = (uint)reader.GetInt32(4); + + var statusType = new Model.Stock.StatusType(statusTypeId, name, foreignKey, reference, accountDict[(int)accountId]); + returnDict.Add(statusTypeId, statusType); + } + } + } + return returnDict; + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Implementation/_Base.cs b/src/bnhtrade.Core/Data/Database/Repository/Implementation/_Base.cs index 5c86041..27485d0 100644 --- a/src/bnhtrade.Core/Data/Database/Repository/Implementation/_Base.cs +++ b/src/bnhtrade.Core/Data/Database/Repository/Implementation/_Base.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace bnhtrade.Core.Data.Database.Repository.Implementation { - abstract class _Base + public abstract class _Base { protected readonly IDbConnection _connection; protected readonly IDbTransaction _transaction; diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/IAccountCodeRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/IAccountCodeRepository.cs new file mode 100644 index 0000000..ca7f752 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Interface/IAccountCodeRepository.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Interface +{ + internal interface IAccountCodeRepository + { + Dictionary ReadAccountCode(List accountIdList = null, List accountCodeList = null); + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/IAccountTaxRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/IAccountTaxRepository.cs new file mode 100644 index 0000000..959b5b5 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Interface/IAccountTaxRepository.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Interface +{ + internal interface IAccountTaxRepository + { + Dictionary ReadTaxCodeInfo(bool? IsActive = null, List taxcodeList = null, List taxcodeIdList = null); + Dictionary GetTaxCodeBySkuNumber(List skuNumberList); + Dictionary ReadTaxCodeByInvoiceLineItemCode(List lineItemCode); + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/IAmazonSettlementRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/IAmazonSettlementRepository.cs new file mode 100644 index 0000000..9e92e28 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Interface/IAmazonSettlementRepository.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Interface +{ + internal interface IAmazonSettlementRepository + { + List ReadAmazonSettlementHeaderInfoBySettlementId(List settlementIdList); + + List ReadAmazonSettlementHeaderInfoBySpapiReportId(List spapiReportIdList); + + Dictionary ReadAmazonSettlements( + List settlementIdList = null, List marketPlaceNameList = null, bool? isProcessed = null, + bool descendingOrder = false, int? returnTop = null); + + bool UpdateAmazonSettlementMarketPlaceName(string settlementId, Model.Amazon.MarketPlaceEnum marketPlace); + + int UpdateAmazonSettlementIsProcessed(List settlementIdList, bool isProcessed); + + bool CreateAmazonSettlements(string filePath, string reportId); + + int SetSpapiReportId(string settlementId, string spapiReportId); + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/IExportInvoiceRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/IExportInvoiceRepository.cs index c5e7004..4be5af6 100644 --- a/src/bnhtrade.Core/Data/Database/Repository/Interface/IExportInvoiceRepository.cs +++ b/src/bnhtrade.Core/Data/Database/Repository/Interface/IExportInvoiceRepository.cs @@ -8,11 +8,11 @@ namespace bnhtrade.Core.Data.Database.Repository.Interface { internal interface IExportInvoiceRepository { - internal Dictionary InsertSalesInvoices(IEnumerable invoiceList); - internal Dictionary GetNewInvoiceNumbers(Model.Account.InvoiceType invoiceType); - internal Dictionary GetSalesInvoiceById(IEnumerable idList); - internal int SetInvoiceIsCompleteValue(Dictionary updateDictionary); - internal int DeleteInvoiceLine(int invoiceLineId); - internal int DeleteInvoice(IEnumerable invoiceIdList); + Dictionary InsertSalesInvoices(IEnumerable invoiceList); + Dictionary GetNewInvoiceNumbers(Model.Account.InvoiceType invoiceType); + Dictionary GetSalesInvoiceById(IEnumerable idList); + int UpdateInvoiceHeaderDetail(int invoiceId, string invoiceNumber = null, bool? isComplete = null); + int DeleteInvoiceLine(int invoiceLineId); + int DeleteInvoice(IEnumerable invoiceIdList); } } diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/IImportAmazonRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/IImportAmazonRepository.cs deleted file mode 100644 index 21cabda..0000000 --- a/src/bnhtrade.Core/Data/Database/Repository/Interface/IImportAmazonRepository.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Data.Database.Repository.Interface -{ - internal interface IImportAmazonRepository - { - public List ReadAmazonSettlementHeaderInfoBySettlementId(List settlementIdList); - - public List ReadAmazonSettlementHeaderInfoBySpapiReportId(List spapiReportIdList); - - public Dictionary ReadAmazonSettlements( - List settlementIdList = null, List marketPlaceNameList = null, bool? isProcessed = null, - bool descendingOrder = false, int? returnTop = null); - - public int SetAmazonSettlementIsProcessed(List settlementIdList, bool isProcessed); - - public bool CreateAmazonSettlements(string filePath, string reportId); - - public int SetSpapiReportId(string settlementId, string spapiReportId); - } -} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/IInvoiceRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/IInvoiceRepository.cs new file mode 100644 index 0000000..14bb548 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Interface/IInvoiceRepository.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Interface +{ + internal interface IInvoiceRepository + { + int CreateDefaultInvoiceLineItem(string itemCode); + Dictionary GetInvoiceLineItem( + IEnumerable itemIds = null, IEnumerable itemCodes = null, bool includeAccountInfo = true, bool includeTaxInfo = true + ); + Dictionary ReadPurchaseInvoice(IEnumerable purchaseInvoiceIdList); + Dictionary ReadPurchaseInvoiceLine + (List invoiceIdList, List invoiceLineIdList, List statusList, List itemDescriptionList); + Dictionary ReadPurchaseInvoiceLineStatus(); + List ReadPurchaseInvoiceLineSummary(DateTime periodTo, string lineStatus, List descriptionSearch); + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/IJournalRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/IJournalRepository.cs new file mode 100644 index 0000000..8ad3d04 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Interface/IJournalRepository.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Interface +{ + internal interface IJournalRepository + { + Dictionary ReadJournal(List journalIdList); + bool ReadJournalIsLocked(int journalId); + Dictionary ReadJournalType(List journalTypeIds = null, List typeTitles = null); + bool DeleteJournal(int accountJournalId); + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/ISkuRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/ISkuRepository.cs new file mode 100644 index 0000000..085c098 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Interface/ISkuRepository.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Interface +{ + internal interface ISkuRepository + { + int? ReadSkuId(int productId, int conditionId, int accountTaxCodeId); + int InsertNewSku(int productId, int conditionId, int accountTaxCodeId); + } +} diff --git a/src/bnhtrade.Core/Data/Database/Repository/Interface/IStockRepository.cs b/src/bnhtrade.Core/Data/Database/Repository/Interface/IStockRepository.cs new file mode 100644 index 0000000..0ff9470 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Repository/Interface/IStockRepository.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database.Repository.Interface +{ + internal interface IStockRepository + { + List ReadStatus(List statusIds = null, List statusTypeIds = null); + Dictionary ReadStatusType(); + } +} diff --git a/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs b/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs index d397527..e3be59d 100644 --- a/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs +++ b/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Data.SqlClient; +using Microsoft.Data.SqlClient; namespace bnhtrade.Core.Data.Database.Sku { @@ -102,33 +102,7 @@ namespace bnhtrade.Core.Data.Database.Sku /// public int? ByParameters(int productId, int conditionId, int accountTaxCodeId) { - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - int? returnId = null; - - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(@" - SELECT - tblSku.skuSkuID - FROM - tblSku - WHERE - (((tblSku.skuProductID)=@productId) AND ((tblSku.skuSkuConditionID)=@conditionId) AND ((tblSku.AccountTaxCodeID)=@accountTaxCodeId)); - ", conn)) - { - cmd.Parameters.AddWithValue("@productId", productId); - cmd.Parameters.AddWithValue("@conditionId", conditionId); - cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId); - - object obj = cmd.ExecuteScalar(); - if (obj != null || obj == DBNull.Value) - { - returnId = (int)obj; - } - } - return returnId; - } + throw new NotSupportedException("This method is not supported in GetSkuId. Use SkuRepository instead."); } } } diff --git a/src/bnhtrade.Core/Data/Database/SKU/InsertSku.cs b/src/bnhtrade.Core/Data/Database/SKU/InsertSku.cs deleted file mode 100644 index 7578e9d..0000000 --- a/src/bnhtrade.Core/Data/Database/SKU/InsertSku.cs +++ /dev/null @@ -1,85 +0,0 @@ -using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductPricing; -using System; -using System.Collections.Generic; -using Microsoft.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Transactions; - -namespace bnhtrade.Core.Data.Database.Sku -{ - internal class InsertSku : Connection - { - public int InsertNew(int productId, int conditionId, int accountTaxCodeId) - { - using (TransactionScope scope = new TransactionScope()) - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - // check tax code id is a valid for SKU - var dbTax = new Data.Database.Account.ReadTaxCode(); - var taxCodeList = dbTax.GetByTaxCodeId(new List { accountTaxCodeId }); - - if (taxCodeList.ContainsKey(accountTaxCodeId) == false) - { - throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " doesn't exist!"); - } - else if (taxCodeList[accountTaxCodeId].IsValidOnIncome == false) - { - throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " is not a valid type for an SKU."); - } - - // get info to create sku number - int skuCount; - int skuSuffix; - using (SqlCommand cmd = new SqlCommand("SELECT NEXT VALUE FOR SkuCountSequence;", conn)) - { - skuCount = (int)cmd.ExecuteScalar(); - } - - using (SqlCommand cmd = new SqlCommand(@" - SELECT tblSkuCondition.scnSkuNumberSuffix - FROM tblSkuCondition - WHERE (((tblSkuCondition.scnSkuConditionID)=@conditionId)); - ", conn)) - { - cmd.Parameters.AddWithValue("@conditionId", conditionId); - - try - { - skuSuffix = (int)cmd.ExecuteScalar(); - } - catch (Exception ex) - { - throw new Exception("Error retriving SKU number suffix for SkuConditionID=" + conditionId + "." + - System.Environment.NewLine + "Error Message: " + ex.Message); - } - } - string skuNumber = skuCount.ToString("D6") + "-" + skuSuffix.ToString("D2"); - - // insert new sku - int skuId; - using (SqlCommand cmd = new SqlCommand(@" - INSERT INTO tblSku - (skuSkuNumber, skuProductID, skuSkuConditionID, AccountTaxCodeID) - OUTPUT INSERTED.skuSkuID - VALUES - (@skuNumber, @productId, @conditionId, @accountTaxCodeId) - ", conn)) - { - cmd.Parameters.AddWithValue("@skuNumber", skuNumber); - cmd.Parameters.AddWithValue("@productId", productId); - cmd.Parameters.AddWithValue("@conditionId", conditionId); - cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId); - - skuId = (int)cmd.ExecuteScalar(); - } - - scope.Complete(); - return skuId; - } - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/SqlUpdateBuilder.cs b/src/bnhtrade.Core/Data/Database/SqlUpdateBuilder.cs new file mode 100644 index 0000000..6a60bc7 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/SqlUpdateBuilder.cs @@ -0,0 +1,132 @@ +using bnhtrade.Core.Data.Database._BoilerPlate; +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Data.Database +{ + internal class SqlUpdateBuilder + { + private Dictionary _usedUpdateFields = new Dictionary(); + private Dictionary _parameterList = new Dictionary(); + private string _tableName = string.Empty; + private int _parameterCount = 0; + private string _sqlUpdate = string.Empty; + private string _sqlWhere = string.Empty; + private bool _updateIsSet = false; + private bool _whereIsSet = false; + + public SqlUpdateBuilder() { } + + public void Innit() + { + _usedUpdateFields.Clear(); + _parameterList.Clear(); + _tableName = string.Empty; + _parameterCount = 0; + _sqlUpdate = string.Empty; + _sqlWhere = string.Empty; + _updateIsSet = false; + _whereIsSet = false; + } + + public void SetTableName(string tableName) + { + if (string.IsNullOrEmpty(tableName)) + { + throw new ArgumentException("Table name cannot be null or empty.", nameof(tableName)); + } + _tableName = tableName; + } + + public void AddUpdateArugment(string columnName, object newValue) + { + if (string.IsNullOrEmpty(columnName) || newValue == null) + { + throw new ArgumentException("Column name and new value cannot be null or empty."); + } + if (_usedUpdateFields.ContainsKey(columnName)) + { + throw new ArgumentException($"Column '{columnName}' already exists in the update arguments.", nameof(columnName)); + } + + // add the update arguments to sql string and parameter list + if (_updateIsSet) + { + _sqlUpdate += @", + "; + } + else + { + _updateIsSet = true; + } + + _parameterCount++; + _sqlUpdate += columnName + " = @parameter" + _parameterCount; + _parameterList.Add("@parameter" + _parameterCount, newValue); + } + + public void AddWhereArugment(string columnName, object value) + { + if (string.IsNullOrEmpty(columnName) || value == null) + { + throw new ArgumentException("Column name and new value cannot be null or empty."); + } + + // add the where arguments to sql string and parameter list + if (_whereIsSet) + { + _sqlWhere += @", + "; + } + else + { + _whereIsSet = true; + } + + _parameterCount++; + _sqlWhere += columnName + " = @parameter" + _parameterCount; + _parameterList.Add("@parameter" + _parameterCount, value); + } + + public string GetSqlString() + { + if (_updateIsSet == false || _whereIsSet == false || string.IsNullOrEmpty(_tableName)) + { + throw new InvalidOperationException("Table name, update arguments, and where arguments must be set before generating SQL string."); + } + + string sql = @" + UPDATE "+ _tableName + @" + SET " + _sqlUpdate + @" + WHERE " + _sqlWhere + ";"; + + return sql; + } + + public void AddParametersToSqlCommand(System.Data.SqlClient.SqlCommand cmd) + { + if (_parameterList != null) + { + foreach (var item in _parameterList) + { + cmd.Parameters.AddWithValue(item.Key, item.Value); + } + } + } + + public void AddParametersToSqlCommand(Microsoft.Data.SqlClient.SqlCommand cmd) + { + if (_parameterList != null) + { + foreach (var item in _parameterList) + { + cmd.Parameters.AddWithValue(item.Key, item.Value); + } + } + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/SqlWhereBuilder.cs b/src/bnhtrade.Core/Data/Database/SqlWhereBuilder.cs index 7f7159d..ea498f0 100644 --- a/src/bnhtrade.Core/Data/Database/SqlWhereBuilder.cs +++ b/src/bnhtrade.Core/Data/Database/SqlWhereBuilder.cs @@ -63,6 +63,21 @@ namespace bnhtrade.Core.Data.Database } } + public bool ParameterListIsSet + { + get + { + if (ParameterList == null || ParameterList.Any() == false) + { + return false; + } + else + { + return true; + } + } + } + /// /// Initialises the class /// @@ -154,7 +169,7 @@ namespace bnhtrade.Core.Data.Database int listCount = distinctList.Count(); - for (int i = 0; i < listCount; i++, parameterCount++) + for (int i = 0; i < listCount; i++) { if (i > 0) { @@ -170,15 +185,58 @@ namespace bnhtrade.Core.Data.Database sqlWhere += " ( " + columnReference + " LIKE '%' + "; - string param = "@parameter" + parameterCount; - sqlWhere += param; - ParameterList.Add(param, distinctList[i]); - sqlWhere += " + '%' ) "; + sqlWhere = sqlWhere + GetSetParameter(distinctList[i]) + " + '%' ) "; } SqlWhereString = SqlWhereString + sqlWhere; } + + public void IsEqualTo(string columnReference, bool booleanValue, string wherePrefix = null) + { + string sqlWhereString = @" + "; + + if (wherePrefix != null) + { + sqlWhereString += wherePrefix; + } + + sqlWhereString += " ( " + columnReference + " = "; + + if (booleanValue) + { + sqlWhereString += "1 ) "; + } + else + { + sqlWhereString += "0 ) "; + } + + SqlWhereString = SqlWhereString + sqlWhereString; + } + + public void IsEqualTo(string columnReference, string stringValue, string wherePrefix = null) + { + if (string.IsNullOrEmpty(stringValue) || string.IsNullOrEmpty(columnReference)) + { + throw new Exception(wherePrefix + " IsEqualTo method requires a valid column reference and string value."); + } + + string sqlWhereString = @" + "; + + if (wherePrefix != null) + { + sqlWhereString += wherePrefix; + } + + sqlWhereString += " ( " + columnReference + " = " + GetSetParameter(stringValue) + " ) "; + + SqlWhereString = SqlWhereString + sqlWhereString; + } + + /// /// Append an 'In' statement and parameter list to the class properties /// @@ -205,16 +263,14 @@ namespace bnhtrade.Core.Data.Database sqlWhere += " " + columnReference + " IN ( "; int listCount = distinctList.Count(); - for (int i = 0; i < listCount; i++, parameterCount++) + for (int i = 0; i < listCount; i++) { if (i > 0) { sqlWhere += ", "; } - string param = "@parameter" + parameterCount; - sqlWhere += param; - ParameterList.Add(param, distinctList[i]); + sqlWhere = sqlWhere + GetSetParameter(distinctList[i].ToString()); } sqlWhere += " ) "; @@ -298,5 +354,19 @@ namespace bnhtrade.Core.Data.Database In(columnReference, objectList, wherePrefix); } + + /// + /// Adds a string value to the ParameterList and returns '@parameterN' that is then appended to the SQL statement + /// i.e. @parameter1, @parameter2, etc. + /// + /// parameter string that is then appended to the SQL statement + /// + private string GetSetParameter(string value) + { + parameterCount++; + string parameterString = "@parameter" + parameterCount; + ParameterList.Add(parameterString, value); + return parameterString; + } } } diff --git a/src/bnhtrade.Core/Data/Database/Stock/Status.cs b/src/bnhtrade.Core/Data/Database/Stock/Status.cs deleted file mode 100644 index 77243ce..0000000 --- a/src/bnhtrade.Core/Data/Database/Stock/Status.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static bnhtrade.Core.Data.Database.Constants; - -namespace bnhtrade.Core.Data.Database.Stock -{ - internal class Status : Connection - { - private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder; - - public List StatusIds { get; set; } - - public List StatusTypeIds { get; set; } - - public Status () - { - Init(); - } - - public void Init() - { - sqlBuilder = new SqlWhereBuilder(); - StatusIds = new List(); - StatusTypeIds = new List(); - } - - public List Read() - { - var returnList = new List(); - sqlBuilder.Init(); - - //build sql query - string sql = @" - SELECT [StockStatusID] - ,[StatusCode] - ,[StockStatus] - ,[StockStatusTypeID] - ,[Reference] - ,[ForeignKeyID] - ,[IsCreditOnly] - ,[IsClosed] - ,[RecordCreated] - FROM [e2A].[dbo].[tblStockStatus] - WHERE 1=1 "; - - // build the where statments - if (StatusIds.Any()) - { - sqlBuilder.In("StockStatusID", StatusIds, "AND"); - } - if (StatusTypeIds.Any()) - { - sqlBuilder.In("StockStatusTypeID", StatusTypeIds, "AND"); - } - - // append where string to the sql - if (sqlBuilder.IsSetSqlWhereString) - { - sql = sql + sqlBuilder.SqlWhereString; - } - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - sqlBuilder.AddParametersToSqlCommand(cmd); - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.HasRows) - { - var typeDict = new Data.Database.Stock.StatusType().Read(); - - while (reader.Read()) - { - int statusId = reader.GetInt32(0); - int? statusCode = null; - if (!reader.IsDBNull(1)) { statusCode = reader.GetInt32(1); } - string stockStatus = reader.GetString(2); - int typeId = reader.GetInt32(3); - string reference = null; - if (!reader.IsDBNull(4)) { reference = reader.GetString(4); } - int? foreignKeyId = null; - if (!reader.IsDBNull(5)) { foreignKeyId = reader.GetInt32(5); } - bool isCreditOnly = reader.GetBoolean(6); - bool isClosed = reader.GetBoolean(7); - DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc); - - var newItem = new Model.Stock.Status(statusId - , statusCode - , stockStatus - , typeDict[typeId] - , reference - , foreignKeyId - , isCreditOnly - , isClosed - , recordCreated - ); - - returnList.Add(newItem); - } - } - } - } - } - return returnList; - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/Stock/StatusType.cs b/src/bnhtrade.Core/Data/Database/Stock/StatusType.cs deleted file mode 100644 index 1b394e1..0000000 --- a/src/bnhtrade.Core/Data/Database/Stock/StatusType.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data.SqlClient; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Data.Database.Stock -{ - public class StatusType : Connection - { - public StatusType() - { - } - - /// - /// Reads all Status Types from database - /// - /// - public Dictionary Read() - { - var returnDict = new Dictionary(); - - // get all account info before we start - var accountDict = new Data.Database.Account.ReadAccountCode().All(); - - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) - { - conn.Open(); - - using (SqlCommand cmd = new SqlCommand(@" - SELECT [StockStatusTypeID] - ,[StatusTypeName] - ,[ForeignKeyType] - ,[ReferenceType] - ,[AccountChartOfID] - FROM [e2A].[dbo].[tblStockStatusType] - ", conn)) - { - using (SqlDataReader reader = cmd.ExecuteReader()) - { - var accountIdDict = new Dictionary(); - - while (reader.Read()) - { - int statusTypeId = reader.GetInt32(0); - string name = reader.GetString(1); - string foreignKey = null; - if (!reader.IsDBNull(2)) { foreignKey = reader.GetString(2); } - string reference = null; - if (!reader.IsDBNull(3)) { reference = reader.GetString(3); } - uint accountId = (uint)reader.GetInt32(4); - - var statusType = new Model.Stock.StatusType(statusTypeId, name, foreignKey, reference, accountDict[accountId]); - returnDict.Add(statusTypeId, statusType); - } - } - } - } - return returnDict; - } - } -} diff --git a/src/bnhtrade.Core/Data/Database/UnitOfWork/Connection.cs b/src/bnhtrade.Core/Data/Database/UnitOfWork/Connection.cs index 6a178f4..b077cce 100644 --- a/src/bnhtrade.Core/Data/Database/UnitOfWork/Connection.cs +++ b/src/bnhtrade.Core/Data/Database/UnitOfWork/Connection.cs @@ -8,7 +8,7 @@ using System.Configuration; namespace bnhtrade.Core.Data.Database.UnitOfWork { - internal class Connection + public class Connection { //protected readonly string SqlConnectionString; private Model.Credentials.bnhtradeDB _dbCredentials; diff --git a/src/bnhtrade.Core/Data/Database/UnitOfWork/IUnitOfWork.cs b/src/bnhtrade.Core/Data/Database/UnitOfWork/IUnitOfWork.cs index 58f6e7c..cfe61d8 100644 --- a/src/bnhtrade.Core/Data/Database/UnitOfWork/IUnitOfWork.cs +++ b/src/bnhtrade.Core/Data/Database/UnitOfWork/IUnitOfWork.cs @@ -10,10 +10,16 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork internal interface IUnitOfWork : IDisposable { // Properties for repositories, add here for each repository - public ICurrencyRepository CurrencyRepository { get; } + IAccountCodeRepository AccountCodeRepository { get; } + IAccountTaxRepository AccountTaxRepository { get; } + ICurrencyRepository CurrencyRepository { get; } IExportInvoiceRepository ExportInvoiceRepository { get; } - IImportAmazonRepository ImportAmazonRepository { get; } + IAmazonSettlementRepository AmazonSettlementRepository { get; } + IInvoiceRepository InvoiceRepository { get; } + IJournalRepository JournalRepository { get; } ISequenceGenerator SequenceGenerator { get; } + ISkuRepository SkuRepository { get; } + IStockRepository StockRepository { get; } // Methods to manage the transaction void Commit(); diff --git a/src/bnhtrade.Core/Data/Database/UnitOfWork/UnitOfWork.cs b/src/bnhtrade.Core/Data/Database/UnitOfWork/UnitOfWork.cs index 9e4b82b..4ab6005 100644 --- a/src/bnhtrade.Core/Data/Database/UnitOfWork/UnitOfWork.cs +++ b/src/bnhtrade.Core/Data/Database/UnitOfWork/UnitOfWork.cs @@ -18,18 +18,60 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork private bool _disposed; // Private field for lazy loading, add here for each repository + private IAccountCodeRepository _accountCodeRepository; + private IAccountTaxRepository _accountTaxRepository; + private IAmazonSettlementRepository _amazonSettlementRepository; private ICurrencyRepository _currencyRepository; private IExportInvoiceRepository _exportInvoiceRepository; - private IImportAmazonRepository _importAmazonRepository; + private IInvoiceRepository _invoiceRepository; + private IJournalRepository _journalRepository; private ISequenceGenerator _sequenceGenerator; + private ISkuRepository _skuRepository; + private IStockRepository _stockRepository; - public UnitOfWork() + internal UnitOfWork() { _connection = new SqlConnection(this.SqlConnectionString); _connection.Open(); _transaction = _connection.BeginTransaction(); } + public IAccountCodeRepository AccountCodeRepository + { + get + { + if (_accountCodeRepository == null) + { + _accountCodeRepository = new AccountCodeRepository(_connection, _transaction); + } + return _accountCodeRepository; + } + } + + public IAccountTaxRepository AccountTaxRepository + { + get + { + if (_accountTaxRepository == null) + { + _accountTaxRepository = new AccountTaxRepository(_connection, _transaction); + } + return _accountTaxRepository; + } + } + + public IAmazonSettlementRepository AmazonSettlementRepository + { + get + { + if (_amazonSettlementRepository == null) + { + _amazonSettlementRepository = new AmazonSettlementRepository(_connection, _transaction); + } + return _amazonSettlementRepository; + } + } + // Properties for repositories, add here for each repository public ICurrencyRepository CurrencyRepository { @@ -55,15 +97,26 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork } } - public IImportAmazonRepository ImportAmazonRepository + public IInvoiceRepository InvoiceRepository { + get + { + if (_invoiceRepository == null) + { + _invoiceRepository = new InvoiceRepository(_connection, _transaction); + } + return _invoiceRepository; + } + } + + public IJournalRepository JournalRepository { get { - if (_importAmazonRepository == null) + if (_journalRepository == null) { - _importAmazonRepository = new ImportAmazonRepository(_connection, _transaction); + _journalRepository = new JournalRepository(_connection, _transaction); } - return _importAmazonRepository; + return _journalRepository; } } @@ -79,6 +132,30 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork } } + public ISkuRepository SkuRepository + { + get + { + if (_skuRepository == null) + { + _skuRepository = new SkuRepository(_connection, _transaction); + } + return _skuRepository; + } + } + + public IStockRepository StockRepository + { + get + { + if (_stockRepository == null) + { + _stockRepository = new StockRepository(_connection, _transaction); + } + return _stockRepository; + } + } + public void Commit() { try diff --git a/src/bnhtrade.Core/Data/Xero/SalesInvoice.cs b/src/bnhtrade.Core/Data/Xero/SalesInvoice.cs index 8fb05ec..0caf1ee 100644 --- a/src/bnhtrade.Core/Data/Xero/SalesInvoice.cs +++ b/src/bnhtrade.Core/Data/Xero/SalesInvoice.cs @@ -94,10 +94,8 @@ namespace bnhtrade.Core.Data.Xero public string BrandingTheme { get; set; } } - internal void ExportToCsv(List salesInvoiceList, int startingInvoiceNumber, string savePath, bool unitAmountIsTaxExclusive = true) + internal void ExportToCsv(List salesInvoiceList, string savePath, bool unitAmountIsTaxExclusive = true) { - int invoiceNumberCount = startingInvoiceNumber; - // convert invoice to unitAmountIsTaxExclusive = true foreach (var invoice in salesInvoiceList) { @@ -123,7 +121,7 @@ namespace bnhtrade.Core.Data.Xero } string contactName = invoice.ContactName; - string invoiceNumber = "INV-" + invoiceNumberCount.ToString("000000"); + string invoiceNumber = invoice.InvoiceNumber; string reference = invoice.InvoiceReference; string invoiceDate = invoice.InvoiceDate.GetValueOrDefault().ToString("dd MMM yyyy", CultureInfo.InvariantCulture); string dueDate = invoice.InvoiceDueDate.GetValueOrDefault().ToString("dd MMM yyyy", CultureInfo.InvariantCulture); @@ -153,8 +151,6 @@ namespace bnhtrade.Core.Data.Xero csvLineList.Add(csvLine); } - - invoiceNumberCount++; } var config = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.CurrentCulture); diff --git a/src/bnhtrade.Core/Logic/Account/GetAccountCodeInfo.cs b/src/bnhtrade.Core/Logic/Account/AccountCodeService.cs similarity index 73% rename from src/bnhtrade.Core/Logic/Account/GetAccountCodeInfo.cs rename to src/bnhtrade.Core/Logic/Account/AccountCodeService.cs index d2019f4..b0611dd 100644 --- a/src/bnhtrade.Core/Logic/Account/GetAccountCodeInfo.cs +++ b/src/bnhtrade.Core/Logic/Account/AccountCodeService.cs @@ -6,18 +6,18 @@ using System.Threading.Tasks; namespace bnhtrade.Core.Logic.Account { - public class GetAccountCodeInfo + public class AccountCodeService : UnitOfWorkBase { - private Data.Database.Account.ReadAccountCode readAccountCode; - - public GetAccountCodeInfo() + public AccountCodeService() { - readAccountCode = new Data.Database.Account.ReadAccountCode(); } - public Dictionary GetAll() + public Dictionary GetAll() { - return readAccountCode.All(); + return WithUnitOfWork(uow => + { + return uow.AccountCodeRepository.ReadAccountCode(); + }); } public Model.Account.Account ByAccountCode(int accountCode) @@ -35,7 +35,10 @@ namespace bnhtrade.Core.Logic.Account public List ByAccountCode(List accountCodeList) { - return readAccountCode.ByAccountCode(accountCodeList).Values.ToList(); + return WithUnitOfWork(uow => + { + return uow.AccountCodeRepository.ReadAccountCode(null, accountCodeList).Values.ToList(); + }); } public Dictionary ConvertToDictionary(List accountCodeList) diff --git a/src/bnhtrade.Core/Logic/Account/GetTaxCodeInfo.cs b/src/bnhtrade.Core/Logic/Account/GetTaxCodeInfo.cs index cce8b34..cc900e3 100644 --- a/src/bnhtrade.Core/Logic/Account/GetTaxCodeInfo.cs +++ b/src/bnhtrade.Core/Logic/Account/GetTaxCodeInfo.cs @@ -3,21 +3,22 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows.Forms; namespace bnhtrade.Core.Logic.Account { - public class GetTaxCodeInfo + public class GetTaxCodeInfo : UnitOfWorkBase { - private Data.Database.Account.ReadTaxCode dbRead; - public GetTaxCodeInfo() { - dbRead = new Data.Database.Account.ReadTaxCode(); } public List GetByTaxCode(List taxCodeList) { - return dbRead.GetByTaxCode(taxCodeList); + return WithUnitOfWork(uow => + { + return uow.AccountTaxRepository.ReadTaxCodeInfo(null, taxCodeList).Values.ToList(); + }); } public Model.Account.TaxCodeInfo GetByTaxCode(string taxCode) @@ -48,7 +49,11 @@ namespace bnhtrade.Core.Logic.Account } // get db list - var dbList = dbRead.GetTaxCodeBySkuNumber(skuNumberList); + var dbList = WithUnitOfWork(uow => + { + return uow.AccountTaxRepository.GetTaxCodeBySkuNumber(skuNumberList); + }); + // build dictionary foreach (var item in dbList) diff --git a/src/bnhtrade.Core/Logic/Account/InvoiceLineItemService.cs b/src/bnhtrade.Core/Logic/Account/InvoiceLineItemService.cs index 6fdde4a..bd1ef2e 100644 --- a/src/bnhtrade.Core/Logic/Account/InvoiceLineItemService.cs +++ b/src/bnhtrade.Core/Logic/Account/InvoiceLineItemService.cs @@ -1,4 +1,5 @@ -using System; +using bnhtrade.Core.Data.Database.UnitOfWork; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,9 +7,17 @@ using System.Threading.Tasks; namespace bnhtrade.Core.Logic.Account { - public class InvoiceLineItemService + public class InvoiceLineItemService : UnitOfWorkBase { - private Logic.Log.LogEvent log = new Logic.Log.LogEvent(); + private Logic.Log.LogEvent _log = new Logic.Log.LogEvent(); + + public InvoiceLineItemService() + { + } + + internal InvoiceLineItemService(IUnitOfWork unitOfWork) : base(unitOfWork) + { + } /// /// Creates new 'default' item code entry. The item code and title are set, will require updating by user before use. @@ -17,25 +26,32 @@ namespace bnhtrade.Core.Logic.Account /// public Model.Account.InvoiceLineItem CreateNew(string itemCode) { - new Data.Database.Account.CreateInvoiceLineItem().CreateDefault(itemCode); - var item = new Data.Database.Account.ReadInvoiceLineItem().ByItemCode(new List { itemCode }); - if (item == null || item.Count == 0) + return WithUnitOfWork(uow => { - log.LogError("InvoiceLineItemService.CreateNew", "Error creating new invoice line item in database for item code: " + itemCode); - throw new Exception("Error creating new invoice line item in database"); - } - return item[0]; + uow.InvoiceRepository.CreateDefaultInvoiceLineItem(itemCode); + var item = uow.InvoiceRepository.GetInvoiceLineItem(null, new List { itemCode }); + if (item == null || item.Count == 0) + { + _log.LogError("InvoiceLineItemService.CreateNew", "Error creating new invoice line item in database for item code: " + itemCode); + throw new Exception("Error creating new invoice line item in database"); + } + CommitIfOwned(uow); + return item[0]; + }); } public Dictionary GetLineItems(List itemCodes) { - var dbResult = new Data.Database.Account.ReadInvoiceLineItem().ByItemCode(itemCodes); - var returnDict = new Dictionary(); - foreach ( var item in dbResult) + return WithUnitOfWork(uow => { - returnDict.Add(item.Value.ItemCode, item.Value); - } - return returnDict; + var dbResult = uow.InvoiceRepository.GetInvoiceLineItem(null, itemCodes); + var returnDict = new Dictionary(); + foreach (var item in dbResult) + { + returnDict.Add(item.Value.ItemCode, item.Value); + } + return returnDict; + }); } } } \ No newline at end of file diff --git a/src/bnhtrade.Core/Logic/Account/Journal.cs b/src/bnhtrade.Core/Logic/Account/Journal.cs index 690c85f..8cd434b 100644 --- a/src/bnhtrade.Core/Logic/Account/Journal.cs +++ b/src/bnhtrade.Core/Logic/Account/Journal.cs @@ -8,7 +8,7 @@ using System.Transactions; namespace bnhtrade.Core.Logic.Account { - public class Journal + public class Journal : UnitOfWorkBase { public int AccountJournalInsert(int journalTypeId, DateTime entryDate, string currencyCode, decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false) @@ -19,7 +19,12 @@ namespace bnhtrade.Core.Logic.Account public bool AccountJournalDelete(int accountJournalId) { - return new Data.Database.Account.DeleteJournal().AccountJournalDelete(accountJournalId); + return WithUnitOfWork(uow => + { + bool result = uow.JournalRepository.DeleteJournal(accountJournalId); + CommitIfOwned(uow); + return result; + }); } } } diff --git a/src/bnhtrade.Core/Logic/Account/PurchaseInvoice.cs b/src/bnhtrade.Core/Logic/Account/PurchaseInvoice.cs deleted file mode 100644 index 53fe9b0..0000000 --- a/src/bnhtrade.Core/Logic/Account/PurchaseInvoice.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Logic.Account -{ - public class PurchaseInvoice - { - /// - /// Get purchase invoices by id - /// - /// purchase id list - /// dictionary where key=id, value=purchaseinvoice - public Dictionary GetPurchaseInvoice(IEnumerable purchaseIdList) - { - var dbRead = new Data.Database.Account.ReadPurchaseInvoice(); - dbRead.PurchaseInvoiceIdList = purchaseIdList; - return dbRead.Read(); - } - } -} diff --git a/src/bnhtrade.Core/Logic/Account/PurchaseInvoiceMisc.cs b/src/bnhtrade.Core/Logic/Account/PurchaseInvoiceMisc.cs deleted file mode 100644 index 10eeb98..0000000 --- a/src/bnhtrade.Core/Logic/Account/PurchaseInvoiceMisc.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Logic.Account -{ - public class PurchaseInvoiceMisc - { - public List ReadLineStatusToList() - { - return new Data.Database.Account.ReadPurchaseInvoiceLineStatus().Read().Values.ToList(); - } - - public List GetLineSummary(DateTime maxDate, string lineStatus, List wordSearchList) - { - return new Data.Database.Account.ReadPurchaseInvoiceLineSummary().Read(maxDate,lineStatus, wordSearchList); - } - } -} diff --git a/src/bnhtrade.Core/Logic/Account/PurchaseInvoiceService.cs b/src/bnhtrade.Core/Logic/Account/PurchaseInvoiceService.cs new file mode 100644 index 0000000..a69fa94 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Account/PurchaseInvoiceService.cs @@ -0,0 +1,55 @@ +using bnhtrade.Core.Data.Database.UnitOfWork; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Account +{ + public class PurchaseInvoiceService : UnitOfWorkBase + { + public PurchaseInvoiceService() { } + + internal PurchaseInvoiceService(IUnitOfWork unitOfWork) : base(unitOfWork) + { + } + + /// + /// Get purchase invoices by id + /// + /// purchase id list + /// dictionary where key=id, value=purchaseinvoice + public Dictionary GetPurchaseInvoice(IEnumerable purchaseIdList) + { + return WithUnitOfWork(uow => + { + + var invoiceRepository = uow.InvoiceRepository; + var returnList = invoiceRepository.ReadPurchaseInvoice(purchaseIdList); + return returnList; + }); + } + + public List ReadLineStatusToList() + { + return WithUnitOfWork(uow => + { + + var invoiceRepository = uow.InvoiceRepository; + var returnList = invoiceRepository.ReadPurchaseInvoiceLineStatus().Values.ToList(); + return returnList; + }); + } + + public List GetLineSummary(DateTime maxDate, string lineStatus, List wordSearchList) + { + return WithUnitOfWork(uow => + { + var invoiceRepository = uow.InvoiceRepository; + var returnList = invoiceRepository.ReadPurchaseInvoiceLineSummary(maxDate, lineStatus, wordSearchList); + return returnList; + }); + } + } +} diff --git a/src/bnhtrade.Core/Logic/Export/AccountInvoice/AmazonSettlement.cs b/src/bnhtrade.Core/Logic/Export/AccountInvoice/AmazonSettlement.cs index 122e72a..f80735e 100644 --- a/src/bnhtrade.Core/Logic/Export/AccountInvoice/AmazonSettlement.cs +++ b/src/bnhtrade.Core/Logic/Export/AccountInvoice/AmazonSettlement.cs @@ -1,5 +1,6 @@ using Amazon.SQS.Model.Internal.MarshallTransformations; using bnhtrade.Core.Data.Database.UnitOfWork; +using bnhtrade.Core.Model.Account; using bnhtrade.Core.Model.Amazon; using bnhtrade.Core.Test.Export; using FikaAmazonAPI.ReportGeneration.ReportDataTable; @@ -17,24 +18,18 @@ using static bnhtrade.Core.Model.Import.AmazonSettlement; namespace bnhtrade.Core.Logic.Export.AccountInvoice { - internal class AmazonSettlement : Data.Database.Connection + internal class AmazonSettlement : UnitOfWorkBase { - private readonly IUnitOfWork _providedUnitOfWork = null; - private readonly bool _ownsUnitOfWork = false; - private Logic.Log.LogEvent _log = new Logic.Log.LogEvent(); private List _lineItemCodeList = new List(); private bool _settlementAmountIsTaxExclusive = false; // i.e. they're tax inclusive public AmazonSettlement() { - _ownsUnitOfWork = true; } - internal AmazonSettlement(IUnitOfWork unitOfWork) + internal AmazonSettlement(IUnitOfWork unitOfWork) : base(unitOfWork) { - _providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork)); - _ownsUnitOfWork = false; } public string ErrorMessage { get; private set; } @@ -53,34 +48,34 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice Init(); _log.LogInformation("Starting processing of Amazon settlement data into export invoice table..."); - // get list of unprocessed settlement reports to export - var settlementList = GetListOfUnprocessedSettlementReports(); - if (settlementList == null) + return WithUnitOfWork(uow => { - return false; - } + // get list of unprocessed settlement reports to export + var settlementList = GetUnprocessedSettlementReports(uow, true); + if (settlementList == null) + { + return false; + } - // create list of settlement ids for later use - var settlementIdList = new List(); - foreach (var settlement in settlementList) - { - settlementIdList.Add(settlement.SettlementId); - } + // create list of settlement ids for later use + var settlementIdList = new List(); + foreach (var settlement in settlementList) + { + settlementIdList.Add(settlement.SettlementId); + } - // create list of invoices from settlement reports - var invoiceList = CreateInvoices(settlementList, convertToGbp); - if (invoiceList == null || invoiceList.Any() == false) - { - return false; - } + // create list of invoices from settlement reports + var invoiceList = CreateInvoices(settlementList, convertToGbp); + if (invoiceList == null || invoiceList.Any() == false) + { + return false; + } - // add invoice to export queue and set settlements as processed - Console.Write("\rWriting to database... "); - using (UnitOfWork unitOfWork = new UnitOfWork()) - { + // add invoice to export queue and set settlements as processed + Console.Write("\rWriting to database... "); try { - var queueService = new Logic.Export.AccountInvoice.QueueService(unitOfWork); + var queueService = new Logic.Export.AccountInvoice.QueueService(uow); // add temp invoice numbers queueService.AddTempInvoiceNumber(invoiceList, true); @@ -89,12 +84,15 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice if (queueService.ErrorMessageIsSet == false && queueInsertResult.Count() == invoiceList.Count()) { // set settlements to isprocessed - unitOfWork.ImportAmazonRepository.SetAmazonSettlementIsProcessed(settlementIdList, true); - unitOfWork.Commit(); + uow.AmazonSettlementRepository.UpdateAmazonSettlementIsProcessed(settlementIdList, true); + uow.Commit(); + Console.Write("\r"); + _log.LogInformation("\rFinished processing of Amazon settlement data. " + invoiceList.Count() + " invoices created from " + settlementIdList.Count() + " Amazon settlement reports."); + return true; } else { - unitOfWork.Rollback(); + uow.Rollback(); string error = queueService.ErrorMessage; ErrorMessage = "Cancelled processing of Amazon settlement data into export invoice table. " + error; _log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table..."); @@ -109,115 +107,115 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice _log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table..."); return false; } - } - Console.Write("\r"); - _log.LogInformation("\rFinished processing of Amazon settlement data. " + invoiceList.Count() + " invoices created from " + settlementIdList.Count() + " Amazon settlement reports."); - return true; + }); } /// /// Retrives a list of unprocessed settlement reports from the database, checks for gaps in settlement periods, and validates /// the settlement data. /// - /// Import will fail on new marketplace, add here to bypass this check + /// Insert 'Amazon.co.uk' if the market place name is missing and the currecy is GBP /// - private List GetListOfUnprocessedSettlementReports() + private List GetUnprocessedSettlementReports(IUnitOfWork uow, bool updateNullMarketplaceByCurrency = true) { List settlementList = null; - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) + // get list of unprocessed settlement reports to export + settlementList = uow.AmazonSettlementRepository.ReadAmazonSettlements(null, null, false).Values.ToList(); + + if (settlementList.Any() == false) { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; + ErrorMessage = "No new settlement reports to process"; + return null; } - // get list of unprocssed settlement reports to export - using (currentUow != null && _ownsUnitOfWork ? currentUow : null) + // test marketplace-name has been sucsessfully entered into settlement table -- + // as this is not supplied in the original report from Amazon and has to be inferred from settlement line data or added below + // via currency (null marketplace anme is not picked up in validate stage as null value is valid) + foreach (var settlement in settlementList) { - settlementList = currentUow.ImportAmazonRepository.ReadAmazonSettlements(null, null, false).Values.ToList(); - - if (settlementList.Any() == false) + if (settlement.MarketPlaceNameIsSet == false && updateNullMarketplaceByCurrency && settlement.CurrencyCode == CurrencyCode.GBP.ToString()) { - ErrorMessage = "No new settlement reports to process"; + // update database with market place name + uow.AmazonSettlementRepository.UpdateAmazonSettlementMarketPlaceName( + settlement.SettlementId + , MarketPlaceEnum.AmazonUK + ); + + // add to settlement + settlement.MarketPlace = MarketPlaceEnum.AmazonUK; + } + else if (settlement.MarketPlaceNameIsSet == false) + { + string error = "User action required: Enter market place name for amazon settlelment report id:" + settlement.SettlementId + "."; + ErrorMessage = "Cancelled processing of Amazon settlement data into export invoice table: " + error; + _log.LogError( + error + , "Unable to process settlement data from report '" + settlement.SettlementId + + "'. Report header table requires a market place name, which is not supplied in original " + + "report from Amazon. This is useually inferred from settlement lines. " + + "However, in this case, it was not not possible. Manual edit/entry for database table required." + ); + _log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table..."); return null; } + } - // test marketplace-name has been sucsessfully entered into settlement table -- - // as this is not supplied in the original report from Amazon and has to be inferred from settlement line data - // this is not picked up in validate stage as null value is valid - foreach (var settlement in settlementList) + // check for time gaps between settlement periods + settlementList = settlementList.OrderBy(x => x.MarketPlace).ThenBy(x => x.StartDate).ToList(); + for (var i = 0; i < settlementList.Count; i++) + { + // first marketplace of type in list? retrive the previously completed settlement for that marketplace to compare datetimes + if (i == 0 || settlementList[i].MarketPlace != settlementList[i - 1].MarketPlace) { - if (settlement.MarketPlaceNameIsSet == false) + // get previously completed settlement for this marketplace + var completedSettlement = uow.AmazonSettlementRepository.ReadAmazonSettlements( + null, new List { settlementList[i].MarketPlace.GetMarketplaceUrl() }, true, true, 1); + if (completedSettlement.Any()) { - string error = "User action required: Enter market place name for amazon settlelment report id:" + settlement.SettlementId + "."; - ErrorMessage = "Cancelled processing of Amazon settlement data into export invoice table: " + error; - _log.LogError( - error - , "Unable to process settlement data from report '" + settlement.SettlementId + - "'. Report header table requires a market place name, which is not supplied in original " + - "report from Amazon. This is useually inferred from settlement lines. " + - "However, in this case, it was not not possible. Manual edit/entry for database table required." - ); - _log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table..."); - return null; - } - } - - // check for time gaps between settlement periods - settlementList = settlementList.OrderBy(x => x.MarketPlace).ThenBy(x => x.StartDate).ToList(); - for (var i = 0; i < settlementList.Count; i++) - { - // first marketplace of type in list? retrive the previously completed settlement for that marketplace to compare datetimes - if (i == 0 || settlementList[i].MarketPlace != settlementList[i - 1].MarketPlace) - { - // get previously completed settlement for this marketplace - var completedSettlement = currentUow.ImportAmazonRepository.ReadAmazonSettlements( - null, new List { settlementList[i].MarketPlace.GetMarketplaceUrl() }, true, true, 1); - if (completedSettlement.Any()) - { - if (completedSettlement.FirstOrDefault().Value.EndDate != settlementList[i].StartDate) - { - string error = (settlementList[i].StartDate - settlementList[i - 1].EndDate).Days + " day gap in " - + settlementList[i].MarketPlace.GetMarketplaceUrl() + " settlement data (" + settlementList[i - 1].EndDate.ToString("dd MMM yyyy") - + " to " + settlementList[i].StartDate.ToString("dd MMM yyyy") + "). Ensure all settlement reports have been imported."; - ErrorMessage = error; - _log.LogError("Cancelled processing of Amazon settlement data into invoice export queue: " + error); - return null; - } - } - else - { - // first settlement for this marketplace, no previous settlement to compare against - // continue on - } - } - else - { - if (settlementList[i - 1].EndDate != settlementList[i].StartDate) + if (completedSettlement.FirstOrDefault().Value.EndDate != settlementList[i].StartDate) { string error = (settlementList[i].StartDate - settlementList[i - 1].EndDate).Days + " day gap in " - + settlementList[i].MarketPlace + " settlement data (" + settlementList[i - 1].EndDate.ToString("dd MMM yyyy") + + settlementList[i].MarketPlace.GetMarketplaceUrl() + " settlement data (" + settlementList[i - 1].EndDate.ToString("dd MMM yyyy") + " to " + settlementList[i].StartDate.ToString("dd MMM yyyy") + "). Ensure all settlement reports have been imported."; ErrorMessage = error; _log.LogError("Cancelled processing of Amazon settlement data into invoice export queue: " + error); return null; } } + else + { + // first settlement for this marketplace, no previous settlement to compare against + // continue on + } + } + else + { + if (settlementList[i - 1].EndDate != settlementList[i].StartDate) + { + string error = (settlementList[i].StartDate - settlementList[i - 1].EndDate).Days + " day gap in " + + settlementList[i].MarketPlace + " settlement data (" + settlementList[i - 1].EndDate.ToString("dd MMM yyyy") + + " to " + settlementList[i].StartDate.ToString("dd MMM yyyy") + "). Ensure all settlement reports have been imported."; + ErrorMessage = error; + _log.LogError("Cancelled processing of Amazon settlement data into invoice export queue: " + error); + return null; + } } - } - // validate settlelments + if (settlementList == null || settlementList.Any() == false) + { + _log.LogInformation("No new settlement reports to process."); + return null; + } + + // validate settlements var validate = new Logic.Validate.AmazonSettlement(); foreach (var settlement in settlementList) { if (!validate.IsValid(settlement)) { - _log.LogError("Error procesing Amazon Settlement data for export.", validate.ValidationResultListToString()); + _log.LogError("Error processing Amazon Settlement data for export.", validate.ValidationResultListToString()); } } if (validate.IsValidResult == false) diff --git a/src/bnhtrade.Core/Logic/Export/AccountInvoice/InvoiceService.cs b/src/bnhtrade.Core/Logic/Export/AccountInvoice/InvoiceService.cs deleted file mode 100644 index 5fa5772..0000000 --- a/src/bnhtrade.Core/Logic/Export/AccountInvoice/InvoiceService.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Logic.Export.AccountInvoice -{ - internal class InvoiceService - { - } -} diff --git a/src/bnhtrade.Core/Logic/Export/AccountInvoice/QueueService.cs b/src/bnhtrade.Core/Logic/Export/AccountInvoice/QueueService.cs index 5f5df6a..4240f28 100644 --- a/src/bnhtrade.Core/Logic/Export/AccountInvoice/QueueService.cs +++ b/src/bnhtrade.Core/Logic/Export/AccountInvoice/QueueService.cs @@ -15,22 +15,17 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice /// /// Processes the Export Invoice table and exports to Xero /// - public class QueueService + public class QueueService : UnitOfWorkBase { private Log.LogEvent _log = new Log.LogEvent(); - private IEnumerable _exportSaleInvoiceIdList = new List(); - private readonly IUnitOfWork _providedUnitOfWork = null; - private readonly bool _ownsUnitOfWork = false; + private UnitOfWork _exportUow = null; public QueueService() { - _ownsUnitOfWork = true; } - internal QueueService(IUnitOfWork unitOfWork) + internal QueueService(IUnitOfWork unitOfWork) : base(unitOfWork) { - _providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork)); - _ownsUnitOfWork = false; } public string ErrorMessage { get; private set; } = null; @@ -64,26 +59,11 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice { Init(); - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) - { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; - } - string result = null; - using (currentUow != null && _ownsUnitOfWork ? currentUow : null) + return WithUnitOfWork(uow => { - result = "_tmp" + currentUow.SequenceGenerator.GetNext("ExportTempInvoiceNumber").ToString("00000000"); - if (_ownsUnitOfWork) - { - currentUow.Commit(); - } - } - return result; + return "_tmp" + uow.SequenceGenerator.GetNext("ExportTempInvoiceNumber").ToString("00000000"); + }); } public void AddTempInvoiceNumber(IEnumerable invoiceList, bool overwriteExisting) @@ -110,30 +90,26 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice { Init(); - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) + return WithUnitOfWork(uow => { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; - } - using (_ownsUnitOfWork ? currentUow : null) - { - var returnList = currentUow.ExportInvoiceRepository.GetSalesInvoiceById(invoiceIdList); - var validate = new Logic.Validate.Invoice(); - bool isValid = validate.IsValidExportInvoice(returnList.Values.ToList()); + return ReadInvoiceById(uow, invoiceIdList); + }); + } - if (isValid == false) - { - ErrorMessage = "Reading invoices from database failed validation. See logs for further details."; - _log.LogError("ErrorMessage", validate.ValidationResultListToString()); - throw new Exception(ErrorMessage); - } + private Dictionary ReadInvoiceById(IUnitOfWork uow, IEnumerable invoiceIdList) + { + var returnList = uow.ExportInvoiceRepository.GetSalesInvoiceById(invoiceIdList); + var validate = new Logic.Validate.Invoice(); + bool isValid = validate.IsValidExportInvoice(returnList.Values.ToList()); - return returnList; + if (isValid == false) + { + ErrorMessage = "Reading invoices from database failed validation. See logs for further details."; + _log.LogError("ErrorMessage", validate.ValidationResultListToString()); + throw new Exception(ErrorMessage); } + + return returnList; } /// @@ -158,25 +134,12 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice validateInvoice = null; // save to database - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) + return WithUnitOfWork(uow => { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; - } - - using (currentUow != null && _ownsUnitOfWork ? currentUow : null) - { - var result = currentUow.ExportInvoiceRepository.InsertSalesInvoices(invoiceList); - if (_ownsUnitOfWork) - { - currentUow.Commit(); - } + var result = uow.ExportInvoiceRepository.InsertSalesInvoices(invoiceList); + CommitIfOwned(uow); return result; - } + }); } /// @@ -187,25 +150,10 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice { Init(); - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) + return WithUnitOfWork(uow => { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; - } - - using (currentUow != null && _ownsUnitOfWork ? currentUow : null) - { - var result = currentUow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType).Count(); - if (_ownsUnitOfWork) - { - currentUow.Commit(); - } - return result; - } + return uow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType).Count(); + }); } /// @@ -213,80 +161,45 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice /// /// /// - public void ExportSalesInvoice(string filePath, int firstInvoiceNumber) + public bool ExportSalesInvoice(string filePath, int firstInvoiceNumber, Func getUserConfirmation) { Init(); - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) - { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; - } - - using (currentUow != null && _ownsUnitOfWork ? currentUow : null) + return WithUnitOfWork(uow => { var invoiceType = Model.Account.InvoiceType.Sale; - var idList = currentUow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType); - _exportSaleInvoiceIdList = idList.Keys.ToList(); - var invoiceList = ReadInvoiceById(idList.Keys.ToList()); + // get list of unprocessed invoices + var newInvoiceIdDict = uow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType); + + // update db entries with invoice numbers and set to iscompleted=true + foreach (var newInvoiceId in newInvoiceIdDict) + { + string invoiceNumber = "INV-" + firstInvoiceNumber.ToString("000000"); + uow.ExportInvoiceRepository.UpdateInvoiceHeaderDetail(newInvoiceId.Key, invoiceNumber, true); + firstInvoiceNumber++; + } + + // read invoices from database + var invoiceList = ReadInvoiceById(uow, newInvoiceIdDict.Keys.ToList()); var exportToFile = new Data.Xero.SalesInvoice(); - exportToFile.ExportToCsv(invoiceList.Values.ToList(), firstInvoiceNumber, filePath); - } - } + exportToFile.ExportToCsv(invoiceList.Values.ToList(), filePath); - /// - /// Call this after ExportSalesInvoice() to mark exported invoices as complete - /// - /// number of invoices effected - public int? ExportSalesInvoiceIsComplete() - { - Init(); + // get user confitmation before marking as exported + bool userInput = getUserConfirmation.Invoke(); - if (_exportSaleInvoiceIdList.Any() == false) - { - ErrorMessage = "Nothing to set as complete, did you call the ExportSalesInvoice method first?"; - return null; - } - - var parameters = new Dictionary(); - foreach (var id in _exportSaleInvoiceIdList) - { - parameters.Add(id, true); - } - - // update database - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) - { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; - } - - using (currentUow != null && _ownsUnitOfWork ? currentUow : null) - { - int count = currentUow.ExportInvoiceRepository.SetInvoiceIsCompleteValue(parameters); - if (_exportSaleInvoiceIdList.Count() == count) + if (userInput == false) { - currentUow.Commit(); - return count; + RollbackIfOwned(uow); + ErrorMessage = "User cancelled export, invoices not marked as exported."; + _log.LogInformation(ErrorMessage); + return false; } - else - { - currentUow.Rollback(); - ErrorMessage = "ExportSalesInvoiceIsComplete() Incorrect number of rows updated, changes rolled back."; - _log.LogError(ErrorMessage); - throw new Exception(ErrorMessage); - } - } + + CommitIfOwned(uow); + return true; + }); } } } diff --git a/src/bnhtrade.Core/Logic/Import/AmazonSettlement.cs b/src/bnhtrade.Core/Logic/Import/AmazonSettlement.cs index bb9a18d..6a5710e 100644 --- a/src/bnhtrade.Core/Logic/Import/AmazonSettlement.cs +++ b/src/bnhtrade.Core/Logic/Import/AmazonSettlement.cs @@ -5,43 +5,26 @@ using System.Linq; namespace bnhtrade.Core.Logic.Import { - public class AmazonSettlement + public class AmazonSettlement : UnitOfWorkBase { - private readonly IUnitOfWork _providedUnitOfWork = null; - private readonly bool _ownsUnitOfWork = false; - private Data.Amazon.Report.SettlementReport amazonReport; private Logic.Log.LogEvent log = new Log.LogEvent(); public AmazonSettlement() { - _ownsUnitOfWork = true; } - internal AmazonSettlement(IUnitOfWork unitOfWork) + internal AmazonSettlement(IUnitOfWork unitOfWork) : base(unitOfWork) { - _providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork)); - _ownsUnitOfWork = false; } public void SyncDatabase() { string operation = "Import Amazon Settlement Reports"; log.LogInformation("Started '" + operation + "' operation."); + var amazonReport = new Data.Amazon.Report.SettlementReport(); // get avaiable reports from amazon api - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) - { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; - } - - - - using (currentUow != null && _ownsUnitOfWork ? currentUow : null) + WithUnitOfWork(uow => { // get avaiable reports from amazon api var spapiReportIdList = amazonReport.ListAvaliableReports(); @@ -54,7 +37,7 @@ namespace bnhtrade.Core.Logic.Import } // query db and remove reports that have already been imported - var dbReportList = currentUow.ImportAmazonRepository.ReadAmazonSettlementHeaderInfoBySpapiReportId(spapiReportIdList); + var dbReportList = uow.AmazonSettlementRepository.ReadAmazonSettlementHeaderInfoBySpapiReportId(spapiReportIdList); foreach (var dbReport in dbReportList) { if (dbReport.SpapiReportIdIsSet) @@ -82,16 +65,12 @@ namespace bnhtrade.Core.Logic.Import { UI.Console.WriteLine("Importing settlement report " + (i + 1) + " of " + spapiReportIdList.Count() + " (ReportID:" + spapiReportIdList[i] + ")."); var filePath = amazonReport.GetReportFile(spapiReportIdList[i]); - bool ack = currentUow.ImportAmazonRepository.CreateAmazonSettlements(filePath, spapiReportIdList[i]); + bool ack = uow.AmazonSettlementRepository.CreateAmazonSettlements(filePath, spapiReportIdList[i]); log.LogInformation("Settlment Report imported (ReportID:" + spapiReportIdList[i] + ")."); } - if (_ownsUnitOfWork) - { - currentUow.Commit(); - } - return; - } + CommitIfOwned(uow); + }); } } } diff --git a/src/bnhtrade.Core/Logic/Sku/GetSkuId.cs b/src/bnhtrade.Core/Logic/Sku/SkuService.cs similarity index 67% rename from src/bnhtrade.Core/Logic/Sku/GetSkuId.cs rename to src/bnhtrade.Core/Logic/Sku/SkuService.cs index 230c608..2ad1696 100644 --- a/src/bnhtrade.Core/Logic/Sku/GetSkuId.cs +++ b/src/bnhtrade.Core/Logic/Sku/SkuService.cs @@ -1,10 +1,12 @@ using System; +using System.Collections.Generic; using System.Data.SqlClient; using System.Transactions; +using System.Windows.Forms; namespace bnhtrade.Core.Logic.Sku { - public class GetSkuId + public class SkuService : UnitOfWorkBase { /// /// Used for retriving an SKU ID by parameters. If no match, can create a new SKU if required. @@ -15,11 +17,11 @@ namespace bnhtrade.Core.Logic.Sku /// When set to true, if no match is made, function will create a new sku and return the id for that /// Return the id for the new or existing sku or, dependant on set parameters, 0 if not found /// - public int Request(int productId, int conditionId, int accountTaxCodeId, bool noMatchCreateNew) + public int GetSkuId(int productId, int conditionId, int accountTaxCodeId, bool noMatchCreateNew) { - using (TransactionScope scope = new TransactionScope()) + return WithUnitOfWork(uow => { - int? skuId = new Data.Database.Sku.GetSkuId().ByParameters(productId, conditionId, accountTaxCodeId); + int? skuId = uow.SkuRepository.ReadSkuId(productId, conditionId, accountTaxCodeId); if (skuId != null) { return (int)skuId; @@ -30,9 +32,11 @@ namespace bnhtrade.Core.Logic.Sku } else { - return new Data.Database.Sku.InsertSku().InsertNew(productId, conditionId, accountTaxCodeId); + int newSkuId = uow.SkuRepository.InsertNewSku(productId, conditionId, accountTaxCodeId); + CommitIfOwned(uow); + return newSkuId; } - } + }); } } } diff --git a/src/bnhtrade.Core/Logic/Stock/StatusBalance.cs b/src/bnhtrade.Core/Logic/Stock/StatusBalance.cs index efcff13..d5fa3d6 100644 --- a/src/bnhtrade.Core/Logic/Stock/StatusBalance.cs +++ b/src/bnhtrade.Core/Logic/Stock/StatusBalance.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace bnhtrade.Core.Logic.Stock { - public class StatusBalance + public class StatusBalance : UnitOfWorkBase { public StatusBalance() { @@ -35,91 +35,93 @@ namespace bnhtrade.Core.Logic.Stock /// public Model.Stock.StatusBalance GetStatusBalance(string skuNumber, int statusId, bool includeDetails = true) { - if (string.IsNullOrWhiteSpace(skuNumber)) + // need to enroll moree of the code into the unit of work as I redo the database layer + return WithUnitOfWork(uow => { - throw new Exception("SKU number is null, empty, or whitespace"); - } - - // get list of transactions for availale stock - var readStatusTransaction = new Data.Database.Stock.ReadStatusTransaction(); - var statusTransaction = readStatusTransaction.BySku(statusId, skuNumber); - - // create quantity list - List qtyList = new List(); - for (int i = 0; i < statusTransaction.TransactionList.Count; i++) - { - qtyList.Add(statusTransaction.TransactionList[i].Quantity); - } - - // tally list - // loop, in reverse, to find credits to tally with debits - for (int iCr = qtyList.Count - 1; iCr > -1; iCr--) - { - if (qtyList[iCr] < 0) + if (string.IsNullOrWhiteSpace(skuNumber)) { - int crStockNumber = statusTransaction.TransactionList[iCr].StockNumber; - DateTime crDate = statusTransaction.TransactionList[iCr].EntryDate; + throw new Exception("SKU number is null, empty, or whitespace"); + } - // loop, in reverse, to find debits - for (int iDr = qtyList.Count - 1; iDr > -1; iDr--) + // get list of transactions for availale stock + var readStatusTransaction = new Data.Database.Stock.ReadStatusTransaction(); // ambient uow open above + var statusTransaction = readStatusTransaction.BySku(statusId, skuNumber); // ambient uow open above + + // create quantity list + List qtyList = new List(); + for (int i = 0; i < statusTransaction.TransactionList.Count; i++) + { + qtyList.Add(statusTransaction.TransactionList[i].Quantity); + } + + // tally list + // loop, in reverse, to find credits to tally with debits + for (int iCr = qtyList.Count - 1; iCr > -1; iCr--) + { + if (qtyList[iCr] < 0) { - // find debits, last in first out (filter by date) - if (statusTransaction.TransactionList[iDr].StockNumber == crStockNumber - && statusTransaction.TransactionList[iDr].EntryDate <= crDate - && qtyList[iDr] > 0) + int crStockNumber = statusTransaction.TransactionList[iCr].StockNumber; + DateTime crDate = statusTransaction.TransactionList[iCr].EntryDate; + + // loop, in reverse, to find debits + for (int iDr = qtyList.Count - 1; iDr > -1; iDr--) { - // credit fully assigned - if ((qtyList[iCr] + qtyList[iDr]) >= 0) + // find debits, last in first out (filter by date) + if (statusTransaction.TransactionList[iDr].StockNumber == crStockNumber + && statusTransaction.TransactionList[iDr].EntryDate <= crDate + && qtyList[iDr] > 0) { - qtyList[iDr] = qtyList[iDr] + qtyList[iCr]; - qtyList[iCr] = 0; - break; - } - // credit partially assigned - else - { - qtyList[iCr] = qtyList[iDr] + qtyList[iCr]; - qtyList[iDr] = 0; + // credit fully assigned + if ((qtyList[iCr] + qtyList[iDr]) >= 0) + { + qtyList[iDr] = qtyList[iDr] + qtyList[iCr]; + qtyList[iCr] = 0; + break; + } + // credit partially assigned + else + { + qtyList[iCr] = qtyList[iDr] + qtyList[iCr]; + qtyList[iDr] = 0; + } } } } } - } - // build result list from tally results - var entryList = new List<(DateTime EntryDate, int StockNumber, int Quantity)>(); - for (int i = 0; i < qtyList.Count; i++) - { - if (qtyList[i] != 0) + // build result list from tally results + var entryList = new List<(DateTime EntryDate, int StockNumber, int Quantity)>(); + for (int i = 0; i < qtyList.Count; i++) { - (DateTime EntryDate, int StockNumber, int Quantity) entryItem = ( - statusTransaction.TransactionList[i].EntryDate, - statusTransaction.TransactionList[i].StockNumber, - qtyList[i]); - entryList.Add(entryItem); + if (qtyList[i] != 0) + { + (DateTime EntryDate, int StockNumber, int Quantity) entryItem = ( + statusTransaction.TransactionList[i].EntryDate, + statusTransaction.TransactionList[i].StockNumber, + qtyList[i]); + entryList.Add(entryItem); + } } - } - if (includeDetails) - { - // get the sku obj - var readSku = new Logic.Sku.GetSkuInfo(); - readSku.IncludeConditionInfo = true; - readSku.IncludeProductInfo = true; - readSku.IncludeTaxCodeInfo = true; - var sku = readSku.BySkuNumber(statusTransaction.SkuNumber); + if (includeDetails) + { + // get the sku obj + var readSku = new Logic.Sku.GetSkuInfo(); // ambient uow open above + readSku.IncludeConditionInfo = true; + readSku.IncludeProductInfo = true; + readSku.IncludeTaxCodeInfo = true; + var sku = readSku.BySkuNumber(statusTransaction.SkuNumber); - // get the status obj - var readStatus = new Data.Database.Stock.Status(); - readStatus.StatusIds = new List { statusTransaction.StockStatusId }; - var status = readStatus.Read()[0]; + // get the status obj + var status = uow.StockRepository.ReadStatus(new List { statusTransaction.StockStatusId })[0]; - return new Model.Stock.StatusBalance(status, sku, entryList); - } - else - { - return new Model.Stock.StatusBalance(statusTransaction.StockStatusId, statusTransaction.SkuNumber, entryList); - } + return new Model.Stock.StatusBalance(status, sku, entryList); + } + else + { + return new Model.Stock.StatusBalance(statusTransaction.StockStatusId, statusTransaction.SkuNumber, entryList); + } + }); } /// diff --git a/src/bnhtrade.Core/Logic/UnitOfWorkBase.cs b/src/bnhtrade.Core/Logic/UnitOfWorkBase.cs new file mode 100644 index 0000000..d034c47 --- /dev/null +++ b/src/bnhtrade.Core/Logic/UnitOfWorkBase.cs @@ -0,0 +1,76 @@ +using bnhtrade.Core.Data.Database.UnitOfWork; +using System; + +namespace bnhtrade.Core.Logic +{ + public abstract class UnitOfWorkBase + { + private readonly IUnitOfWork _providedUnitOfWork; + private readonly bool _ownsUnitOfWork; + + protected UnitOfWorkBase() + { + _ownsUnitOfWork = true; + } + + internal UnitOfWorkBase(IUnitOfWork unitOfWork) + { + _providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork)); + _ownsUnitOfWork = false; + } + + /// + /// Executes an action with a managed UnitOfWork, handling disposal and commit if owned. + /// + internal void WithUnitOfWork(Action action) + { + IUnitOfWork currentUow = _ownsUnitOfWork ? new UnitOfWork() : _providedUnitOfWork; + try + { + action(currentUow); + } + finally + { + if (_ownsUnitOfWork && currentUow is IDisposable disposable) + disposable.Dispose(); + } + } + + /// + /// Executes a function with a managed UnitOfWork, handling disposal and commit if owned. + /// + internal T WithUnitOfWork(Func func) + { + IUnitOfWork currentUow = _ownsUnitOfWork ? new UnitOfWork() : _providedUnitOfWork; + try + { + return func(currentUow); + } + finally + { + if (_ownsUnitOfWork && currentUow is IDisposable disposable) + disposable.Dispose(); + } + } + + /// + /// Executes an action with a managed UnitOfWork, committing if owned. + /// + /// + internal void CommitIfOwned(IUnitOfWork uow) + { + if (_ownsUnitOfWork) + uow.Commit(); + } + + /// + /// Executes an action with a managed UnitOfWork, rolling back if owned. + /// + /// + internal void RollbackIfOwned(IUnitOfWork uow) + { + if (_ownsUnitOfWork) + uow.Rollback(); + } + } +} diff --git a/src/bnhtrade.Core/Logic/_boilerplate/UnitOfWorkPattern.cs b/src/bnhtrade.Core/Logic/_boilerplate/UnitOfWorkPattern.cs deleted file mode 100644 index 93fabc8..0000000 --- a/src/bnhtrade.Core/Logic/_boilerplate/UnitOfWorkPattern.cs +++ /dev/null @@ -1,53 +0,0 @@ -using bnhtrade.Core.Data.Database.UnitOfWork; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Logic._BoilerPlate -{ - internal class UnitOfWorkPattern - { - private readonly IUnitOfWork _providedUnitOfWork = null; - private readonly bool _ownsUnitOfWork = false; - - public UnitOfWorkPattern() - { - _ownsUnitOfWork = true; - } - - internal UnitOfWorkPattern(IUnitOfWork unitOfWork) - { - _providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork)); - _ownsUnitOfWork = false; - } - - public void LogicThatUsesService() - { - IUnitOfWork currentUow = null; - if (_ownsUnitOfWork) - { - currentUow = new UnitOfWork(); - } - else - { - currentUow = _providedUnitOfWork; - } - - using (currentUow != null && _ownsUnitOfWork ? currentUow : null) - { - - // - // Perform operations using currentUow, e.g. repository calls - // - - if (_ownsUnitOfWork) - { - currentUow.Commit(); - } - } - } - - } -} \ No newline at end of file diff --git a/src/bnhtrade.Core/Logic/_boilerplate/UnitOfWorkService.cs b/src/bnhtrade.Core/Logic/_boilerplate/UnitOfWorkService.cs new file mode 100644 index 0000000..a0d01fd --- /dev/null +++ b/src/bnhtrade.Core/Logic/_boilerplate/UnitOfWorkService.cs @@ -0,0 +1,38 @@ +using bnhtrade.Core.Data.Database.UnitOfWork; +using System; +using System.Collections.Generic; + +namespace bnhtrade.Core.Logic._boilerplate +{ + public class UnitOfWorkService : UnitOfWorkBase + { + public UnitOfWorkService() : base() { } + internal UnitOfWorkService(IUnitOfWork unitOfWork) : base(unitOfWork) { } + + public Model.Account.InvoiceLineItem ReturnExample(string itemCode) + { + return WithUnitOfWork(uow => + { + // add all code in here that uses the unit of work, this will ensure that the unit of work is disposed of correctly + var item = uow.InvoiceRepository.GetInvoiceLineItem(null, new List { itemCode }); + + // use the base method to commit, it will check if the unit of work is owned by this service before committing + CommitIfOwned(uow); + + // return + return item[0]; + }); + } + + public void VoidExample() + { + WithUnitOfWork(uow => + { + var items = uow.InvoiceRepository.GetInvoiceLineItem(); + + // use the base method to commit, it will check if the unit of work is owned by this service before committing + CommitIfOwned(uow); + }); + } + } +} \ No newline at end of file diff --git a/src/bnhtrade.Core/Model/Account/Account.cs b/src/bnhtrade.Core/Model/Account/Account.cs index 985b4e2..e8a85bc 100644 --- a/src/bnhtrade.Core/Model/Account/Account.cs +++ b/src/bnhtrade.Core/Model/Account/Account.cs @@ -9,7 +9,7 @@ namespace bnhtrade.Core.Model.Account { public class Account { - public Account(uint id, uint accountCode, string accountName, string description, string type, string basicType, int multiplier) + public Account(int id, int accountCode, string accountName, string description, string type, string basicType, int multiplier) { Id = id; AccountCode = accountCode; @@ -23,9 +23,9 @@ namespace bnhtrade.Core.Model.Account /// /// Database record id /// - public uint Id { get; private set; } + public int Id { get; private set; } - public uint AccountCode { get; private set; } + public int AccountCode { get; private set; } public string AccountName { get; private set; } diff --git a/src/bnhtrade.Core/Model/Account/Journal.cs b/src/bnhtrade.Core/Model/Account/Journal.cs index 3ddbdb2..6b69896 100644 --- a/src/bnhtrade.Core/Model/Account/Journal.cs +++ b/src/bnhtrade.Core/Model/Account/Journal.cs @@ -10,7 +10,7 @@ namespace bnhtrade.Core.Model.Account { public class Journal : IValidatableObject { - internal Journal(uint journalId, Core.Model.Account.JournalType type, List posts, DateTime entryDate, DateTime postDate, DateTime lastModifed, bool isLocked) + internal Journal(int journalId, Core.Model.Account.JournalType type, List posts, DateTime entryDate, DateTime postDate, DateTime lastModifed, bool isLocked) { JournalId = journalId; Type = type; @@ -21,7 +21,7 @@ namespace bnhtrade.Core.Model.Account IsLocked = isLocked; } - public uint JournalId { get; private set; } + public int JournalId { get; private set; } public Core.Model.Account.JournalType Type { get; private set; } public List Posts { get; private set; } = new List(); public DateTime EntryDate { get; private set; } @@ -31,14 +31,14 @@ namespace bnhtrade.Core.Model.Account public class Post { - internal Post(uint postId, Core.Model.Account.Account account, decimal amountGbp) + internal Post(int postId, Core.Model.Account.Account account, decimal amountGbp) { PostId = postId; Account = account; AmountGbp = amountGbp; } - public uint PostId { get; private set; } + public int PostId { get; private set; } public Core.Model.Account.Account Account { get; private set; } public decimal AmountGbp { get; private set; } } diff --git a/src/bnhtrade.Core/Model/Account/JournalType.cs b/src/bnhtrade.Core/Model/Account/JournalType.cs index e31c717..8970dd1 100644 --- a/src/bnhtrade.Core/Model/Account/JournalType.cs +++ b/src/bnhtrade.Core/Model/Account/JournalType.cs @@ -8,7 +8,7 @@ namespace bnhtrade.Core.Model.Account { public class JournalType { - internal JournalType(uint journalTypeId, string title, Model.Account.Account defaultCreditAccount = null, Model.Account.Account defaultDebitAccount = null) + internal JournalType(int journalTypeId, string title, Model.Account.Account defaultCreditAccount = null, Model.Account.Account defaultDebitAccount = null) { JournalTypeId = journalTypeId; Title = title; @@ -22,7 +22,7 @@ namespace bnhtrade.Core.Model.Account DefaultDebitAccount = defaultDebitAccount; } - public uint JournalTypeId { get ; private set; } + public int JournalTypeId { get ; private set; } public string Title { get; private set; } diff --git a/src/bnhtrade.Core/Program.cs b/src/bnhtrade.Core/Program.cs index c21cb8c..c3fa03d 100644 --- a/src/bnhtrade.Core/Program.cs +++ b/src/bnhtrade.Core/Program.cs @@ -1,11 +1,14 @@ -using System; +using bnhtrade.Core.Logic; +using Microsoft.Data.SqlClient; +using System; using System.Collections.Generic; -using System.Data.SqlClient; +using System.Data; +using System.Data.Common; +using System.Data.SqlTypes; using System.IO; using System.Linq; -using System.Transactions; -using System.Data.SqlTypes; using System.Security.Cryptography; +using System.Transactions; namespace bnhtrade.Core { @@ -231,7 +234,7 @@ namespace bnhtrade.Core namespace Stock { - public class StockCreate + public class StockCreate : UnitOfWorkBase { private int WIP_StockInsert(string sqlConnectionString, int accountJournalType, int stockJournalType, string currencyCode, decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId) @@ -337,7 +340,7 @@ namespace bnhtrade.Core } // get/set an skuId - int skuId = new Logic.Sku.GetSkuId().Request(productId, conditionId, accountTaxCodeId, true); + int skuId = new Logic.Sku.SkuService().GetSkuId(productId, conditionId, accountTaxCodeId, true); // add the entry to the stock table (minus stockJournalId) int stockId = 0; @@ -563,10 +566,10 @@ namespace bnhtrade.Core // to be used by other methods within a transaction scope private static void WIP_StockDeleteSubAccountJournalEntry(string sqlConnectionString, int stockId) { - using (TransactionScope scope = new TransactionScope()) using (SqlConnection conn = new SqlConnection(sqlConnectionString)) { conn.Open(); + var trans = conn.BeginTransaction(); // get the account journal id int accountJournalId = 0; @@ -576,6 +579,7 @@ namespace bnhtrade.Core WHERE StockID=@stockId; ", conn)) { + cmd.Transaction = trans; cmd.Parameters.AddWithValue("@stockId", stockId); object obj = cmd.ExecuteScalar(); @@ -601,6 +605,7 @@ namespace bnhtrade.Core WHERE StockID=@stockId; ", conn)) { + cmd.Transaction = trans; cmd.Parameters.AddWithValue("@stockId", stockId); int count = cmd.ExecuteNonQuery(); @@ -612,9 +617,9 @@ namespace bnhtrade.Core } // delete account journal entry - new Data.Database.Account.DeleteJournal().AccountJournalDelete(accountJournalId); + new Data.Database.Repository.Implementation.JournalRepository(conn, trans).DeleteJournal(accountJournalId); - scope.Complete(); + trans.Commit(); } } @@ -1457,10 +1462,10 @@ namespace bnhtrade.Core public static void WIP_PurchaseLineTransactionDelete(string sqlConnectionString, int purchaseLineId, int accountJournalId) { - using (TransactionScope scope = new TransactionScope()) using (SqlConnection conn = new SqlConnection(sqlConnectionString)) { conn.Open(); + var trans = conn.BeginTransaction(); // check accountJournalId does not exist in stock table using (SqlCommand cmd = new SqlCommand(@" @@ -1469,6 +1474,7 @@ namespace bnhtrade.Core WHERE AccountJournalID=@accountJournalId; ", conn)) { + cmd.Transaction = trans; cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId); using (var reader = cmd.ExecuteReader()) @@ -1493,6 +1499,7 @@ namespace bnhtrade.Core WHERE AccountJournalID=@accountJournalId; ", conn)) { + cmd.Transaction = trans; cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId); int count = cmd.ExecuteNonQuery(); @@ -1504,9 +1511,9 @@ namespace bnhtrade.Core } // delete account journal entry - new Data.Database.Account.DeleteJournal().AccountJournalDelete(accountJournalId); + new Data.Database.Repository.Implementation.JournalRepository(conn, trans).DeleteJournal(accountJournalId); - scope.Complete(); + trans.Commit(); } } } diff --git a/src/bnhtrade.Core/Test/Account/Account.cs b/src/bnhtrade.Core/Test/Account/Account.cs index 4180fc6..b58226a 100644 --- a/src/bnhtrade.Core/Test/Account/Account.cs +++ b/src/bnhtrade.Core/Test/Account/Account.cs @@ -1,4 +1,5 @@ using bnhtrade.Core.Data.Database.Account; +using bnhtrade.Core.Data.Database.UnitOfWork; using System; using System.Collections.Generic; using System.Linq; @@ -25,28 +26,28 @@ namespace bnhtrade.Core.Test.Account public void PurchaseInvoice() { - var result = new bnhtrade.Core.Logic.Account.PurchaseInvoice().GetPurchaseInvoice( new List { 14718, 100, 101, 102, 300, 400, 1200, 2734, 6339, 9999 }); // 10 in total + var result = new bnhtrade.Core.Logic.Account.PurchaseInvoiceService().GetPurchaseInvoice( new List { 14718, 100, 101, 102, 300, 400, 1200, 2734, 6339, 9999 }); // 10 in total } public void PurchaseInvoiceLine() { - var read = new Data.Database.Account.ReadPurchaseInvoiceLine(); - read.ItemDescription = new List { "xbox", "kill" }; - var result = read.Read(); + var uof = new UnitOfWork(); + var result = uof.InvoiceRepository.ReadPurchaseInvoiceLine(null, null, null, new List { "xbox", "kill" }); } public void Journal() { - var read = new Data.Database.Account.ReadJournal(); - read.AccountJournalId = new List { 123, 300, 324, 5678, 22 }; - var result = read.Read(); + //var read = new Data.Database.Account.ReadJournal(); + //read.AccountJournalId = new List { 123, 300, 324, 5678, 22 }; + //var result = read.Read(); } public void InoivceCurrencyConversion() { - var invoiceService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService(); + var uof = new UnitOfWork(); + var invoiceService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService(uof); var invoiceList = invoiceService.ReadInvoiceById(new List { 349, 371, 375, 379 }); - var currencyService = new bnhtrade.Core.Logic.Account.CurrencyService(); + var currencyService = new bnhtrade.Core.Logic.Account.CurrencyService(uof); foreach (var invoice in invoiceList.Values.ToList()) { diff --git a/src/bnhtrade.Core/Test/Export/Export.cs b/src/bnhtrade.Core/Test/Export/Export.cs index bdf2358..8362497 100644 --- a/src/bnhtrade.Core/Test/Export/Export.cs +++ b/src/bnhtrade.Core/Test/Export/Export.cs @@ -11,7 +11,7 @@ namespace bnhtrade.Core.Test.Export { public Export() { - DeleteExportInvoice(); + UPdateInvoiceHeaderDetail(); } private void SubmitAmazonInventoryLoader() @@ -43,24 +43,22 @@ namespace bnhtrade.Core.Test.Export var list = unitOfWork.ExportInvoiceRepository.GetSalesInvoiceById(new List { 550, 555 }); } - private void ExportSalesInvoiceQueue() - { - var invoice = new Model.Account.SalesInvoice(true); - invoice.InvoiceLineList = new List(); - - string path = @"%USERPROFILE%\Downloads\TEST.CSV"; - var queueService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService(); - queueService.ImportAll(); - queueService.ExportSalesInvoice(path, 1234); - var return1 = queueService.ExportSalesInvoiceIsComplete(); - } private void DeleteExportInvoice() { - //var uow = new bnhtrade.Core.Data.Database.UnitOfWork.UnitOfWork(); + throw new Exception("This method is for testing purposes only, it will delete export invoices from the database. Use with caution."); using (var uow = new bnhtrade.Core.Data.Database.UnitOfWork.UnitOfWork()) { - int dfkjl = uow.ExportInvoiceRepository.DeleteInvoice(new List { 576, 577, 584 }); - int lskdjflsd = uow.ImportAmazonRepository.SetAmazonSettlementIsProcessed(new List { "24684639382f", "14720584692f", "14386695522f" }, false); + int dfkjl = uow.ExportInvoiceRepository.DeleteInvoice(new List { 591, 590, 589, 588, 587, 586, 585, 583, 582, 581, 580, 579, 578 }); + int lskdjflsd = uow.AmazonSettlementRepository.UpdateAmazonSettlementIsProcessed(new List { "24945698052", "24684639382", "24859276062", "24769420562", "24684661532", "14720584692", "24593881302", "24508182552", "14386695522", "24416840332", "24334973902", "24162226452" }, false); + uow.Commit(); + } + } + + private void UPdateInvoiceHeaderDetail() + { + using (var uow = new bnhtrade.Core.Data.Database.UnitOfWork.UnitOfWork()) + { + int dfkjl = uow.ExportInvoiceRepository.UpdateInvoiceHeaderDetail(123333, "douche", true); uow.Commit(); } } diff --git a/src/bnhtrade.Core/Test/Logic/Export.cs b/src/bnhtrade.Core/Test/Logic/Export.cs index 1875b12..38ca34f 100644 --- a/src/bnhtrade.Core/Test/Logic/Export.cs +++ b/src/bnhtrade.Core/Test/Logic/Export.cs @@ -23,7 +23,7 @@ namespace bnhtrade.Core.Test.Logic { using (var uow = new Data.Database.UnitOfWork.UnitOfWork()) { - var list = uow.ImportAmazonRepository.ReadAmazonSettlements(marketPlaceNameList: new List { "Amazon.fr" }, returnTop: 3); + var list = uow.AmazonSettlementRepository.ReadAmazonSettlements(marketPlaceNameList: new List { "Amazon.fr" }, returnTop: 3); } } public void UpdateExportInvoiceQueue() diff --git a/src/bnhtrade.Core/Test/Stock/Stock.cs b/src/bnhtrade.Core/Test/Stock/Stock.cs index 342670b..0e349ec 100644 --- a/src/bnhtrade.Core/Test/Stock/Stock.cs +++ b/src/bnhtrade.Core/Test/Stock/Stock.cs @@ -60,11 +60,11 @@ namespace bnhtrade.Core.Test.Stock public void ReadStockStatus() { - var db = new Status(); - db.StatusIds = new List { 3, 4, 5, 6, 7, 11, 12, 13, 15 }; - db.StatusTypeIds = new List { 12, 5 }; - var result = db.Read(); - int i = 0; + //var db = new Status(); + //db.StatusIds = new List { 3, 4, 5, 6, 7, 11, 12, 13, 15 }; + //db.StatusTypeIds = new List { 12, 5 }; + //var result = db.Read(); + //int i = 0; } } } diff --git a/src/bnhtrade.gui/Home.cs b/src/bnhtrade.gui/Home.cs index 0fb7d93..f03337a 100644 --- a/src/bnhtrade.gui/Home.cs +++ b/src/bnhtrade.gui/Home.cs @@ -53,7 +53,7 @@ namespace bnhtrade.gui private void InitialiseTabReceiving() { Cursor.Current = Cursors.WaitCursor; - purchaseLineStatusBindingSource.DataSource = new Core.Logic.Account.PurchaseInvoiceMisc().ReadLineStatusToList(); + purchaseLineStatusBindingSource.DataSource = new Core.Logic.Account.PurchaseInvoiceService().ReadLineStatusToList(); comboBox1.SelectedIndex = 3; ListBoxQuery(); initTabReceiving = true; @@ -96,7 +96,7 @@ namespace bnhtrade.gui comboBox = comboBox1.Text; } - bsReceivingLines.DataSource = new Core.Logic.Account.PurchaseInvoiceMisc().GetLineSummary( + bsReceivingLines.DataSource = new Core.Logic.Account.PurchaseInvoiceService().GetLineSummary( dateTimeOrderSearch.Value , comboBox , searchList); @@ -120,7 +120,7 @@ namespace bnhtrade.gui var row = dataGridView1.CurrentCell.RowIndex; var lineSummary = (bnhtrade.Core.Model.Account.PurchaseInvoiceLineSummary)bsReceivingLines[row]; int purchaseId = lineSummary.PurchaseId; - var purchaseInvoiceList = new Core.Logic.Account.PurchaseInvoice().GetPurchaseInvoice(new List { purchaseId }); + var purchaseInvoiceList = new Core.Logic.Account.PurchaseInvoiceService().GetPurchaseInvoice(new List { purchaseId }); var purchaseInvoice = purchaseInvoiceList[purchaseId]; var form = new PurchaseInvoice(purchaseInvoice); form.Show(); @@ -177,12 +177,6 @@ namespace bnhtrade.gui } } - - // create export invoices and export to CSV - var queueService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService(); - queueService.ImportAll(); - queueService.ExportSalesInvoice(savePath, nextInvoiceNumber); - // open import page Process.Start(new ProcessStartInfo { @@ -190,33 +184,42 @@ namespace bnhtrade.gui UseShellExecute = true }); - // did the import go okay - var result = MessageBox.Show( - "Import invoices to Xero ensuring UnitAmount field option is set to 'Tax Exclusive' on the import page." - + Environment.NewLine + Environment.NewLine - + "Once the import has completed suscessfully click 'Okay' to mark the invoice(s) as complete/imported.", - "Import Confirmation", - MessageBoxButtons.OKCancel, - MessageBoxIcon.Question - ); - - if (result == DialogResult.OK) + // create export invoices and export to CSV + var queueService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService(); + queueService.ImportAll(); + queueService.ExportSalesInvoice(savePath, nextInvoiceNumber, () => { - var completeCount = queueService.ExportSalesInvoiceIsComplete(); - if (completeCount != invoices) + // did the import go okay + var result = MessageBox.Show( + "Import invoices to Xero ensuring UnitAmount field option is set to 'Tax Exclusive' on the import page." + + Environment.NewLine + Environment.NewLine + + "Once the import has completed suscessfully click 'Okay' to mark the invoice(s) as complete/imported.", + "Import Confirmation", + MessageBoxButtons.OKCancel, + MessageBoxIcon.Question + ); + + if (result == DialogResult.OK) { - MessageBox.Show("Error marking invoices as complete. Please check the logs for more details.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - log.LogError("ExportSalesInvoiceIsComplete returned " + completeCount + " but expected " + invoices + ". Please check the logs for more details.", queueService.ErrorMessage); + return true; } else { - MessageBox.Show(completeCount + " invoices marked as complete.", "Export Complete", MessageBoxButtons.OK, MessageBoxIcon.Information); + return false; } - } - else + }); + + if (queueService.ErrorMessageIsSet) { - MessageBox.Show("Operation cancelled. No invoices marked as complete."); + MessageBox.Show("Error exporting invoices: " + queueService.ErrorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + log.LogError("Error exporting invoices: " + queueService.ErrorMessage); + return; } + else + { + MessageBox.Show("Exported " + invoices + " invoices to " + savePath, "Export Complete", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + UpdateInvoiceExportBox(); return; }