From cb54dc364cdf1fdda222dcc0677a5f5927c79a02 Mon Sep 17 00:00:00 2001 From: Bobbie Hodgetts Date: Mon, 9 Jun 2025 21:00:18 +0100 Subject: [PATCH] Pulled changes on master into branch (#28) * 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 | 311 +++++++++++------- src/bnhtrade.Core/Data/Database/Constants.cs | 14 +- .../Database/Import/AmazonSettlementInsert.cs | 10 +- .../Data/Database/SqlWhereBuilder.cs | 15 +- src/bnhtrade.Core/Logic/Account/Currency.cs | 189 ++++++++++- 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 + .../Model/Account/CurrencyCode.cs | 191 +++++++++++ .../Model/Account/CurrencyExchangeRate.cs | 71 ++++ src/bnhtrade.Core/Model/Account/Invoice.cs | 2 +- .../Model/Credentials/bnhtradeDB.cs | 2 +- .../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 | 29 ++ .../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 ++ 32 files changed, 1236 insertions(+), 232 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..f2ed460 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,209 @@ 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 +242,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/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/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/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/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/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 e438418..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"); @@ -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 @@