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.
This commit is contained in:
Bobbie Hodgetts
2025-06-09 20:56:26 +01:00
committed by GitHub
parent 8e7cd00b74
commit ea0a52b2a0
25 changed files with 1095 additions and 179 deletions

View File

@@ -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

View File

@@ -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)
/// <summary>
/// Returns excahnge rate, in decimal format, for a given currency and datetime
/// </summary>
/// <param name="currencyCode">currency code</param>
/// <param name="date">dat and time</param>
/// <returns></returns>
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<Model.Account.CurrencyExchangeRate> ReadExchangeRate(List<Model.Account.CurrencyCode> currencyCodeList = null, DateTime date = default(DateTime))
{
throw new NotImplementedException("Complete, but untested");
var returnList = new List<Model.Account.CurrencyExchangeRate>();
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<string> stringList = new List<string>();
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<Model.Account.CurrencyExchangeRate> ReadExchangeRateLatest(List<Model.Account.CurrencyCode> currencyCodeList = null)
{
var returnList = new List<Model.Account.CurrencyExchangeRate>();
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<string>();
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();

View File

@@ -8,14 +8,22 @@ namespace bnhtrade.Core.Data.Database
{
public static class Constants
{
/// <summary>
/// Gets the date bnhtrade started trading, UK time (datetime kind unspecified).
/// </summary>
/// <returns>The UK date and time the business started (datetime kind unspecified)</returns>
public static DateTime GetBusinessStartUk()
{
return new Logic.Utilities.DateTime().ConvertUtcToUk(GetBusinessStartUtc());
}
/// <summary>
/// Gets the date bnhtrade started trading.
/// Gets the date bnhtrade started trading, as UTC time
/// </summary>
/// <returns>Date and time</returns>
/// <returns>The UTC date and time the business started (datetime kind UTC)</returns>
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);
}

View File

@@ -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])); }

View File

@@ -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<string, object>();
}
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)
{

View File

@@ -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.");
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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() { }
/// <summary>
/// Outputs a unique list from an input list
/// </summary>
/// <param name="inputList"></param>
/// <param name="includeWhiteSpace"></param>
/// <returns>Unique list</returns>
public List<string> UniqueList(List<string> inputList, bool removeNullorWhitespace = true)
{
List<string> outputList = new List<string>();
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<string> UniqueList(List<Enum> inputList, bool removeNullorWhitespace = true)
{
List<string> stringList = new List<string>();
foreach (Enum input in inputList)
{
stringList.Add(input.ToString());
}
return UniqueList(stringList, removeNullorWhitespace);
}
}
}

View File

@@ -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(); }

View File

@@ -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
}
}

View File

@@ -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; }
/// <summary>
/// Checks whether a given datetime falls within the the exchange rate period
/// </summary>
/// <param name="dateTimeToCheck">The date and time to check</param>
/// <returns>True or false</returns>
public bool DateTimeWithinPeriodCheck(DateTime dateTimeToCheck)
{
if (dateTimeToCheck >= DateTimeStartUtc && dateTimeToCheck < DateTimeEndUtc)
{
return true;
}
else
{
return false;
}
}
}
}

View File

@@ -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";
}
}

View File

@@ -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()

View File

@@ -36,6 +36,7 @@
<PackageReference Include="CSharpAmazonSpAPI" Version="1.7.17" />
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
<PackageReference Include="RestSharp" Version="112.1.0" />
<PackageReference Include="RestSharp.Serializers.NewtonsoftJson" Version="112.1.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.9.0" />