From 30174290cf8a6d5f8a64ff196b935622ee7dfe40 Mon Sep 17 00:00:00 2001 From: Bobbie Hodgetts Date: Mon, 9 Jun 2025 21:23:42 +0100 Subject: [PATCH] pull master into branch * Migrated projects to dotnet8 migrated all projects over to .net8 incomplete feature for gui shipments * Amazon inventory ledger testing and implementation Tested what I can until more data for the Amazon Ledger Detail table comes in * amazon settlement amounts now set to tax inclusive when exporting to invoice * Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead * feature exchange rate update automation Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications. Also added a form to show the console output in form application. --- src/bnhtrade.ComTypeLib/Account/Account.cs | 3 +- .../ILRepack.Config.props.old2 | 6 + src/bnhtrade.ComTypeLib/ILRepack.targets | 12 +- src/bnhtrade.ComTypeLib/README.md | 11 + .../bnhtrade.ComTypeLib.csproj | 20 +- .../Data/Database/Account/CreateJournal.cs | 2 +- .../Data/Database/Account/Currency.cs | 310 +++++++++++------- src/bnhtrade.Core/Data/Database/Constants.cs | 14 +- .../Database/Import/AmazonFbaReimbursement.cs | 4 +- .../Database/Import/AmazonSettlementInsert.cs | 10 +- .../Data/Database/SqlWhereBuilder.cs | 15 +- .../Stock/InsertSkuTransactionType.cs | 38 +-- .../Database/Stock/ReadSkuTransactionType.cs | 99 ++---- src/bnhtrade.Core/Logic/Account/Currency.cs | 189 ++++++++++- .../Logic/Import/AmazonFbaCustomerReturn.cs | 2 +- .../Logic/Stock/SkuTransactionCrud.cs | 3 - .../Logic/Stock/SkuTransactionImport.cs | 129 ++++---- .../Logic/Stock/SkuTransactionTypeCrud.cs | 14 +- src/bnhtrade.Core/Logic/Utilities/DateTime.cs | 51 +++ .../Logic/Utilities/DateTimeCheck.cs | 8 +- .../Logic/Utilities/DateTimeParse.cs | 23 -- .../Logic/Utilities/ListFunction.cs | 59 ++++ .../Logic/Utilities/NightlyRoutine.cs | 2 + src/bnhtrade.Core/Logic/Validate/Format.cs | 17 +- .../Model/Account/CurrencyCode.cs | 191 +++++++++++ .../Model/Account/CurrencyExchangeRate.cs | 71 ++++ src/bnhtrade.Core/Model/Account/Invoice.cs | 2 +- .../Model/Credentials/bnhtradeDB.cs | 2 +- .../Model/Stock/SkuTransactionCreate.cs | 4 +- .../Properties/Settings.Designer.cs | 2 +- src/bnhtrade.Core/Test/Account/Account.cs | 13 +- src/bnhtrade.Core/bnhtrade.Core.csproj | 40 ++- src/bnhtrade.ScheduledTasks/Program.cs | 37 ++- .../bnhtrade.ScheduledTasks.csproj | 3 +- src/bnhtrade.gui/FormConsole.Designer.cs | 72 ++++ src/bnhtrade.gui/FormConsole.cs | 44 +++ src/bnhtrade.gui/FormConsole.resx | 120 +++++++ src/bnhtrade.gui/Home.Designer.cs | 104 ++++-- src/bnhtrade.gui/Home.cs | 7 + src/bnhtrade.gui/Home.resx | 4 +- src/bnhtrade.gui/TextBoxStreamWriter.cs | 28 ++ 41 files changed, 1370 insertions(+), 415 deletions(-) create mode 100644 src/bnhtrade.ComTypeLib/ILRepack.Config.props.old2 create mode 100644 src/bnhtrade.ComTypeLib/README.md create mode 100644 src/bnhtrade.Core/Logic/Utilities/DateTime.cs delete mode 100644 src/bnhtrade.Core/Logic/Utilities/DateTimeParse.cs create mode 100644 src/bnhtrade.Core/Logic/Utilities/ListFunction.cs create mode 100644 src/bnhtrade.Core/Model/Account/CurrencyCode.cs create mode 100644 src/bnhtrade.Core/Model/Account/CurrencyExchangeRate.cs create mode 100644 src/bnhtrade.gui/FormConsole.Designer.cs create mode 100644 src/bnhtrade.gui/FormConsole.cs create mode 100644 src/bnhtrade.gui/FormConsole.resx create mode 100644 src/bnhtrade.gui/TextBoxStreamWriter.cs diff --git a/src/bnhtrade.ComTypeLib/Account/Account.cs b/src/bnhtrade.ComTypeLib/Account/Account.cs index 7d42ea3..491ac29 100644 --- a/src/bnhtrade.ComTypeLib/Account/Account.cs +++ b/src/bnhtrade.ComTypeLib/Account/Account.cs @@ -54,8 +54,7 @@ namespace bnhtrade.ComTypeLib public int CurrencyExchangeRateInsert(ConnectionCredential sqlConnCred, int exchangeRateSource, string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal currencyUnitsPerGbp, DateTime periodStart, DateTime periodEnd, bool checkOverride = false) { - return new Core.Logic.Account.Currency().CurrencyExchangeRateInsert(exchangeRateSource, currencyCode, - currencyUnitsPerGbp, periodStart, periodEnd, checkOverride); + throw new Exception("This function has been retired, now handled by nightly routines"); } } diff --git a/src/bnhtrade.ComTypeLib/ILRepack.Config.props.old2 b/src/bnhtrade.ComTypeLib/ILRepack.Config.props.old2 new file mode 100644 index 0000000..35e9ad5 --- /dev/null +++ b/src/bnhtrade.ComTypeLib/ILRepack.Config.props.old2 @@ -0,0 +1,6 @@ + + + + True + + \ No newline at end of file diff --git a/src/bnhtrade.ComTypeLib/ILRepack.targets b/src/bnhtrade.ComTypeLib/ILRepack.targets index 8bf0115..24ac6c2 100644 --- a/src/bnhtrade.ComTypeLib/ILRepack.targets +++ b/src/bnhtrade.ComTypeLib/ILRepack.targets @@ -1,8 +1,12 @@ + - + + + + + LibraryPath="$(OutputPath)" + /> - \ No newline at end of file + + \ No newline at end of file diff --git a/src/bnhtrade.ComTypeLib/README.md b/src/bnhtrade.ComTypeLib/README.md new file mode 100644 index 0000000..d78c968 --- /dev/null +++ b/src/bnhtrade.ComTypeLib/README.md @@ -0,0 +1,11 @@ +To setup on new computer: + +1. Add the app.local.config to the users ..\AppData\Local\bnhtrade\ folder (create the bnhtrade folder) + +2. CLone bnhtrade solution from the repo + +3. Build bnhtradeCOM project + +4. Register the COM host for COM. With an elevated prompt, navigate to the build directory and run "regsvr32 bnhtradeCOM.comhost.dll" + +5. \ No newline at end of file diff --git a/src/bnhtrade.ComTypeLib/bnhtrade.ComTypeLib.csproj b/src/bnhtrade.ComTypeLib/bnhtrade.ComTypeLib.csproj index 263137a..599052e 100644 --- a/src/bnhtrade.ComTypeLib/bnhtrade.ComTypeLib.csproj +++ b/src/bnhtrade.ComTypeLib/bnhtrade.ComTypeLib.csproj @@ -4,8 +4,17 @@ Library bnhtradeCOM false + + - + + + true + + + + + false @@ -24,15 +33,11 @@ - + - - copy "$(ProjectDir)_RegAsmInstall.bat" "$(TargetDir)" -copy "$(ProjectDir)_RegAsmRefresh.bat" "$(TargetDir)" -copy "$(ProjectDir)_RegAsmUninstall.bat" "$(TargetDir)" bnhtrade COM Type Library bnhtrade bnhtradeCOMAsm @@ -40,4 +45,7 @@ copy "$(ProjectDir)_RegAsmUninstall.bat" "$(TargetDir)" 1.0.0.0 1.0.0.0 + + + \ No newline at end of file diff --git a/src/bnhtrade.Core/Data/Database/Account/CreateJournal.cs b/src/bnhtrade.Core/Data/Database/Account/CreateJournal.cs index 01a4f04..a149dbf 100644 --- a/src/bnhtrade.Core/Data/Database/Account/CreateJournal.cs +++ b/src/bnhtrade.Core/Data/Database/Account/CreateJournal.cs @@ -162,7 +162,7 @@ namespace bnhtrade.Core.Data.Database.Account // currency conversion if (currencyCode != "GBP") { - amount = new Data.Database.Account.Currency().CurrencyConvertToGbp(currencyCode, amount, entryDate); + amount = new Logic.Account.Currency().CurrencyConvertToGbp(currencyCode, amount, entryDate); } // ensure decimal is rounded diff --git a/src/bnhtrade.Core/Data/Database/Account/Currency.cs b/src/bnhtrade.Core/Data/Database/Account/Currency.cs index da36093..5172f47 100644 --- a/src/bnhtrade.Core/Data/Database/Account/Currency.cs +++ b/src/bnhtrade.Core/Data/Database/Account/Currency.cs @@ -1,26 +1,25 @@ using System; using System.Collections.Generic; -using System.Data.SqlClient; +using Microsoft.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Collections; +using FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentOutbound; +using System.Data; namespace bnhtrade.Core.Data.Database.Account { internal class Currency : Connection { - public decimal CurrencyConvertToGbp(string currencyCode, decimal amount, DateTime conversionDate) + /// + /// Returns excahnge rate, in decimal format, for a given currency and datetime + /// + /// currency code + /// dat and time + /// + public decimal? ReadExchangeRate(string currencyCode, DateTime date) { - if (currencyCode == "GBP" || amount == 0M) - { - return amount; - } - - if (currencyCode.Length != 3) - { - throw new Exception("Invalid currency code '" + currencyCode + "'"); - } - using (SqlConnection sqlConn = new SqlConnection(SqlConnectionString)) { sqlConn.Open(); @@ -32,145 +31,210 @@ namespace bnhtrade.Core.Data.Database.Account ", sqlConn)) { cmd.Parameters.AddWithValue("@currencyCode", currencyCode); - cmd.Parameters.AddWithValue("@conversionDate", conversionDate); + cmd.Parameters.AddWithValue("@conversionDate", date); object result = cmd.ExecuteScalar(); if (result != null) { - return amount / Convert.ToDecimal(result); - } - } - - // return reason for no record found - using (SqlCommand cmd = new SqlCommand(@" - SELECT CurrencyUnitsPerGBP - FROM tblAccountExchangeRate - WHERE CurrencyCode=@currencyCode - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@currencyCode", currencyCode); - - object result = cmd.ExecuteScalar(); - if (result == null) - { - throw new Exception("Currency code '" + currencyCode + "' does not exist in Exchange Rate table"); + return Convert.ToDecimal(result); } else { - throw new Exception("Date range for " + currencyCode + " " + conversionDate.ToShortDateString() + " " + - conversionDate.ToLongTimeString() + "' does not exist in Exchange Rate table"); + return null; } } } } - public int CurrencyExchangeRateInsert(int exchangeRateSource, string currencyCode, - decimal currencyUnitsPerGbp, DateTime periodStart, DateTime periodEnd, bool checkOverride = false) + public List ReadExchangeRate(List currencyCodeList = null, DateTime date = default(DateTime)) { + throw new NotImplementedException("Complete, but untested"); + + var returnList = new List(); + + string sql = @" + SELECT AccountEchangeRateID, ExchangeRateSource, CurrencyCode, CurrencyUnitsPerGBP, StartDate, EndDate + FROM tblAccountExchangeRate + WHERE 1=1 "; + + if (date != default(DateTime)) + { + sql = sql + " AND (@dateTime >= StartDate AND @dateTime < endDate) "; + } + + var sqlWhere = new Data.Database.SqlWhereBuilder(); + + // create string list + List stringList = new List(); + if (currencyCodeList != null) + { + stringList = currencyCodeList.ConvertAll(f => f.ToString()); + if (stringList.Any()) + { + sqlWhere.In("CurrencyCode", stringList, "AND"); + } + } + + sql = sql + sqlWhere.SqlWhereString; + + using (SqlConnection sqlConn = new SqlConnection(SqlConnectionString)) + { + sqlConn.Open(); + + using (SqlCommand cmd = new SqlCommand(sql)) + { + if (date != default(DateTime)) + { + cmd.Parameters.AddWithValue("@dateTime", date); + } + if (stringList.Any()) + { + sqlWhere.AddParametersToSqlCommand(cmd); + } + + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int id = reader.GetInt32(0); + int exchangeRateSource = reader.GetInt32(1); + string currencyCodeString = reader.GetString(2); + decimal currencyUnitsPerGBP = reader.GetDecimal(3); + DateTime startDate = DateTime.SpecifyKind( reader.GetDateTime(4), DateTimeKind.Utc); + DateTime endDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc); + + + // convert string to enum + if (Enum.TryParse(currencyCodeString, out Model.Account.CurrencyCode currencyCode) == false) + { + throw new Exception("Failed converting database string to enum"); + } + + var item = new Model.Account.CurrencyExchangeRate( + currencyCode + , exchangeRateSource + , startDate + , endDate + ); + + returnList.Add(item); + } + } + } + } + return returnList; + } + + public List ReadExchangeRateLatest(List currencyCodeList = null) + { + var returnList = new List(); + + string sql = @" + SELECT t1.AccountExchangeRateID, t1.ExchangeRateSource, t1.CurrencyCode, t1.CurrencyUnitsPerGBP, t1.StartDate, t1.EndDate, + t2.maxdate + FROM tblAccountExchangeRate AS t1 + INNER JOIN + (SELECT max(StartDate) AS maxdate, + CurrencyCode + FROM tblAccountExchangeRate + GROUP BY CurrencyCode + "; + + // add any filters + var sqlWhere = new Data.Database.SqlWhereBuilder(); + var codeStringList = new List(); + if (currencyCodeList != null && currencyCodeList.Any() == true) + { + // convert to string list + foreach ( var currencyCode in currencyCodeList) + { + codeStringList.Add(currencyCode.ToString()); + } + + // add to where statement + sqlWhere.In("CurrencyCode", codeStringList, "HAVING"); + sql = sql + sqlWhere.SqlWhereString; + } + + sql = sql + @" ) AS t2 + ON t1.CurrencyCode = t2.CurrencyCode + AND t1.StartDate = t2.maxdate + ORDER BY t1.CurrencyCode;"; + + //query db + using (SqlConnection sqlConn = new SqlConnection(SqlConnectionString)) + { + sqlConn.Open(); + + using (SqlCommand cmd = new SqlCommand(sql, sqlConn)) + { + if (codeStringList.Any()) + { + sqlWhere.AddParametersToSqlCommand(cmd); + } + + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int id = reader.GetInt32(0); + int exchangeRateSource = reader.GetInt32(1); + string currencyCodeString = reader.GetString(2); + decimal currencyUnitsPerGBP = reader.GetDecimal(3); + DateTime startDate = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc); + DateTime endDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc); + + + // convert string to enum + if (Enum.TryParse(currencyCodeString, out Model.Account.CurrencyCode currencyCode) == false) + { + throw new Exception("Failed converting database string to enum"); + } + + var item = new Model.Account.CurrencyExchangeRate( + currencyCode + , exchangeRateSource + , startDate + , endDate + ); + + returnList.Add(item); + } + } + } + } + return returnList; + } + + public int InsertExchangeRate(int exchangeRateSource, Model.Account.CurrencyCode currencyCode, + decimal currencyUnitsPerGbp, DateTime periodStartUtc, DateTime periodEnd, bool checkOverride = false) + { + // checks + if (periodStartUtc.Kind != DateTimeKind.Utc || periodEnd.Kind != DateTimeKind.Utc) + { + throw new FormatException("Currency date time kind must be UTC"); + } + currencyUnitsPerGbp = decimal.Round(currencyUnitsPerGbp, 4); - periodStart = DateTime.SpecifyKind(periodStart, DateTimeKind.Utc); - periodEnd = DateTime.SpecifyKind(periodEnd, DateTimeKind.Utc); // CHECKS - // HMRC source only - if (exchangeRateSource != 1) - { - throw new Exception("Function does not currently accept exchange rates from sources other than HMRC"); - } - // currency code upper case only - currencyCode = currencyCode.ToUpper(); - if (currencyCode.Length != 3) - { - throw new Exception("Invalid currency code '" + currencyCode + "'"); - } - - if (periodEnd <= periodStart) + if (periodEnd <= periodStartUtc) { throw new Exception("Invalid date period."); } - if (checkOverride == false && (periodEnd - periodStart).Days > 31) + if (checkOverride == false && (periodEnd - periodStartUtc).Days > 31) { throw new Exception("Date period is greater than 31 days."); } - // retirve previous data + // make the insert DateTime? periodEndLast = null; using (SqlConnection sqlConn = new SqlConnection(SqlConnectionString)) { sqlConn.Open(); - using (SqlCommand cmd = new SqlCommand(@" - SELECT Max(tblAccountExchangeRate.EndDate) AS MaxOfEndDate - FROM tblAccountExchangeRate - WHERE (((tblAccountExchangeRate.CurrencyCode) = @currencyCode)) - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@currencyCode", currencyCode); - object obj = cmd.ExecuteScalar(); - - // currency code not existing - if (obj == DBNull.Value && checkOverride == false) - { - throw new Exception("Currency code '" + currencyCode + "' does not exist in table"); - } - // currency code exists - else - { - periodEndLast = DateTime.SpecifyKind(Convert.ToDateTime(obj), DateTimeKind.Utc); - - if (periodStart != periodEndLast) - { - throw new Exception("Invalid period start date -- must equal previous period end-date."); - } - } - } - - // retrive previous exchange rate and check - decimal currencyUnitsPerGbpLast = 0; - if (periodEndLast != null) - { - using (SqlCommand cmd = new SqlCommand(@" - SELECT tblAccountExchangeRate.AccountExchangeRateID, tblAccountExchangeRate.CurrencyUnitsPerGBP - FROM tblAccountExchangeRate - WHERE (tblAccountExchangeRate.EndDate = @periodEndLast) - AND (CurrencyCode = @currencyCode); - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@periodEndLast", periodEndLast); - cmd.Parameters.AddWithValue("@currencyCode", currencyCode); - - using (var reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - currencyUnitsPerGbpLast = reader.GetDecimal(1); - } - else - { - throw new Exception("Error that shouldn't happen! Check code @ 5129f3e6-2f7e-4883-bc73-b317d8fa4050"); - } - // error if >1 line - if (reader.Read()) - { - string errText = "Multiple lines in currency exchange table for '" + currencyCode + "' where [EndDate]=" + periodEndLast.ToString(); - new Logic.Log.LogEvent().LogError(errText); - throw new Exception(errText); - } - } - } - } - - // check difference between current and previous exchange rates isn't too great - if (checkOverride == false && - (currencyUnitsPerGbpLast > (currencyUnitsPerGbp * 1.05m) || currencyUnitsPerGbpLast < (currencyUnitsPerGbp * 0.95m)) - ) - { - throw new Exception("Difference between supplied and previous exchange rates is greater than 5%"); - } - - // MAKE THE INSERT int recordId = 0; using (SqlCommand cmd = new SqlCommand(@" INSERT INTO tblAccountExchangeRate (ExchangeRateSource, CurrencyCode, CurrencyUnitsPerGBP, StartDate, EndDate) @@ -179,9 +243,9 @@ namespace bnhtrade.Core.Data.Database.Account ", sqlConn)) { cmd.Parameters.AddWithValue("@exchangeRateSource", exchangeRateSource); - cmd.Parameters.AddWithValue("@currencyCode", currencyCode); + cmd.Parameters.AddWithValue("@currencyCode", currencyCode.ToString()); cmd.Parameters.AddWithValue("@currencyUnitsPerGbp", currencyUnitsPerGbp); - cmd.Parameters.AddWithValue("@periodStart", periodStart); + cmd.Parameters.AddWithValue("@periodStart", periodStartUtc); cmd.Parameters.AddWithValue("@periodEnd", periodEnd); recordId = (int)cmd.ExecuteScalar(); diff --git a/src/bnhtrade.Core/Data/Database/Constants.cs b/src/bnhtrade.Core/Data/Database/Constants.cs index 8fae4df..6795e36 100644 --- a/src/bnhtrade.Core/Data/Database/Constants.cs +++ b/src/bnhtrade.Core/Data/Database/Constants.cs @@ -8,14 +8,22 @@ namespace bnhtrade.Core.Data.Database { public static class Constants { + /// + /// Gets the date bnhtrade started trading, UK time (datetime kind unspecified). + /// + /// The UK date and time the business started (datetime kind unspecified) + public static DateTime GetBusinessStartUk() + { + return new Logic.Utilities.DateTime().ConvertUtcToUk(GetBusinessStartUtc()); + } /// - /// Gets the date bnhtrade started trading. + /// Gets the date bnhtrade started trading, as UTC time /// - /// Date and time + /// The UTC date and time the business started (datetime kind UTC) public static DateTime GetBusinessStartUtc() { - DateTime businessStart = new DateTime(2014, 09, 01); + DateTime businessStart = new DateTime(2014, 08, 31, 23, 00, 00); // 2014-09-01 uk date time return DateTime.SpecifyKind(businessStart, DateTimeKind.Utc); } diff --git a/src/bnhtrade.Core/Data/Database/Import/AmazonFbaReimbursement.cs b/src/bnhtrade.Core/Data/Database/Import/AmazonFbaReimbursement.cs index acb78ce..77f2c54 100644 --- a/src/bnhtrade.Core/Data/Database/Import/AmazonFbaReimbursement.cs +++ b/src/bnhtrade.Core/Data/Database/Import/AmazonFbaReimbursement.cs @@ -354,8 +354,8 @@ namespace bnhtrade.Core.Data.Database.Import item.Asin = reader.GetString(8); item.Condition = reader.GetString(9); item.CurrencyUnit = reader.GetString(10); - item.AmountPerUnit = reader.GetInt32(11); - item.AmountTotal = reader.GetInt32(12); + item.AmountPerUnit = reader.GetDecimal(11); + item.AmountTotal = reader.GetDecimal(12); item.QuantityReimbursedCash = reader.GetInt32(13); item.QuantityReimbursedInventory = reader.GetInt32(14); item.QuantityReimbursedTotal = reader.GetInt32(15); diff --git a/src/bnhtrade.Core/Data/Database/Import/AmazonSettlementInsert.cs b/src/bnhtrade.Core/Data/Database/Import/AmazonSettlementInsert.cs index 4719cb9..778368b 100644 --- a/src/bnhtrade.Core/Data/Database/Import/AmazonSettlementInsert.cs +++ b/src/bnhtrade.Core/Data/Database/Import/AmazonSettlementInsert.cs @@ -146,16 +146,16 @@ namespace bnhtrade.Core.Data.Database.Import sqlCommand.Parameters.AddWithValue("@settlementId", settlementRef); } - var parseDateTime = new Core.Logic.Utilities.DateTimeParse(); + var parseDateTime = new Core.Logic.Utilities.DateTime(); if (indexSettlementStartDate == -1 || items[indexSettlementStartDate].Length == 0) { sqlCommand.Parameters.AddWithValue("@settlementStartDate", DBNull.Value); } - else { sqlCommand.Parameters.AddWithValue("@settlementStartDate", parseDateTime.ParseMwsReportDateTime(items[indexSettlementStartDate])); } + else { sqlCommand.Parameters.AddWithValue("@settlementStartDate", parseDateTime.ParseIsoDateTimeString(items[indexSettlementStartDate])); } if (indexSettlementEndDate == -1 || items[indexSettlementEndDate].Length == 0) { sqlCommand.Parameters.AddWithValue("@settlementEndDate", DBNull.Value); } - else { sqlCommand.Parameters.AddWithValue("@settlementEndDate", parseDateTime.ParseMwsReportDateTime(items[indexSettlementEndDate])); } + else { sqlCommand.Parameters.AddWithValue("@settlementEndDate", parseDateTime.ParseIsoDateTimeString(items[indexSettlementEndDate])); } if (indexDepositDate == -1 || items[indexDepositDate].Length == 0) { sqlCommand.Parameters.AddWithValue("@depositDate", DBNull.Value); } - else { sqlCommand.Parameters.AddWithValue("@depositDate", parseDateTime.ParseMwsReportDateTime(items[indexDepositDate])); } + else { sqlCommand.Parameters.AddWithValue("@depositDate", parseDateTime.ParseIsoDateTimeString(items[indexDepositDate])); } if (indexTotalAmount == -1 || items[indexTotalAmount].Length == 0) { sqlCommand.Parameters.AddWithValue("@totalAmount", DBNull.Value); } else { sqlCommand.Parameters.AddWithValue("@settlementotalAmounttId", settlementAmount); } @@ -245,7 +245,7 @@ namespace bnhtrade.Core.Data.Database.Import else { sqlCommand.Parameters.AddWithValue("@FulfillmentRef", items[indexFulfillmentId]); } if (indexPostedDateTime == -1 || items[indexPostedDateTime].Length == 0) { sqlCommand.Parameters.AddWithValue("@PostedDateTimeUTC", DBNull.Value); } - else { sqlCommand.Parameters.AddWithValue("@PostedDateTimeUTC", new Logic.Utilities.DateTimeParse().ParseMwsReportDateTime(items[indexPostedDateTime])); } + else { sqlCommand.Parameters.AddWithValue("@PostedDateTimeUTC", new Logic.Utilities.DateTime().ParseIsoDateTimeString(items[indexPostedDateTime])); } if (indexOrderItemCode == -1 || items[indexOrderItemCode].Length == 0) { sqlCommand.Parameters.AddWithValue("@OrderItemCode", DBNull.Value); } else { sqlCommand.Parameters.AddWithValue("@OrderItemCode", long.Parse(items[indexOrderItemCode])); } diff --git a/src/bnhtrade.Core/Data/Database/SqlWhereBuilder.cs b/src/bnhtrade.Core/Data/Database/SqlWhereBuilder.cs index 812e4a7..73687f1 100644 --- a/src/bnhtrade.Core/Data/Database/SqlWhereBuilder.cs +++ b/src/bnhtrade.Core/Data/Database/SqlWhereBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Data.SqlClient; +using Microsoft.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -53,7 +54,19 @@ namespace bnhtrade.Core.Data.Database ParameterList = new Dictionary(); } - public void AddParametersToSqlCommand(SqlCommand cmd) + // delete this once all references use the new Microsoft.Data.SqlClient + public void AddParametersToSqlCommand(System.Data.SqlClient.SqlCommand cmd) + { + if (ParameterList != null) + { + foreach (var item in ParameterList) + { + cmd.Parameters.AddWithValue(item.Key, item.Value); + } + } + } + + public void AddParametersToSqlCommand(Microsoft.Data.SqlClient.SqlCommand cmd) { if (ParameterList != null) { diff --git a/src/bnhtrade.Core/Data/Database/Stock/InsertSkuTransactionType.cs b/src/bnhtrade.Core/Data/Database/Stock/InsertSkuTransactionType.cs index 83d483d..4a6236f 100644 --- a/src/bnhtrade.Core/Data/Database/Stock/InsertSkuTransactionType.cs +++ b/src/bnhtrade.Core/Data/Database/Stock/InsertSkuTransactionType.cs @@ -6,23 +6,19 @@ namespace bnhtrade.Core.Data.Database.Stock { public class InsertSkuTransactionType : Connection { - /// - /// The insert command will not participate in any amibent transaction scope. Default is true. - /// - public bool SuppressTransactionScope { get; set; } = true; - /// /// Creates a new SKU Transaction Type /// /// /// + /// The insert command will not participate in any amibent transaction scope /// ID of the created record /// - public int Create(string skuTransactionCode, int stockJournalTypeId) + public int Create(string skuTransactionCode, int stockJournalTypeId, bool transactionScopeSuppress = false) { int id; var scopeOption = new TransactionScopeOption(); - if (SuppressTransactionScope) + if (transactionScopeSuppress) { scopeOption = TransactionScopeOption.Suppress; } @@ -32,12 +28,13 @@ namespace bnhtrade.Core.Data.Database.Stock } using (TransactionScope scope = new TransactionScope(scopeOption)) - using (SqlConnection conn = new SqlConnection(SqlConnectionString)) { - conn.Open(); + using (SqlConnection conn = new SqlConnection(SqlConnectionString)) + { + conn.Open(); - // insert new and retrive new value - using (SqlCommand cmd = new SqlCommand(@" + // insert new and retrive new value + using (SqlCommand cmd = new SqlCommand(@" INSERT INTO tblStockSkuTransactionType ( TypeName, StockJournalTypeID, TypeCode ) OUTPUT @@ -45,19 +42,20 @@ namespace bnhtrade.Core.Data.Database.Stock VALUES ( @typeName, @stockJournalTypeId, @typeCode ); ", conn)) - { - cmd.Parameters.AddWithValue("@typeName", skuTransactionCode); - cmd.Parameters.AddWithValue("@typeCode", skuTransactionCode); - cmd.Parameters.AddWithValue("@stockJournalTypeId", stockJournalTypeId); + { + cmd.Parameters.AddWithValue("@typeName", skuTransactionCode); + cmd.Parameters.AddWithValue("@stockJournalTypeId", stockJournalTypeId); + cmd.Parameters.AddWithValue("@typeCode", skuTransactionCode); - object obj = cmd.ExecuteScalar(); + object obj = cmd.ExecuteScalar(); - if (obj == null || obj == DBNull.Value) - throw new Exception("tblStockSkuTransactionType insert operation returned null"); + if (obj == null || obj == DBNull.Value) + throw new Exception("tblStockSkuTransactionType insert operation returned null"); - id = (int)obj; + id = (int)obj; + } + scope.Complete(); } - scope.Complete(); } return id; } diff --git a/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransactionType.cs b/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransactionType.cs index 8f4cedd..df2d71d 100644 --- a/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransactionType.cs +++ b/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransactionType.cs @@ -4,7 +4,9 @@ using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Transactions; using Dapper; +using static System.Formats.Asn1.AsnWriter; namespace bnhtrade.Core.Data.Database.Stock { @@ -14,81 +16,10 @@ namespace bnhtrade.Core.Data.Database.Stock { } - /// - /// Depriciated, delete when not required by other code - /// - /// - /// - /// - public int GetTypeId(string typeCode) + private List Execute(string sqlWhere, DynamicParameters param, bool transactionScopeSuppress = false) { - /* GetStockTransactionTypeId return meanings - * >0 use as the TypeId when inserting transaction - * 0 Skip transpose, type doesn't exist or is new (not reviewed yet) - * -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */ + var returnList = new List(); - // old optional parameters - // , bool onNewReturnId = false, bool onNewDisableInsert = false - - if (typeCode.Length == 0) - { - throw new Exception("Empty match string passed to method"); - } - using (SqlConnection sqlConn = new SqlConnection(SqlConnectionString)) - { - sqlConn.Open(); - using (SqlCommand cmd = new SqlCommand(@" - SELECT - StockSkuTransactionTypeID, - IsNewReviewRequired, - TransactionImportEnabled - FROM - tblStockSkuTransactionType - WHERE - TypeCode=@typeCode; - ", sqlConn)) - { - cmd.Parameters.AddWithValue("@typeCode", typeCode); - - 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 0 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("Sku TransactionTypeId lookup method failed, is one of the 'enabled' boolean on table set to null?"); - } - } - else - { - return 0; - } - } - } - } - } - - private List Execute(string sqlWhere, DynamicParameters param) - { string sql = @" SELECT tblStockSkuTransactionType.StockSkuTransactionTypeID AS TypeId ,tblStockSkuTransactionType.TypeName @@ -117,13 +48,25 @@ namespace bnhtrade.Core.Data.Database.Stock using (SqlConnection conn = new SqlConnection(SqlConnectionString)) { - conn.Open(); - - return conn.Query(sql, param).ToList(); + if (transactionScopeSuppress) + { + using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress)) + { + conn.Open(); + returnList = conn.Query(sql, param).ToList(); + } + } + else + { + conn.Open(); + returnList = conn.Query(sql, param).ToList(); + } } + + return returnList; } - public List ByTypeCode(List typeCodeList) + public List ByTypeCode(List typeCodeList, bool transactionScopeSuppress = false) { typeCodeList.RemoveAll(string.IsNullOrWhiteSpace); @@ -138,7 +81,7 @@ namespace bnhtrade.Core.Data.Database.Stock return Execute(sqlWhere, param); } - public List ByTypeName(List typeName) + public List ByTypeName(List typeName, bool transactionScopeSuppress = false) { typeName.RemoveAll(string.IsNullOrWhiteSpace); diff --git a/src/bnhtrade.Core/Logic/Account/Currency.cs b/src/bnhtrade.Core/Logic/Account/Currency.cs index 0aa682d..49ced0b 100644 --- a/src/bnhtrade.Core/Logic/Account/Currency.cs +++ b/src/bnhtrade.Core/Logic/Account/Currency.cs @@ -1,23 +1,200 @@ -using System; +using FikaAmazonAPI.ConstructFeed.Messages; +using System; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Data.SqlClient; +using System.Globalization; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; +using System.Xml.Linq; namespace bnhtrade.Core.Logic.Account { public class Currency { + Log.LogEvent log = new Log.LogEvent(); + public decimal CurrencyConvertToGbp(string currencyCode, decimal amount, DateTime conversionDate) { - return new Data.Database.Account.Currency().CurrencyConvertToGbp(currencyCode, amount, conversionDate); + if (currencyCode == "GBP" || amount == 0M) + { + return amount; + } + + if (currencyCode.Length != 3) + { + throw new Exception("Invalid currency code '" + currencyCode + "'"); + } + + var db = new Data.Database.Account.Currency(); + var exchageRate = db.ReadExchangeRate(currencyCode, conversionDate); + + if (exchageRate != null) + { + return amount / Convert.ToDecimal(exchageRate); + } + else + { + throw new Exception("Currency code '" + currencyCode + "' or date " + conversionDate.ToShortDateString() + " " + conversionDate.ToLongTimeString() + "' does not exist in the Exchange Rate table"); + } + } - public int CurrencyExchangeRateInsert(int exchangeRateSource, string currencyCode, - decimal currencyUnitsPerGbp, DateTime periodStart, DateTime periodEnd, bool checkOverride = false) + private DateTime GetHmrcMaxPeriodAvaible() { - return new Data.Database.Account.Currency().CurrencyExchangeRateInsert(exchangeRateSource, currencyCode, - currencyUnitsPerGbp, periodStart, periodEnd, checkOverride); + // HMRC monthly sxchange rates are published on the penultimate Thursday of the month before + // For some leeway we'll use the penultimate Friday + + // find penultimate Friday for current month + var ukTimeNow = new Logic.Utilities.DateTime().ConvertUtcToUk(DateTime.UtcNow); + var monthDayCount = DateTime.DaysInMonth(ukTimeNow.Year, ukTimeNow.Month); + var thisMonthPenultimateFriday = DateTime.SpecifyKind(new DateTime(ukTimeNow.Year, ukTimeNow.Month, monthDayCount), DateTimeKind.Unspecified); + int count = 0; + int fridayCount = 0; + while (count != 15) + { + if (thisMonthPenultimateFriday.DayOfWeek == DayOfWeek.Friday) + { + fridayCount++; + if (fridayCount == 2) + { + break; + } + } + thisMonthPenultimateFriday = thisMonthPenultimateFriday.AddDays(-1); + count++; + } + + if (count == 15) + { + throw new Exception("Something went wrong here ErrorID:ef7f5d8f-0f7b-4014-aa65-421ecd5d7367"); + } + + var mostRecentPeriodAvaible = DateTime.SpecifyKind(new DateTime(ukTimeNow.Year, ukTimeNow.Month, 1), DateTimeKind.Unspecified); ; + if (ukTimeNow >= thisMonthPenultimateFriday) + { + mostRecentPeriodAvaible = mostRecentPeriodAvaible.AddMonths(1); + } + + return mostRecentPeriodAvaible; + } + + public void UpdateHmrcExchageRates() + { + log.LogInformation("Starting update database HMRC exchange rates"); + + int exchangeRateSourceId = 1; // id for hmrc + + // retrive most recent data from db + var db = new Data.Database.Account.Currency(); + var dbLatestRates = db.ReadExchangeRateLatest(); + + // sanity check, make sure there are no duplicates + int count = 0; + foreach (var exchageRate in dbLatestRates) + { + count = 0; + var currency = exchageRate.CurrencyCode; + foreach (var subExchageRate in dbLatestRates) + { + if (exchageRate.CurrencyCode == subExchageRate.CurrencyCode) + { + count = 1; + } + } + if (count > 1) + { + throw new FormatException("Datebase returned duplicate information"); + } + } + + // test for no data (first time running) + var hmrcMonthToRetrive = new DateTime(); + if (dbLatestRates.Any() == false) + { + hmrcMonthToRetrive = Data.Database.Constants.GetBusinessStartUk(); + } + + // set first/earliest month to retrive from hmrc website + foreach (var exchageRate in dbLatestRates) + { + var dbEndDateTime = exchageRate.DateTimeEndUk; + + if (hmrcMonthToRetrive == default(DateTime)) + { + hmrcMonthToRetrive = dbEndDateTime; + } + else + { + if (dbEndDateTime < hmrcMonthToRetrive) + { + hmrcMonthToRetrive = dbEndDateTime; + } + } + } + + // check - more coding required to retrive periods before 2021-01-01 + if (hmrcMonthToRetrive < DateTime.SpecifyKind(new DateTime(2021, 1, 1), DateTimeKind.Unspecified)) + { + throw new Exception("This function does not currently retirve exchange rates from HMRC for dates before 2021-01-01"); + } + + // check if retrival from hmrc is required + var hmrcMaxMonthAvaible = GetHmrcMaxPeriodAvaible(); + if (hmrcMonthToRetrive.Year == hmrcMaxMonthAvaible.Year && hmrcMonthToRetrive.Month > hmrcMaxMonthAvaible.Month) + { + // nothing to retrive + log.LogInformation("Exchange rates curretly up to date, exiting."); + return; + } + + // get info from hmrc and insert data in db + while (hmrcMonthToRetrive <= hmrcMaxMonthAvaible) + { + count = 0; + + var url = new string( + "https://www.trade-tariff.service.gov.uk/api/v2/exchange_rates/files/monthly_xml_" + + hmrcMonthToRetrive.Year.ToString() + + "-" + + hmrcMonthToRetrive.Month.ToString() + + ".xml" + ); + var xd = new XDocument(); + xd = XDocument.Load(url); + + foreach (var exchageRate in dbLatestRates) + { + if (exchageRate.DateTimeStartUtc < hmrcMonthToRetrive) + { + //retrive exchange rate from xml + XElement node = xd.Root.Elements("exchangeRate").Where(e => e.Element("currencyCode").Value == exchageRate.CurrencyCode.ToString()).FirstOrDefault(); + decimal rate = decimal.Parse(node.Element("rateNew").Value); + rate = decimal.Round(rate, 4); + + // insert into db + new Data.Database.Account.Currency().InsertExchangeRate( + exchangeRateSourceId + , exchageRate.CurrencyCode + , rate + , new Utilities.DateTime().ConvertUkToUtc(hmrcMonthToRetrive) + , new Utilities.DateTime().ConvertUkToUtc(hmrcMonthToRetrive.AddMonths(1)) + ); + + count++; + } + } + + log.LogInformation( + count + " new exchange rate(s) added to database for " + hmrcMonthToRetrive.ToString("MMMM") + " " + hmrcMonthToRetrive.Year.ToString() + ); + + hmrcMonthToRetrive = hmrcMonthToRetrive.AddMonths(1); + } + + log.LogInformation("Updating database currency exchange rates complete."); } } } diff --git a/src/bnhtrade.Core/Logic/Import/AmazonFbaCustomerReturn.cs b/src/bnhtrade.Core/Logic/Import/AmazonFbaCustomerReturn.cs index 206fd87..193db10 100644 --- a/src/bnhtrade.Core/Logic/Import/AmazonFbaCustomerReturn.cs +++ b/src/bnhtrade.Core/Logic/Import/AmazonFbaCustomerReturn.cs @@ -45,7 +45,7 @@ namespace bnhtrade.Core.Logic.Import dateLog.SetDateTimeUtc(reportName, utcEndDate); scope.Complete(); } - log.LogInformation("Amazon report '" + reportName + "' sync with database comlpete."); + log.LogInformation("Amazon report '" + reportName + "' sync with database complete."); } } } diff --git a/src/bnhtrade.Core/Logic/Stock/SkuTransactionCrud.cs b/src/bnhtrade.Core/Logic/Stock/SkuTransactionCrud.cs index 1bf36d8..4e8637d 100644 --- a/src/bnhtrade.Core/Logic/Stock/SkuTransactionCrud.cs +++ b/src/bnhtrade.Core/Logic/Stock/SkuTransactionCrud.cs @@ -126,9 +126,6 @@ namespace bnhtrade.Core.Logic.Stock /// public int Create(Model.Stock.SkuTransactionCreate skuTransaction) { - // need to add function to check if transaction type exists, if not, create a new one. - throw new NotImplementedException(); - if (skuTransaction == null) { throw new Exception(err + "Object was null"); diff --git a/src/bnhtrade.Core/Logic/Stock/SkuTransactionImport.cs b/src/bnhtrade.Core/Logic/Stock/SkuTransactionImport.cs index 27618d6..1b1faef 100644 --- a/src/bnhtrade.Core/Logic/Stock/SkuTransactionImport.cs +++ b/src/bnhtrade.Core/Logic/Stock/SkuTransactionImport.cs @@ -39,10 +39,10 @@ namespace bnhtrade.Core.Logic.Stock private string ConstructTransactionTypeCode(Model.Import.AmazonFbaInventoryLedgerDetail record) { - if (string.IsNullOrEmpty(record.Reason)) - { - return null; - } + //if (string.IsNullOrEmpty(record.Reason)) + //{ + // return null; + //} string transactionCode = "<" + record.EventType + ">"; @@ -66,33 +66,26 @@ namespace bnhtrade.Core.Logic.Stock } /// - /// Imports/Transaposes all data required for reconcilation, into the sku transaction table. + /// Imports/Transaposes all required data into sku transaction table for reconcilation. /// public void ImportAll() { - bool inventoryLedgerDetail = false; - bool reimbursement = false; + string methodName = "'Import all' data to 'Stock SKU Transactions'"; - while (true) + log.LogInformation(methodName + " started..."); + + try { - try - { - if (true) - { - if (inventoryLedgerDetail == false) { inventoryLedgerDetail = true; ImportAmazonFbaLedgerDetail(); } - if (reimbursement == false) { reimbursement = true; ImportAmazonFbaReimbursement(); } - } - - break; - } - catch (Exception ex) - { - log.LogError( - "Exception caught running Importing amazon reports in the SKU transaction table, see for further details", - ex.ToString() - ); - } + ImportAmazonFbaLedgerDetail(); + ImportAmazonFbaReimbursement(); } + catch + { + log.LogError(methodName + " did not complete."); + throw; + } + + log.LogInformation(methodName + " complete."); } /// @@ -101,7 +94,9 @@ namespace bnhtrade.Core.Logic.Stock /// public void ImportAmazonFbaReimbursement() { - throw new NotImplementedException("Needs testing"); + string methodName = "Import 'Amazon FBA Reimbursement' into 'Stock SKU Transactions'"; + + //throw new NotImplementedException("Needs testing"); /* * Not to be used for stock reconciliation! A single stock item can have multiple reimburesements aginst it. @@ -112,9 +107,9 @@ namespace bnhtrade.Core.Logic.Stock * and also the 'Cost of goods' amounts moved to the appropreate account id */ - log.LogInformation("Starting TransposeFbaRemovalOrderReport()"); - int transposeCount = 0; - int transposeSkip = 0; + log.LogInformation(methodName + " started..."); + int importedCount = 0; + int processedCount = 0; var dbAmznReport = new Data.Database.Import.AmazonFbaReimbursement(); var dbTransType = new Logic.Stock.SkuTransactionTypeCrud(); @@ -128,6 +123,8 @@ namespace bnhtrade.Core.Logic.Stock var transTypeCodeList = new List(); foreach (var item in importList) { + processedCount++; + transTypeCodeList.Add(ConstructTransactionTypeCode(item, false)); // any that reimburse inventory, will have two entries if(item.QuantityReimbursedInventory > 0) @@ -170,7 +167,7 @@ namespace bnhtrade.Core.Logic.Stock // don't go any further until the transaction-type has been reviewed/setup if (foundNewType) { - log.LogWarning("Cannot complete ImportAmazonFbaReimbursement, new 'Stock Trnasaction Type' found. Review required/"); + log.LogWarning(methodName + " unable to complete. New 'Stock Trnasaction Type' found. Review required/"); return; } @@ -189,7 +186,7 @@ namespace bnhtrade.Core.Logic.Stock if (transType.IsNewReviewRequired) { - throw new Exception("Fail safe: Buggy code, should not get here!"); + throw new Exception(methodName + " fail safe: Buggy code, should not get here!"); } else if (transType.TransactionImportEnabled) { @@ -214,7 +211,7 @@ namespace bnhtrade.Core.Logic.Stock if (transType.IsNewReviewRequired) { - throw new Exception("Fail safe: Buggy code, should not get here!"); + throw new Exception(methodName + " fail safe: Buggy code, should not get here!"); } else if (transType.TransactionImportEnabled) { @@ -233,20 +230,26 @@ namespace bnhtrade.Core.Logic.Stock } // update the amazon report table dbAmznReport.UpdateIsProcessed(item.FbaReimbursementReportID, true, transId); - transposeCount = transposeCount + 1; + importedCount++; } // drop out of loop scope.Complete(); } Console.Write("\r"); - log.LogInformation("ProcessFbaReimbursementData() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped."); + + log.LogInformation( + methodName + " complete. Records transferred/processed " + importedCount + "/" + processedCount + ); } catch (Exception ex) { - log.LogError("Exception catch, aborting ProcessFbaReimbursementData(), see detailed info. " - + transposeCount + " total records completed, " + transposeSkip + " records skipped.", ex.ToString()); - } + log.LogError( + methodName + " aborted due an exception, no records where modified." + , ex.ToString() + ); + throw; + } } /// @@ -255,12 +258,11 @@ namespace bnhtrade.Core.Logic.Stock /// public void ImportAmazonFbaLedgerDetail() { - // Done but needs testing!! - throw new NotImplementedException("Done but needs testing!!"); + string methodName = "Import 'Amazon FBA Ledger Detail' into 'Stock SKU Transactions'"; - log.LogInformation("Starting TransposeFbaAdustmentReport()"); - int transposeCount = 0; - int transposeSkip = 0; + log.LogInformation(methodName + " started"); + int transferredCount = 0; + int processedCount = 0; using (var scope = new TransactionScope()) { @@ -275,6 +277,8 @@ namespace bnhtrade.Core.Logic.Stock var transCodeToJournalTypeId = new Dictionary(); foreach (var item in reportDict) { + processedCount++; + // test for internal Amazon stuff that we don't care about and mark as processed if (item.Value.EventType == "WhseTransfers") { @@ -340,21 +344,25 @@ namespace bnhtrade.Core.Logic.Stock } } - // check for any new types codes, and add them if ther are - var dbTransType = new Logic.Stock.SkuTransactionTypeCrud(); - var transTypeList = dbTransType.GetByTypeCode(transCodeToJournalTypeId.Keys.ToList()); - - foreach ( var transType in transTypeList) + // check for any new types codes, remove existing from list and add remaing to db + using (TransactionScope scope2 = new TransactionScope(TransactionScopeOption.Suppress)) { - if (transCodeToJournalTypeId.ContainsKey(transType.Key)) + var dbTransType = new Logic.Stock.SkuTransactionTypeCrud(); + + var transTypeList = dbTransType.GetByTypeCode(transCodeToJournalTypeId.Keys.ToList()); + + foreach (var transType in transTypeList) { - transCodeToJournalTypeId.Remove(transType.Key); + if (transCodeToJournalTypeId.ContainsKey(transType.Key)) + { + transCodeToJournalTypeId.Remove(transType.Key); + } } - } - foreach (var newItem in transCodeToJournalTypeId) - { - dbTransType.Create(newItem.Key, newItem.Value); + foreach (var newItem in transCodeToJournalTypeId) + { + dbTransType.Create(newItem.Key, newItem.Value); + } } // finally, add the transction list to the table @@ -363,33 +371,28 @@ namespace bnhtrade.Core.Logic.Stock { int id = dbTransaction.Create(item); dbImport.UpdateIsProcessed((int)item.ForeignKey, id); + transferredCount++; } scope.Complete(); log.LogInformation( - "TransposeFbaAdustmentReport() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped." + methodName + " complete. Records transferred/processed " + transferredCount + "/" + processedCount ); - if (transposeSkip > 0) - { - log.LogInformation( - transposeSkip + " number records skipped during TransposeFbaAdustmentReport() operation." - ); - } } catch (Exception ex) { scope.Dispose(); log.LogError( - "Exception catch, aborting TransposeFbaAdustmentReport(), see detailed info. " - + transposeCount + " total records completed, " + transposeSkip + " records skipped." + methodName + " aborted, no records modified. See additional info exception details." , ex.ToString() ); + + throw; } } - return; } } } diff --git a/src/bnhtrade.Core/Logic/Stock/SkuTransactionTypeCrud.cs b/src/bnhtrade.Core/Logic/Stock/SkuTransactionTypeCrud.cs index 7192928..62e9352 100644 --- a/src/bnhtrade.Core/Logic/Stock/SkuTransactionTypeCrud.cs +++ b/src/bnhtrade.Core/Logic/Stock/SkuTransactionTypeCrud.cs @@ -25,15 +25,15 @@ namespace bnhtrade.Core.Logic.Stock /// /// Id for new record entry /// Transaction type code already exists - public int Create(string skuTransactionTypeCode, int stockJournalTypeId) + public int Create(string skuTransactionTypeCode, int stockJournalTypeId, bool transactionScopeSuppress = false) { //check to see if type already exists - var result = dbRead.ByTypeCode(new List { skuTransactionTypeCode }); + var result = dbRead.ByTypeCode(new List { skuTransactionTypeCode }, transactionScopeSuppress); if (result.Any()) throw new InvalidOperationException("Create SKU Transaction Type failed, typecode already exists failed"); // okay to proceed - int id = new Data.Database.Stock.InsertSkuTransactionType().Create(skuTransactionTypeCode, stockJournalTypeId); + int id = new Data.Database.Stock.InsertSkuTransactionType().Create(skuTransactionTypeCode, stockJournalTypeId, transactionScopeSuppress); return id; } @@ -42,14 +42,14 @@ namespace bnhtrade.Core.Logic.Stock /// /// /// The object, or null - public Model.Stock.SkuTransactionType GetByTypeCode(string typeCode) + public Model.Stock.SkuTransactionType GetByTypeCode(string typeCode, bool transactionScopeSuppress = false) { if (string.IsNullOrWhiteSpace(typeCode)) { return null; } - var result = dbRead.ByTypeCode(new List { typeCode }); + var result = dbRead.ByTypeCode(new List { typeCode }, transactionScopeSuppress); if (result.Any()) { @@ -66,7 +66,7 @@ namespace bnhtrade.Core.Logic.Stock /// /// list of transaction type codes /// DIctionary key=transactionTypeCode, value=transactionType object - public Dictionary GetByTypeCode(List typeCodeList) + public Dictionary GetByTypeCode(List typeCodeList, bool transactionScopeSuppress = false) { var returnDict = new Dictionary(); if (!typeCodeList.Any()) @@ -74,7 +74,7 @@ namespace bnhtrade.Core.Logic.Stock return returnDict; } - var dbResult = dbRead.ByTypeCode(typeCodeList); + var dbResult = dbRead.ByTypeCode(typeCodeList, transactionScopeSuppress); foreach(var item in dbResult) { diff --git a/src/bnhtrade.Core/Logic/Utilities/DateTime.cs b/src/bnhtrade.Core/Logic/Utilities/DateTime.cs new file mode 100644 index 0000000..efb1e45 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Utilities/DateTime.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 DateTime + { + public System.DateTime ConvertUkToUtc(System.DateTime ukDateTime) + { + if (ukDateTime.Kind == DateTimeKind.Local && TimeZoneInfo.Local.Id != "GMT Standard Time") + { + throw new System.ArgumentException("DateTime kind set to local, local is not set to 'GMT Standard Time'"); + } + else if (ukDateTime.Kind == DateTimeKind.Utc) + { + throw new System.ArgumentException("DateTime kind is UTC"); + } + + TimeZoneInfo ukZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"); + System.DateTime ukTime = TimeZoneInfo.ConvertTimeToUtc(ukDateTime, ukZone); + return ukTime; // is returned as DateTimeKind 'unspecified' + } + + public System.DateTime ConvertUtcToUk(System.DateTime utcDateTime) + { + if (utcDateTime.Kind != DateTimeKind.Utc) + { + throw new System.ArgumentException("DateTime kind is not UTC"); + } + + TimeZoneInfo ukZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"); + System.DateTime ukTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, ukZone); + return ukTime; // is returned as DateTimeKind 'unspecified' + } + + public System.DateTime ParseIsoDateTimeString(string reportDateTime) + { + string isoDateTime = + reportDateTime.Substring(6, 4) + "-" + + reportDateTime.Substring(3, 2) + "-" + + reportDateTime.Substring(0, 2) + "T" + + reportDateTime.Substring(11, 2) + ":" + + reportDateTime.Substring(14, 2) + ":" + + reportDateTime.Substring(17, 2) + "Z"; + return System.DateTime.Parse(isoDateTime); + } + } +} diff --git a/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs b/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs index dacc3fe..a1a2d2f 100644 --- a/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs +++ b/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs @@ -8,9 +8,9 @@ namespace bnhtrade.Core.Logic.Utilities { public class DateTimeCheck : Validate.Validate { - public bool IsUtc(DateTime dateTimeToCheck) + public bool IsUtc(System.DateTime dateTimeToCheck) { - if (dateTimeToCheck == default(DateTime)) + if (dateTimeToCheck == default(System.DateTime)) { ValidationResultAdd( "DateTime value set to default."); return false; @@ -22,9 +22,9 @@ namespace bnhtrade.Core.Logic.Utilities } return true; } - public bool IsLocal(DateTime dateTimeToCheck) + public bool IsLocal(System.DateTime dateTimeToCheck) { - if (dateTimeToCheck == default(DateTime)) + if (dateTimeToCheck == default(System.DateTime)) { ValidationResultAdd("DateTime value set to default."); return false; diff --git a/src/bnhtrade.Core/Logic/Utilities/DateTimeParse.cs b/src/bnhtrade.Core/Logic/Utilities/DateTimeParse.cs deleted file mode 100644 index 970a387..0000000 --- a/src/bnhtrade.Core/Logic/Utilities/DateTimeParse.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace bnhtrade.Core.Logic.Utilities -{ - public class DateTimeParse - { - public DateTime ParseMwsReportDateTime(string reportDateTime) - { - string isoDateTime = - reportDateTime.Substring(6, 4) + "-" + - reportDateTime.Substring(3, 2) + "-" + - reportDateTime.Substring(0, 2) + "T" + - reportDateTime.Substring(11, 2) + ":" + - reportDateTime.Substring(14, 2) + ":" + - reportDateTime.Substring(17, 2) + "Z"; - return DateTime.Parse(isoDateTime); - } - } -} diff --git a/src/bnhtrade.Core/Logic/Utilities/ListFunction.cs b/src/bnhtrade.Core/Logic/Utilities/ListFunction.cs new file mode 100644 index 0000000..5712e89 --- /dev/null +++ b/src/bnhtrade.Core/Logic/Utilities/ListFunction.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Logic.Utilities +{ + public class ListFunction + { + public ListFunction() { } + + /// + /// Outputs a unique list from an input list + /// + /// + /// + /// Unique list + public List UniqueList(List inputList, bool removeNullorWhitespace = true) + { + List outputList = new List(); + + foreach (string input in inputList) + { + if (string.IsNullOrWhiteSpace(input) && removeNullorWhitespace) + { + break; + } + + bool stringExists = false; + foreach (string output in outputList) + { + if (output == input) + { + stringExists = true; + break; + } + } + + if (stringExists == false) + { + outputList.Add(input); + } + } + + return outputList; + } + + public List UniqueList(List inputList, bool removeNullorWhitespace = true) + { + List stringList = new List(); + foreach (Enum input in inputList) + { + stringList.Add(input.ToString()); + } + return UniqueList(stringList, removeNullorWhitespace); + } + } +} diff --git a/src/bnhtrade.Core/Logic/Utilities/NightlyRoutine.cs b/src/bnhtrade.Core/Logic/Utilities/NightlyRoutine.cs index 586f2f3..153b206 100644 --- a/src/bnhtrade.Core/Logic/Utilities/NightlyRoutine.cs +++ b/src/bnhtrade.Core/Logic/Utilities/NightlyRoutine.cs @@ -21,6 +21,7 @@ namespace bnhtrade.Core.Logic.Utilities var export = new bnhtrade.Core.Logic.Export.AmazonSettlement(); bool stockUpdate = false; + bool exchangeRate = false; bool accountProcess = false; while (true) @@ -28,6 +29,7 @@ namespace bnhtrade.Core.Logic.Utilities try { if (stockUpdate == false) { stockUpdate = true; new bnhtrade.Core.Logic.Import.Amazon().SyncAllWithDatabase(); ; } + if (exchangeRate == false) { exchangeRate = true; new Logic.Account.Currency().UpdateHmrcExchageRates(); } if (accountProcess == false) { accountProcess = true; export.ToInvoice(); } // if (stockProcess == false) { stockProcess = true; stock.ProcessFbaStockImportData(); } diff --git a/src/bnhtrade.Core/Logic/Validate/Format.cs b/src/bnhtrade.Core/Logic/Validate/Format.cs index 08c35cf..989b485 100644 --- a/src/bnhtrade.Core/Logic/Validate/Format.cs +++ b/src/bnhtrade.Core/Logic/Validate/Format.cs @@ -15,7 +15,10 @@ namespace bnhtrade.Core.Logic.Validate /// public static bool SkuNumber(string skuNumber) { - if (string.IsNullOrEmpty(skuNumber)) { return false;} + if (string.IsNullOrEmpty(skuNumber)) + { + return false; + } int count = 0; foreach (char c in skuNumber) @@ -50,11 +53,17 @@ namespace bnhtrade.Core.Logic.Validate public static bool DateTime(DateTime dateTime) { if (dateTime == default(DateTime)) - { return false; } + { + return false; + } else if (dateTime.Kind != DateTimeKind.Utc) - { return false; } + { + return false; + } else - { return true; } + { + return true; + } } } } diff --git a/src/bnhtrade.Core/Model/Account/CurrencyCode.cs b/src/bnhtrade.Core/Model/Account/CurrencyCode.cs new file mode 100644 index 0000000..f6629e2 --- /dev/null +++ b/src/bnhtrade.Core/Model/Account/CurrencyCode.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Account +{ + public enum CurrencyCode + { + AED, + AFN, + ALL, + AMD, + ANG, + AOA, + ARS, + AUD, + AWG, + AZN, + BAM, + BBD, + BDT, + BGN, + BHD, + BIF, + BMD, + BND, + BOB, + BOV, + BRL, + BSD, + BTN, + BWP, + BYN, + BYR, + BZD, + CAD, + CDF, + CHE, + CHF, + CHW, + CLF, + CLP, + CNY, + COP, + COU, + CRC, + CUC, + CUP, + CVE, + CZK, + DJF, + DKK, + DOP, + DZD, + EGP, + ERN, + ETB, + EUR, + FJD, + FKP, + GBP, + GEL, + GHS, + GIP, + GMD, + GNF, + GTQ, + GYD, + HKD, + HNL, + HRK, + HTG, + HUF, + IDR, + ILS, + INR, + IQD, + IRR, + ISK, + JMD, + JOD, + JPY, + KES, + KGS, + KHR, + KMF, + KPW, + KRW, + KWD, + KYD, + KZT, + LAK, + LBP, + LKR, + LRD, + LSL, + LYD, + MAD, + MDL, + MGA, + MKD, + MMK, + MNT, + MOP, + MRO, + MUR, + MVR, + MWK, + MXN, + MXV, + MYR, + MZN, + NAD, + NGN, + NIO, + NOK, + NPR, + NZD, + OMR, + PAB, + PEN, + PGK, + PHP, + PKR, + PLN, + PYG, + QAR, + RON, + RSD, + RUB, + RWF, + SAR, + SBD, + SCR, + SDG, + SEK, + SGD, + SHP, + SLL, + SOS, + SRD, + SSP, + STD, + SVC, + SYP, + SZL, + THB, + TJS, + TMT, + TND, + TOP, + TRY, + TTD, + TWD, + TZS, + UAH, + UGX, + USD, + USN, + UYI, + UYU, + UZS, + VEF, + VND, + VUV, + WST, + XAF, + XAG, + XAU, + XBA, + XBB, + XBC, + XBD, + XCD, + XDR, + XOF, + XPD, + XPF, + XPT, + XSU, + XTS, + XUA, + XXX, + YER, + ZAR, + ZMW, + ZWL + } +} diff --git a/src/bnhtrade.Core/Model/Account/CurrencyExchangeRate.cs b/src/bnhtrade.Core/Model/Account/CurrencyExchangeRate.cs new file mode 100644 index 0000000..5558f78 --- /dev/null +++ b/src/bnhtrade.Core/Model/Account/CurrencyExchangeRate.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace bnhtrade.Core.Model.Account +{ + public class CurrencyExchangeRate + { + public CurrencyExchangeRate(CurrencyCode currencyCode, int exchangeRateSource, DateTime dateTimeStartUtc, DateTime dateTimeEndUtc) + { + this.CurrencyCode = currencyCode; + this.ExchangeRateSource = exchangeRateSource; + + if (dateTimeEndUtc > dateTimeStartUtc) + { + this.DateTimeStartUtc = dateTimeStartUtc; + this.DateTimeEndUtc = dateTimeEndUtc; + } + else + { + throw new ArgumentException("Incorrect start and/or end date value(s)"); + } + } + + public CurrencyCode CurrencyCode { get; private set; } + + public int ExchangeRateSource { get; private set; } + + public decimal CurrencyUnitsPerGbp { get; private set; } + + public DateTime DateTimeStartUk + { + get + { + return new Logic.Utilities.DateTime().ConvertUtcToUk(DateTimeStartUtc); + } + } + + public DateTime DateTimeStartUtc { get; private set; } + + public DateTime DateTimeEndUk + { + get + { + return new Logic.Utilities.DateTime().ConvertUtcToUk(DateTimeEndUtc); + } + } + + public DateTime DateTimeEndUtc { get; private set; } + + + /// + /// Checks whether a given datetime falls within the the exchange rate period + /// + /// The date and time to check + /// True or false + public bool DateTimeWithinPeriodCheck(DateTime dateTimeToCheck) + { + if (dateTimeToCheck >= DateTimeStartUtc && dateTimeToCheck < DateTimeEndUtc) + { + return true; + } + else + { + return false; + } + } + } +} diff --git a/src/bnhtrade.Core/Model/Account/Invoice.cs b/src/bnhtrade.Core/Model/Account/Invoice.cs index c908775..aae6d67 100644 --- a/src/bnhtrade.Core/Model/Account/Invoice.cs +++ b/src/bnhtrade.Core/Model/Account/Invoice.cs @@ -42,7 +42,7 @@ namespace bnhtrade.Core.Model.Account public abstract class Invoice : InvoiceHeader, IInvoice { - private bool unitAmountIsTaxExclusive = true; + private bool unitAmountIsTaxExclusive = false; public decimal InvoiceNetAmount { get; } diff --git a/src/bnhtrade.Core/Model/Credentials/bnhtradeDB.cs b/src/bnhtrade.Core/Model/Credentials/bnhtradeDB.cs index 6071447..c8140ab 100644 --- a/src/bnhtrade.Core/Model/Credentials/bnhtradeDB.cs +++ b/src/bnhtrade.Core/Model/Credentials/bnhtradeDB.cs @@ -28,7 +28,7 @@ namespace bnhtrade.Core.Model.Credentials { return "Data Source=" + DataSource + ";Initial Catalog=" + InitialCatalog + ";Persist Security Info=" + PersistSecurityInfo.ToString() + ";User ID=" + UserId + ";Password=" + UserPassword + ";MultipleActiveResultSets=" + MultipleActiveResultSets.ToString() - + ";Connect Timeout=" + ConnectionTimeout; + + ";Connect Timeout=" + ConnectionTimeout + ";Encrypt=True;TrustServerCertificate=True"; } } diff --git a/src/bnhtrade.Core/Model/Stock/SkuTransactionCreate.cs b/src/bnhtrade.Core/Model/Stock/SkuTransactionCreate.cs index f959e12..03c00e1 100644 --- a/src/bnhtrade.Core/Model/Stock/SkuTransactionCreate.cs +++ b/src/bnhtrade.Core/Model/Stock/SkuTransactionCreate.cs @@ -54,7 +54,7 @@ namespace bnhtrade.Core.Model.Stock { var result = new List(); - if (Logic.Validate.Format.DateTime(TransactionDate)) + if (Logic.Validate.Format.DateTime(TransactionDate) == false) { result.Add(new ValidationResult("Invalid transaction date")); } @@ -62,7 +62,7 @@ namespace bnhtrade.Core.Model.Stock { result.Add(new ValidationResult("Invalid transaction type code")); } - if (Logic.Validate.Format.SkuNumber(SkuNumber)) + if (Logic.Validate.Format.SkuNumber(SkuNumber) == false) { result.Add(new ValidationResult("Invalid SKU number")); } diff --git a/src/bnhtrade.Core/Properties/Settings.Designer.cs b/src/bnhtrade.Core/Properties/Settings.Designer.cs index a3552dd..54f8522 100644 --- a/src/bnhtrade.Core/Properties/Settings.Designer.cs +++ b/src/bnhtrade.Core/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace bnhtrade.Core.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/src/bnhtrade.Core/Test/Account/Account.cs b/src/bnhtrade.Core/Test/Account/Account.cs index cbd55e2..04c9ded 100644 --- a/src/bnhtrade.Core/Test/Account/Account.cs +++ b/src/bnhtrade.Core/Test/Account/Account.cs @@ -1,9 +1,12 @@ -using System; +using bnhtrade.Core.Data.Database.Account; +using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms.Design; +using System.Xml; +using System.Xml.Linq; namespace bnhtrade.Core.Test.Account { @@ -11,7 +14,13 @@ namespace bnhtrade.Core.Test.Account { public Account() { - Journal(); + UpdateHmrcExchageRates(); + } + + public void UpdateHmrcExchageRates() + { + var logic = new bnhtrade.Core.Logic.Account.Currency(); + logic.UpdateHmrcExchageRates(); } public void PurchaseInvoice() diff --git a/src/bnhtrade.Core/bnhtrade.Core.csproj b/src/bnhtrade.Core/bnhtrade.Core.csproj index 55a9e13..924196e 100644 --- a/src/bnhtrade.Core/bnhtrade.Core.csproj +++ b/src/bnhtrade.Core/bnhtrade.Core.csproj @@ -5,6 +5,8 @@ false true true + + false @@ -30,28 +32,30 @@ - - - - - - - - - true - + - - - - true - - - - + + + + + + + + + True + True + Settings.settings + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + \ No newline at end of file diff --git a/src/bnhtrade.ScheduledTasks/Program.cs b/src/bnhtrade.ScheduledTasks/Program.cs index 3e4af66..f797450 100644 --- a/src/bnhtrade.ScheduledTasks/Program.cs +++ b/src/bnhtrade.ScheduledTasks/Program.cs @@ -25,6 +25,7 @@ namespace bnhtradeScheduledTasks Console.WriteLine(); Console.WriteLine("<1> Amazon reports"); Console.WriteLine("<2> Stock functions"); + Console.WriteLine("<3> Account functions"); Console.WriteLine(""); Console.WriteLine("<8> Start scheduled nightly tasks"); Console.WriteLine("<9> Dev functions"); @@ -50,12 +51,12 @@ namespace bnhtradeScheduledTasks 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("<3> Update FBA Inventory Ledger Data (new)"); Console.WriteLine("<4> Update Amazon Settlement Data"); - Console.WriteLine("<5> Update Fba Inventory Receipt Data"); + Console.WriteLine("<5> (depreciated) Update Fba Inventory Receipt Data"); Console.WriteLine("<6> Update Fba Sale Shipment Data"); Console.WriteLine("<7> Update Fba Return Data"); - Console.WriteLine("<8> Update Fba Adustment Data"); + Console.WriteLine("<8> (depreciated) Update Fba Adustment Data"); Console.WriteLine("<9> Update Fba Removal Order Data"); Console.WriteLine(); Console.WriteLine("<0> Back"); @@ -84,7 +85,7 @@ namespace bnhtradeScheduledTasks else if (input == "3") { Console.Clear(); - new bnhtrade.Core.Logic.Import.AmazonFbaInventoryAge().SyncDatabaseWithAmazon(); + new bnhtrade.Core.Logic.Import.AmazonFbaInventoryLedgerDetail().SyncDatabaseWithAmazon(); Console.WriteLine("Complete, press any key to continue..."); Console.ReadKey(); } @@ -242,6 +243,34 @@ namespace bnhtradeScheduledTasks } while (true); } + else if (input == "3") + { + do + { + Console.Clear(); + Console.WriteLine(consoleHeader); + Console.WriteLine("Main Menu > Account"); + Console.WriteLine(); + Console.WriteLine("<1> Update HMRC Exchange Rates"); + Console.WriteLine(); + Console.WriteLine("<0> Back"); + Console.WriteLine(""); + Console.Write("Enter an option >"); + input = Console.ReadLine(); + + if (input == "0") + { + break; + } + else if (input == "1") + { + Console.Clear(); + new bnhtrade.Core.Logic.Account.Currency().UpdateHmrcExchageRates(); + Console.WriteLine("Complete, press any key to continue..."); + Console.ReadKey(); + } + } while (true); + } else if (input == "8") { Console.Clear(); diff --git a/src/bnhtrade.ScheduledTasks/bnhtrade.ScheduledTasks.csproj b/src/bnhtrade.ScheduledTasks/bnhtrade.ScheduledTasks.csproj index 4b3c2a2..29c1d33 100644 --- a/src/bnhtrade.ScheduledTasks/bnhtrade.ScheduledTasks.csproj +++ b/src/bnhtrade.ScheduledTasks/bnhtrade.ScheduledTasks.csproj @@ -64,8 +64,7 @@ - - + bnhtrade Scheduled Tasks diff --git a/src/bnhtrade.gui/FormConsole.Designer.cs b/src/bnhtrade.gui/FormConsole.Designer.cs new file mode 100644 index 0000000..1f77957 --- /dev/null +++ b/src/bnhtrade.gui/FormConsole.Designer.cs @@ -0,0 +1,72 @@ +namespace bnhtrade.gui +{ + partial class FormConsole + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + button1 = new Button(); + txtConsole = new TextBox(); + SuspendLayout(); + // + // button1 + // + button1.Location = new Point(610, 389); + button1.Name = "button1"; + button1.Size = new Size(152, 49); + button1.TabIndex = 2; + button1.Text = "Close"; + button1.UseVisualStyleBackColor = true; + button1.Click += button1_Click; + // + // txtConsole + // + txtConsole.Location = new Point(53, 41); + txtConsole.Multiline = true; + txtConsole.Name = "txtConsole"; + txtConsole.Size = new Size(709, 337); + txtConsole.TabIndex = 3; + // + // FormConsole + // + AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 450); + Controls.Add(txtConsole); + Controls.Add(button1); + Name = "FormConsole"; + Text = "Form1"; + Load += FormConsole_Load; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private Button button1; + private TextBox txtConsole; + } +} \ No newline at end of file diff --git a/src/bnhtrade.gui/FormConsole.cs b/src/bnhtrade.gui/FormConsole.cs new file mode 100644 index 0000000..a5314c4 --- /dev/null +++ b/src/bnhtrade.gui/FormConsole.cs @@ -0,0 +1,44 @@ +using ConsoleRedirection; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace bnhtrade.gui +{ + public partial class FormConsole : Form + { + // That's our custom TextWriter class + TextWriter _writer = null; + + public FormConsole() + { + InitializeComponent(); + } + + private void FormConsole_Load(object sender, EventArgs e) + { + // Instantiate the writer + _writer = new TextBoxStreamWriter(txtConsole); + // Redirect the out Console stream + Console.SetOut(_writer); + } + + // This is called when the "Say Hello" button is clicked + private void txtSayHello_Click(object sender, EventArgs e) + { + // Writing to the Console now causes the text to be displayed in the text box. + Console.WriteLine("Hello world"); + } + + private void button1_Click(object sender, EventArgs e) + { + this.Close(); + } + } +} diff --git a/src/bnhtrade.gui/FormConsole.resx b/src/bnhtrade.gui/FormConsole.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/src/bnhtrade.gui/FormConsole.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/bnhtrade.gui/Home.Designer.cs b/src/bnhtrade.gui/Home.Designer.cs index ed278d1..43c956d 100644 --- a/src/bnhtrade.gui/Home.Designer.cs +++ b/src/bnhtrade.gui/Home.Designer.cs @@ -48,11 +48,14 @@ dateTimeOrderSearch = new DateTimePicker(); label1 = new Label(); textboxOrderSearch = new TextBox(); + tabAccounts = new TabPage(); + btnExchangeRate = new Button(); tabControl1.SuspendLayout(); Receiving.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)dataGridView1).BeginInit(); ((System.ComponentModel.ISupportInitialize)bsReceivingLines).BeginInit(); ((System.ComponentModel.ISupportInitialize)purchaseLineStatusBindingSource).BeginInit(); + tabAccounts.SuspendLayout(); SuspendLayout(); // // tabControl1 @@ -61,19 +64,22 @@ tabControl1.Controls.Add(tabPage1); tabControl1.Controls.Add(tabPage2); tabControl1.Controls.Add(Receiving); - tabControl1.Location = new Point(12, 12); + tabControl1.Controls.Add(tabAccounts); + tabControl1.Location = new Point(14, 16); + tabControl1.Margin = new Padding(3, 4, 3, 4); tabControl1.Name = "tabControl1"; tabControl1.SelectedIndex = 0; - tabControl1.Size = new Size(1022, 533); + tabControl1.Size = new Size(1168, 711); tabControl1.TabIndex = 0; tabControl1.SelectedIndexChanged += tabControl1_SelectedIndexChanged; // // tabPage1 // - tabPage1.Location = new Point(4, 24); + tabPage1.Location = new Point(4, 29); + tabPage1.Margin = new Padding(3, 4, 3, 4); tabPage1.Name = "tabPage1"; - tabPage1.Padding = new Padding(3); - tabPage1.Size = new Size(1014, 505); + tabPage1.Padding = new Padding(3, 4, 3, 4); + tabPage1.Size = new Size(1160, 678); tabPage1.TabIndex = 0; tabPage1.Text = "Home"; tabPage1.UseVisualStyleBackColor = true; @@ -81,10 +87,11 @@ // tabPage2 // tabPage2.AccessibleName = ""; - tabPage2.Location = new Point(4, 24); + tabPage2.Location = new Point(4, 29); + tabPage2.Margin = new Padding(3, 4, 3, 4); tabPage2.Name = "tabPage2"; - tabPage2.Padding = new Padding(3); - tabPage2.Size = new Size(1014, 505); + tabPage2.Padding = new Padding(3, 4, 3, 4); + tabPage2.Size = new Size(1160, 678); tabPage2.TabIndex = 1; tabPage2.Text = "FBA Shipments"; tabPage2.UseVisualStyleBackColor = true; @@ -98,10 +105,11 @@ Receiving.Controls.Add(dateTimeOrderSearch); Receiving.Controls.Add(label1); Receiving.Controls.Add(textboxOrderSearch); - Receiving.Location = new Point(4, 24); + Receiving.Location = new Point(4, 29); + Receiving.Margin = new Padding(3, 4, 3, 4); Receiving.Name = "Receiving"; - Receiving.Padding = new Padding(3); - Receiving.Size = new Size(1014, 505); + Receiving.Padding = new Padding(3, 4, 3, 4); + Receiving.Size = new Size(1160, 678); Receiving.TabIndex = 2; Receiving.Text = "Receiving"; Receiving.UseVisualStyleBackColor = true; @@ -111,10 +119,10 @@ // labelDataGridCount.Anchor = AnchorStyles.Right; labelDataGridCount.ImageAlign = ContentAlignment.MiddleRight; - labelDataGridCount.Location = new Point(857, 70); + labelDataGridCount.Location = new Point(979, 93); labelDataGridCount.Name = "labelDataGridCount"; labelDataGridCount.RightToLeft = RightToLeft.Yes; - labelDataGridCount.Size = new Size(129, 21); + labelDataGridCount.Size = new Size(147, 28); labelDataGridCount.TabIndex = 6; labelDataGridCount.Text = "labelListCount"; labelDataGridCount.TextAlign = ContentAlignment.MiddleLeft; @@ -126,11 +134,13 @@ dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; dataGridView1.Columns.AddRange(new DataGridViewColumn[] { purchaseNumberDataGridViewTextBoxColumn, purchaseDateDataGridViewTextBoxColumn, itemDescriptionDataGridViewTextBoxColumn, purchaseLineIdDataGridViewTextBoxColumn, lineStatusDataGridViewTextBoxColumn, purchaseIdDataGridViewTextBoxColumn }); dataGridView1.DataSource = bsReceivingLines; - dataGridView1.Location = new Point(31, 94); + dataGridView1.Location = new Point(35, 125); + dataGridView1.Margin = new Padding(3, 4, 3, 4); dataGridView1.MultiSelect = false; dataGridView1.Name = "dataGridView1"; + dataGridView1.RowHeadersWidth = 51; dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dataGridView1.Size = new Size(955, 396); + dataGridView1.Size = new Size(1091, 528); dataGridView1.TabIndex = 5; dataGridView1.DoubleClick += dataGridView1_DoubleClick; // @@ -138,18 +148,23 @@ // purchaseNumberDataGridViewTextBoxColumn.DataPropertyName = "PurchaseNumber"; purchaseNumberDataGridViewTextBoxColumn.HeaderText = "PurchaseNumber"; + purchaseNumberDataGridViewTextBoxColumn.MinimumWidth = 6; purchaseNumberDataGridViewTextBoxColumn.Name = "purchaseNumberDataGridViewTextBoxColumn"; + purchaseNumberDataGridViewTextBoxColumn.Width = 125; // // purchaseDateDataGridViewTextBoxColumn // purchaseDateDataGridViewTextBoxColumn.DataPropertyName = "PurchaseDate"; purchaseDateDataGridViewTextBoxColumn.HeaderText = "PurchaseDate"; + purchaseDateDataGridViewTextBoxColumn.MinimumWidth = 6; purchaseDateDataGridViewTextBoxColumn.Name = "purchaseDateDataGridViewTextBoxColumn"; + purchaseDateDataGridViewTextBoxColumn.Width = 125; // // itemDescriptionDataGridViewTextBoxColumn // itemDescriptionDataGridViewTextBoxColumn.DataPropertyName = "ItemDescription"; itemDescriptionDataGridViewTextBoxColumn.HeaderText = "ItemDescription"; + itemDescriptionDataGridViewTextBoxColumn.MinimumWidth = 6; itemDescriptionDataGridViewTextBoxColumn.Name = "itemDescriptionDataGridViewTextBoxColumn"; itemDescriptionDataGridViewTextBoxColumn.Width = 500; // @@ -157,19 +172,25 @@ // purchaseLineIdDataGridViewTextBoxColumn.DataPropertyName = "PurchaseLineId"; purchaseLineIdDataGridViewTextBoxColumn.HeaderText = "PurchaseLineId"; + purchaseLineIdDataGridViewTextBoxColumn.MinimumWidth = 6; purchaseLineIdDataGridViewTextBoxColumn.Name = "purchaseLineIdDataGridViewTextBoxColumn"; + purchaseLineIdDataGridViewTextBoxColumn.Width = 125; // // lineStatusDataGridViewTextBoxColumn // lineStatusDataGridViewTextBoxColumn.DataPropertyName = "LineStatus"; lineStatusDataGridViewTextBoxColumn.HeaderText = "LineStatus"; + lineStatusDataGridViewTextBoxColumn.MinimumWidth = 6; lineStatusDataGridViewTextBoxColumn.Name = "lineStatusDataGridViewTextBoxColumn"; + lineStatusDataGridViewTextBoxColumn.Width = 125; // // purchaseIdDataGridViewTextBoxColumn // purchaseIdDataGridViewTextBoxColumn.DataPropertyName = "PurchaseId"; purchaseIdDataGridViewTextBoxColumn.HeaderText = "PurchaseId"; + purchaseIdDataGridViewTextBoxColumn.MinimumWidth = 6; purchaseIdDataGridViewTextBoxColumn.Name = "purchaseIdDataGridViewTextBoxColumn"; + purchaseIdDataGridViewTextBoxColumn.Width = 125; // // bsReceivingLines // @@ -177,9 +198,10 @@ // // buttonSearch // - buttonSearch.Location = new Point(865, 37); + buttonSearch.Location = new Point(989, 49); + buttonSearch.Margin = new Padding(3, 4, 3, 4); buttonSearch.Name = "buttonSearch"; - buttonSearch.Size = new Size(109, 25); + buttonSearch.Size = new Size(125, 33); buttonSearch.TabIndex = 4; buttonSearch.Text = "Search"; buttonSearch.UseVisualStyleBackColor = true; @@ -190,9 +212,10 @@ comboBox1.DataSource = purchaseLineStatusBindingSource; comboBox1.DisplayMember = "PurchaseLineStatusName"; comboBox1.FormattingEnabled = true; - comboBox1.Location = new Point(195, 39); + comboBox1.Location = new Point(223, 52); + comboBox1.Margin = new Padding(3, 4, 3, 4); comboBox1.Name = "comboBox1"; - comboBox1.Size = new Size(189, 23); + comboBox1.Size = new Size(215, 28); comboBox1.TabIndex = 3; comboBox1.ValueMember = "PurchaseLineStatusId"; comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged; @@ -204,35 +227,59 @@ // // dateTimeOrderSearch // - dateTimeOrderSearch.Location = new Point(31, 39); + dateTimeOrderSearch.Location = new Point(35, 52); + dateTimeOrderSearch.Margin = new Padding(3, 4, 3, 4); dateTimeOrderSearch.Name = "dateTimeOrderSearch"; - dateTimeOrderSearch.Size = new Size(131, 23); + dateTimeOrderSearch.Size = new Size(149, 27); dateTimeOrderSearch.TabIndex = 2; dateTimeOrderSearch.ValueChanged += dateTimeOrderSearch_ValueChanged; // // label1 // label1.AutoSize = true; - label1.Location = new Point(31, 21); + label1.Location = new Point(35, 28); label1.Name = "label1"; - label1.Size = new Size(75, 15); + label1.Size = new Size(95, 20); label1.TabIndex = 1; label1.Text = "Order Search"; // // textboxOrderSearch // - textboxOrderSearch.Location = new Point(417, 39); + textboxOrderSearch.Location = new Point(477, 52); + textboxOrderSearch.Margin = new Padding(3, 4, 3, 4); textboxOrderSearch.Name = "textboxOrderSearch"; - textboxOrderSearch.Size = new Size(415, 23); + textboxOrderSearch.Size = new Size(474, 27); textboxOrderSearch.TabIndex = 0; textboxOrderSearch.KeyPress += textboxOrderSearch_KeyPress; // + // tabAccounts + // + tabAccounts.Controls.Add(btnExchangeRate); + tabAccounts.Location = new Point(4, 29); + tabAccounts.Name = "tabAccounts"; + tabAccounts.Padding = new Padding(3); + tabAccounts.Size = new Size(1160, 678); + tabAccounts.TabIndex = 3; + tabAccounts.Text = "Accounts"; + tabAccounts.UseVisualStyleBackColor = true; + // + // btnExchangeRate + // + btnExchangeRate.Location = new Point(48, 50); + btnExchangeRate.Name = "btnExchangeRate"; + btnExchangeRate.Size = new Size(237, 50); + btnExchangeRate.TabIndex = 0; + btnExchangeRate.Text = "Update exchange rates"; + btnExchangeRate.UseVisualStyleBackColor = true; + btnExchangeRate.Click += btnExchangeRate_Click; + // // Home // - AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1046, 557); + ClientSize = new Size(1195, 743); Controls.Add(tabControl1); + Margin = new Padding(3, 4, 3, 4); Name = "Home"; Text = "Form1"; Load += Form1_Load; @@ -242,6 +289,7 @@ ((System.ComponentModel.ISupportInitialize)dataGridView1).EndInit(); ((System.ComponentModel.ISupportInitialize)bsReceivingLines).EndInit(); ((System.ComponentModel.ISupportInitialize)purchaseLineStatusBindingSource).EndInit(); + tabAccounts.ResumeLayout(false); ResumeLayout(false); } @@ -266,5 +314,7 @@ private DataGridViewTextBoxColumn lineStatusDataGridViewTextBoxColumn; private DataGridViewTextBoxColumn purchaseIdDataGridViewTextBoxColumn; private Label labelDataGridCount; + private TabPage tabAccounts; + private Button btnExchangeRate; } } diff --git a/src/bnhtrade.gui/Home.cs b/src/bnhtrade.gui/Home.cs index 39117f8..b4ce227 100644 --- a/src/bnhtrade.gui/Home.cs +++ b/src/bnhtrade.gui/Home.cs @@ -110,5 +110,12 @@ namespace bnhtrade.gui var form = new PurchaseInvoice(purchaseInvoice); form.Show(); } + + private void btnExchangeRate_Click(object sender, EventArgs e) + { + var myForm = new FormConsole(); + myForm.Show(); + new bnhtrade.Core.Logic.Account.Currency().UpdateHmrcExchageRates(); + } } } diff --git a/src/bnhtrade.gui/Home.resx b/src/bnhtrade.gui/Home.resx index 70d97fa..a298a7f 100644 --- a/src/bnhtrade.gui/Home.resx +++ b/src/bnhtrade.gui/Home.resx @@ -1,7 +1,7 @@