From 7e50da21e766f4ba8b54f88643a9f5b2a516849c Mon Sep 17 00:00:00 2001 From: Bobbie Hodgetts Date: Thu, 6 Feb 2020 21:20:15 +0000 Subject: [PATCH] Export amazon settlement report fix --- .../Data/Database/Account/ReadAccountCode.cs | 137 +++ .../Account/ReadInvoiceLineItemCode.cs | 144 ++++ .../Data/Database/Account/ReadTaxCode.cs | 227 +++++ src/bnhtrade.Core/Data/Database/Connection.cs | 1 + .../Consistency/ImportAmazonSettlement.cs | 50 ++ .../Database/Export/CreateSalesInvoice.cs | 171 ++++ .../FBAInbound/GetShipmentHeaderInfo.cs | 2 +- .../Database/FBAInbound/SetShipmentInfo.cs | 6 +- .../Database/Import/ReadAmazonSettlement.cs | 323 +++++++ .../Database/Import/UpdateAmazonSettlement.cs | 54 ++ .../Data/Database/Log/LogEvent.cs | 77 ++ .../Data/Database/Programmability/Sequence.cs | 49 ++ .../Data/Database/SKU/GetSKUId.cs | 4 +- src/bnhtrade.Core/Data/Database/SKU/GetSku.cs | 158 ++++ .../Logic/Account/ValidateAccountCode.cs | 77 ++ .../Logic/Account/ValidateCurrencyCode.cs | 31 + .../Logic/Account/ValidateInvoice.cs | 267 ++++++ .../Logic/Account/ValidateSalesInvoice.cs | 34 + .../Logic/Account/ValidateTaxCode.cs | 145 ++++ .../Logic/Export/AmazonSettlementData.cs | 270 ++++++ .../Logic/Export/ValidateSalesInvoice.cs | 134 +++ .../Logic/Import/ValidateAmazonSettlement.cs | 499 +++++++++++ src/bnhtrade.Core/Logic/Log/LogEvent.cs | 131 +++ .../Logic/Utilities/AccountVat.cs | 16 + .../Logic/Utilities/DateTimeCheck.cs | 40 + .../Logic/Utilities/DecimalCheck.cs | 51 ++ .../Logic/Utilities/PropertyCheck.cs | 36 + .../Logic/Utilities/StringCheck.cs | 188 +++++ src/bnhtrade.Core/Logic/Validate.cs | 56 ++ .../Model/Account/AccountCode.cs | 58 ++ src/bnhtrade.Core/Model/Account/Invoice.cs | 179 ++++ .../Model/Account/InvoiceHeader.cs | 135 +++ .../Model/Account/InvoiceLineItem.cs | 47 ++ .../Model/Account/SalesInvoice.cs | 13 + src/bnhtrade.Core/Model/Account/TaxCode.cs | 102 +++ .../Model/Import/AmazonSettlement.cs | 193 +++++ .../Model/Import/AmazonSettlementHeader.cs | 107 +++ src/bnhtrade.Core/Model/SKU/SKUInfo.cs | 15 - src/bnhtrade.Core/Model/SKU/Sku.cs | 68 ++ src/bnhtrade.Core/Program.cs | 787 +----------------- src/bnhtrade.Core/Test/Account/GetTaxInfo.cs | 19 + src/bnhtrade.Core/Test/AutoExec.cs | 31 + .../Test/Import/AmazonSettlement.cs | 25 + src/bnhtrade.Core/Test/InboundShipmentInfo.cs | 5 - src/bnhtrade.Core/Test/Logic/Export.cs | 26 + src/bnhtrade.Core/Test/SQLLoop.cs | 2 +- .../Test/_BoilerPlate/ClassFromSql.cs | 139 ++++ src/bnhtrade.Core/Test/_BoilerPlate/Sql.cs | 196 +++++ .../ProgressBar.cs} | 10 +- src/bnhtrade.Core/UI/Console/Update.cs | 35 + src/bnhtrade.Core/bnhtrade.Core.csproj | 52 +- src/bnhtrade.ScheduledTasks/Program.cs | 24 +- 52 files changed, 4827 insertions(+), 819 deletions(-) create mode 100644 src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs create mode 100644 src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItemCode.cs create mode 100644 src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs create mode 100644 src/bnhtrade.Core/Data/Database/Consistency/ImportAmazonSettlement.cs create mode 100644 src/bnhtrade.Core/Data/Database/Export/CreateSalesInvoice.cs create mode 100644 src/bnhtrade.Core/Data/Database/Import/ReadAmazonSettlement.cs create mode 100644 src/bnhtrade.Core/Data/Database/Import/UpdateAmazonSettlement.cs create mode 100644 src/bnhtrade.Core/Data/Database/Log/LogEvent.cs create mode 100644 src/bnhtrade.Core/Data/Database/Programmability/Sequence.cs create mode 100644 src/bnhtrade.Core/Data/Database/SKU/GetSku.cs create mode 100644 src/bnhtrade.Core/Logic/Account/ValidateAccountCode.cs create mode 100644 src/bnhtrade.Core/Logic/Account/ValidateCurrencyCode.cs create mode 100644 src/bnhtrade.Core/Logic/Account/ValidateInvoice.cs create mode 100644 src/bnhtrade.Core/Logic/Account/ValidateSalesInvoice.cs create mode 100644 src/bnhtrade.Core/Logic/Account/ValidateTaxCode.cs create mode 100644 src/bnhtrade.Core/Logic/Export/AmazonSettlementData.cs create mode 100644 src/bnhtrade.Core/Logic/Export/ValidateSalesInvoice.cs create mode 100644 src/bnhtrade.Core/Logic/Import/ValidateAmazonSettlement.cs create mode 100644 src/bnhtrade.Core/Logic/Log/LogEvent.cs create mode 100644 src/bnhtrade.Core/Logic/Utilities/AccountVat.cs create mode 100644 src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs create mode 100644 src/bnhtrade.Core/Logic/Utilities/DecimalCheck.cs create mode 100644 src/bnhtrade.Core/Logic/Utilities/PropertyCheck.cs create mode 100644 src/bnhtrade.Core/Logic/Utilities/StringCheck.cs create mode 100644 src/bnhtrade.Core/Logic/Validate.cs create mode 100644 src/bnhtrade.Core/Model/Account/AccountCode.cs create mode 100644 src/bnhtrade.Core/Model/Account/Invoice.cs create mode 100644 src/bnhtrade.Core/Model/Account/InvoiceHeader.cs create mode 100644 src/bnhtrade.Core/Model/Account/InvoiceLineItem.cs create mode 100644 src/bnhtrade.Core/Model/Account/SalesInvoice.cs create mode 100644 src/bnhtrade.Core/Model/Account/TaxCode.cs create mode 100644 src/bnhtrade.Core/Model/Import/AmazonSettlement.cs create mode 100644 src/bnhtrade.Core/Model/Import/AmazonSettlementHeader.cs delete mode 100644 src/bnhtrade.Core/Model/SKU/SKUInfo.cs create mode 100644 src/bnhtrade.Core/Model/SKU/Sku.cs create mode 100644 src/bnhtrade.Core/Test/Account/GetTaxInfo.cs create mode 100644 src/bnhtrade.Core/Test/AutoExec.cs create mode 100644 src/bnhtrade.Core/Test/Import/AmazonSettlement.cs create mode 100644 src/bnhtrade.Core/Test/Logic/Export.cs create mode 100644 src/bnhtrade.Core/Test/_BoilerPlate/ClassFromSql.cs create mode 100644 src/bnhtrade.Core/Test/_BoilerPlate/Sql.cs rename src/bnhtrade.Core/UI/{Utility/ConsoleProgressBar.cs => Console/ProgressBar.cs} (93%) create mode 100644 src/bnhtrade.Core/UI/Console/Update.cs diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs b/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs new file mode 100644 index 0000000..1e5fb86 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs @@ -0,0 +1,137 @@ +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 +{ + public class ReadAccountCode : Connection + { + private bool allRetrived; + private Dictionary cache; + protected ReadAccountCode(string sqlConnectionString) : base(sqlConnectionString) + { + allRetrived = false; + cache = new Dictionary(); + } + protected void ClearCache() + { + allRetrived = false; + cache.Clear(); + } + public List GetAll() + { + if (allRetrived == false) + { + UpdateCache(-1); + allRetrived = true; + } + + var returnList = new List(); + foreach (var item in cache) + { + returnList.Add(item.Value); + } + + return returnList; + } + public Model.Account.AccountCode GetByAccountCode(int accountCode) + { + if (cache.ContainsKey(accountCode)) + { + return cache[accountCode]; + } + else if (allRetrived) + { + return null; + } + else + { + UpdateCache(accountCode); + if (cache.ContainsKey(accountCode)) + { + return cache[accountCode]; + } + else + { + return null; + } + } + } + protected void UpdateCache(int accountCode = -1) + { + var dicCache = new Dictionary(); + + bool whereClause = false; + //build sql query + string sqlString = @" + SELECT tblAccountChartOf.AccountChartOfID + ,tblAccountChartOf.AccountCode + ,tblAccountChartOf.AccountName + ,tblAccountChartOf.Description + ,tblAccountChartOfType.AccountChartOfType + ,tblAccountChartOfType.BasicType + FROM tblAccountChartOf + INNER JOIN tblAccountChartOfType ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID"; + if (accountCode > -1) + { + whereClause = true; + sqlString = sqlString + @" + WHERE (((tblAccountChartOf.AccountCode) = @accountCode))"; + } + + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(sqlString, conn)) + { + if (whereClause) + { + cmd.Parameters.AddWithValue("@accountCode", accountCode); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.HasRows) + { + while (reader.Read()) + { + var result = new Model.Account.AccountCode(); + + int tablePk = reader.GetInt32(0); + result.AccountCodeId = reader.GetInt32(1); + result.Title = reader.GetString(2); + if (!reader.IsDBNull(3)) { result.Description = reader.GetString(3); } + result.Type = reader.GetString(4); + result.BasicType = reader.GetString(5); + + if (whereClause) + { + if (cache.ContainsKey(result.AccountCodeId)) + { + cache.Remove(result.AccountCodeId); + } + cache.Add(result.AccountCodeId, result); + } + else + { + dicCache.Add(result.AccountCodeId, result); + } + } + } + } + } + } + // update cache + if (!whereClause) + { + cache.Clear(); + allRetrived = true; + cache = dicCache; + } + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItemCode.cs b/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItemCode.cs new file mode 100644 index 0000000..bed3bc6 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItemCode.cs @@ -0,0 +1,144 @@ +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 +{ + public class ReadInvoiceLineItemCode : Connection + { + public ReadInvoiceLineItemCode(string sqlConnectionString) : base (sqlConnectionString) + { + cacheLineItemByTablePk = new Dictionary(); + cacheTablePkByItemCode = new Dictionary(); + } + private Dictionary cacheLineItemByTablePk; + private Dictionary cacheTablePkByItemCode; + public bool InsertNewOnNoMatch { get; set; } = false; + + public void CacheClear() + { + cacheLineItemByTablePk.Clear(); + cacheTablePkByItemCode.Clear(); + } + + private void CacheRemove(int tablePk) + { + if (cacheLineItemByTablePk.ContainsKey(tablePk)) + { + string itemCode = cacheLineItemByTablePk[tablePk].ItemCode; + cacheLineItemByTablePk.Remove(tablePk); + cacheTablePkByItemCode.Remove(itemCode); + } + } + + public void CacheRemove(string itemCode) + { + if (cacheTablePkByItemCode.ContainsKey(itemCode)) + { + CacheRemove(cacheTablePkByItemCode[itemCode]); + } + } + + private void CacheUpdate(int tablePk, Model.Account.InvoiceLineItem lineItem) + { + if (cacheLineItemByTablePk.ContainsKey(tablePk)) + { + CacheRemove(tablePk); + } + cacheLineItemByTablePk.Add(tablePk, lineItem); + cacheTablePkByItemCode.Add(lineItem.ItemCode, tablePk); + } + + public Model.Account.InvoiceLineItem ByItemCode(string itemCode, bool forceCacheUpdate = false) + { + // check cache + if (!forceCacheUpdate && cacheTablePkByItemCode.ContainsKey(itemCode)) + { + return cacheLineItemByTablePk[cacheTablePkByItemCode[itemCode]]; + } + + var returnObject = new Model.Account.InvoiceLineItem(); + returnObject.ItemCode = itemCode; + + using (TransactionScope scopeSupress = new TransactionScope(TransactionScopeOption.Suppress)) + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(@" + SELECT tblExportAccountInvoiceLineType.ExportAccountInvoiceLineTypeID + ,tblExportAccountInvoiceLineType.TypeTitle + ,tblExportAccountInvoiceLineType.TypeDescription + ,tblExportAccountInvoiceLineType.IsNewReviewRequired + ,tblExportAccountInvoiceLineType.InvoiceLineEntryEnable + ,tblAccountChartOf.AccountCode + ,tblAccountTaxCode.TaxCode + FROM ( + tblExportAccountInvoiceLineType LEFT JOIN tblAccountChartOf ON tblExportAccountInvoiceLineType.AccountChartOfID_Default = tblAccountChartOf.AccountChartOfID + ) + LEFT JOIN tblAccountTaxCode ON tblExportAccountInvoiceLineType.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID + WHERE (((tblExportAccountInvoiceLineType.MatchString) = @matchString)) + ", conn)) + { + cmd.Parameters.AddWithValue("@matchString", returnObject.ItemCode); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + int tablePk = reader.GetInt32(0); + returnObject.Title = reader.GetString(1); + if (!reader.IsDBNull(2)) { returnObject.Description = reader.GetString(2); } + returnObject.IsNewReviewRequired = reader.GetBoolean(3); + returnObject.InvoiceLineEntryEnabled = reader.GetBoolean(4); + if (!reader.IsDBNull(5)) { returnObject.DefaultAccountCode = reader.GetInt32(5); } + if (!reader.IsDBNull(6)) { returnObject.DefaultTaxCode = reader.GetString(6); } + + // add to cache + CacheUpdate(tablePk, returnObject); + + // return object + return returnObject; + } + } + } + + // insert new and retrive new value, if required + if (InsertNewOnNoMatch) + { + int tablePk = 0; + returnObject.Title = "NEW TYPE"; + returnObject.ItemCode = itemCode; + returnObject.IsNewReviewRequired = true; + + using (SqlCommand insertCmd = new SqlCommand(@" + INSERT INTO tblExportAccountInvoiceLineType ( TypeTitle, MatchString ) + OUTPUT INSERTED.ExportAccountInvoiceLineTypeID + VALUES ( @typeTitle, @matchString ) + ", conn)) + { + insertCmd.Parameters.AddWithValue("@typeTitle", returnObject.Title); + insertCmd.Parameters.AddWithValue("@matchString", returnObject.ItemCode); + + tablePk = (int)insertCmd.ExecuteScalar(); + + scopeSupress.Complete(); + } + // add to cache + CacheUpdate(tablePk, returnObject); + + // return object + return returnObject; + } + else + { + return null; + } + } + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs b/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs new file mode 100644 index 0000000..7332673 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs @@ -0,0 +1,227 @@ +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 +{ + public class ReadTaxCode : Connection + { + private bool allRetrived; + private Dictionary cache; + public ReadTaxCode(string sqlConnectionString) : base(sqlConnectionString) + { + allRetrived = false; + cache = new Dictionary(); + } + private void ClearCache() + { + allRetrived = false; + cache.Clear(); + } + public List GetAll() + { + if (allRetrived == false) + { + UpdateCache(null); + allRetrived = true; + } + + var returnList = new List(); + foreach (var item in cache) + { + returnList.Add(item.Value); + } + + return returnList; + } + public Dictionary BySkuNumber(List skuNumberList) + { + // check input list for items + if (skuNumberList == null || !skuNumberList.Any()) + { + return null; + } + + // build SQL string + string sqlString = @" + SELECT + tblSku.skuSkuNumber, tblAccountTaxCode.TaxCode + FROM + tblAccountTaxCode INNER JOIN tblSku ON tblAccountTaxCode.AccountTaxCodeID = tblSku.AccountTaxCodeID + WHERE + "; + + var parameterValueList = new List>(); + foreach (var item in skuNumberList) + { + if (!string.IsNullOrWhiteSpace(item)) + { + int count = parameterValueList.Count; + var parameterValue = new Tuple("@parameter" + count, item); + parameterValueList.Add(parameterValue); + if (count == 0) + { + sqlString = sqlString + @" + skuSkuNumber = " + parameterValue.Item1; + } + else + { + sqlString = sqlString + @" + OR skuSkuNumber = " + parameterValue.Item1; + } + } + } + + if (parameterValueList.Count == 0) + { + return null; + } + + // execute query and build result list + var skuTaxCodeList = new List>(); + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(sqlString, conn)) + { + foreach (var item in parameterValueList) + { + cmd.Parameters.AddWithValue(item.Item1, item.Item2); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + return null; + } + + while (reader.Read()) + { + var skuTaxCode = new Tuple( + reader.GetString(0), + reader.GetString(1) + ); + skuTaxCodeList.Add(skuTaxCode); + } + } + } + + // build dictionary of skuNumber to TaxCodeInfo + var returnDictionary = new Dictionary(); + foreach (var item in skuTaxCodeList) + { + returnDictionary.Add(item.Item1, GetByTaxCodeId(item.Item2)); + } + + return returnDictionary; + } + } + public Model.Account.TaxCode GetByTaxCodeId(string taxCode) + { + if (cache.ContainsKey(taxCode)) + { + return cache[taxCode]; + } + else if (allRetrived) + { + return null; + } + else + { + UpdateCache(taxCode); + if (cache.ContainsKey(taxCode)) + { + return cache[taxCode]; + } + else + { + return null; + } + } + } + private void UpdateCache(string taxCode) + { + var dicCache = new Dictionary(); + + bool whereClause = false; + //build sql query + string sqlString = @" + SELECT + TaxCode + ,TaxRateName + ,TaxRateMultiplierNet + ,TaxRateMultiplierGross + ,IsValidOnExpense + ,IsVailidOnIncome + ,Description + ,IsActive + ,TaxType + FROM tblAccountTaxCode"; + if (!string.IsNullOrWhiteSpace(taxCode)) + { + whereClause = true; + sqlString = sqlString + @" + WHERE TaxCode = @taxCode"; + } + + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(sqlString, conn)) + { + if (whereClause) + { + cmd.Parameters.AddWithValue("@taxCode", taxCode); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.HasRows) + { + while (reader.Read()) + { + var result = new Model.Account.TaxCode(); + + result.TaxCodeId = reader.GetString(0); + result.TaxRateTitle = reader.GetString(1); + result.NetAmountMultiplier = reader.GetDecimal(2); + result.GrossAmountMultiplier = reader.GetDecimal(3); + result.IsValidOnExpense = reader.GetBoolean(4); + result.IsValidOnIncome = reader.GetBoolean(5); + if (!reader.IsDBNull(6)) { result.TaxRateDescription = reader.GetString(6); } + result.IsActive = reader.GetBoolean(7); + result.TaxType = reader.GetString(8); + + if (whereClause) + { + if (cache.ContainsKey(result.TaxCodeId)) + { + cache.Remove(result.TaxCodeId); + } + cache.Add(result.TaxCodeId, result); + } + else + { + dicCache.Add(result.TaxCodeId, result); + } + } + } + } + } + } + // update cache + if (!whereClause) + { + cache.Clear(); + allRetrived = true; + cache = dicCache; + } + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Connection.cs b/src/bnhtrade.Core/Data/Database/Connection.cs index 53a2578..ec28d19 100644 --- a/src/bnhtrade.Core/Data/Database/Connection.cs +++ b/src/bnhtrade.Core/Data/Database/Connection.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Data.SqlClient; namespace bnhtrade.Core.Data.Database { diff --git a/src/bnhtrade.Core/Data/Database/Consistency/ImportAmazonSettlement.cs b/src/bnhtrade.Core/Data/Database/Consistency/ImportAmazonSettlement.cs new file mode 100644 index 0000000..04b1274 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Consistency/ImportAmazonSettlement.cs @@ -0,0 +1,50 @@ +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.Consistency +{ + public class ImportAmazonSettlement : Connection + { + public string ErrorMessage { get; set; } + public ImportAmazonSettlement(string sqlConnectionString) : base(sqlConnectionString) + { + + } + public bool RunCheck() + { + ErrorMessage = null; + + using (var sqlConn = new SqlConnection()) + { + sqlConn.Open(); + + using (SqlCommand cmd = new SqlCommand(@" + SELECT Count(tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID) AS CountOfID + FROM tblImportAmazonSettlementReportLine + INNER JOIN tblImportAmazonSettlementReport ON tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportID = tblImportAmazonSettlementReport.ImportAmazonSettlementReportID + WHERE ( + ((tblImportAmazonSettlementReport.IsProcessed) = 0) + AND ((tblImportAmazonSettlementReportLine.AccountTransactionID) IS NOT NULL) + ) + OR ( + ((tblImportAmazonSettlementReport.IsProcessed) = 0) + AND ((tblImportAmazonSettlementReportLine.IsProcessed) = 1) + ); + ", sqlConn)) + { + int count = Convert.ToInt32(cmd.ExecuteScalar()); + if (count != 0) + { + ErrorMessage = "Error, " + count + " settlement report lines have transactionId/IsProcessed set on an unprocessed settlement"; + return false; + } + } + } + return true; + } + } +} \ No newline at end of file diff --git a/src/bnhtrade.Core/Data/Database/Export/CreateSalesInvoice.cs b/src/bnhtrade.Core/Data/Database/Export/CreateSalesInvoice.cs new file mode 100644 index 0000000..a3f56c9 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Export/CreateSalesInvoice.cs @@ -0,0 +1,171 @@ +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.Export +{ + public class CreateSalesInvoice : Connection + { + private Logic.Log.LogEvent log = new Logic.Log.LogEvent(); + + public CreateSalesInvoice(string sqlConnectionString) : base(sqlConnectionString) + { + + } + + public void SaveInvoice(List invoiceList) + { + using (TransactionScope scope = new TransactionScope()) + { + // get table pks for invoice type line and fill in invoice line details + var readItemCode = new Data.Database.Account.ReadInvoiceLineItemCode(sqlConnectionString); + readItemCode.InsertNewOnNoMatch = true; + bool newTypeFound = false; + for (int i = 0; i < invoiceList.Count(); i++) + { + for (int j = 0; j < invoiceList[i].InvoiceLineList.Count(); j++) + { + var itemCodeInfo = readItemCode.ByItemCode(invoiceList[i].InvoiceLineList[j].ItemCode); + if (itemCodeInfo.IsNewReviewRequired) + { newTypeFound = true; } + else + { + invoiceList[i].InvoiceLineList[j].AccountCode = itemCodeInfo.DefaultAccountCode; + invoiceList[i].InvoiceLineList[j].TaxCode = itemCodeInfo.DefaultTaxCode; + invoiceList[i].InvoiceLineList[j].Description = itemCodeInfo.Description; + } + } + } + if (newTypeFound) + { + log.LogError("New line ItemCode created while processing Amazon settlements. Update table to complete."); + return; + } + + // add temp invoice numbers to invoices + var sequence = new Programmability.Sequence(sqlConnectionString); + for (int i = 0; i < invoiceList.Count(); i++) + { + if (invoiceList[i].InvoiceNumberIsSet) + { + var log = new Logic.Log.LogEvent(); + log.LogError("Unexpected invoice number found."); + return; + } + invoiceList[i].InvoiceNumber = "_tmp" + sequence.GetNext("ExportTempInvoiceNumber").ToString("00000000"); + } + + // validate the list of invoices + var validateInvoice = new Logic.Account.ValidateSalesInvoice(); + validateInvoice.InvoiceLineDescriptionIsRequired = false; + validateInvoice.IsValidInvoice(invoiceList); + if (validateInvoice.ErrorListIsSet) + { + log.LogError("Invalid Sales invoice(s) found during Amazon Settlement process. See extended info.", validateInvoice.ErrorListToString()); + return; + } + validateInvoice = null; + + using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString)) + { + sqlConn.Open(); + + // make the inserts + for (int i = 0; i < invoiceList.Count(); i++) + { + int invoiceId = 0; + using (SqlCommand cmd = new SqlCommand(@" + INSERT INTO tblExportAccountInvoice ( + ExportAccountInvoiceTypeID + ,Contact + ,InvoiceDate + ,InvoiceDueDate + ,InvoiceNumber + ,Reference + ,CurrencyCode + ,InvoiceAmount + ,IsComplete + ) + OUTPUT INSERTED.ExportAccountInvoiceID + VALUES ( + @invoiceTypeId + ,@contact + ,@invoiceDate + ,@invoiceDueDate + ,@invoiceNumber + ,@reference + ,@currencyCode + ,@invoiceAmount + ,@markComplete + ); + ", sqlConn)) + { + cmd.Parameters.AddWithValue("@invoiceTypeId", 2); + cmd.Parameters.AddWithValue("@contact", invoiceList[i].ContactName); + cmd.Parameters.AddWithValue("@invoiceDate", invoiceList[i].InvoiceDate); + cmd.Parameters.AddWithValue("@invoiceDueDate", invoiceList[i].InvoiceDueDate); + cmd.Parameters.AddWithValue("@reference", invoiceList[i].InvoiceReference); + cmd.Parameters.AddWithValue("@currencyCode", invoiceList[i].InvoiceCurrencyCode); + cmd.Parameters.AddWithValue("@markComplete", false); + cmd.Parameters.AddWithValue("@invoiceNumber", invoiceList[i].InvoiceNumber); + cmd.Parameters.AddWithValue("@invoiceAmount", invoiceList[i].InvoiceAmount); + + invoiceId = (int)cmd.ExecuteScalar(); + } + + for (int j = 0; j < invoiceList[i].InvoiceLineList.Count(); j++) + { + // insert record + using (SqlCommand cmd = new SqlCommand(@" + INSERT INTO tblExportAccountInvoiceLine ( + ExportAccountInvoiceID + ,ExportAccountInvoiceLineTypeID + ,NetAmount + ,AccountChartOfID + ,TaxAmount + ,AccountTaxCodeID + ) + OUTPUT INSERTED.ExportAccountInvoiceLineID + VALUES ( + @invoiceId + ,( + SELECT ExportAccountInvoiceLineTypeID + FROM tblExportAccountInvoiceLineType + WHERE MatchString = @itemCode + ) + ,@netAmount + ,( + SELECT AccountChartOfID + FROM tblAccountChartOf + WHERE AccountCode = @accountCode + ) + ,@taxAmount + ,( + SELECT AccountTaxCodeID + FROM tblAccountTaxCode + WHERE TaxCode = @taxCode + ) + ); + ", sqlConn)) + { + cmd.Parameters.AddWithValue("@invoiceID", invoiceId); + cmd.Parameters.AddWithValue("@itemCode", invoiceList[i].InvoiceLineList[j].ItemCode); + cmd.Parameters.AddWithValue("@netAmount", invoiceList[i].InvoiceLineList[j].TotalNetAmount); + cmd.Parameters.AddWithValue("@accountCode", invoiceList[i].InvoiceLineList[j].AccountCode); + cmd.Parameters.AddWithValue("@taxAmount", invoiceList[i].InvoiceLineList[j].TaxAmount); + cmd.Parameters.AddWithValue("@taxCode", invoiceList[i].InvoiceLineList[j].TaxCode); + + int lineId = (int)cmd.ExecuteScalar(); + } + } + } + } + scope.Complete(); + } + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentHeaderInfo.cs b/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentHeaderInfo.cs index 607aaf5..9dd3ca6 100644 --- a/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentHeaderInfo.cs +++ b/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentHeaderInfo.cs @@ -84,7 +84,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound foreach (string item in ShipmentIdList) { countShipId = countShipId + 1; - string parameterString = "@shipmentId" + countShipId.ToString().PadLeft(6, '0'); + string parameterString = "@shipmentId" + countShipId; dicShipIdByParameterString.Add(parameterString, item); if (countShipId == 1) { diff --git a/src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs b/src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs index f54a770..049e77b 100644 --- a/src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs +++ b/src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs @@ -11,7 +11,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound public class SetShipmentInfo : Connection { private GetShipmentPrimaryKey getPK; - private Data.Database.SKU.GetSKUId skuIdLoopkup; + private Data.Database.SKU.GetSkuId skuIdLoopkup; public SetShipmentInfo(string sqlConnectionString) : base(sqlConnectionString) { } private GetShipmentPrimaryKey GetPK { @@ -28,13 +28,13 @@ namespace bnhtrade.Core.Data.Database.FBAInbound getPK = value; } } - private Data.Database.SKU.GetSKUId SkuIdLoopkup + private Data.Database.SKU.GetSkuId SkuIdLoopkup { get { if (skuIdLoopkup == null) { - skuIdLoopkup = new SKU.GetSKUId(sqlConnectionString); + skuIdLoopkup = new SKU.GetSkuId(sqlConnectionString); } return skuIdLoopkup; } diff --git a/src/bnhtrade.Core/Data/Database/Import/ReadAmazonSettlement.cs b/src/bnhtrade.Core/Data/Database/Import/ReadAmazonSettlement.cs new file mode 100644 index 0000000..f5d6b3e --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Import/ReadAmazonSettlement.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Data.SqlClient; + +namespace bnhtrade.Core.Data.Database.Import +{ + public class ReadAmazonSettlement : Connection + { + private Dictionary dicTablePkBySettlementId = new Dictionary(); + private int? returnTop = null; + private List settlementIdList; + + private bool FilterOutIsProcessed { get; set; } + + public bool DescendingOrder { get; set; } + + public int ReturnTop + { + get { return (int)returnTop; } + set + { + if (value > 0) + { returnTop = value; } + else + { returnTop = null; } + } + } + + public bool ReturnTopIsSet + { + get { return returnTop != null; } + } + + private List SettlementIdList + { + get { return settlementIdList; } + set + { + if (value.Any()) + { settlementIdList = value; } + } + + } + + private bool SettlementIdListIsSet + { + get { return SettlementIdList != null; } + } + + public ReadAmazonSettlement(string sqlConnectionString) : base(sqlConnectionString) + { + Innit(); + } + + private void Innit() + { + DescendingOrder = false; + FilterOutIsProcessed = false; + ReturnTop = 0; + settlementIdList = null; + } + + public List AllUnprocessed() + { + Innit(); + FilterOutIsProcessed = true; + return ExecuteDbQuery(); + } + + public Model.Import.AmazonSettlement BySettlementId(string settlementId) + { + Innit(); + + // create settlement list + var idList = new List(); + idList.Add(settlementId); + var settlementList = BySettlementId(idList); + + // return answer + if (settlementList == null || !settlementList.Any()) + { return null; } + else + { return settlementList.First(); } + } + + public List BySettlementId(List settlementIdList) + { + Innit(); + + if (settlementIdList == null || !settlementIdList.Any()) + { return null; } + + SettlementIdList = settlementIdList; + + return ExecuteDbQuery(); + } + + private List ExecuteDbQuery() + { + // get header info + var settlementList = ReadHeaderList(); + if (settlementList == null || !settlementList.Any()) + { + return null; + } + + // add lines to header + foreach (var item in settlementList) + { + if (!dicTablePkBySettlementId.ContainsKey(item.SettlementId)) + { + throw new Exception("This shouldnt' happen!"); + } + int tablePk = dicTablePkBySettlementId[item.SettlementId]; + + item.SettlementLineList = ReadLineList(tablePk); + } + + return settlementList; + } + + private List ReadHeaderList() + { + // build the sql string + string sqlString = "SELECT "; + + if (ReturnTopIsSet) + { + sqlString = sqlString + "TOP " + ReturnTop + " "; + } + + sqlString = sqlString + @" + ImportAmazonSettlementReportID + ,[marketplace-name] + ,[settlement-id] + ,[settlement-start-date] + ,[settlement-end-date] + ,[deposit-date] + ,[total-amount] + ,currency + ,IsProcessed + FROM tblImportAmazonSettlementReport + WHERE 1 = 1"; + + if (FilterOutIsProcessed) + { + sqlString = sqlString + @" + AND IsProcessed = 0"; + } + + // build dictionary of parameter and values + var dicSettlementIdByParameterString = new Dictionary(); + if (SettlementIdListIsSet) + { + int count = 0; + foreach (string item in SettlementIdList) + { + if (!string.IsNullOrWhiteSpace(item)) + { + count = count + 1; + string parameterString = "@settlementId" + count; + dicSettlementIdByParameterString.Add(parameterString, item); + } + } + } + + if (dicSettlementIdByParameterString.Any()) + { + int count = 0; + foreach (var item in dicSettlementIdByParameterString) + { + count = count + 1; + if (count == 1) + { + sqlString = sqlString + @" + AND ( [settlement-id] = " + item.Key; + } + else + { + sqlString = sqlString + @" + OR [settlement-id] = " + item.Key; + } + } + sqlString = sqlString + " )"; + } + + sqlString = sqlString + @" + ORDER BY [settlement-start-date] "; + if (DescendingOrder) { sqlString = sqlString + " DESC"; } + + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(sqlString, conn)) + { + if (dicSettlementIdByParameterString.Any()) + { + foreach (var item in dicSettlementIdByParameterString) + { + cmd.Parameters.AddWithValue(item.Key, item.Value); + } + } + + using (var reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + return null; + } + + var headerList = new List(); + while (reader.Read()) + { + var header = new Model.Import.AmazonSettlement(); + + int tablePk = reader.GetInt32(0); + if (!reader.IsDBNull(1)) { header.MarketPlaceName = reader.GetString(1); } + header.SettlementId = reader.GetString(2); + header.StartDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc); + header.EndDate = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc); + header.DepositDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc); + header.TotalAmount = reader.GetDecimal(6); + header.CurrencyCode = reader.GetString(7); + header.IsProcessed = reader.GetBoolean(8); + + // update dictionary + if (!dicTablePkBySettlementId.ContainsKey(header.SettlementId)) + { + dicTablePkBySettlementId.Add(header.SettlementId, tablePk); + } + + // add header to list + headerList.Add(header); + } + + return headerList; + } + } + } + } + + private List ReadLineList(int settlementPk) + { + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(@" + SELECT ImportAmazonSettlementReportLineID + ,[transaction-type] + ,[order-id] + ,[merchant-order-id] + ,[adjustment-id] + ,[shipment-id] + ,[marketplace-name] + ,[amount-type] + ,[amount-description] + ,amount + ,currency + ,[fulfillment-id] + ,[posted-date-time] + ,[order-item-code] + ,[merchant-order-item-id] + ,[merchant-adjustment-item-id] + ,sku + ,[quantity-purchased] + ,[promotion-id] + ,IsProcessed + ,ExportAccountInvoiceLineID + FROM tblImportAmazonSettlementReportLine + WHERE ImportAmazonSettlementReportID = @settlementPk + ORDER BY [posted-date-time] + ", conn)) + { + cmd.Parameters.AddWithValue("@settlementPk", settlementPk); + + using (var reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + return null; + } + + var lineList = new List(); + while (reader.Read()) + { + var line = new Model.Import.AmazonSettlement.SettlementLine(); + + int tablePk = reader.GetInt32(0); + line.TransactionType = reader.GetString(1); + if (!reader.IsDBNull(2)) { line.OrderId = reader.GetString(2); } + if (!reader.IsDBNull(3)) { line.MerchantOrderId = reader.GetString(3); } + if (!reader.IsDBNull(4)) { line.AdjustmentId = reader.GetString(4); } + if (!reader.IsDBNull(5)) { line.ShipmentId = reader.GetString(5); } + if (!reader.IsDBNull(6)) { line.MarketPlaceName = reader.GetString(6); } + line.AmountType = reader.GetString(7); + line.AmountDescription = reader.GetString(8); + line.Amount = reader.GetDecimal(9); + line.CurrenyCode = reader.GetString(10); + if (!reader.IsDBNull(11)) { line.FulfillmentId = reader.GetString(11); } + line.PostDateTime = DateTime.SpecifyKind(reader.GetDateTime(12), DateTimeKind.Utc); + if (!reader.IsDBNull(13)) { line.OrderItemCode = reader.GetString(13); } + if (!reader.IsDBNull(14)) { line.MerchantOrderItemId = reader.GetString(14); } + if (!reader.IsDBNull(15)) { line.MerchantAdjustmentItemId = reader.GetString(15); } + if (!reader.IsDBNull(16)) { line.Sku = reader.GetString(16); } + if (!reader.IsDBNull(17)) { line.QuantityPurchased = reader.GetInt32(17); } + if (!reader.IsDBNull(18)) { line.PromotionId = reader.GetString(18); } + line.IsProcessed = reader.GetBoolean(19); + if (!reader.IsDBNull(20)) { int exportAccountInvoiceLineId = reader.GetInt32(20); } + + lineList.Add(line); + } + return lineList; + } + } + } + } + } +} \ No newline at end of file diff --git a/src/bnhtrade.Core/Data/Database/Import/UpdateAmazonSettlement.cs b/src/bnhtrade.Core/Data/Database/Import/UpdateAmazonSettlement.cs new file mode 100644 index 0000000..630fe18 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Import/UpdateAmazonSettlement.cs @@ -0,0 +1,54 @@ +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.Import +{ + public class UpdateAmazonSettlement : Connection + { + public UpdateAmazonSettlement(string sqlConnectionString) : base(sqlConnectionString) + { + + } + + public void SetIsProcessedTrue(List settlementIdList) + { + if (settlementIdList == null || !settlementIdList.Any()) + { + throw new Exception("Settlement ID list is empty."); + } + + string sqlString = @" + UPDATE tblImportAmazonSettlementReport + SET IsProcessed = 1 + WHERE (1=0)"; + + for (int i = 0; i < settlementIdList.Count(); i++) + { + sqlString += @" + OR ([settlement-id] = @settlementId" + i + ")"; + } + + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(sqlString, conn)) + { + for (int i = 0; i < settlementIdList.Count(); i++) + { + cmd.Parameters.AddWithValue("@settlementId" + i, settlementIdList[i]); + } + + if (cmd.ExecuteNonQuery() == 0) + { + throw new Exception("Something went wrong updating settlement status."); + } + } + } + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Log/LogEvent.cs b/src/bnhtrade.Core/Data/Database/Log/LogEvent.cs new file mode 100644 index 0000000..9932e3e --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Log/LogEvent.cs @@ -0,0 +1,77 @@ +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.Log +{ + public class LogEvent + { + protected void DatabaseLogInsert + (string detailShort, int eventType, string detailLong, DateTime eventDateTime, bool consolePrint = true) + { + var console = new UI.Console.Update(); + if (consolePrint) + { + if (string.IsNullOrWhiteSpace(detailLong)) + { console.WriteLine(detailShort); } + else { console.WriteLine(detailShort + Environment.NewLine + detailLong); } + } + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // need to remove this section once code has been rewritten, writing to console will be handled + // in the business layer + + // login credentials only allow insert on log table + string userId = "Log_bnhtrade"; + string password = "52ya9dky55cniyynwro5e48mV9"; + string sqlConnectionString = + "Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=TRUE;User ID=" + userId + + ";Password=" + password + ";MultipleActiveResultSets=TRUE"; + + using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress)) + { + using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString)) + { + sqlConn.Open(); + try + { + using (SqlCommand cmd = new SqlCommand(@" + INSERT INTO tblLogEvent ( + EventDateTime + ,LogEventTypeID + ,LogEventSourceID + ,Detail + ,DetailLong + ) + VALUES ( + @eventDateTime + ,@eventType + ,1 + ,@detailShort + ,@detailLong + ) + ", sqlConn)) + { + cmd.Parameters.AddWithValue("@eventDateTime", eventDateTime); + cmd.Parameters.AddWithValue("@eventType", eventType); + cmd.Parameters.AddWithValue("@detailShort", detailShort); + if (detailLong == null) { cmd.Parameters.AddWithValue("@detailLong", DBNull.Value); } + else { cmd.Parameters.AddWithValue("@detailLong", detailLong); } + + cmd.ExecuteNonQuery(); + } + } + catch (Exception ex) + { + console.WriteLine("WTF!!!! Error with error logging, jobs foooked!"); + throw ex; + } + scope.Complete(); + } + } + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/Programmability/Sequence.cs b/src/bnhtrade.Core/Data/Database/Programmability/Sequence.cs new file mode 100644 index 0000000..83edd95 --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/Programmability/Sequence.cs @@ -0,0 +1,49 @@ +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.Programmability +{ + public class Sequence : Connection + { + public Sequence (string sqlConnectionString) : base(sqlConnectionString) + { + + } + public int GetNext(string sequenceName) + { + if (string.IsNullOrWhiteSpace(sequenceName)) + { + throw new Exception("Sequence name is null or whitespace."); + } + + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(@" + SELECT NEXT VALUE FOR " + sequenceName + , conn)) + { + //cmd.Parameters.AddWithValue("@sequenceName", sequenceName); + // it wouldn't let me use parameters + + object obj = cmd.ExecuteScalar(); + + try + { + //string whaaaat = (string)obj; + return Convert.ToInt32(obj); + } + catch (Exception ex) + { + throw new Exception("Error returning next value in sequence: " + ex.Message); + } + } + } + } + } +} diff --git a/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs b/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs index f508758..4662e03 100644 --- a/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs +++ b/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs @@ -4,12 +4,12 @@ using System.Data.SqlClient; namespace bnhtrade.Core.Data.Database.SKU { - public class GetSKUId + public class GetSkuId { private Dictionary SKUIdBySKUNumber { get; set; } private Dictionary SKUNumberBySKUId { get; set; } private string SqlConnectionString { get; set; } - public GetSKUId(string sqlConnectionString) + public GetSkuId(string sqlConnectionString) { // setup sql parameters if (sqlConnectionString.Length == 0) diff --git a/src/bnhtrade.Core/Data/Database/SKU/GetSku.cs b/src/bnhtrade.Core/Data/Database/SKU/GetSku.cs new file mode 100644 index 0000000..835b7fe --- /dev/null +++ b/src/bnhtrade.Core/Data/Database/SKU/GetSku.cs @@ -0,0 +1,158 @@ +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.SKU +{ + class GetSku : Connection + { + private Dictionary cache; + protected GetSku (string sqlConnection) : base(sqlConnection) + { + Default(); + } + protected List BySkuNumberList(List skuNumberList, bool forceRequery = false) + { + if (skuNumberList == null || !skuNumberList.Any()) + { + return null; + } + + var getList = new List(); + foreach(string item in skuNumberList) + { + if (forceRequery || !cache.ContainsKey(item)) + { + getList.Add(item); + } + } + + // update the cache + CacheUpdate(getList); + + // build the return list + var returnList = new List(); + foreach (string item in skuNumberList) + { + if (cache.ContainsKey(item)) + { + returnList.Add(cache[item]); + } + } + + //return the list + if (returnList.Any()) + { + return returnList; + } + else + { + return null; + } + } + protected void CacheClear() + { + cache.Clear(); + } + private void CacheUpdate(List skuNumberList) + { + // build the sql string + string sqlString = @" + SELECT + skuSkuID + ,skuSkuNumber + ,skuAmazonFNSKU + ,skuActive + FROM tblSku + WHERE 1 = 1"; + + // build dictionary of parameters and skunumbers + var dicSkuNumberByParameterString = new Dictionary(); + int count = 0; + foreach (string item in skuNumberList) + { + if (!string.IsNullOrWhiteSpace(item)) + { + count = count + 1; + string parameterString = "@skuNumber" + count; + dicSkuNumberByParameterString.Add(parameterString, item); + } + } + + if (dicSkuNumberByParameterString.Any()) + { + count = 0; + foreach (var item in dicSkuNumberByParameterString) + { + count = count + 1; + if (count == 1) + { + sqlString = sqlString + @" + AND ( skuSkuNumber = " + item.Key; + } + else + { + sqlString = sqlString + @" + OR skuSkuNumber = " + item.Key; + } + } + sqlString = sqlString + " )"; + } + else + { + return; + } + + sqlString = sqlString + @" + ORDER BY skuSkuNumber"; + + using (SqlConnection conn = new SqlConnection(sqlConnectionString)) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(sqlString, conn)) + { + if (dicSkuNumberByParameterString.Any()) + { + foreach (var item in dicSkuNumberByParameterString) + { + cmd.Parameters.AddWithValue(item.Key, item.Value); + } + } + + using (var reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + return; + } + + while (reader.Read()) + { + var sku = new Model.Sku.Sku(); + + int tablePk = reader.GetInt32(0); + sku.SkuNumber = reader.GetString(1); + if (!reader.IsDBNull(2)) { sku.AmazonFNSKU = reader.GetString(2); } + sku.IsActive = reader.GetBoolean(3); + + // update cache + if (cache.ContainsKey(sku.SkuNumber)) + { + cache.Remove(sku.SkuNumber); + } + cache.Add(sku.SkuNumber, sku); + } + } + } + } + } + protected void Default() + { + cache = new Dictionary(); + } + } +} diff --git a/src/bnhtrade.Core/Logic/Account/ValidateAccountCode.cs b/src/bnhtrade.Core/Logic/Account/ValidateAccountCode.cs new file mode 100644 index 0000000..0d3980f --- /dev/null +++ b/src/bnhtrade.Core/Logic/Account/ValidateAccountCode.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Account +{ + public class ValidateAccountCode : Validate + { + private Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck(); + + public new void Innit() + { + base.Innit(); + stringCheck = new Logic.Utilities.StringCheck(); + } + public bool IsValidAccountCodeId(int accountCode) + { + if (accountCode >=0) + { return true; } + else + { + ErrorListAdd("Invalid account code."); + return false; + } + } + public bool IsValidTitle(string title) + { + if (stringCheck.MaxLength(title, 150)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList); + return false; + } + } + public bool IsValidDescription(string description) + { + if (stringCheck.MaxLength(description, 500)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList); + return false; + } + } + public bool IsValidType(string type) + { + if (stringCheck.MaxLength(type, 50)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList); + return false; + } + } + public bool IsValidBasicType(string basicType) + { + if (stringCheck.MaxLength(basicType, 50)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList); + return false; + } + } + } +} diff --git a/src/bnhtrade.Core/Logic/Account/ValidateCurrencyCode.cs b/src/bnhtrade.Core/Logic/Account/ValidateCurrencyCode.cs new file mode 100644 index 0000000..478f842 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Account/ValidateCurrencyCode.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Account +{ + public class ValidateCurrencyCode : Validate + { + private Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck(); + public new void Innit() + { + base.Innit(); + stringCheck = new Logic.Utilities.StringCheck(); + } + public bool IsValidCurrencyCode(string currencyCode) + { + if (stringCheck.Length(currencyCode, 3) && stringCheck.IsAlpha(currencyCode, true)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList); + return false; + } + } + } +} diff --git a/src/bnhtrade.Core/Logic/Account/ValidateInvoice.cs b/src/bnhtrade.Core/Logic/Account/ValidateInvoice.cs new file mode 100644 index 0000000..69fd9ad --- /dev/null +++ b/src/bnhtrade.Core/Logic/Account/ValidateInvoice.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Account +{ + public abstract class ValidateInvoice : Validate + { + protected Account.ValidateAccountCode validateAccountCode = new Account.ValidateAccountCode(); + protected Account.ValidateCurrencyCode validateCurrencyCode = new Account.ValidateCurrencyCode(); + protected Account.ValidateTaxCode validateTaxCode = new ValidateTaxCode(); + protected Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck(); + + public bool InvoiceNumberIsRequired { get; set; } = true; + public bool InvoiceLineDescriptionIsRequired { get; set; } = true; + + public new void Innit() + { + base.Innit(); + validateAccountCode.Innit(); + validateCurrencyCode.Innit(); + validateTaxCode.Innit(); + stringCheck.Innit(); + } + + protected bool IsValidInvoice(Model.Account.IInvoice invoice) + { + return IsValidInvoice(new List { invoice }); + } + + protected bool IsValidInvoice(List invoiceList) + { + Innit(); + + if (invoiceList == null || !invoiceList.Any()) + { + ErrorListAdd("Invoice list is null or empty."); + return false; + } + + var tempErrorList = new List(); + for (int i = 0; i < invoiceList.Count(); i++) + { + Innit(); + + // check header info + if (invoiceList[i].ContactNameIsSet) { IsValidInvoiceContact(invoiceList[i].ContactName); } + else { ErrorListAdd("'Contact Name' is a required value"); } + + if (invoiceList[i].InvoiceAmountIsSet) + { + if (!invoiceList[i].IsCreditNoteIsSet) + { ErrorListAdd("'Is Credit Note' is a required value"); } + else + { + if (invoiceList[i].IsCreditNote && invoiceList[i].InvoiceAmount > 0) + { ErrorListAdd("Credit Note amount cannot be greater than zero"); } + else if (!invoiceList[i].IsCreditNote && invoiceList[i].InvoiceAmount < 0) + { ErrorListAdd("Invoice amount cannot be less than zero"); } + } + } + else { ErrorListAdd("'Invoice Amount' is a required value"); } + + if (invoiceList[i].InvoiceCurrencyCodeIsSet) { IsValidInvoiceCurrency(invoiceList[i].InvoiceCurrencyCode); } + else { ErrorListAdd("'Invoice Currency Code' is a required value"); } + + if (invoiceList[i].InvoiceDateIsSet) { IsValidInvoiceDate(invoiceList[i].InvoiceDate); } + else { ErrorListAdd("'Invoice Date' is a required value"); } + + if (!invoiceList[i].InvoiceDateKindIsSet) { ErrorListAdd("'Invoice Date Kind' is a required value"); } + + if (invoiceList[i].InvoiceDueDateIsSet) { IsValidInvoiceDueDate(invoiceList[i].InvoiceDueDate); } + + if (invoiceList[i].InvoiceNumberIsSet) + { IsValidInvoiceNumber(invoiceList[i].InvoiceNumber); } + else + { + if (InvoiceNumberIsRequired) { ErrorListAdd("'Invoice Number' is a required value"); } + } + + if (invoiceList[i].InvoiceReferenceIsSet) { IsValidInvoiceReference(invoiceList[i].InvoiceReference); } + else { ErrorListAdd("'Invoice Reference' is a required value"); } + + if (!invoiceList[i].IsCreditNoteIsSet) { ErrorListAdd("'Invoice Reference' is a required value"); } + + + // loop though lines and check and sum totals + if (!invoiceList[i].InvoiceLineListIsSet) + { ErrorListAdd("Invoice is required to have lines."); } + else + { + decimal lineTotal = 0; + for (int j = 0; j < invoiceList[i].InvoiceLineList.Count(); j++) + { + if (!invoiceList[i].InvoiceLineList[j].AccountCodeIsSet) { ErrorListAdd("Line 'Account Code' is a required value"); } + else { IsValidInvoiceLineAccount(invoiceList[i].InvoiceLineList[j].AccountCode); } + + if (!invoiceList[i].InvoiceLineList[j].DescriptionIsSet) + { + if (InvoiceLineDescriptionIsRequired) { ErrorListAdd("Line 'Description' is a required value"); } + } + else { IsValidInvoiceLineDescription(invoiceList[i].InvoiceLineList[j].Description); } + + if (!invoiceList[i].InvoiceLineList[j].GrossTotalAmountIsSet) { ErrorListAdd("Line 'Gross Total Amount' is a required value"); } + + if (!invoiceList[i].InvoiceLineList[j].ItemCodeIsSet) { ErrorListAdd("Line 'Item Code' is a required value"); } + else { IsValidLineItemCode(invoiceList[i].InvoiceLineList[j].ItemCode); } + + if (!invoiceList[i].InvoiceLineList[j].QuantityIsSet) { ErrorListAdd("Line 'Quantity' is a required value"); } + + if (!invoiceList[i].InvoiceLineList[j].TaxAmountIsSet) { ErrorListAdd("Line 'Tax Amount' is a required value"); } + + if (!invoiceList[i].InvoiceLineList[j].TaxCodeIsSet) { ErrorListAdd("Line 'Tax Code' is a required value"); } + else { IsValidLineTaxCode(invoiceList[i].InvoiceLineList[j].TaxCode); } + + if (!invoiceList[i].InvoiceLineList[j].TotalNetAmountIsSet) { ErrorListAdd("Line 'Total Net Amount' is a required value"); } + + if ((invoiceList[i].InvoiceLineList[j].TaxAmount + + invoiceList[i].InvoiceLineList[j].TaxAmountAdjust + + invoiceList[i].InvoiceLineList[j].TotalNetAmount) != invoiceList[i].InvoiceLineList[j].GrossTotalAmount) + { ErrorListAdd("Incorrect invoice line total (gross) amount."); } + + lineTotal = lineTotal + invoiceList[i].InvoiceLineList[j].GrossTotalAmount; + } + + // check totals + if (invoiceList[i].InvoiceAmountIsSet && (invoiceList[i].InvoiceAmount != lineTotal)) + { ErrorListAdd("Invoice line total does not match invoice total amount."); } + } + tempErrorList.AddRange(ErrorList.Select(x => "[Inv" + i + "] " + x).ToList()); + } + + Innit(); + ErrorListAdd(tempErrorList); + + if (ErrorListIsSet) { return false; } + else { return true; } + } + + protected bool IsValidInvoiceLineAccount(int accountCode) + { + validateAccountCode.Innit(); + if (!validateAccountCode.IsValidAccountCodeId(accountCode)) + { + ErrorListAdd(validateAccountCode.ErrorList.Select(x => "Invalid invoice line account code: " + x).ToList()); + return false; + } + else + { return true; } + } + + protected bool IsValidInvoiceLineDescription(string lineDescription) + { + int maxLength = 150; + stringCheck.Innit(); + if (!stringCheck.MaxLength(lineDescription, maxLength)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice line description: " + x).ToList()); + return false; + } + return true; + } + + protected bool IsValidInvoiceContact(string contactName) + { + int maxlength = 150; + stringCheck.Innit(); + if (!stringCheck.MaxLength(contactName, maxlength)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice nontact name: " + x).ToList()); + return false; + } + return true; + } + + protected bool IsValidInvoiceDate(DateTime invoiceDate) + { + if (invoiceDate.Kind != DateTimeKind.Utc) + { + ErrorListAdd(@"Invalid date/time, UTC kind required."); + return false; + } + else if (invoiceDate == default(DateTime)) + { + ErrorListAdd("Date and time is default value."); + return false; + } + return true; + } + + protected bool IsValidInvoiceDueDate(DateTime invoiceDueDate) + { + if (invoiceDueDate.Kind != DateTimeKind.Utc) + { + ErrorListAdd(@"Invalid date/time, UTC kind required."); + return false; + } + else if (invoiceDueDate == default(DateTime)) + { + ErrorListAdd("Date and time is default value."); + return false; + } + return true; + } + + protected bool IsValidInvoiceCurrency(string currencyCode) + { + validateCurrencyCode.Innit(); + if (!validateCurrencyCode.IsValidCurrencyCode(currencyCode)) + { + ErrorListAdd(validateCurrencyCode.ErrorList.Select(x => "Invalid invoice currency code: " + x).ToList()); + return false; + } + else { return true; } + } + + protected bool IsValidInvoiceNumber(string invoiceNumber) + { + int maxlength = 64; + stringCheck.Innit(); + if (!stringCheck.MaxLength(invoiceNumber, maxlength)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice number: " + x).ToList()); + return false; + } + return true; + } + + protected bool IsValidInvoiceReference(string invoiceReference) + { + int maxlength = 50; + stringCheck.Innit(); + if (!stringCheck.MaxLength(invoiceReference, maxlength)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice reference: " + x).ToList()); + return false; + } + return true; + } + + protected bool IsValidLineItemCode(string itemCode) + { + int maxlength = 250; + stringCheck.Innit(); + if (!stringCheck.MaxLength(itemCode, maxlength)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice line item code: " + x).ToList()); + return false; + } + return true; + } + + protected bool IsValidLineTaxCode(string taxCode) + { + validateTaxCode.Innit(); + if (validateTaxCode.IsValidTaxCodeId(taxCode)) + { return true; } + else + { + ErrorListAdd(validateTaxCode.ErrorList.Select(x => "Invalid invoice line " + x).ToList()); + return false; + } + } + } +} diff --git a/src/bnhtrade.Core/Logic/Account/ValidateSalesInvoice.cs b/src/bnhtrade.Core/Logic/Account/ValidateSalesInvoice.cs new file mode 100644 index 0000000..ef6a103 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Account/ValidateSalesInvoice.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Account +{ + public class ValidateSalesInvoice : ValidateInvoice + { + public ValidateSalesInvoice() + { + int propertyCount = new Model.Account.SalesInvoice().GetType().GetProperties().Count(); + if (propertyCount != 20) + { throw new Exception("Model.Account.SalesInvoice property count has altered. Validate class requires an update."); } + + propertyCount = new Model.Account.SalesInvoice.InvoiceLine().GetType().GetProperties().Count(); + if (propertyCount != 18) + { throw new Exception("Model.Account.SalesInvoice property count has altered. Validate class requires an update."); } + } + + public bool IsValidInvoice(Model.Account.SalesInvoice invoice) + { + return IsValidInvoice(new List { invoice }); + } + + public bool IsValidInvoice(List invoiceList) + { + var interfaceList = invoiceList.Cast().ToList(); + + return IsValidInvoice(interfaceList); + } + } +} diff --git a/src/bnhtrade.Core/Logic/Account/ValidateTaxCode.cs b/src/bnhtrade.Core/Logic/Account/ValidateTaxCode.cs new file mode 100644 index 0000000..ccf72e8 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Account/ValidateTaxCode.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Account +{ + public class ValidateTaxCode : Validate + { + private Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck(); + + public new void Innit() + { + base.Innit(); + stringCheck.Innit(); + } + public bool IsValidGrossAmountMultiplier(decimal multiplier) + { + if (multiplier >= 0 && multiplier <= 1) + { + return true; + } + else + { + ErrorListAdd( "Gross multiplier must be equal to, or between, 0 and 1."); + return false; + } + } + public bool IsValidNetAmountMultiplier(decimal multiplier) + { + if (multiplier >= 0 && multiplier <= 1) + { + return true; + } + else + { + ErrorListAdd("Net multiplier must not be less than 0 or greater than 1."); + return false; + } + } + public bool IsValidOnExpense(Model.Account.TaxCode taxInfo) + { + if (taxInfo.IsValidOnExpense || taxInfo.IsSetIsValidOnIncome) + { + if (taxInfo.IsSetIsValidOnExpense) + { + return true; + } + else + { + ErrorListAdd("Is Valid On Expense has not been set."); + return false; + } + } + else + { + ErrorListAdd("Either 'IsValidOnExpense' or 'IsSetIsValidOnSale' must be set to true."); + return false; + } + } + public bool IsValidOnIncome(Model.Account.TaxCode taxInfo) + { + if (taxInfo.IsValidOnExpense || taxInfo.IsSetIsValidOnIncome) + { + if (taxInfo.IsSetIsValidOnIncome) + { + return true; + } + else + { + ErrorListAdd("Is Valid On Income has not been set."); + return false; + } + } + else + { + ErrorListAdd("Either 'IsValidOnPurchase' or 'IsSetIsValidOnSale' must be set to true."); + return false; + } + } + public bool IsValidTaxCodeId(string taxCodeId) + { + if (!stringCheck.IsAlphaNumeric(taxCodeId, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Code: " + x).ToList()); + return false; + } + if (taxCodeId.Length != 4) + { + ErrorListAdd("Invalid Tax Code: Length does not equal 4 charaters."); + return false; + } + return true; + } + public bool IsValidTaxRateDescription(string description) + { + if (stringCheck.MaxLength(description, 250, true)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Rate Description: " + x).ToList()); + return false; + } + } + public bool IsValidTaxRateTitle(string title) + { + if (stringCheck.MaxLength(title, 50, false)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Rate Title: " + x).ToList()); + return false; + } + } + public bool IsValidTaxRateTitleShort(string title) + { + if (stringCheck.MaxLength(title, 50, false)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Rate Title Short: " + x).ToList()); + return false; + } + } + public bool IsValidTaxType(string taxType) + { + if (stringCheck.MaxLength(taxType, 50, false)) + { + return true; + } + else + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Rate Type: " + x).ToList()); + return false; + } + } + } +} diff --git a/src/bnhtrade.Core/Logic/Export/AmazonSettlementData.cs b/src/bnhtrade.Core/Logic/Export/AmazonSettlementData.cs new file mode 100644 index 0000000..3095113 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Export/AmazonSettlementData.cs @@ -0,0 +1,270 @@ +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.Logic.Export +{ + public class AmazonSettlementData + { + private string sqlConnectionString; + private Dictionary taxCodeBySkuNumer; + + public AmazonSettlementData(string sqlConnectionString) + { + this.sqlConnectionString = sqlConnectionString; + } + public void ToInvoice() + { + var console = new UI.Console.Update(); + var log = new Logic.Log.LogEvent(); + log.LogInformation("Starting processing of Amazon settlement data into export invoice table..."); + + // get list of unprocssed settlement reports to export + var settlementData = new Data.Database.Import.ReadAmazonSettlement(sqlConnectionString); + var settlementList = settlementData.AllUnprocessed(); + settlementData = null; + + if (settlementList == null) + { + log.LogInformation("No new settlements to process, exiting import..."); + return; + } + + // create list of settlement ids + var settlementIdList = new List(); + for (int i = 0; i < settlementList.Count(); i++) + { + settlementIdList.Add(settlementList[i].SettlementId); + } + + // 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 + for (int i = 0; i < settlementList.Count(); i++) + { + if (!settlementList[i].MarketPlaceNameIsSet) + { + log.LogError( + "Action required: Enter market place name for settlelment report id " + settlementList[i].SettlementId + "." + , "Unable to process settlement data from one settlement report '" + settlementList[i].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." + ); + } + } + + // validate settlelments + var validate = new Logic.Import.ValidateAmazonSettlement(); + for (int i = 0; i < settlementList.Count(); i++) + { + if (!validate.IsValid(settlementList[i])) + { + log.LogError("Error procesing Amazon Settlement data for export.", validate.ErrorListToString()); + } + } + if (validate.ErrorListIsSet) { return; } + + // get dictionary of sku-number to taxcodeId + Console.Write("\rBuilding SKU list... "); + var dicSkuNumberToTaxCodeId = new Dictionary(); + for (int i = 0; i < settlementList.Count(); i++) + { + if (settlementList[i].SettlementLineListIsSet) + { + for (int j = 0; j < settlementList[i].SettlementLineList.Count(); j++) + { + if (settlementList[i].SettlementLineList[j].SkuIsSet + && !string.IsNullOrWhiteSpace(settlementList[i].SettlementLineList[j].Sku)) + { + if (!dicSkuNumberToTaxCodeId.ContainsKey(settlementList[i].SettlementLineList[j].Sku)) + { + dicSkuNumberToTaxCodeId.Add(settlementList[i].SettlementLineList[j].Sku, null); + } + } + } + } + } + var readTaxCode = new Data.Database.Account.ReadTaxCode(sqlConnectionString); + taxCodeBySkuNumer = readTaxCode.BySkuNumber(dicSkuNumberToTaxCodeId.Keys.ToList()); + + // loop through each settlement and build list of invoices to export + Console.Write("\rBuilding invoices to export... "); + var invoiceList = new List(); + for (int i = 0; i < settlementList.Count(); i++) + { + // split settlement line list into months + // List + var monthList = settlementList[i].SettlementLineList + .GroupBy(x => new DateTime(x.PostDateTime.Year, x.PostDateTime.Month, 1, 0, 0, 0, x.PostDateTime.Kind)); + //.GroupBy(x => string.Format("{0}-{1}", x.PostDateTime.Year, x.PostDateTime.Month)); + //.GroupBy(x => new { x.PostDateTime.Month, x.PostDateTime.Year }); + + int monthCount = 0; + foreach (var month in monthList) + { + monthCount++; + var itemCodeTotal = new Dictionary(); + foreach (var line in month) + { + string itemCode = BuildLineItemCode(line.Sku, line.TransactionType, line.AmountType, line.AmountDescription); + if (itemCodeTotal.ContainsKey(itemCode)) + { + itemCodeTotal[itemCode] += line.Amount; + } + else + { + itemCodeTotal.Add(itemCode, line.Amount); + } + } + + // create invoice, one for each month + var invoice = new Model.Account.SalesInvoice(); + + // create invoice lines forsy + invoice.InvoiceLineList = new List(); + decimal lineNetTotal = 0m; + decimal lineTaxTotal = 0m; + foreach (var item in itemCodeTotal) + { + var line = new Model.Account.SalesInvoice.InvoiceLine(); + line.ItemCode = item.Key; + line.TotalNetAmount = item.Value; + lineNetTotal += item.Value; + line.TaxAmount = 0; + lineTaxTotal += 0; + line.Quantity = 1; + invoice.InvoiceLineList.Add(line); + } + + invoice.ContactName = settlementList[i].MarketPlaceName; + invoice.InvoiceCurrencyCode = settlementList[i].CurrencyCode; + if (monthList.Count() == 1 || monthList.Count() == monthCount) + { invoice.InvoiceDate = settlementList[i].EndDate; } + else + { invoice.InvoiceDate = new DateTime(month.Key.Year, month.Key.Month, 1, 0, 0, 0, DateTimeKind.Utc).AddMonths(1).AddDays(-1); } + invoice.InvoiceDateKind = DateTimeKind.Utc; + invoice.InvoiceDueDate = settlementList[i].DepositDate; + invoice.InvoiceReference = settlementList[i].SettlementId; + invoice.InvoiceAmount = lineNetTotal + lineTaxTotal; + if (invoice.InvoiceAmount < 0) { invoice.IsCreditNote = true; } + else { invoice.IsCreditNote = false; } + + // invoice complete, add to list + invoiceList.Add(invoice); + } + } + + // sort list of invoices + invoiceList = invoiceList.OrderBy(x => x.InvoiceReference).ThenBy(x => x.InvoiceDate).ToList(); + + // check invoice total against settlement totals + var invoiceTotal = new Dictionary(); + for (int i = 0; i < invoiceList.Count(); i++) + { + if (invoiceTotal.ContainsKey(invoiceList[i].InvoiceReference)) + { + invoiceTotal[invoiceList[i].InvoiceReference] += invoiceList[i].InvoiceAmount; + } + else + { + invoiceTotal.Add(invoiceList[i].InvoiceReference, invoiceList[i].InvoiceAmount); + } + } + for (int i = 0; i < settlementList.Count(); i++) + { + if (settlementList[i].TotalAmount != invoiceTotal[settlementList[i].SettlementId]) + { + throw new Exception("invoice totals does not match settlement total."); + } + } + if (settlementIdList.Count != invoiceTotal.Count()) + { + log.LogError("Stopping Settlement export. Not all settlements have been transposed into invoices."); + return; + } + + // postfix invoices spanning multiple months with -n + if (invoiceList.Count() > 1) + { + string lastRef = invoiceList[0].InvoiceReference; + int countRef = 1; + for (int i = 1; i < invoiceList.Count(); i++) + { + if (invoiceList[i].InvoiceReference == lastRef) + { + if (countRef == 1) + { + invoiceList[i - 1].InvoiceReference = lastRef + "-" + countRef; + } + invoiceList[i].InvoiceReference = lastRef + "-" + (countRef += 1); + } + else + { + // shouldn't normally be more than 2 date ranges, log and move on. + if (countRef > 2) + { + log.LogError( + countRef + " total numner of export invoices created from Amazon Settlement Id" + lastRef + "." + , "Settlement period appears to span more 3 months or more. Whilst this is possible, it is unsual. Confirm his is correct."); + } + + lastRef = invoiceList[i].InvoiceReference; + countRef = 1; + } + } + } + + Console.Write("\rWriting to database... "); + using (TransactionScope scope = new TransactionScope()) + { + try + { + // write to the database (gets validated there) + new Data.Database.Export.CreateSalesInvoice(sqlConnectionString).SaveInvoice(invoiceList); + + // set settlements to isprocessed + new Data.Database.Import.UpdateAmazonSettlement(sqlConnectionString).SetIsProcessedTrue(settlementIdList); + + scope.Complete(); + } + catch (Exception ex) + { + log.LogError(ex.Message); + return; + } + } + Console.Write("\r"); + log.LogInformation("Finished processing of Amazon settlement data. " + invoiceList.Count() + " invoices created from "+ settlementIdList.Count() + " Amazon settlement reports."); + } + + private string BuildLineItemCode(string skuNumber, string transactionType, string amountType, string amountDescription) + { + // build the match string + // NB special case for global accounting sale and refunds (also note Goodlwill is included) and sku's where tax is included + string match01 = transactionType; + string match02 = amountType; + string match03 = amountDescription; + string matchString = "<" + match01 + "><" + match02 + "><" + match03 + ">"; + + // add tax info if required + if ((match01 == "Order" || match01 == "Refund") + && (match02 == "ItemPrice" || match02 == "Promotion")) + { + if (taxCodeBySkuNumer.ContainsKey(skuNumber)) + { + matchString = matchString + ""; + } + else + { + throw new Exception("Sku#" + skuNumber + " tax info not found in dictionary list."); + } + } + return matchString; + } + } +} \ No newline at end of file diff --git a/src/bnhtrade.Core/Logic/Export/ValidateSalesInvoice.cs b/src/bnhtrade.Core/Logic/Export/ValidateSalesInvoice.cs new file mode 100644 index 0000000..f07e20b --- /dev/null +++ b/src/bnhtrade.Core/Logic/Export/ValidateSalesInvoice.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Export +{ + class ValidateSalesInvoice : Logic.Account.ValidateInvoice + { + //public bool IsValidInvoice(Model.Export.SetSalesInvoice invoice) + //{ + // ErrorMessage = null; + + // var baseInvoice = CopyInvoiceToBase(invoice); + // if (!base.IsValidInvoice(baseInvoice)) + // { + // return false; + // } + + // // check each match string only appears once + // var dicLookup = new Dictionary(); + // foreach (var line in invoice.InvoiceLineList) + // { + // if (dicLookup.ContainsKey(line.LineTypeMatchString)) + // { + // ErrorMessage = "'Line type match string' duplication."; + // return false; + // } + // else + // { + // dicLookup.Add(line.LineTypeMatchString, null); + // } + // } + + // return true; + //} + //public bool IsValidInvoiceHeader(Model.Export.SetSalesInvoice invoice) + //{ + // ErrorMessage = null; + + // var baseInvoice = CopyInvoiceHeaderToBase(invoice); + // if (base.IsValidInvoiceHeader(baseInvoice)) + // { + // return true; + // } + // else + // { + // return false; + // } + //} + //public bool IsValidInvoiceLine(Model.Export.SetSalesInvoiceLine invoiceLine) + //{ + // ErrorMessage = null; + + // var baseLine = CopyInvoiceLineToBase(invoiceLine); + // if (!IsValidLineTypeMatchString(invoiceLine.LineTypeMatchString) + // || !base.IsValidInvoiceLine(baseLine)) + // { + // return false; + // } + + // return true; + //} + //public bool IsValidLineTypeMatchString(string matchString) + //{ + // ErrorMessage = null; + // var stringCheck = new Logic.Utilities.StringCheck(); + // if (!stringCheck.MaxLength(matchString, 250)) + // { + // ErrorMessage = "Invalid Line Type Match String: " + stringCheck.ErrorMessage; + // return false; + // } + // return true; + //} + //private Model.Account.SalesInvoice CopyInvoiceToBase(Model.Export.SetSalesInvoice invoice) + //{ + // var baseInvoice = CopyInvoiceHeaderToBase(invoice); + // if (invoice.IsSetInvoiceLineList) + // { + // var baseLineList = new List(); + // foreach (var line in invoice.InvoiceLineList) + // { + // baseLineList.Add(CopyInvoiceLineToBase(line)); + // } + // baseInvoice.InvoiceLineList = baseLineList; + // } + // return baseInvoice; + //} + + //private Model.Account.SalesInvoice CopyInvoiceHeaderToBase(Model.Export.SetSalesInvoice invoice) + //{ + // var baseInvoice = new Model.Account.SalesInvoice(); + + // if (invoice.IsSetContactName) + // { baseInvoice.ContactName = invoice.ContactName; } + // if (invoice.IsSetInvoiceAmount) + // { baseInvoice.InvoiceAmount = invoice.InvoiceAmount; } + // if (invoice.IsSetInvoiceCurrencyCode) + // { baseInvoice.InvoiceCurrencyCode = invoice.InvoiceCurrencyCode; } + // if (invoice.IsSetInvoiceDate) + // { baseInvoice.InvoiceDate = invoice.InvoiceDate; } + // if (invoice.IsSetInvoiceNumber) + // { baseInvoice.InvoiceNumber = invoice.InvoiceNumber; } + // if (invoice.IsSetInvoiceReference) + // { baseInvoice.InvoiceReference = invoice.InvoiceReference; } + // if (invoice.IsSetIsComplete) + // { baseInvoice.IsComplete = invoice.IsComplete; } + + // return baseInvoice; + //} + //private Model.Account.SalesInvoiceLine CopyInvoiceLineToBase(Model.Export.SetSalesInvoiceLine invoiceLine) + //{ + // var baseLine = new Model.Account.SalesInvoiceLine(); + + // if (invoiceLine.IsSetAccountCode) + // { baseLine.AccountCode = invoiceLine.AccountCode; } + + // // something missing here ?????? + + // if (invoiceLine.IsSetDescription) + // { baseLine.Description = invoiceLine.Description; } + // if (invoiceLine.IsSetNetAmount) + // { baseLine.TotalNetAmount = invoiceLine.NetAmount; } + + // // tax adjustment to set ?????????? + + // if (invoiceLine.IsSetTaxCode) + // { baseLine.TaxCode = invoiceLine.TaxCode; } + + // return baseLine; + //} + } +} diff --git a/src/bnhtrade.Core/Logic/Import/ValidateAmazonSettlement.cs b/src/bnhtrade.Core/Logic/Import/ValidateAmazonSettlement.cs new file mode 100644 index 0000000..63a1c21 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Import/ValidateAmazonSettlement.cs @@ -0,0 +1,499 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Import +{ + public class ValidateAmazonSettlement : Validate + { + protected Utilities.StringCheck stringCheck = new Utilities.StringCheck(); + protected Utilities.DateTimeCheck timeCheck = new Utilities.DateTimeCheck(); + protected Account.ValidateCurrencyCode currencyCheck = new Account.ValidateCurrencyCode(); + protected Utilities.DecimalCheck decimalCheck = new Utilities.DecimalCheck(); + + public ValidateAmazonSettlement() : base() + { + + } + + public bool ValidateMarketPlaceName { get; set; } = true; + + public new void Innit() + { + base.Innit(); + timeCheck.Innit(); + stringCheck.Innit(); + currencyCheck.Innit(); + decimalCheck.Innit(); + } + + public bool IsValid(Model.Import.AmazonSettlement settlement) + { + return IsValid(new List { settlement }); + } + + public bool IsValid(List settlementList) + { + Innit(); + + for (int i = 0; i < settlementList.Count; i++) + { + if (!settlementList[i].CurrencyCodeIsSet) { ErrorListAdd("CurrencyCode is a required value."); } + else { IsValidCurrencyCode(settlementList[i].CurrencyCode); } + + if (!settlementList[i].DepositDateIsSet) { ErrorListAdd("DepositDate is a required value."); } + else { IsValidDepositDate(settlementList[i].DepositDate); } + + if (!settlementList[i].EndDateIsSet) { ErrorListAdd("EndDate is a required value."); } + else { IsValidEndDate(settlementList[i].EndDate); } + + if (!settlementList[i].IsProcessedIsSet) { ErrorListAdd("IsProcessed is a required value."); } + else { IsValidIsProcessed(settlementList[i].IsProcessed); } + + if (!settlementList[i].MarketPlaceNameIsSet) + { + if (ValidateMarketPlaceName) { ErrorListAdd("MarketPlaceName is a required value."); } + } + else { IsValidMarketPlaceName(settlementList[i].MarketPlaceName); } + + if (!settlementList[i].SettlementIdIsSet) { ErrorListAdd("SettlementId is a required value."); } + else { IsValidSettlementId(settlementList[i].SettlementId); } + + if (!settlementList[i].StartDateIsSet) { ErrorListAdd("StartDate is a required value."); } + else { IsValidStartDate(settlementList[i].StartDate); } + + if (!settlementList[i].TotalAmountIsSet) { ErrorListAdd("TotalAmount is a required value."); } + else { IsValidTotalAmount(settlementList[i].TotalAmount); } + + + // check line list + if (!settlementList[i].SettlementLineListIsSet) + { + ErrorListAdd("Settlement line list is null or empty"); + continue; + } + else + { + // loop though lines and check + decimal lineSum = 0; + for (int j = 0; j < settlementList[i].SettlementLineList.Count(); j++) + { + IsValid(settlementList[i].SettlementLineList[j]); + if (settlementList[i].SettlementLineList[j].AmountIsSet) + { lineSum += settlementList[i].SettlementLineList[j].Amount; } + } + + // check totals + if (lineSum != settlementList[i].TotalAmount) + { + ErrorListAdd("Settlement header total (" + settlementList[i].TotalAmount + + ") does not match line total (" + lineSum + ")"); + } + } + } + + if (ErrorListIsSet) { return false; } + else { return true; } + } + + public bool IsValid(Model.Import.AmazonSettlement.SettlementLine settlementLine) + { + if (settlementLine.AdjustmentIdIsSet) + { + if (!IsValidAdjustmentId(settlementLine.AdjustmentId)) { } + } + + if (settlementLine.AmountIsSet) + { + if (!IsValidAmount(settlementLine.Amount)) { } + } + else + { + ErrorListAdd("Amount is a required value."); + } + + + if (settlementLine.AmountDescriptionIsSet) + { + if (!IsValidAmountDescription(settlementLine.AmountDescription)) { } + } + else + { + ErrorListAdd("Amount Description is a required value."); + } + + + if (settlementLine.AmountTypeIsSet) + { + if (!IsValidAmountType(settlementLine.AmountType)) { } + } + else + { + ErrorListAdd("Amount Type is a required value."); + } + + + if (settlementLine.CurrenyCodeIsSet) + { + if (!IsValidCurrenyCode(settlementLine.CurrenyCode)) { } + } + else + { + ErrorListAdd("Currency Code is a required value."); + } + + + if (settlementLine.ExportAccountInvoiceLineIdIsSet) + { + if (!IsValidExportAccountInvoiceLineId(settlementLine.ExportAccountInvoiceLineId)) { } + } + + if (settlementLine.FulfillmentIdIsSet) + { + if (!IsValidFulfillmentId(settlementLine.FulfillmentId)) { } + } + + if (settlementLine.IsProcessedIsSet) + { + if (!IsValidIsProcessed(settlementLine.IsProcessed)) { } + } + else + { + ErrorListAdd("Is Processed is a required value."); + } + + + if (settlementLine.MarketPlaceNameIsSet) + { + if (!IsValidMarketPlaceName(settlementLine.MarketPlaceName)) { } + } + + if (settlementLine.MerchantAdjustmentItemIdIsSet) + { + if (!IsValidMerchantAdjustmentItemId(settlementLine.MerchantAdjustmentItemId)) { } + } + + if (settlementLine.MerchantOrderIdIsSet) + { + if (!IsValidMerchantOrderId(settlementLine.MerchantOrderId)) { } + } + + if (settlementLine.MerchantOrderItemIdIsSet) + { + if (!IsValidMerchantOrderItemId(settlementLine.MerchantOrderItemId)) { } + } + + if (settlementLine.OrderIdIsSet) + { + if (!IsValidOrderId(settlementLine.OrderId)) { } + } + + if (settlementLine.OrderItemCodeIsSet) + { + if (!IsValidOrderItemCode(settlementLine.OrderItemCode)) { } + } + + if (settlementLine.PostDateTimeIsSet) + { + if (!IsValidPostDateTime(settlementLine.PostDateTime)) { } + } + else + { + ErrorListAdd("Posted DateTime is a required value."); + } + + if (settlementLine.PromotionIdIsSet) + { + if (!IsValidPromotionId(settlementLine.PromotionId)) { } + } + + if (settlementLine.QuantityPurchasedIsSet) + { + if (!IsValidQuantityPurchased(settlementLine.QuantityPurchased)) { } + } + + if (settlementLine.ShipmentIdIsSet) + { + if (!IsValidShipmentId(settlementLine.ShipmentId)) { } + } + + if (settlementLine.SkuIsSet) + { + if (!IsValidSku(settlementLine.Sku)) { } + } + + if (settlementLine.TransactionTypeIsSet) + { + if (!IsValidTransactionType(settlementLine.TransactionType)) { } + } + else + { + ErrorListAdd("Transaction Type is a required value."); + } + + if (ErrorListIsSet) { return false; } + else { return true; } + } + + public bool IsValidSettlementId(string settlementId) + { + if (!stringCheck.IsNumeric(settlementId)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid settlement Id: " + x).ToList()); + return false; + } + if (!stringCheck.MaxLength(settlementId, 50)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid settlement Id: " + x).ToList()); + return false; + } + return true; + } + + public bool IsValidIsProcessed(bool isProcessed) + { + return true; + } + + public bool IsValidMarketPlaceName(string marketPlaceName) + { + if (!stringCheck.MaxLength(marketPlaceName, 50, true)) + { + ErrorListAdd("Invalid market place name."); + return false; + } + return true; + } + + public bool IsValidStartDate(DateTime startDate) + { + if (!timeCheck.IsUtc(startDate)) + { + ErrorListAdd(timeCheck.ErrorList.Select(x => "Invalid StartDate: " + x).ToList()); + return false; + } + return true; + } + + public bool IsValidEndDate(DateTime endDate) + { + if (!timeCheck.IsUtc(endDate)) + { + ErrorListAdd(timeCheck.ErrorList.Select(x => "Invalid EndDate: " + x).ToList()); + return false; + } + return true; + } + + public bool IsValidDepositDate(DateTime depositDate) + { + if (!timeCheck.IsUtc(depositDate)) + { + ErrorListAdd(timeCheck.ErrorList.Select(x => "Invalid DepositDate: " + x).ToList()); + return false; + } + return true; + } + + public bool IsValidTotalAmount(decimal totalAmount) + { + if (!decimalCheck.SqlLength92(totalAmount)) + { + ErrorListAdd(decimalCheck.ErrorList.Select(x => "Total Amount Invalid: " + x).ToList()); + return false; + } + return true; + } + + public bool IsValidCurrencyCode(string currencyCode) + { + if (!currencyCheck.IsValidCurrencyCode(currencyCode)) + { + ErrorListAdd(currencyCheck.ErrorList.Select(x => "Total Amount CurrencyCode: " + x).ToList()); + return false; + } + return true; + } + + + + + + + + + + + + + + + + + + + public bool IsValidTransactionType(string transactionType) + { + if (!stringCheck.MaxLength(transactionType, 50)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid transaction type: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidOrderId(string orderId) + { + if (!stringCheck.MaxLength(orderId, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid order id: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidMerchantOrderId(string merchantOrderId) + { + if (!stringCheck.MaxLength(merchantOrderId, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid merchant order id: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidAdjustmentId(string adjustmentId) + { + if (!stringCheck.MaxLength(adjustmentId, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid adjustment id: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidShipmentId(string shipmentId) + { + if (!stringCheck.MaxLength(shipmentId, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid shipment id: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidAmountType(string amountType) + { + if (!stringCheck.MaxLength(amountType, 50)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid amount type: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidAmountDescription(string amountDescription) + { + if (!stringCheck.MaxLength(amountDescription, 100)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid amount description: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidAmount(decimal amount) + { + if (!decimalCheck.SqlLength92(amount)) + { + ErrorListAdd(decimalCheck.ErrorList.Select(x => "Invalid amount: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidCurrenyCode(string currenyCode) + { + if (!currencyCheck.IsValidCurrencyCode(currenyCode)) + { + ErrorListAdd(currencyCheck.ErrorList.Select(x => "Invalid curreny code: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidFulfillmentId(string fulfillmentId) + { + if (!stringCheck.MaxLength(fulfillmentId, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid fulfillment Id: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidPostDateTime(DateTime postDateTime) + { + var timeCheck = new Logic.Utilities.DateTimeCheck(); + if (!timeCheck.IsUtc(postDateTime)) + { + ErrorListAdd(@"Invalid post date/time, not set to UTC kind."); + return false; + } + return true; + } + public bool IsValidOrderItemCode(string orderItemCode) + { + if (!stringCheck.MaxLength(orderItemCode, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid order item code: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidMerchantOrderItemId(string merchantOrderItemId) + { + if (!stringCheck.MaxLength(merchantOrderItemId, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid merchant order item id: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidMerchantAdjustmentItemId(string merchantAdjustmentItemId) + { + if (!stringCheck.MaxLength(merchantAdjustmentItemId, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid merchant adjustment item id: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidSku(string skuNumber) + { + if (!stringCheck.MaxLength(skuNumber, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid sku number: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidQuantityPurchased(int quantityPurchased) + { + return true; + } + public bool IsValidPromotionId(string promotionId) + { + if (!stringCheck.MaxLength(promotionId, 50, true)) + { + ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid promotion id: " + x).ToList()); + return false; + } + return true; + } + public bool IsValidExportAccountInvoiceLineId(int exportAccountInvoiceLineId) + { + if (exportAccountInvoiceLineId > 0) + { + return true; + } + else + { + ErrorListAdd("Export account invoice line id cannot be less than 1"); + return false; + } + } + } +} diff --git a/src/bnhtrade.Core/Logic/Log/LogEvent.cs b/src/bnhtrade.Core/Logic/Log/LogEvent.cs new file mode 100644 index 0000000..ac1a34b --- /dev/null +++ b/src/bnhtrade.Core/Logic/Log/LogEvent.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Log +{ + public class LogEvent : Data.Database.Log.LogEvent + { + private DateTime? eventDateTimeUtc; + private int? eventType; + private bool? printToConsole; + public DateTime EventDateTimeUtc + { + get { return (DateTime)eventDateTimeUtc; } + set { eventDateTimeUtc = DateTime.SpecifyKind(value, DateTimeKind.Utc); } + } + private int EventType + { + get { return (int)eventType; } + set { eventType = value; } + } + private string DetailShort { get; set; } + private string DetailLong { get; set; } + public bool PrintToConsole + { + get { return (bool)printToConsole; } + set { printToConsole = value; } + } + public LogEvent() + { + EventType = 3; + PrintToConsole = true; + } + private void Execute() + { + // ensure we have enough parameter set + if (!(IsSetDetailShort + && IsSetEventType + && IsSetPrintToConsole)) + { + throw new Exception("Insurficent Log Event parameters set"); + } + + // add datetime value if required + bool resetDateTime = false; + if (!IsSetEventDateTime) + { + EventDateTimeUtc = DateTime.UtcNow; + resetDateTime = true; + } + + // update console + var console = new UI.Console.Update(); + if (!IsSetDetailLong) + { console.WriteLine(DetailShort); } + else { console.WriteLine(DetailShort + Environment.NewLine + DetailLong); } + + // log in database + DatabaseLogInsert(DetailShort, EventType, DetailLong, EventDateTimeUtc, false); // remove false on end once code is re-writtien + + // clean up + if (resetDateTime) + { eventDateTimeUtc = null; } + } + public void LogAuditFailure(string detailShort, string detailLong = null) + { + eventType = 5; + DetailShort = detailShort; + DetailLong = detailLong; + Execute(); + } + public void LogAuditSuccess(string detailShort, string detailLong = null) + { + eventType = 4; + DetailShort = detailShort; + DetailLong = detailLong; + Execute(); + } + public void LogError(string detailShort, string detailLong = null) + { + eventType = 1; + DetailShort = detailShort; + DetailLong = detailLong; + Execute(); + } + public void LogWarning(string detailShort, string detailLong = null) + { + eventType = 2; + DetailShort = detailShort; + DetailLong = detailLong; + Execute(); + } + public void LogInformation(string detailShort, string detailLong = null) + { + eventType = 3; + DetailShort = detailShort; + DetailLong = detailLong; + Execute(); + } + public void Initialise() + { + eventDateTimeUtc = null; + eventType = null; + DetailShort = null; + DetailLong = null; + PrintToConsole = true; + } + public bool IsSetEventDateTime + { + get { return eventDateTimeUtc != null; } + } + public bool IsSetEventType + { + get { return eventType != null; } + } + public bool IsSetDetailShort + { + get { return DetailShort != null; } + } + public bool IsSetDetailLong + { + get { return DetailLong != null; } + } + public bool IsSetPrintToConsole + { + get { return printToConsole != null; } + } + } +} diff --git a/src/bnhtrade.Core/Logic/Utilities/AccountVat.cs b/src/bnhtrade.Core/Logic/Utilities/AccountVat.cs new file mode 100644 index 0000000..bbfae90 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Utilities/AccountVat.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Utilities +{ + public class AccountVat + { + public decimal Round(decimal vatToRound) + { + return decimal.Round(vatToRound, 2, MidpointRounding.AwayFromZero); + } + } +} diff --git a/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs b/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs new file mode 100644 index 0000000..e5d63ac --- /dev/null +++ b/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Utilities +{ + public class DateTimeCheck : Validate + { + public bool IsUtc(DateTime dateTimeToCheck) + { + if (dateTimeToCheck == default(DateTime)) + { + ErrorListAdd( "DateTime value set to default."); + return false; + } + if (dateTimeToCheck.Kind != DateTimeKind.Utc) + { + ErrorListAdd("DateTime not set to UTC kind."); + return false; + } + return true; + } + public bool IsLocal(DateTime dateTimeToCheck) + { + if (dateTimeToCheck == default(DateTime)) + { + ErrorListAdd("DateTime value set to default."); + return false; + } + if (dateTimeToCheck.Kind != DateTimeKind.Local) + { + ErrorListAdd("DateTime not set to Local kind."); + return false; + } + return true; + } + } +} diff --git a/src/bnhtrade.Core/Logic/Utilities/DecimalCheck.cs b/src/bnhtrade.Core/Logic/Utilities/DecimalCheck.cs new file mode 100644 index 0000000..eed1d1a --- /dev/null +++ b/src/bnhtrade.Core/Logic/Utilities/DecimalCheck.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Utilities +{ + public class DecimalCheck : Validate + { + /// + /// Finds total number of digits in a decimal number, does not include decimal point. + /// + /// Decimal number to check + /// + public int GetLength(decimal decimalNumber) + { + return (decimalNumber.ToString().Length - 1); + } + /// + /// Finds total number of digits to the right of the decimal point in a decimal number. + /// + /// Decimal number to check + /// + public int GetPrecision(decimal decimalNumber) + { + return BitConverter.GetBytes(decimal.GetBits(decimalNumber)[3])[2]; + } + /// + /// Checks decimal number is match for SQL Server datatype 'decimal(9, 2)' + /// + /// Decimal number to check + /// + public bool SqlLength92(decimal decimalToCheck) + { + int precision = GetPrecision(decimalToCheck); + if (precision > 2) + { + ErrorListAdd("Decimal precision overload"); + return false; + } + int length = GetLength(decimalToCheck); + if (length > 9) + { + ErrorListAdd("Decimal length overload"); + return false; + } + return true; + } + } +} diff --git a/src/bnhtrade.Core/Logic/Utilities/PropertyCheck.cs b/src/bnhtrade.Core/Logic/Utilities/PropertyCheck.cs new file mode 100644 index 0000000..27a1541 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Utilities/PropertyCheck.cs @@ -0,0 +1,36 @@ +using System; + +namespace bnhtrade.Core.Logic.Utilities +{ + class PropertyCheck + { + public string ErrorMessage { get; set; } + public bool IsPropertyExist(dynamic classObject, string propertyName) + { + ErrorMessage = null; + + if (classObject == null) + { + throw new Exception("Object is null."); + //ErrorMessage = "Object is null."; + //return false; + } + + if (string.IsNullOrWhiteSpace(propertyName)) + { + throw new Exception("Property name is null or whitespace."); + //ErrorMessage = "Property name is null or whitespace."; + //return false; + } + + dynamic val = classObject[propertyName]; + if (object.ReferenceEquals(val, null)) + { + ErrorMessage = "Property '" + propertyName + "' does not exist in '" + classObject.GetType().Name + "'."; + return false; + } + + return true; + } + } +} diff --git a/src/bnhtrade.Core/Logic/Utilities/StringCheck.cs b/src/bnhtrade.Core/Logic/Utilities/StringCheck.cs new file mode 100644 index 0000000..b75429e --- /dev/null +++ b/src/bnhtrade.Core/Logic/Utilities/StringCheck.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Utilities +{ + public class StringCheck : Validate + { + public bool AllowEmpty { get; set; } = false; + public bool AllowWhiteSpace { get; set; } = false; + public void ResetToDefault() + { + Innit(); + AllowEmpty = false; + AllowWhiteSpace = false; + } + public bool IsAlpha(string stringToCheck, bool upperCaseOnly = false, bool allowNull = false) + { + if (stringToCheck == null) + { + if (!allowNull) + { + ErrorListAdd("String is null"); + return false; + } + } + else + { + foreach (char c in stringToCheck) + { + if (!((c >= 'A' && c <= 'Z') + || ((c >= 'a' && c <= 'z') && !upperCaseOnly))) + { + if ((c >= 'a' && c <= 'z') && upperCaseOnly) + { + ErrorListAdd("String contains lower case numerical charater(s)."); + return false; + } + else + { + ErrorListAdd("String contains non-alpha charater(s)."); + return false; + } + } + } + } + return true; + } + public bool IsAlphaNumeric(string stringToCheck, bool upperCaseOnly = false, bool allowNull = false) + { + if (stringToCheck == null) + { + if (!allowNull) + { + ErrorListAdd("String is null"); + return false; + } + } + else + { + foreach (char c in stringToCheck) + { + if (!((c >= '0' && c <= '9') + || (c >= 'A' && c <= 'Z') + || ((c >= 'a' && c <= 'z') && !upperCaseOnly))) + { + if ((c >= 'a' && c <= 'z') && upperCaseOnly) + { + ErrorListAdd("String contains lower case numerical charater(s)."); + return false; + } + else + { + ErrorListAdd("String contains non-alphanumeric charater(s)."); + return false; + } + } + } + } + return true; + } + public bool IsNumeric(string stringToCheck, bool allowNull = false) + { + if (stringToCheck == null) + { + if (allowNull == false) + { + ErrorListAdd("String is null"); + return false; + } + } + else + { + foreach (char c in stringToCheck) + { + if (c < '0' || c > '9') + { + ErrorListAdd("String contains non-numeric charater(s)."); + return false; + } + } + } + return true; + } + public bool Length(string stringToCheck, int stringLength, bool allowNull = false) + { + if (!NullOrWhiteSpaceCheck(stringToCheck, allowNull)) + { + return false; + } + + int length = stringToCheck.Length; + if (length != stringLength) + { + ErrorListAdd("String length (" + length + ") does not equal " + stringLength + " charaters."); + return false; + } + return true; + } + public bool MaxLength(string stringToCheck, int maxLength, bool allowNull = false) + { + if (!NullOrWhiteSpaceCheck(stringToCheck, allowNull)) + { + return false; + } + + if (stringToCheck != null) + { + int length = stringToCheck.Length; + if (length > maxLength) + { + ErrorListAdd("String length (" + length + ") is greater than " + maxLength + " charaters."); + return false; + } + } + return true; + } + public bool MinLength(string stringToCheck, int minLength, bool allowNull = false) + { + if (!NullOrWhiteSpaceCheck(stringToCheck, allowNull)) + { + return false; + } + + int length = stringToCheck.Length; + if (length <= minLength) + { + ErrorListAdd("String length (" + length + ") is less than " + minLength + " charaters."); + return false; + } + return true; + } + + private bool NullOrWhiteSpaceCheck(string stringToCheck, bool allowNull = false) + { + if (string.IsNullOrWhiteSpace(stringToCheck)) + { + if (stringToCheck == null) + { + if (!allowNull) + { + ErrorListAdd("String is null, empty or white space."); + return false; + } + } + else if (stringToCheck == "") + { + if (!AllowEmpty) + { + ErrorListAdd("String is empty."); + return false; + } + } + else + { + if (!AllowWhiteSpace) + { + ErrorListAdd("String is white space."); + return false; + } + } + } + return true; + } + } +} \ No newline at end of file diff --git a/src/bnhtrade.Core/Logic/Validate.cs b/src/bnhtrade.Core/Logic/Validate.cs new file mode 100644 index 0000000..6c56590 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Validate.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic +{ + public abstract class Validate + { + private List errorList = new List(); + + public List ErrorList + { + get { return errorList; } + } + + public bool ErrorListIsSet + { + get + { + if (errorList == null || !errorList.Any()) { return false; } + else { return true; } + } + } + + protected void ErrorListAdd(string errorString) + { + this.errorList.Add(errorString); + } + + protected void ErrorListAdd(List errorList) + { + this.errorList.AddRange(errorList); + } + + public string ErrorListToString() + { + if (ErrorListIsSet) + { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < ErrorList.Count; i++) + { + result.AppendLine(ErrorList[i]); + } + return result.ToString(); + } + else { return null; } + } + + public void Innit() + { + this.errorList = new List(); + } + } +} diff --git a/src/bnhtrade.Core/Model/Account/AccountCode.cs b/src/bnhtrade.Core/Model/Account/AccountCode.cs new file mode 100644 index 0000000..054a14e --- /dev/null +++ b/src/bnhtrade.Core/Model/Account/AccountCode.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Account +{ + public class AccountCode + { + private int? accountCodeId; + public int AccountCodeId + { + get { return (int)accountCodeId; } + set { accountCodeId = value; } + } + public string Title + { + get; + set; + } + public string Description + { + get; + set; + } + public string Type + { + get; + set; + } + public string BasicType + { + get; + set; + } + public bool IsSetAccountCodeId + { + get { return accountCodeId != null; } + } + public bool IsSetTitle + { + get { return Title != null; } + } + public bool IsSetDescription + { + get { return Description != null; } + } + public bool IsSetType + { + get { return Type != null; } + } + public bool IsSetBasicType + { + get { return BasicType != null; } + } + } +} diff --git a/src/bnhtrade.Core/Model/Account/Invoice.cs b/src/bnhtrade.Core/Model/Account/Invoice.cs new file mode 100644 index 0000000..e00265f --- /dev/null +++ b/src/bnhtrade.Core/Model/Account/Invoice.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Account +{ + public interface IInvoice : IInvoiceHeader + { + List InvoiceLineList { get; set; } + + bool InvoiceLineListIsSet { get; } + } + + public interface IInvoiceLine + { + string ItemCode { get; set; } + + bool ItemCodeIsSet { get; } + + bool DescriptionIsSet { get; } + + string Description { get; set; } + + int Quantity { get; set; } + + bool QuantityIsSet { get; } + + decimal TotalNetAmount { get; set; } + + bool TotalNetAmountIsSet { get; } + + bool AccountCodeIsSet { get; } + + int AccountCode { get; set; } + + bool TaxCodeIsSet { get; } + + string TaxCode { get; set; } + + decimal TaxAmountAdjust { get; set; } + + bool TaxAmountAdjustIsSet { get; } + + decimal TaxAmount { get; } + + bool TaxAmountIsSet { get; } + + decimal GrossTotalAmount { get; } + + bool GrossTotalAmountIsSet { get; } + } + + + public abstract class Invoice : InvoiceHeader, IInvoice + { + public List InvoiceLineList { get; set; } = new List(); + + public bool InvoiceLineListIsSet + { + get + { + if (InvoiceLineList == null || !InvoiceLineList.Any()) + { return false; } + else + { return true; } + } + } + + public class InvoiceLine : IInvoiceLine + { + private int? accountCode; + private decimal? netAmount; + private decimal? taxAmount; + private decimal? taxAmountAdjust; + private int? quantity; + private decimal? discount; + + public string ItemCode + { + get; + set; + } + + public bool ItemCodeIsSet + { + get { return ItemCode != null; } + } + + public string Description + { + get; + set; + } + + public bool DescriptionIsSet + { + get { return Description != null; } + } + + public int Quantity + { + get { return (int)quantity.GetValueOrDefault(); } + set { quantity = value; } + } + + public bool QuantityIsSet + { + get { return quantity != null; } + } + + public decimal TotalNetAmount + { + get { return (decimal)netAmount.GetValueOrDefault(); } + set { netAmount = value; } + } + + public bool TotalNetAmountIsSet + { + get { return netAmount != null; } + } + + public int AccountCode + { + get { return (int)accountCode.GetValueOrDefault(); } + set { accountCode = value; } + } + + public bool AccountCodeIsSet + { + get { return accountCode != null; } + } + + public string TaxCode + { + get; + set; + } + + public bool TaxCodeIsSet + { + get { return TaxCode != null; } + } + + public decimal TaxAmount + { + get { return (decimal)taxAmount.GetValueOrDefault(); } + set { taxAmount = decimal.Round(value, 2); } + } + + public bool TaxAmountIsSet + { + get { return taxAmount != null; } + } + + public decimal TaxAmountAdjust + { + get { return (decimal)taxAmountAdjust.GetValueOrDefault(); } + set { taxAmountAdjust = decimal.Round(value, 2); } + } + + public bool TaxAmountAdjustIsSet + { + get { return taxAmountAdjust != null; } + } + + public decimal GrossTotalAmount + { + get { return (decimal)netAmount.GetValueOrDefault() + TaxAmount; } + } + + public bool GrossTotalAmountIsSet + { + get { return (TotalNetAmountIsSet && TaxAmountIsSet); } + } + } + } +} diff --git a/src/bnhtrade.Core/Model/Account/InvoiceHeader.cs b/src/bnhtrade.Core/Model/Account/InvoiceHeader.cs new file mode 100644 index 0000000..895b1b6 --- /dev/null +++ b/src/bnhtrade.Core/Model/Account/InvoiceHeader.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Account +{ + public interface IInvoiceHeader + { + string ContactName { get; set; } + bool ContactNameIsSet { get; } + decimal InvoiceAmount { get; set; } + bool InvoiceAmountIsSet { get; } + string InvoiceCurrencyCode { get; set; } + bool InvoiceCurrencyCodeIsSet { get; } + DateTime InvoiceDate { get; set; } + bool InvoiceDateIsSet { get; } + DateTime InvoiceDueDate { get; set; } + bool InvoiceDueDateIsSet { get; } + DateTimeKind InvoiceDateKind { get; set; } + bool InvoiceDateKindIsSet { get; } + string InvoiceNumber { get; set; } + bool InvoiceNumberIsSet { get; } + string InvoiceReference { get; set; } + bool InvoiceReferenceIsSet { get; } + bool IsCreditNote { get; set; } + bool IsCreditNoteIsSet { get; } + } + + public abstract class InvoiceHeader : IInvoiceHeader + { + private string invoiceCurrencyCode; + private DateTime? invoiceDate; + private DateTime? invoiceDueDate; + private DateTimeKind? invoiceDateKind = DateTimeKind.Utc; + private decimal? invoiceAmount; + + public InvoiceHeader() + { + IsCreditNote = false; + } + + public string ContactName { get; set; } + + public bool ContactNameIsSet + { + get { return ContactName != null; } + } + + public DateTime InvoiceDate + { + get { return (DateTime)invoiceDate.GetValueOrDefault(); } + set { invoiceDate = value; } + } + + public bool InvoiceDateIsSet + { + get { return invoiceDate != null; } + } + + public DateTime InvoiceDueDate + { + get { return (DateTime)invoiceDueDate.GetValueOrDefault(); } + set { invoiceDueDate = value; } + } + + public bool InvoiceDueDateIsSet + { + get { return invoiceDueDate != null; } + } + + public DateTimeKind InvoiceDateKind + { + get { return (DateTimeKind)invoiceDateKind; } + set { invoiceDateKind = value; } + } + + public bool InvoiceDateKindIsSet + { + get { return invoiceDateKind != null; } + } + + public string InvoiceCurrencyCode + { + get { return invoiceCurrencyCode; } + set + { + if (!string.IsNullOrWhiteSpace(value)) + { + invoiceCurrencyCode = value.ToUpper(); + } + } + } + + public bool InvoiceCurrencyCodeIsSet + { + get { return InvoiceCurrencyCode != null; } + } + + public string InvoiceNumber { get; set; } + + public bool InvoiceNumberIsSet + { + get { return InvoiceNumber != null; } + } + + public string InvoiceReference { get; set; } + + public bool InvoiceReferenceIsSet + { + get { return InvoiceReference != null; } + } + + public decimal InvoiceAmount + { + get { return (decimal)invoiceAmount; } + set { invoiceAmount = value; } + } + + public bool InvoiceAmountIsSet + { + get { return invoiceAmount != null; } + } + public bool IsCreditNote + { + get; + set; + } + public bool IsCreditNoteIsSet + { + get { return true; } + } + } +} diff --git a/src/bnhtrade.Core/Model/Account/InvoiceLineItem.cs b/src/bnhtrade.Core/Model/Account/InvoiceLineItem.cs new file mode 100644 index 0000000..83dd0df --- /dev/null +++ b/src/bnhtrade.Core/Model/Account/InvoiceLineItem.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Account +{ + public class InvoiceLineItem + { + public string ItemCode + { + get; + set; + } + public string Title + { + get; + set; + } + public string Description + { + get; + set; + } + public bool IsNewReviewRequired + { + get; + set; + } + public bool InvoiceLineEntryEnabled + { + get; + set; + } + public int DefaultAccountCode + { + get; + set; + } + public string DefaultTaxCode + { + get; + set; + } + } +} diff --git a/src/bnhtrade.Core/Model/Account/SalesInvoice.cs b/src/bnhtrade.Core/Model/Account/SalesInvoice.cs new file mode 100644 index 0000000..02d522c --- /dev/null +++ b/src/bnhtrade.Core/Model/Account/SalesInvoice.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Account +{ + public class SalesInvoice : Invoice + { + + } +} \ No newline at end of file diff --git a/src/bnhtrade.Core/Model/Account/TaxCode.cs b/src/bnhtrade.Core/Model/Account/TaxCode.cs new file mode 100644 index 0000000..bbd4588 --- /dev/null +++ b/src/bnhtrade.Core/Model/Account/TaxCode.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Account +{ + public class TaxCode + { + private decimal? netAmountMultiplier = null; + private decimal? grossAmountMultiplier = null; + private bool? isActive = null; + private bool? isValidOnExpense = null; + private bool? isValidOnIncome = null; + + public string TaxCodeId { get; set; } + public string TaxRateDescription { get; set; } + public string TaxRateTitle { get; set; } + public string TaxType { get; set; } + public decimal NetAmountMultiplier + { + get { return (decimal)netAmountMultiplier; } + set { netAmountMultiplier = value; } + } + public decimal GrossAmountMultiplier + { + get { return (decimal)grossAmountMultiplier; } + set { grossAmountMultiplier = value; } + } + public bool IsActive + { + get { return (bool)isActive; } + set { isActive = value; } + } + public bool IsSetAll + { + get + { + if (IsSetGrossAmountMultiplier + && IsSetIsActive + && IsSetIsValidOnExpense + && IsSetIsValidOnIncome + && IsSetNetAmountMultiplier + && IsSetTaxCodeId + && IsSetTaxRateTitle + && IsSetTaxRateDescription + ) + { + return true; + } + else { return false; } + } + } + public bool IsSetGrossAmountMultiplier + { + get { return grossAmountMultiplier != null; } + } + public bool IsSetIsActive + { + get { return isActive != null; } + } + public bool IsSetIsValidOnExpense + { + get { return isValidOnExpense != null; } + } + public bool IsSetIsValidOnIncome + { + get { return isValidOnIncome != null; } + } + public bool IsSetNetAmountMultiplier + { + get { return netAmountMultiplier != null; } + } + public bool IsSetTaxCodeId + { + get { return TaxCodeId != null; } + } + public bool IsSetTaxRateTitle + { + get { return TaxRateTitle != null; } + } + public bool IsSetTaxRateDescription + { + get { return TaxRateDescription != null; } + } + public bool IsSetTaxType + { + get { return TaxType != null; } + } + public bool IsValidOnExpense + { + get { return (bool)isValidOnExpense; } + set { isValidOnExpense = value; } + } + public bool IsValidOnIncome + { + get { return (bool)isValidOnIncome; } + set { isValidOnIncome = value; } + } + } +} diff --git a/src/bnhtrade.Core/Model/Import/AmazonSettlement.cs b/src/bnhtrade.Core/Model/Import/AmazonSettlement.cs new file mode 100644 index 0000000..0b42c36 --- /dev/null +++ b/src/bnhtrade.Core/Model/Import/AmazonSettlement.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Import +{ + public class AmazonSettlement : AmazonSettlementHeader + { + public List SettlementLineList { get; set; } = new List(); + + public bool SettlementLineListIsSet + { + get + { + if (SettlementLineList == null || !SettlementLineList.Any()) + { return false; } + else + { return true; } + } + } + + public class SettlementLine + { + private decimal? amount = null; + private DateTime? postDateTime = null; + private int? quantityPurchased = null; + private bool? isProcessed = null; + private int? exportAccountInvoiceLineId = null; + + public string TransactionType { get; set; } + + public bool TransactionTypeIsSet + { + get { return TransactionType != null; } + } + + public string OrderId { get; set; } + + public bool OrderIdIsSet + { + get { return OrderId != null; } + } + + public string MerchantOrderId { get; set; } + + public bool MerchantOrderIdIsSet + { + get { return MerchantOrderId != null; } + } + + public string AdjustmentId { get; set; } + + public bool AdjustmentIdIsSet + { + get { return AdjustmentId != null; } + } + + public string ShipmentId { get; set; } + + public bool ShipmentIdIsSet + { + get { return ShipmentId != null; } + } + + public string MarketPlaceName { get; set; } + + public bool MarketPlaceNameIsSet + { + get { return MarketPlaceName != null; } + } + + public string AmountType { get; set; } + + public bool AmountTypeIsSet + { + get { return AmountType != null; } + } + + public string AmountDescription { get; set; } + + public bool AmountDescriptionIsSet + { + get { return AmountDescription != null; } + } + + public decimal Amount + { + get { return (decimal)amount.GetValueOrDefault(); } + set { amount = value; } + } + + public bool AmountIsSet + { + get { return amount != null; } + } + + public string CurrenyCode { get; set; } + + public bool CurrenyCodeIsSet + { + get { return CurrenyCode != null; } + } + + public string FulfillmentId { get; set; } + + public bool FulfillmentIdIsSet + { + get { return FulfillmentId != null; } + } + + public DateTime PostDateTime + { + get { return (DateTime)postDateTime.GetValueOrDefault(); } + set { postDateTime = value; } + } + + public bool PostDateTimeIsSet + { + get { return PostDateTime != null; } + } + + public string OrderItemCode { get; set; } + + public bool OrderItemCodeIsSet + { + get { return OrderItemCode != null; } + } + + public string MerchantOrderItemId { get; set; } + + public bool MerchantOrderItemIdIsSet + { + get { return MerchantOrderItemId != null; } + } + + public string MerchantAdjustmentItemId { get; set; } + + public bool MerchantAdjustmentItemIdIsSet + { + get { return MerchantAdjustmentItemId != null; } + } + + public string Sku { get; set; } + + public bool SkuIsSet + { + get { return Sku != null; } + } + + public int QuantityPurchased + { + get { return (int)quantityPurchased.GetValueOrDefault(); } + set { quantityPurchased = value; } + } + + public bool QuantityPurchasedIsSet + { + get { return quantityPurchased != null; } + } + + public string PromotionId { get; set; } + + public bool PromotionIdIsSet + { + get { return PromotionId != null; } + } + + public bool IsProcessed + { + get { return (bool)isProcessed.GetValueOrDefault(); } + set { isProcessed = value; } + } + + public bool IsProcessedIsSet + { + get { return isProcessed != null; } + } + + public int ExportAccountInvoiceLineId + { + get { return exportAccountInvoiceLineId.GetValueOrDefault(); } + set { exportAccountInvoiceLineId = value; } + } + + public bool ExportAccountInvoiceLineIdIsSet + { + get { return exportAccountInvoiceLineId != null; } + } + } + } +} diff --git a/src/bnhtrade.Core/Model/Import/AmazonSettlementHeader.cs b/src/bnhtrade.Core/Model/Import/AmazonSettlementHeader.cs new file mode 100644 index 0000000..14c45eb --- /dev/null +++ b/src/bnhtrade.Core/Model/Import/AmazonSettlementHeader.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Import +{ + public class AmazonSettlementHeader + { + private DateTime? startDate = null; + private DateTime? endDate = null; + private DateTime? depositDate = null; + private decimal? totalAmount = null; + private bool? isProcessed = null; + + public string MarketPlaceName + { + get; + set; + } + + public bool MarketPlaceNameIsSet + { + get { return MarketPlaceName != null; } + } + + public string SettlementId + { + get; + set; + } + + public bool SettlementIdIsSet + { + get { return SettlementId != null; } + } + + public DateTime StartDate + { + get { return (DateTime)startDate.GetValueOrDefault(); } + set { startDate = value; } + } + + public bool StartDateIsSet + { + get { return startDate != null; } + } + + public DateTime EndDate + { + get { return (DateTime)endDate.GetValueOrDefault(); } + set { endDate = value; } + } + + public bool EndDateIsSet + { + get { return endDate != null; } + } + + public DateTime DepositDate + { + get { return (DateTime)depositDate.GetValueOrDefault(); } + set { depositDate = value; } + } + + public bool DepositDateIsSet + { + get { return depositDate != null; } + } + + public decimal TotalAmount + { + get { return (decimal)totalAmount.GetValueOrDefault(); } + set { totalAmount = value; } + } + + public bool TotalAmountIsSet + { + get { return totalAmount != null; } + } + + public string CurrencyCode + { + get; + set; + } + + public bool CurrencyCodeIsSet + { + get { return CurrencyCode != null; } + } + + + public bool IsProcessed + { + get { return (bool)isProcessed.GetValueOrDefault(); } + set { isProcessed = value; } + } + + public bool IsProcessedIsSet + { + get { return isProcessed != null; } + } + } +} diff --git a/src/bnhtrade.Core/Model/SKU/SKUInfo.cs b/src/bnhtrade.Core/Model/SKU/SKUInfo.cs deleted file mode 100644 index e281118..0000000 --- a/src/bnhtrade.Core/Model/SKU/SKUInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Model.SKU -{ - class SKUInfo - { - public string SkuNumber { get; set; } - public string AmazonFNSKU { get; set; } - public bool IsActive { get; set; } - } -} diff --git a/src/bnhtrade.Core/Model/SKU/Sku.cs b/src/bnhtrade.Core/Model/SKU/Sku.cs new file mode 100644 index 0000000..d87eabb --- /dev/null +++ b/src/bnhtrade.Core/Model/SKU/Sku.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Sku +{ + public class Sku + { + private bool? isActive; + public string ConditionModelPlaceholder + { + get; + set; + } + public string ProductModelPlaceholder + { + get; + set; + } + public string SkuNumber + { + get; + set; + } + public Account.TaxCode TaxCode + { + get; + set; + } + public string AmazonFNSKU + { + get; + set; + } + public bool IsActive + { + get { return (bool)isActive; } + set { isActive = value; } + } + public bool IsSetConditionModelPlaceholder + { + get { return ConditionModelPlaceholder != null; } + } + public bool IsSetProductModelPlaceholder + { + get { return ProductModelPlaceholder != null; } + } + public bool IsSetSkuNumber + { + get { return SkuNumber != null; } + } + public bool IsSetTaxCode + { + get { return TaxCode != null; } + } + public bool IsSetAmazonFNSKU + { + get { return AmazonFNSKU != null; } + } + public bool IsSetIsActive + { + get { return isActive != null; } + } + + } +} diff --git a/src/bnhtrade.Core/Program.cs b/src/bnhtrade.Core/Program.cs index 33c0513..b78b2b2 100644 --- a/src/bnhtrade.Core/Program.cs +++ b/src/bnhtrade.Core/Program.cs @@ -289,220 +289,7 @@ namespace bnhtrade.Core } } } - namespace Export - { - public class ExportQuery - { - public static int WIP_ExportAccountInvoiceInsert(string sqlConnectionString, int invoiceTypeId, string contact, DateTime invoiceDate, - DateTime invoiceDueDate, string reference, string currencyCode, string invoiceNumber = "", bool markComplete = false) - { - //checks - if (currencyCode.Length != 3) - { - throw new Exception("Incorrect currency code"); - } - - // onto business - using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString)) - { - sqlConn.Open(); - - using (SqlCommand cmd = new SqlCommand(@" - INSERT INTO tblExportAccountInvoice - (ExportAccountInvoiceTypeID, Contact, InvoiceDate, InvoiceDueDate, InvoiceNumber, Reference, CurrencyCode, IsComplete) - OUTPUT - INSERTED.ExportAccountInvoiceID - VALUES - (@invoiceTypeId, @contact, @invoiceDate, @invoiceDueDate, @invoiceNumber, @reference, @currencyCode, @markComplete); - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@invoiceTypeId", invoiceTypeId); - cmd.Parameters.AddWithValue("@contact", contact); - cmd.Parameters.AddWithValue("@invoiceDate", invoiceDate); - cmd.Parameters.AddWithValue("@invoiceDueDate", invoiceDueDate); - cmd.Parameters.AddWithValue("@reference", reference); - cmd.Parameters.AddWithValue("@currencyCode", currencyCode); - //cmd.Parameters.AddWithValue("@invoiceTotal", invoiceTotal); - cmd.Parameters.AddWithValue("@markComplete", markComplete); - if (invoiceNumber == "") - { cmd.Parameters.AddWithValue("@invoiceNumber", DBNull.Value); } - else - { cmd.Parameters.AddWithValue("@invoiceNumber", invoiceNumber); } - - return (int)cmd.ExecuteScalar(); - } - } - } - - // function returns Id of inserted line, 0 for lineInsert disabled, exception for IsNew - public static int WIP_ExportAccountInvoiceLineInsert(string sqlConnectionString, int invoiceId, int invoiceLineTypeId, - decimal netAmount, decimal taxAmount) - { - int netAccountId; - int taxAccountId; - - // get default net and tax account IDs - // suppress any ambient transactions, can cause locks on table inserts - using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress)) - using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString)) - { - sqlConn.Open(); - - using (SqlCommand cmd = new SqlCommand(@" - SELECT - IsNewReviewRequired, InvoiceLineEntryEnable, AccountChartOfID_Default, AccountTaxCodeID_Default - FROM - tblExportAccountInvoiceLineType - WHERE - ExportAccountInvoiceLineTypeID=@invoiceLineTypeId; - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@invoiceLineTypeId", invoiceLineTypeId); - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - // checks - if (reader.GetBoolean(0) == true) - { - throw new Exception("New Type requires review where ExportAccountInvoiceLineTypeID=" + invoiceLineTypeId); - } - //// any invoice lines that shouldn't be entered will be taken out after the fact - //if (reader.GetBoolean(1) == false) - //{ - // return 0; - //} - if (reader.IsDBNull(2) || reader.IsDBNull(3)) - { - throw new Exception("Default account values missing where ExportAccountInvoiceLineTypeID=" + invoiceLineTypeId); - } - - netAccountId = reader.GetInt32(2); - taxAccountId = reader.GetInt32(3); - } - else - { - throw new Exception("Supplied TypeId does not exist in table, where ExportAccountInvoiceLineTypeID=" + invoiceLineTypeId); - } - } - } - scope.Complete(); - } - - using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString)) - { - sqlConn.Open(); - - // insert record - using (SqlCommand cmd = new SqlCommand(@" - INSERT INTO tblExportAccountInvoiceLine - (ExportAccountInvoiceID, ExportAccountInvoiceLineTypeID, NetAmount, AccountChartOfID, TaxAmount, AccountTaxCodeID) - OUTPUT - INSERTED.ExportAccountInvoiceLineID - VALUES - (@invoiceId, @invoiceLineTypeId, @netAmount, @netAccountId, @taxAmount, @taxAccountId); - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@invoiceID", invoiceId); - cmd.Parameters.AddWithValue("@invoiceLineTypeID", invoiceLineTypeId); - cmd.Parameters.AddWithValue("@netAmount", netAmount); - cmd.Parameters.AddWithValue("@netAccountId", netAccountId); - cmd.Parameters.AddWithValue("@taxAmount", taxAmount); - cmd.Parameters.AddWithValue("@taxAccountId", taxAccountId); - - return (int)cmd.ExecuteScalar(); - } - } - - } - - public static int WIP_GetImportInvoiceLineTypeId(string sqlConnectionString, string matchString) - { - /* GetStockTransactionTypeId return meanings - * >0 use the as the TypeId when inserting transaction - * 0 Skip transpose, type is new or has not been reviewed yet */ - - if (matchString.Length == 0) - { - throw new Exception("Matchstring is of zero lenth"); - } - - bool insertNew = false; - using (TransactionScope scopeSupress = new TransactionScope(TransactionScopeOption.Suppress)) - using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString)) - { - sqlConn.Open(); - - using (SqlCommand cmd = new SqlCommand(@" - SELECT ExportAccountInvoiceLineTypeID, IsNewReviewRequired, InvoiceLineEntryEnable - FROM tblExportAccountInvoiceLineType - WHERE MatchString=@matchString; - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@matchString", matchString); - - using (SqlDataReader reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - int transactionTypeId = reader.GetInt32(0); - bool isNew = reader.GetBoolean(1); - bool? importEnabled = reader.GetBoolean(2); - - if (isNew == true) - { - // return null and 'skip' item - return 0; - } - //else if (importEnabled == false) - //{ - // // mark IsProcessed=true and leave transactionId=null - // return -1; - //} - else if (transactionTypeId > 0) - { - return transactionTypeId; - } - else - { - throw new Exception("Account TransactionTypeId lookup method went wrong, is one of the 'enabled' boolean on table set to null?"); - } - } - else - { - insertNew = true; - } - } - } - - // insert new and retrive new value, if required - if (insertNew) - { - - using (SqlCommand insertCmd = new SqlCommand( - "INSERT INTO tblExportAccountInvoiceLineType ( TypeTitle, MatchString ) " + - "OUTPUT INSERTED.ExportAccountInvoiceLineTypeID " + - "VALUES ( @typeTitle, @matchString );" - , sqlConn)) - { - insertCmd.Parameters.AddWithValue("@typeTitle", "NEW TYPE"); - insertCmd.Parameters.AddWithValue("@matchString", matchString); - - int transactionTypeId = (int)insertCmd.ExecuteScalar(); - - scopeSupress.Complete(); - } - return 0; - } - else - { - throw new Exception("This is only here so 'all code paths return a value', this can never be reached!"); - } - } - } - } - } + namespace Purchase { public class PurchaseQuery @@ -3541,6 +3328,8 @@ namespace bnhtrade.Core public DateTime LastItemDateTime { get; set; } } + + // downloads new inventory data from mws and updates stock import tables public void UpdateFbaStockImportData(string sqlConnectionString) { @@ -3616,559 +3405,6 @@ namespace bnhtrade.Core } } - public void WIP_ProcessAmazonSettlementData(string sqlConnectionString) - { - - MiscFunction.EventLogInsert("Starting import of Amazon settlement data into account transaction table..."); - int reportCount = 0; - int reportLineCount = 0; - int lineCount = 0; - - using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString)) - { - sqlConn.Open(); - - try - { - // test wether there are records to process - using (SqlCommand cmd = new SqlCommand(@" - SELECT - Count(ImportAmazonSettlementReportID) AS CountOfID - FROM - tblImportAmazonSettlementReport - WHERE - (((tblImportAmazonSettlementReport.IsProcessed)=0)); - ", sqlConn)) - { - int records = (int)cmd.ExecuteScalar(); - - if (records == 0) - { - MiscFunction.EventLogInsert("No new settlements to process, exiting import..."); - return; - } - } - - // ensure settlement lines have not been processed or had transactions added - using (SqlCommand cmd = new SqlCommand(@" - SELECT - Count(tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID) AS CountOfID - FROM - tblImportAmazonSettlementReportLine - INNER JOIN tblImportAmazonSettlementReport - ON tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportID = tblImportAmazonSettlementReport.ImportAmazonSettlementReportID - WHERE - (((tblImportAmazonSettlementReport.IsProcessed)=0) AND ((tblImportAmazonSettlementReportLine.AccountTransactionID) Is Not Null)) - OR (((tblImportAmazonSettlementReport.IsProcessed)=0) AND ((tblImportAmazonSettlementReportLine.IsProcessed)=1)); - ", sqlConn)) - { - int count = Convert.ToInt32(cmd.ExecuteScalar()); - if (count != 0) - { - throw new Exception("Error, " + count + " settlement report lines have transactionId/IsProcessed set on an unprocessed settlement"); - } - } - - // build dictionary of SKU's and Vat type - var dicSkuToTaxCodeId = new Dictionary(); - - using (SqlCommand cmd = new SqlCommand(@" - SELECT - tblImportAmazonSettlementReportLine.sku, - tblSku.AccountTaxCodeID - FROM - (tblImportAmazonSettlementReport INNER JOIN tblImportAmazonSettlementReportLine - ON tblImportAmazonSettlementReport.ImportAmazonSettlementReportID = tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportID) - INNER JOIN tblSku ON tblImportAmazonSettlementReportLine.sku = tblSku.skuSkuNumber - WHERE - (((tblImportAmazonSettlementReport.IsProcessed)=0)) - GROUP BY - tblImportAmazonSettlementReportLine.sku, - tblSku.AccountTaxCodeID; - ", sqlConn)) - { - int i = 0; - using (var reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - i = i + 1; - Console.Write("\rBuilding SKU list... " + i); - dicSkuToTaxCodeId.Add(reader.GetString(0), reader.GetByte(1)); - } - } - } - - // get list of unprocessed settlements to loop thorugh - using (SqlCommand selectCmd = new SqlCommand(@" - SELECT * FROM tblImportAmazonSettlementReport - WHERE IsProcessed=0 - ORDER BY [settlement-end-date] - ", sqlConn)) - using (var reader = selectCmd.ExecuteReader()) - { - int index01 = reader.GetOrdinal("ImportAmazonSettlementReportID"); - int index02 = reader.GetOrdinal("settlement-id"); - int index03 = reader.GetOrdinal("settlement-end-date"); - int index04 = reader.GetOrdinal("total-amount"); - int index05 = reader.GetOrdinal("currency"); - int index06 = reader.GetOrdinal("marketplace-name"); - int index07 = reader.GetOrdinal("deposit-date"); - - while (reader.Read()) - { - reportCount = reportCount + 1; - string consoleLine = "\rProcessing report #" + reportCount + " "; - Console.Write("\r "); - Console.Write(consoleLine); - - int settlementId = reader.GetInt32(index01); - string settlementRef = reader.GetString(index02); - DateTime settlementEndDate = DateTime.SpecifyKind(reader.GetDateTime(index03), DateTimeKind.Utc); - decimal settlementAmount = reader.GetDecimal(index04); - string currency = reader.GetString(index05); - DateTime depositDate = DateTime.SpecifyKind(reader.GetDateTime(index07), DateTimeKind.Utc); - string marketPlace = ""; - List insertedInvoiceIds = new List(); - - // test marketplace-name has been sucsessfully entered into settlement table -- - // this is not supplied in the original report from Amazon and has to be inferred from settlement line data - if (!reader.IsDBNull(index06)) - { - marketPlace = reader.GetString(index06); - } - else - { - MiscFunction.EventLogInsert( - "Action required: Enter market place name for settlelment report (ImportAmazonSettlementReportID=" + settlementId + ")." - , 1 - , "Unable to process settlement data from one settlement report '"+ settlementRef + - "'. 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." - ); - reportCount = reportCount - 1; - continue; - } - - // build list of cut off dates (multiple when date range straddles two months) - DateTime maxDate; - DateTime minDate; - List dateList = new List(); - - using (SqlCommand cmd = new SqlCommand(@" - SELECT Max([posted-date-time]) AS ReturnDate - FROM tblImportAmazonSettlementReportLine - WHERE ImportAmazonSettlementReportID=@settlementReportId; - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@settlementReportId", settlementId); - - maxDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc); - } - - using (SqlCommand cmd = new SqlCommand(@" - SELECT Min([posted-date-time]) AS ReturnDate - FROM tblImportAmazonSettlementReportLine - WHERE ImportAmazonSettlementReportID=@settlementReportId; - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@settlementReportId", settlementId); - - minDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc); - } - - for (int i = 1; true; i++) - { - DateTime splitDate = new DateTime(minDate.Year, minDate.Month, 1, 0, 0, 0, DateTimeKind.Utc); - splitDate = splitDate.AddMonths(i); - splitDate = splitDate.AddSeconds(-1); - if (splitDate < maxDate) - { - dateList.Add(splitDate); - } - else - { - dateList.Add(maxDate); - break; - } - if (i > 10) - { - throw new Exception("Error when building Date list, too many loops."); - } - } - - // shouldn't normally be more than 2 date ranges - if (dateList.Count > 2 || dateList.Count == 0) - { - MiscFunction.EventLogInsert( - dateList.Count + " total numner of items in date list (ImportAmazonSettlementReportID=" + settlementId + ")." - , 1, - "Settlement period appears to span more 3 months or more. Whilst this is possible, it is unsual. Confirm his is correct."); - } - - // loop through settlement lines - using (SqlConnection transConn = new SqlConnection(sqlConnectionString)) - using (TransactionScope scope = new TransactionScope()) - { - transConn.Open(); - - decimal settlementLineTotal = 0; - - for (int i = 0; i < dateList.Count; i++) - { - Console.Write("\r "); - Console.Write(consoleLine + "- creating export invoice and invoice lines..."); - - //setup dictionaries for this round - var dicMatchToLineType = new Dictionary(); - var dicSettlementLineToLineType = new Dictionary(); - var dicLineTypeTotal = new Dictionary(); - //var dicTransTypeToJournal = new Dictionary(); - var dicLineTypeToLineId = new Dictionary(); - - using (SqlCommand cmd = new SqlCommand(@" - SELECT - tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID, - tblImportAmazonSettlementReportLine.[transaction-type], - tblImportAmazonSettlementReportLine.[amount-type], - tblImportAmazonSettlementReportLine.[amount-description], - tblImportAmazonSettlementReportLine.amount, - tblImportAmazonSettlementReportLine.currency, - tblImportAmazonSettlementReportLine.sku - FROM - tblImportAmazonSettlementReportLine - WHERE - (((tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportID)=@settlementReportId) - AND ((tblImportAmazonSettlementReportLine.[posted-date-time])<=@maxDate) - AND tblImportAmazonSettlementReportLine.IsProcessed=0); - ", transConn)) - { - cmd.Parameters.AddWithValue("@settlementReportId", settlementId); - cmd.Parameters.AddWithValue("@maxDate", dateList[i].ToUniversalTime()); - - using (var readerLine = cmd.ExecuteReader()) - { - // settlement period can, on occasion, span multiple months. Some months having no transactions - // account for this here - if (!readerLine.HasRows) - { continue; } - - while (readerLine.Read()) - { - reportLineCount = reportLineCount + 1; - - int settlementLineId = readerLine.GetInt32(0); - string match01 = readerLine.GetString(1); - string match02 = readerLine.GetString(2); - string match03 = readerLine.GetString(3); - decimal lineAmount = readerLine.GetDecimal(4); - string lineCurrency = readerLine.GetString(5); - string lineSku = ""; - if (!readerLine.IsDBNull(6)) - { - lineSku = readerLine.GetString(6); - } - - // double check currency matches settlement parent table - if (lineCurrency != currency) - { - throw new Exception("Currency code of settlement-line does not match parent settlement (ImportAmazonReportSettlementID=" + settlementId + ")."); - } - - // get transaction type id for line - // build the match string - // NB special case for global accounting sale and refunds (also note Goodlwill is included) and sku's where tax is included - string matchString = "<" + match01 + "><" + match02 + ">"; - if ((match01 == "Order" || match01 == "Refund") && match02 == "ItemPrice" && (match03 == "Principal" || match03 == "Goodwill" || match03 == "Tax")) - { - if (lineSku == "") - { - throw new Exception("Could not retrive Sku from SettleLineId=" + settlementLineId); - } - - if (match03 == "Goodwill") - { - matchString = matchString + ""; - } - else - { - matchString = matchString + "<" + match03 + ">"; - } - - if (dicSkuToTaxCodeId.ContainsKey(lineSku)) - { - matchString = matchString + ""; - } - else - { - throw new Exception("Sku '" + lineSku + "' not found in dictionary list."); - } - } - else - { - matchString = matchString + "<" + match03 + ">"; - } - - // get/set linetypeid - int lineTypeId = 0; - if (dicMatchToLineType.ContainsKey(matchString)) - { - lineTypeId = dicMatchToLineType[matchString]; - } - else - { - lineTypeId = Export.ExportQuery.WIP_GetImportInvoiceLineTypeId(sqlConnectionString, matchString); - // new type item, requires review before continue - if (lineTypeId == 0) - { - MiscFunction.EventLogInsert("New type found for Export Invoice Line Type. Update table!", 1, matchString, - DateTime.UtcNow, true); - return; - } - - dicMatchToLineType.Add(matchString, lineTypeId); - } - - // line type amount total & invoice total - if (dicLineTypeTotal.ContainsKey(lineTypeId)) - { - dicLineTypeTotal[lineTypeId] = dicLineTypeTotal[lineTypeId] + lineAmount; - } - else - { - dicLineTypeTotal.Add(lineTypeId, lineAmount); - } - - // set line type for settlement report line - dicSettlementLineToLineType.Add(settlementLineId, lineTypeId); - } - } - } - - // finish looping though settlement records (building dictionaries) - - // build info for invoice header - - // set transaction/journal entry date, if last in dateList use settlement end date (minus 1 second) - DateTime invoiceDate; - if ((i + 1) == dateList.Count) - { - invoiceDate = DateTime.SpecifyKind(settlementEndDate, DateTimeKind.Utc); - invoiceDate = invoiceDate.AddSeconds(-1); - } - else - { - invoiceDate = DateTime.SpecifyKind(dateList[i], DateTimeKind.Utc); - } - - //// set invoice total - //decimal invoiceTotal = 0; - //foreach (KeyValuePair entry in dicLineTypeTotal) - //{ - // invoiceTotal = invoiceTotal + entry.Value; - //} - - - // insert invoice header details - int invoiceId = Core.Export.ExportQuery.WIP_ExportAccountInvoiceInsert(sqlConnectionString, - 2, marketPlace, invoiceDate, depositDate, settlementRef, currency, ""); - insertedInvoiceIds.Add(invoiceId); - - // insert invoice lines - foreach (KeyValuePair entry in dicLineTypeTotal) - { - int lineId = Core.Export.ExportQuery.WIP_ExportAccountInvoiceLineInsert(sqlConnectionString, - invoiceId, entry.Key, entry.Value, 0); - if (lineId < 1) - { - throw new Exception("Error inserting invoice line"); - } - lineCount = lineCount + 1; - - // add lineId to transtypeId dictionary - dicLineTypeToLineId.Add(entry.Key, lineId); - } - - // update settlement lines with lineIds (if required) and IsProcessed - Console.Write("\r "); - Console.Write(consoleLine + "- Updating settlement report tables..."); - - foreach (KeyValuePair entry in dicSettlementLineToLineType) - { - using (SqlCommand cmd = new SqlCommand(@" - UPDATE - tblImportAmazonSettlementReportLine - SET - tblImportAmazonSettlementReportLine.ExportAccountInvoiceLineID=@lineId, - tblImportAmazonSettlementReportLine.IsProcessed=1 - WHERE - (((tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID)=@reportLineId)); - ", transConn)) - { - cmd.Parameters.AddWithValue("@reportLineId", entry.Key); - - int lineId = dicLineTypeToLineId[entry.Value]; - if (lineId == -1) { cmd.Parameters.AddWithValue("@lineId", DBNull.Value); } - else { cmd.Parameters.AddWithValue("@lineId", lineId); } - - cmd.ExecuteNonQuery(); - } - } - - // total for settlement check (total of commited transactions) - foreach (KeyValuePair entry in dicLineTypeTotal) - { - settlementLineTotal = settlementLineTotal + entry.Value; - } - } - // finish looping through settlement date splits - - // set settlement report to IsProcessed - - using (SqlCommand cmd = new SqlCommand(@" - UPDATE - tblImportAmazonSettlementReport - SET - tblImportAmazonSettlementReport.IsProcessed=1 - WHERE - (((tblImportAmazonSettlementReport.ImportAmazonSettlementReportID)=@settlementId)); - ", transConn)) - { - cmd.Parameters.AddWithValue("@settlementId", settlementId); - - cmd.ExecuteNonQuery(); - } - - // checks before commiting transactions for settlement - if (settlementLineTotal != settlementAmount) - { - throw new Exception("Totals of inserted transactions do not match settlement amount"); - } - - // Final stage, invoice post processing - // - // remove invoice lines with LineType invoice entry disabled - int invoiceRemoved = 0; - int invoiceLinesRemoved = 0; - - // build sqlPostfix - string sqlPostfix = ""; - foreach (int invoiceId in insertedInvoiceIds) - { - sqlPostfix = sqlPostfix + @" - OR (ExportAccountInvoiceID = " + invoiceId + ")"; - } - sqlPostfix = sqlPostfix + ")"; - - // remove invoice line id from settlement line table - string sql = @" - UPDATE tblImportAmazonSettlementReportLine - SET ExportAccountInvoiceLineID = NULL - FROM tblImportAmazonSettlementReportLine - INNER JOIN tblExportAccountInvoiceLine ON tblImportAmazonSettlementReportLine.ExportAccountInvoiceLineID = tblExportAccountInvoiceLine.ExportAccountInvoiceLineID - INNER JOIN tblExportAccountInvoiceLineType ON tblExportAccountInvoiceLine.ExportAccountInvoiceLineTypeID = tblExportAccountInvoiceLineType.ExportAccountInvoiceLineTypeID - WHERE (tblExportAccountInvoiceLineType.InvoiceLineEntryEnable = 0) - AND ( - (1 = 2)"; - sql = sql + sqlPostfix; - - using (SqlCommand cmd = new SqlCommand(sql, transConn)) - { - cmd.ExecuteNonQuery(); - } - - // remove invoice lines - sql = @" - DELETE - FROM tblExportAccountInvoiceLine - FROM tblExportAccountInvoiceLine - INNER JOIN tblExportAccountInvoiceLineType ON tblExportAccountInvoiceLine.ExportAccountInvoiceLineTypeID = tblExportAccountInvoiceLineType.ExportAccountInvoiceLineTypeID - WHERE (tblExportAccountInvoiceLineType.IsNewReviewRequired = 0) - AND (tblExportAccountInvoiceLineType.InvoiceLineEntryEnable = 0) - AND ( - (1 = 2)"; - sql = sql + sqlPostfix; - - using (SqlCommand cmd = new SqlCommand(sql, transConn)) - { - invoiceLinesRemoved = cmd.ExecuteNonQuery(); - } - - // remove any invoices with no lines - sql = @" - DELETE - FROM tblExportAccountInvoice - WHERE - not exists - ( - select 1 from tblExportAccountInvoiceLine where tblExportAccountInvoice.ExportAccountInvoiceID = tblExportAccountInvoiceLine.ExportAccountInvoiceID - ) - AND ( - (1 = 2)"; - sql = sql + sqlPostfix; - - using (SqlCommand cmd = new SqlCommand(sql, transConn)) - { - invoiceRemoved = cmd.ExecuteNonQuery(); - } - - // add postfix to invoice ref, if required - var dicInvoiceIdToRef = new Dictionary(); - sql = @" - SELECT ExportAccountInvoiceID - FROM tblExportAccountInvoice - WHERE ((1 = 2) "; - sql = sql + sqlPostfix + " ORDER BY InvoiceDate"; - using (SqlCommand readerCmd = new SqlCommand(sql, transConn)) - { - using (var readerInvRef = readerCmd.ExecuteReader()) - { - while (readerInvRef.Read()) - { - dicInvoiceIdToRef.Add(readerInvRef.GetInt32(0), settlementRef); - } - } - } - if (dicInvoiceIdToRef.Count > 1) - { - int i = 0; - foreach (var item in dicInvoiceIdToRef) - { - i = i + 1; - using (SqlCommand cmd = new SqlCommand(@" - UPDATE tblExportAccountInvoice - SET Reference = @reference - WHERE tblExportAccountInvoice.ExportAccountInvoiceID = @invoiceId - ", transConn)) - { - cmd.Parameters.AddWithValue("@reference", item.Value + "-" + i); - cmd.Parameters.AddWithValue("@invoiceId", item.Key); - - cmd.ExecuteNonQuery(); - } - } - } - - // complete the transaction and move to next settlement report - scope.Complete(); - } - } - Console.Write("\r"); - MiscFunction.EventLogInsert( - "Settlement report import complete. " + reportCount + " reports imported, " + lineCount + " transactions inserted, " - + reportLineCount + " report lines processed."); - } - } - catch (Exception ex) - { - MiscFunction.EventLogInsert( - "Import of Amazon settlement table data into transaction table and journal failed", - 1, - ex.ToString()); - } - } - } public void ProcessFbaInventoryReceiptData(string sqlConnectionString) { MiscFunction.EventLogInsert("Starting TransposeFbaInventoryReceiptReport()"); @@ -4235,7 +3471,7 @@ namespace bnhtrade.Core transactionDate = DateTime.SpecifyKind(transactionDate, DateTimeKind.Utc); int importTableId = reader.GetInt32(index01); string sku = reader.GetString(index03); - var skuData = new Data.Database.SKU.GetSKUId(sqlConnectionString); + var skuData = new Data.Database.SKU.GetSkuId(sqlConnectionString); int skuId = skuData.BySKUNumber(sku, true); if (skuId < 1) { @@ -4432,7 +3668,7 @@ namespace bnhtrade.Core transactionDate = DateTime.SpecifyKind(transactionDate, DateTimeKind.Utc); int importTableId = reader.GetInt32(index01); string sku = reader.GetString(index03); - var skuData = new Data.Database.SKU.GetSKUId(sqlConnectionString); + var skuData = new Data.Database.SKU.GetSkuId(sqlConnectionString); int skuId = skuData.BySKUNumber(sku, true); if (skuId < 1) { transposeSkip = transposeSkip + 1; continue; } @@ -4625,7 +3861,7 @@ namespace bnhtrade.Core if (!reader.IsDBNull(index09)) { detail = detail + Environment.NewLine + "Customer Comments: " + reader.GetString(index09); } - var skuData = new Data.Database.SKU.GetSKUId(sqlConnectionString); + var skuData = new Data.Database.SKU.GetSkuId(sqlConnectionString); int skuId = skuData.BySKUNumber(sku, true); if (skuId < 1) { transposeSkip = transposeSkip + 1; continue; } @@ -4782,7 +4018,7 @@ namespace bnhtrade.Core if (quantity < 0) { quantity = quantity * -1; } string reference = reader.GetString(index05); - var skuData = new Data.Database.SKU.GetSKUId(sqlConnectionString); + var skuData = new Data.Database.SKU.GetSkuId(sqlConnectionString); int skuId = skuData.BySKUNumber(sku, true); if (skuId < 1) { transposeSkip = transposeSkip + 1; continue; } @@ -5127,7 +4363,7 @@ namespace bnhtrade.Core string reference = reader.GetString(index03); int quantityTotal = reader.GetInt32(index06); - var skuData = new Data.Database.SKU.GetSKUId(sqlConnectionString); + var skuData = new Data.Database.SKU.GetSkuId(sqlConnectionString); int skuId = skuData.BySKUNumber(sku, true); if (skuId < 1) { @@ -5260,7 +4496,7 @@ namespace bnhtrade.Core { transactionTypeId = -1; } else { - var skuData = new Data.Database.SKU.GetSKUId(sqlConnectionString); + var skuData = new Data.Database.SKU.GetSkuId(sqlConnectionString); skuId = skuData.BySKUNumber(sku, true); } if (skuId < 1) @@ -6891,11 +6127,11 @@ namespace bnhtrade.Core "SELECT COUNT(*) FROM tblImportAmazonSettlementReport WHERE [settlement-id]=@settlementId;" , sqlConn)) { - sqlCommand.Parameters.AddWithValue("@settlementId", long.Parse(items[indexSettlementId])); + sqlCommand.Parameters.AddWithValue("@settlementId", items[indexSettlementId]); int recordCount = (int)sqlCommand.ExecuteScalar(); if (recordCount > 0) { - MiscFunction.ConsoleUpdate("Settlement report already imported, skipping..."); + MiscFunction.EventLogInsert("Settlement report already imported, skipping..."); return true; } } @@ -8837,6 +8073,7 @@ namespace bnhtrade.Core int reportsImported = 0; foreach (ReportInfo reportInfo in reportInfoList) { + MiscFunction.ConsoleUpdate("Requesting Settlement report " + (reportsImported + 1) + " of " + reportInfoList.Count()); //don't know what this next line does, might need it //if (reportInfo.IsSetReportId() & reportInfo.IsSetAcknowledged()) diff --git a/src/bnhtrade.Core/Test/Account/GetTaxInfo.cs b/src/bnhtrade.Core/Test/Account/GetTaxInfo.cs new file mode 100644 index 0000000..51a90fd --- /dev/null +++ b/src/bnhtrade.Core/Test/Account/GetTaxInfo.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Test.Account +{ + public class GetTaxInfo + { + public GetTaxInfo(string sqlConnectionString) + { + //var inst = new Data.Database.Account.GetTaxCode(sqlConnectionString); + //inst. + + //var taxInfo = inst.GetAll(); + } + } +} diff --git a/src/bnhtrade.Core/Test/AutoExec.cs b/src/bnhtrade.Core/Test/AutoExec.cs new file mode 100644 index 0000000..a08a2ff --- /dev/null +++ b/src/bnhtrade.Core/Test/AutoExec.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Test +{ + public class AutoExec + { + private string sqlConnectionString; + + public AutoExec(string sqlConnectionString) + { + this.sqlConnectionString = sqlConnectionString; + + // --------------- start this ------------------- // + AmazonSettlement(); + } + private void AmazonSettlement() + { + var instance = new Core.Logic.Export.AmazonSettlementData(sqlConnectionString); + instance.ToInvoice(); + } + + private void Import() + { + var instance = new Test.Import.AmazonSettlement(sqlConnectionString); + } + } +} diff --git a/src/bnhtrade.Core/Test/Import/AmazonSettlement.cs b/src/bnhtrade.Core/Test/Import/AmazonSettlement.cs new file mode 100644 index 0000000..a4fac03 --- /dev/null +++ b/src/bnhtrade.Core/Test/Import/AmazonSettlement.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Test.Import +{ + public class AmazonSettlement + { + private string sqlConnectionString; + public AmazonSettlement(string sqlConnectionString) + { + this.sqlConnectionString = sqlConnectionString; + ReadSettlementFromDatabase(); + } + + public void ReadSettlementFromDatabase() + { + + var instance = new Data.Database.Import.ReadAmazonSettlement(sqlConnectionString); + var answer = instance.BySettlementId("11796400482"); + } + } +} diff --git a/src/bnhtrade.Core/Test/InboundShipmentInfo.cs b/src/bnhtrade.Core/Test/InboundShipmentInfo.cs index 31da059..95ad727 100644 --- a/src/bnhtrade.Core/Test/InboundShipmentInfo.cs +++ b/src/bnhtrade.Core/Test/InboundShipmentInfo.cs @@ -74,10 +74,5 @@ namespace bnhtrade.Core.Test var result = task.GetShipmentInfo(); } - public void Test() - { - var job = new Logic.AmazonFBAInbound.UpdateDatabaseShipmentInfo(sqlConnectionString); - job.GetNew(); - } } } diff --git a/src/bnhtrade.Core/Test/Logic/Export.cs b/src/bnhtrade.Core/Test/Logic/Export.cs new file mode 100644 index 0000000..97519fb --- /dev/null +++ b/src/bnhtrade.Core/Test/Logic/Export.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Test.Logic +{ + public class Export + { + private string sqlConnectionString; + public Export(string sqlConnectionString) + { + this.sqlConnectionString = sqlConnectionString; + + // method you want to start here + UpdateXeroWithAmzonSettlementData(); + + } + public void UpdateXeroWithAmzonSettlementData() + { + var instance = new bnhtrade.Core.Logic.Export.AmazonSettlementData(sqlConnectionString); + instance.ToInvoice(); + } + } +} diff --git a/src/bnhtrade.Core/Test/SQLLoop.cs b/src/bnhtrade.Core/Test/SQLLoop.cs index f9718e1..03620c4 100644 --- a/src/bnhtrade.Core/Test/SQLLoop.cs +++ b/src/bnhtrade.Core/Test/SQLLoop.cs @@ -30,7 +30,7 @@ namespace bnhtrade.Core.Test total = (int)cmd.ExecuteScalar(); } - var progress = new UI.Utility.ConsoleProgressBar(total, "Processing " + total + " records..."); + var progress = new UI.Console.ProgressBar(total, "Processing " + total + " records..."); using (SqlCommand cmd = new SqlCommand(@" SELECT * FROM tblStockJournal diff --git a/src/bnhtrade.Core/Test/_BoilerPlate/ClassFromSql.cs b/src/bnhtrade.Core/Test/_BoilerPlate/ClassFromSql.cs new file mode 100644 index 0000000..1cd339e --- /dev/null +++ b/src/bnhtrade.Core/Test/_BoilerPlate/ClassFromSql.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Test._BoilerPlate +{ + class ClassFromSql + { + /* copy the following code in SSMS query, set variables and execute + + DECLARE @TableName VARCHAR(MAX) = 'tblOrder' -- Replace 'tblOrder' with your table name + DECLARE @TableSchema VARCHAR(MAX) = NULL -- If required, replace NULL with your schema name i.e. 'Markets' + DECLARE @result varchar(max) = '' + + SET @result = @result + 'using System;' + CHAR(13) + CHAR(13) + + IF (@TableSchema IS NOT NULL) + BEGIN + SET @result = @result + 'namespace ' + @TableSchema + CHAR(13) + '{' + CHAR(13) + END + + SET @result = @result + 'public class ' + @TableName + CHAR(13) + '{' + + SELECT + @result = @result + CHAR(13) + + ' public ' + ColumnType + ' ' + ColumnName + ' { get; set; } ' + FROM (SELECT + c.COLUMN_NAME AS ColumnName, + CASE c.DATA_TYPE + WHEN 'bigint' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'Int64?' + ELSE 'Int64' + END + WHEN 'binary' THEN 'Byte[]' + WHEN 'bit' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'bool?' + ELSE 'bool' + END + WHEN 'char' THEN 'string' + WHEN 'date' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'DateTime?' + ELSE 'DateTime' + END + WHEN 'datetime' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'DateTime?' + ELSE 'DateTime' + END + WHEN 'datetime2' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'DateTime?' + ELSE 'DateTime' + END + WHEN 'datetimeoffset' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'DateTimeOffset?' + ELSE 'DateTimeOffset' + END + WHEN 'decimal' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'decimal?' + ELSE 'decimal' + END + WHEN 'float' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'Single?' + ELSE 'Single' + END + WHEN 'image' THEN 'Byte[]' + WHEN 'int' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'int?' + ELSE 'int' + END + WHEN 'money' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'decimal?' + ELSE 'decimal' + END + WHEN 'nchar' THEN 'string' + WHEN 'ntext' THEN 'string' + WHEN 'numeric' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'decimal?' + ELSE 'decimal' + END + WHEN 'nvarchar' THEN 'string' + WHEN 'real' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'Double?' + ELSE 'Double' + END + WHEN 'smalldatetime' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'DateTime?' + ELSE 'DateTime' + END + WHEN 'smallint' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'Int16?' + ELSE 'Int16' + END + WHEN 'smallmoney' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'decimal?' + ELSE 'decimal' + END + WHEN 'text' THEN 'string' + WHEN 'time' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'TimeSpan?' + ELSE 'TimeSpan' + END + WHEN 'timestamp' THEN 'Byte[]' + WHEN 'tinyint' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'Byte?' + ELSE 'Byte' + END + WHEN 'uniqueidentifier' THEN CASE C.IS_NULLABLE + WHEN 'YES' THEN 'Guid?' + ELSE 'Guid' + END + WHEN 'varbinary' THEN 'Byte[]' + WHEN 'varchar' THEN 'string' + ELSE 'Object' + END AS ColumnType, + c.ORDINAL_POSITION + FROM INFORMATION_SCHEMA.COLUMNS c + WHERE c.TABLE_NAME = @TableName + AND ISNULL(@TableSchema, c.TABLE_SCHEMA) = c.TABLE_SCHEMA) t + ORDER BY t.ORDINAL_POSITION + + SET @result = @result + CHAR(13) + + SET @result = @result + '}' + CHAR(13) + + IF (@TableSchema IS NOT NULL) + BEGIN + SET @result = @result + CHAR(13) + '}' + END + + PRINT @result + */ + } + + class ourputy + { + + } +} diff --git a/src/bnhtrade.Core/Test/_BoilerPlate/Sql.cs b/src/bnhtrade.Core/Test/_BoilerPlate/Sql.cs new file mode 100644 index 0000000..cdf2d36 --- /dev/null +++ b/src/bnhtrade.Core/Test/_BoilerPlate/Sql.cs @@ -0,0 +1,196 @@ +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.Test._BoilerPlate +{ + public class Sql + { + public void Select() + { + using (SqlConnection conn = new SqlConnection()) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(@" + SELECT + column01 + ,column02 + ,column03 + ,column04 + FROM tblTable + WHERE + column01 = @value01 + OR column01 = @value02 + OR column01 = @value03 + OR column01 = @value04 + ", conn)) + { + cmd.Parameters.AddWithValue("@value01", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value02", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value03", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value04", "xxxxxxxx"); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + // do something + } + else + { + while (reader.Read()) + { + // do some thing with the data + } + } + } + } + } + } + public string SelectByList(List stringList) + { + // check input list for items + if (stringList == null || !stringList.Any()) + { + return null; + } + + // build SQL string + string sqlString = @" + SELECT + value01 + ,value02 + FROM + tblTable + WHERE + "; + + var parameterValueList = new List>(); + foreach (var item in stringList) + { + if (!string.IsNullOrWhiteSpace(item)) + { + int count = parameterValueList.Count; + var parameterValue = new Tuple("@parameter" + count, item); + parameterValueList.Add(parameterValue); + if (count == 0) + { + sqlString = sqlString + @" + value01 = " + parameterValue.Item1; + } + else + { + sqlString = sqlString + @" + OR value01 = " + parameterValue.Item1; + } + } + } + + if (parameterValueList.Count == 0) + { + return null; + } + + // execute query and build result list + var skuTaxCodeList = new List>(); + using (SqlConnection conn = new SqlConnection()) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(sqlString, conn)) + { + foreach (var item in parameterValueList) + { + cmd.Parameters.AddWithValue(item.Item1, item.Item2); + } + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (!reader.HasRows) + { + return null; + } + + while (reader.Read()) + { + // read data and build return object + } + } + } + } + return "Complete"; // return object + } + public void Insert() + { + using (TransactionScope scope = new TransactionScope()) + { + using (SqlConnection conn = new SqlConnection()) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(@" + INSERT INTO tblTable ( + column01 + ,column02 + ,column03 + ,column04 + ) + OUTPUT INSERTED.TablePk + VALUES ( + @value01 + ,@value02 + ,@value03 + ,@value04 + ) + ", conn)) + { + cmd.Parameters.AddWithValue("@value01", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value02", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value03", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value04", "xxxxxxxx"); + + int tablePk = (int)cmd.ExecuteScalar(); + } + } + scope.Complete(); + } + } + public void Update() + { + using (TransactionScope scope = new TransactionScope()) + { + using (SqlConnection conn = new SqlConnection()) + { + conn.Open(); + + using (SqlCommand cmd = new SqlCommand(@" + UPDATE + tblTable + SET + column01 = @value01 + column02 = @value02 + column03 = @value03 + column04 = @value04 + WHERE + column05 = @value05 + ", conn)) + { + cmd.Parameters.AddWithValue("@value01", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value02", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value03", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value04", "xxxxxxxx"); + cmd.Parameters.AddWithValue("@value04", "xxxxxxxx"); + + cmd.ExecuteNonQuery(); + } + } + scope.Complete(); + } + } + } +} \ No newline at end of file diff --git a/src/bnhtrade.Core/UI/Utility/ConsoleProgressBar.cs b/src/bnhtrade.Core/UI/Console/ProgressBar.cs similarity index 93% rename from src/bnhtrade.Core/UI/Utility/ConsoleProgressBar.cs rename to src/bnhtrade.Core/UI/Console/ProgressBar.cs index ea8af46..89f2ac6 100644 --- a/src/bnhtrade.Core/UI/Utility/ConsoleProgressBar.cs +++ b/src/bnhtrade.Core/UI/Console/ProgressBar.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Text; using System.Threading; -namespace bnhtrade.Core.UI.Utility +namespace bnhtrade.Core.UI.Console { - class ConsoleProgressBar : IDisposable, IProgress + class ProgressBar : IDisposable, IProgress { private int MaxProgress { get; set; } private string PostfixMessge { get; set; } @@ -23,7 +23,7 @@ namespace bnhtrade.Core.UI.Utility private bool disposed = false; private int animationIndex = 0; - public ConsoleProgressBar(int maxProgress, string postfixMessge = "") + public ProgressBar(int maxProgress, string postfixMessge = "") { MaxProgress = maxProgress; PostfixMessge = postfixMessge; @@ -34,7 +34,7 @@ namespace bnhtrade.Core.UI.Utility // A progress bar is only for temporary display in a console window. // If the console output is redirected to a file, draw nothing. // Otherwise, we'll end up with a lot of garbage in the target file. - if (!Console.IsOutputRedirected) + if (!System.Console.IsOutputRedirected) { ResetTimer(); } @@ -103,7 +103,7 @@ namespace bnhtrade.Core.UI.Utility outputBuilder.Append('\b', overlapCount); } - Console.Write(outputBuilder); + System.Console.Write(outputBuilder); currentText = text; } diff --git a/src/bnhtrade.Core/UI/Console/Update.cs b/src/bnhtrade.Core/UI/Console/Update.cs new file mode 100644 index 0000000..765d392 --- /dev/null +++ b/src/bnhtrade.Core/UI/Console/Update.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.UI.Console +{ + public class Update + { + public void WriteLine(string consoleText, Boolean newLine = true) + { + if (newLine) + { + System.Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss") + "] " + consoleText); + } + else + { + System.Console.Write("\r[" + DateTime.Now.ToString("HH:mm:ss") + "] " + consoleText); + } + } + public void Wait(string consoleMessage, int waitSeconds) + { + do + { + System.Console.Write("\r[--------] " + consoleMessage, string.Format("{0:00}", waitSeconds)); + System.Threading.Thread.Sleep(1000); + waitSeconds = waitSeconds - 1; + } while (waitSeconds > 0); + System.Console.Write("\r"); + System.Console.Write(new String(' ', System.Console.BufferWidth - 1)); + System.Console.Write("\r"); + } + } +} diff --git a/src/bnhtrade.Core/bnhtrade.Core.csproj b/src/bnhtrade.Core/bnhtrade.Core.csproj index a9d52e3..7b271a9 100644 --- a/src/bnhtrade.Core/bnhtrade.Core.csproj +++ b/src/bnhtrade.Core/bnhtrade.Core.csproj @@ -38,6 +38,7 @@ + @@ -53,20 +54,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + @@ -76,7 +116,8 @@ Settings.settings - + + @@ -86,7 +127,10 @@ Settings.Designer.cs - + + + + {9c7d6775-4f06-4881-87a0-b9514f2f3033} diff --git a/src/bnhtrade.ScheduledTasks/Program.cs b/src/bnhtrade.ScheduledTasks/Program.cs index 37db82b..1da6e0e 100644 --- a/src/bnhtrade.ScheduledTasks/Program.cs +++ b/src/bnhtrade.ScheduledTasks/Program.cs @@ -39,6 +39,7 @@ namespace bnhtradeScheduledTasks Console.WriteLine("<1> Amazon reports"); Console.WriteLine("<2> Stock functions"); Console.WriteLine(""); + Console.WriteLine("<8> Start scheduled nightly tasks"); Console.WriteLine("<9> Dev functions"); Console.WriteLine(""); Console.WriteLine("<0> Exit"); @@ -59,7 +60,8 @@ namespace bnhtradeScheduledTasks Console.WriteLine(consoleHeader); Console.WriteLine("Main Menu > Amazon Reports"); Console.WriteLine(); - Console.WriteLine("<1> Update all Amazon inventory and settlement data"); + Console.WriteLine("<1> Start nightly tasks"); + Console.WriteLine(); Console.WriteLine("<2> Update FBA Inventory Data"); Console.WriteLine("<3> Update FBA Inventory Age Data"); Console.WriteLine("<4> Update Amazon Settlement Data"); @@ -105,9 +107,9 @@ namespace bnhtradeScheduledTasks { Console.Clear(); var task = new AmazonReport(); - var task2 = new StockReconciliation(); + var task2 = new bnhtrade.Core.Logic.Export.AmazonSettlementData(sqlConnectionString); task.UpdateAmazonSettlementData(sqlConnectionString); - task2.WIP_ProcessAmazonSettlementData(sqlConnectionString); + task2.ToInvoice(); Console.WriteLine("Complete, press any key to continue..."); Console.ReadKey(); } @@ -265,6 +267,13 @@ namespace bnhtradeScheduledTasks } while (true); } + else if (input == "8") + { + Console.Clear(); + DownloadAll(); + Console.WriteLine("Complete, press any key to continue..."); + Console.ReadKey(); + } else if (input == "9") { do @@ -281,7 +290,7 @@ namespace bnhtradeScheduledTasks Console.WriteLine("<6> Test Owner intro insert"); Console.WriteLine("<7> Currency exchange rate insert"); Console.WriteLine("<8> SQL Loop function"); - Console.WriteLine("<9> Inbound shipment test"); + Console.WriteLine("<9> AUTOEXEC TEST"); Console.WriteLine(); Console.WriteLine("<0> Back"); Console.WriteLine(""); @@ -398,9 +407,7 @@ namespace bnhtradeScheduledTasks { Console.Clear(); - var bob = new bnhtrade.Core.Test.InboundShipmentInfo(sqlConnectionString); - bob.Test(); - + var inst = new bnhtrade.Core.Test.AutoExec(sqlConnectionString); Console.WriteLine("Complete, press any key to continue..."); Console.ReadKey(); @@ -462,6 +469,7 @@ namespace bnhtradeScheduledTasks var account = new AmazonReport(); var stock = new StockReconciliation(); + var export = new bnhtrade.Core.Logic.Export.AmazonSettlementData(sqlConnectionString); bool accountUpdate = false; bool stockUpdate = false; @@ -474,9 +482,9 @@ namespace bnhtradeScheduledTasks try { if (accountUpdate == false) { accountUpdate = true; account.UpdateAmazonSettlementData(sqlConnectionString); } + if (accountProcess == false) { accountProcess = true; export.ToInvoice(); } if (stockUpdate == false) { stockUpdate = true; stock.UpdateFbaStockImportData(sqlConnectionString); } - if (accountProcess == false) { accountProcess = true; stock.WIP_ProcessAmazonSettlementData(sqlConnectionString); } // if (stockProcess == false) { stockProcess = true; stock.ProcessFbaStockImportData(); } // ^^^^^^ best to process manually, case, fba inventory recepts, if a correction is made days later (ie -1) the already incorrect value // will have been entered in the stocktransaction table and maked as processed in the inventoryreceipt table