mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-03-19 06:27:15 +00:00
SP-API stock reconciliation
Amazon had depreciated a number of reports that were used for stock reconciliation. Application now uses the new fba ledger report to reconcile. It is currently untested, as this requires data from Amazon. Methods that require testing will return a 'NotImplementedException'. Also, removed the depreciated ILMerge and replaced with ILRepack. Plus much more tidying up, and improvements.
This commit is contained in:
@@ -10,13 +10,11 @@ namespace bnhtrade.Core.Logic.Export
|
||||
{
|
||||
public class AmazonSettlement
|
||||
{
|
||||
private string sqlConnectionString;
|
||||
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
|
||||
private List<string> lineItemCodeList = new List<string>();
|
||||
|
||||
public AmazonSettlement(string sqlConnectionString)
|
||||
public AmazonSettlement()
|
||||
{
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
}
|
||||
|
||||
public void ToInvoice()
|
||||
@@ -292,7 +290,7 @@ namespace bnhtrade.Core.Logic.Export
|
||||
{
|
||||
try
|
||||
{
|
||||
var saveInv = new Logic.Export.SalesInvoice(sqlConnectionString);
|
||||
var saveInv = new Logic.Export.SalesInvoice();
|
||||
// add temp invoice numbers
|
||||
saveInv.AddTempInvoiceNumber(invoiceList, true);
|
||||
|
||||
|
||||
@@ -8,12 +8,10 @@ namespace bnhtrade.Core.Logic.Export
|
||||
{
|
||||
public class SalesInvoice
|
||||
{
|
||||
private string sqlConnectionString;
|
||||
private Logic.Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
public SalesInvoice(string sqlConnectionString)
|
||||
public SalesInvoice()
|
||||
{
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
}
|
||||
|
||||
public string GetNextTempInvoiceNumber()
|
||||
|
||||
56
src/bnhtrade.Core/Logic/Import/Amazon.cs
Normal file
56
src/bnhtrade.Core/Logic/Import/Amazon.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class Amazon
|
||||
{
|
||||
Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
public void SyncAllWithDatabase()
|
||||
{
|
||||
bool fbaInventoryLedgerDetail = false;
|
||||
bool fbaReimbursement = false;
|
||||
bool settlement = false;
|
||||
bool fbaInventory = false;
|
||||
bool fbaRemovalOrder = false;
|
||||
bool fbaSaleShipment = false;
|
||||
bool fbaCustomerReturn = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fbaInventoryLedgerDetail == false) { fbaInventoryLedgerDetail = true; new Logic.Import.AmazonFbaInventoryLedgerDetail().SyncDatabaseWithAmazon(); }
|
||||
if (fbaReimbursement == false) { fbaReimbursement = true; new Logic.Import.AmazonFbaReimbursement().SyncDatabaseWithAmazon(); }
|
||||
if (settlement == false) { settlement = true; new Logic.Import.AmazonSettlement().SyncDatabase(); }
|
||||
if (fbaInventory == false) { fbaInventory = true; new Logic.Import.AmazonFbaInventory().SyncDatabaseWithAmazon(); }
|
||||
if (fbaRemovalOrder == false) { fbaRemovalOrder = true; new Logic.Import.AmazonFbaRemovalOrder().SyncDatabaseWithAmazon(); }
|
||||
if (fbaSaleShipment == false) { fbaSaleShipment = true; new Logic.Import.AmazonFbaSaleShipment().SyncDatabaseWithAmazon(); }
|
||||
if (fbaCustomerReturn == false) { fbaCustomerReturn = true; new Logic.Import.AmazonFbaCustomerReturn().SyncDatabaseWithAmazon(); }
|
||||
|
||||
break;
|
||||
|
||||
// depreciated reports
|
||||
if (false)
|
||||
{
|
||||
new Logic.Import.AmazonFbaInventoryAdjustment().SyncDatabaseWithAmazon();
|
||||
new Logic.Import.AmazonFbaInventoryAge().SyncDatabaseWithAmazon();
|
||||
new Logic.Import.AmazonFbaInventoryReceipt().SyncDatabaseWithAmazon();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.LogError(
|
||||
"Exception caught during database sync with Amazon (reports), see for further details",
|
||||
ex.ToString()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,15 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaCustomerReturn
|
||||
{
|
||||
private Log.LogEvent log = new Log.LogEvent();
|
||||
private string reportName = "GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA";
|
||||
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
/*
|
||||
@@ -16,23 +20,32 @@ namespace bnhtrade.Core.Logic.Import
|
||||
* To disambiguate duplicate row, I will use combination of date, orderid, fnsku, quantity, LPN#, disposition, and reason.
|
||||
*/
|
||||
|
||||
// get most recent record from db
|
||||
log.LogInformation("Starting Amazon report '" + reportName + "' sync with database.");
|
||||
|
||||
// get the last report check from log
|
||||
var dateLog = new Data.Database.Log.DateTimeLog();
|
||||
var utcStartDate = dateLog.GetDateTimeUtc(reportName);
|
||||
var utcEndDate = DateTime.UtcNow;
|
||||
|
||||
var db = new Data.Database.Import.AmazonFbaCustomerReturn();
|
||||
var startDate = db.ReadRecentDate().AddDays(-14);
|
||||
|
||||
var getFile = new Data.Amazon.Report.FbaCustomerReturn();
|
||||
getFile.GetReport(startDate, DateTime.UtcNow);
|
||||
getFile.GetReport(utcStartDate.AddDays(-14), utcEndDate);
|
||||
|
||||
if (!getFile.ReportFilePathIsSet)
|
||||
if (!getFile.IsSetReportFilePath)
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
|
||||
2
|
||||
log.LogError(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
db.UpdateByFlatFile(getFile.ReportFilePath);
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
db.UpdateByFlatFile(getFile.ReportFilePath);
|
||||
dateLog.SetDateTimeUtc(reportName, utcEndDate);
|
||||
scope.Complete();
|
||||
}
|
||||
log.LogInformation("Amazon report '" + reportName + "' sync with database comlpete.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,27 @@ namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaInventory
|
||||
{
|
||||
Logic.Log.LogEvent log = new Log.LogEvent();
|
||||
string reportName = "GET_FBA_MYI_ALL_INVENTORY_DATA";
|
||||
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
log.LogInformation("Starting Amazon report '" + reportName + "' sync with database.");
|
||||
|
||||
var getFile = new Data.Amazon.Report.FbaInventory();
|
||||
getFile.GetReport();
|
||||
|
||||
if (!getFile.ReportFilePathIsSet)
|
||||
if (!getFile.IsSetReportFilePath)
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
|
||||
2
|
||||
log.LogWarning(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
new Data.Database.Import.AmazonFbaInventoryData().InsertByFlatFile(getFile.ReportFilePath);
|
||||
log.LogInformation("Amazon report '" + reportName + "' sync with database comlpete.");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,12 @@ namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaInventoryAdjustment
|
||||
{
|
||||
private Logic.Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
|
||||
|
||||
// get most recent record from db
|
||||
var db = new Data.Database.Import.AmazonFbaInventoryAdjustment();
|
||||
var startDate = db.ReadRecentDate().AddDays(-3);
|
||||
@@ -17,11 +21,10 @@ namespace bnhtrade.Core.Logic.Import
|
||||
var getFile = new Data.Amazon.Report.FbaInventoryAdustment();
|
||||
getFile.GetReport(startDate, DateTime.UtcNow);
|
||||
|
||||
if (!getFile.ReportFilePathIsSet)
|
||||
if (!getFile.IsSetReportFilePath)
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
|
||||
2
|
||||
log.LogWarning(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,19 @@ namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaInventoryAge
|
||||
{
|
||||
private Logic.Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
|
||||
|
||||
var getFile = new Data.Amazon.Report.FbaInventoryAge();
|
||||
getFile.GetReport();
|
||||
|
||||
if (!getFile.ReportFilePathIsSet)
|
||||
if (!getFile.IsSetReportFilePath)
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
|
||||
2
|
||||
log.LogWarning(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
using Amazon.SQS.Model;
|
||||
using Amazon.Util.Internal.PlatformServices;
|
||||
using bnhtrade.Core.Data.Database.Log;
|
||||
using FikaAmazonAPI.ConstructFeed.Messages;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaInventoryLedgerDetail : Validate.Validate
|
||||
{
|
||||
Log.LogEvent log = new Log.LogEvent();
|
||||
private string reportName = "GET_LEDGER_DETAIL_VIEW_DATA";
|
||||
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
log.LogInformation("Starting Amazon report '" + reportName + "' sync with database.");
|
||||
var db = new Data.Database.Import.AmazonFbaInventoryLedgerDetail();
|
||||
|
||||
// get the last report check from log
|
||||
var dateLog = new Data.Database.Log.DateTimeLog();
|
||||
var utcStartDate = dateLog.GetDateTimeUtc(reportName);
|
||||
var utcEndDate = DateTime.UtcNow;
|
||||
|
||||
// get data from amazon starting at the recent date, to now...
|
||||
var amazon = new Data.Amazon.Report.FbaInventoryLedgerDetailed();
|
||||
amazon.GetReport(utcStartDate.AddDays(-7), utcEndDate);
|
||||
if (amazon.ReportDoneNoData)
|
||||
{
|
||||
log.LogInformation(reportName + " sync complete, amazon returned no data");
|
||||
return;
|
||||
}
|
||||
else if (amazon.IsSetResultList == false)
|
||||
{
|
||||
string errorMessage = reportName + " did not return done. Unhandled error";
|
||||
log.LogError(errorMessage);
|
||||
throw new Exception(errorMessage);
|
||||
}
|
||||
var listAmazon = amazon.ResultList;
|
||||
|
||||
// validate amazons result
|
||||
foreach (var item in listAmazon)
|
||||
{
|
||||
if (!IsValid(item))
|
||||
{
|
||||
throw new Exception(ValidationResultListToString());
|
||||
}
|
||||
}
|
||||
log.LogInformation(listAmazon.Count + " records sucsefully downloaded from Amazon and validated");
|
||||
|
||||
// reverse the list to oldest first, the records will then be in datetime order in the db
|
||||
listAmazon.Reverse();
|
||||
|
||||
using (TransactionScope scope = new TransactionScope())
|
||||
{
|
||||
// read recent data from db
|
||||
log.LogInformation("Comparing against database and commiting new records.");
|
||||
var listDb = db.Read(utcStartDate.AddDays(-10)).Values.ToList();
|
||||
|
||||
// remove line from amazon data that already exist in the db.
|
||||
int removed = 0;
|
||||
for (var i = 0; i < listAmazon.Count; i++)
|
||||
{
|
||||
for (var j = 0; j < listDb.Count; j++)
|
||||
{
|
||||
// compare objects
|
||||
var a = JsonConvert.SerializeObject(listAmazon[i]);
|
||||
var b = JsonConvert.SerializeObject(listDb[j]);
|
||||
|
||||
if (a == b)
|
||||
{
|
||||
removed++;
|
||||
listAmazon.RemoveAt(i);
|
||||
listDb.RemoveAt(j);
|
||||
i--;
|
||||
j--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write any remaining data to db
|
||||
var dbResult = db.Insert(listAmazon);
|
||||
// set date in log
|
||||
dateLog.SetDateTimeUtc(reportName, utcEndDate);
|
||||
scope.Complete();
|
||||
log.LogInformation(String.Format(reportName + " sync operation complete. {0} records already existed in database, {1} new records committed.", removed, listAmazon.Count));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,12 @@ namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaInventoryReceipt
|
||||
{
|
||||
private Logic.Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
|
||||
|
||||
// get most recent record from db
|
||||
var db = new Data.Database.Import.AmazonFbaInventoryReceipt();
|
||||
var startDate = db.ReadRecentDate().AddSeconds(1);
|
||||
@@ -17,11 +21,10 @@ namespace bnhtrade.Core.Logic.Import
|
||||
var getReport = new Data.Amazon.Report.FbaInventoryReceipt();
|
||||
getReport.GetReport(startDate, DateTime.UtcNow);
|
||||
|
||||
if (!getReport.ReportFilePathIsSet)
|
||||
if (!getReport.IsSetReportFilePath)
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
|
||||
2
|
||||
log.LogWarning(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,30 +3,45 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaReimbursement
|
||||
{
|
||||
Log.LogEvent log = new Log.LogEvent();
|
||||
private string reportName = "GET_FBA_REIMBURSEMENTS_DATA";
|
||||
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
// get most recent record from db
|
||||
var db = new Data.Database.Import.AmazonFbaReimbursement();
|
||||
var startDate = db.ReadRecentDate().AddDays(-3);
|
||||
log.LogInformation("Starting Amazon report '" + reportName + "' sync with database.");
|
||||
|
||||
var getFile = new Data.Amazon.Report.FbaReimbursement();
|
||||
getFile.GetReport(startDate, DateTime.UtcNow);
|
||||
// get the last report check date from log
|
||||
var dateLog = new Data.Database.Log.DateTimeLog();
|
||||
var utcStartDate = dateLog.GetDateTimeUtc(reportName);
|
||||
var utcEndDate = DateTime.UtcNow;
|
||||
|
||||
if (!getFile.ReportFilePathIsSet)
|
||||
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
|
||||
2
|
||||
);
|
||||
return;
|
||||
}
|
||||
var db = new Data.Database.Import.AmazonFbaReimbursement();
|
||||
|
||||
db.InsertByFlatFile(getFile.ReportFilePath);
|
||||
var getFile = new Data.Amazon.Report.FbaReimbursement();
|
||||
getFile.GetReport(utcStartDate.AddDays(-3), utcEndDate);
|
||||
|
||||
if (!getFile.IsSetReportFilePath)
|
||||
{
|
||||
log.LogError(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
db.InsertByFlatFile(getFile.ReportFilePath);
|
||||
dateLog.SetDateTimeUtc(reportName, utcEndDate);
|
||||
scope.Complete();
|
||||
log.LogInformation("Amazon report '" + reportName + "' sync with database comlpete.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,15 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaRemovalOrder
|
||||
{
|
||||
Log.LogEvent log = new Log.LogEvent();
|
||||
private string reportName = "GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA";
|
||||
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
/*
|
||||
@@ -17,23 +21,33 @@ namespace bnhtrade.Core.Logic.Import
|
||||
* Overlap report by 3 days. To disambiguate duplicate shipment reports, use the ShipmentItemId (not the OrderId or the OrderItemId)
|
||||
*/
|
||||
|
||||
// get most recent record from db
|
||||
var db = new Data.Database.Import.AmazonFbaRemovalOrder();
|
||||
var startDate = db.ReadRecentDate().AddDays(-30);
|
||||
log.LogInformation("Starting Amazon report '" + reportName + "' sync with database.");
|
||||
|
||||
var getFile = new Data.Amazon.Report.FbaRemovalOrder();
|
||||
getFile.GetReport(startDate, DateTime.UtcNow);
|
||||
// get the last report check from log
|
||||
var dateLog = new Data.Database.Log.DateTimeLog();
|
||||
var utcStartDate = dateLog.GetDateTimeUtc(reportName);
|
||||
var utcEndDate = DateTime.UtcNow;
|
||||
|
||||
if (!getFile.ReportFilePathIsSet)
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
|
||||
2
|
||||
);
|
||||
return;
|
||||
}
|
||||
var db = new Data.Database.Import.AmazonFbaRemovalOrder();
|
||||
|
||||
db.InsertByFlatFile(getFile.ReportFilePath);
|
||||
var getFile = new Data.Amazon.Report.FbaRemovalOrder();
|
||||
getFile.GetReport(utcStartDate.AddDays(-30), utcEndDate);
|
||||
|
||||
if (!getFile.IsSetReportFilePath)
|
||||
{
|
||||
log.LogError(
|
||||
"Something went wrong retriving report from Amazon SP API. Operation cancelled."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
db.InsertByFlatFile(getFile.ReportFilePath);
|
||||
dateLog.SetDateTimeUtc(reportName, utcEndDate);
|
||||
scope.Complete();
|
||||
log.LogInformation("Amazon report '" + reportName + "' sync with database comlpete.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonFbaSaleShipment
|
||||
{
|
||||
Log.LogEvent log = new Log.LogEvent();
|
||||
private string reportName = "GET_AMAZON_FULFILLED_SHIPMENTS_DATA_GENERAL";
|
||||
private int maxTimePeriodDay = 30;
|
||||
public void SyncDatabaseWithAmazon()
|
||||
{
|
||||
@@ -18,10 +21,16 @@ namespace bnhtrade.Core.Logic.Import
|
||||
* Overlap report by 3 days. To disambiguate duplicate shipment reports, use the ShipmentItemId (not the OrderId or the OrderItemId)
|
||||
*/
|
||||
|
||||
// get most recent record from db
|
||||
log.LogInformation("Starting Amazon report '" + reportName + "' sync with database.");
|
||||
|
||||
// get the last report check from log
|
||||
var dateLog = new Data.Database.Log.DateTimeLog();
|
||||
var utcStartDate = dateLog.GetDateTimeUtc(reportName);
|
||||
var utcEndDate = DateTime.UtcNow;
|
||||
|
||||
var db = new Data.Database.Import.AmazonFbaSaleShipment();
|
||||
var dataSart = db.ReadRecentDate().AddDays(-3);
|
||||
var dataEnd = DateTime.UtcNow;
|
||||
var dataSart = utcStartDate.AddDays(-3);
|
||||
var dataEnd = utcEndDate;
|
||||
|
||||
// error check
|
||||
if (dataSart >= dataEnd)
|
||||
@@ -35,38 +44,45 @@ namespace bnhtrade.Core.Logic.Import
|
||||
|
||||
do
|
||||
{
|
||||
var getFile = new Data.Amazon.Report.FbaSaleShipment();
|
||||
getFile.GetReport(requestStart, requestEnd);
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
var getFile = new Data.Amazon.Report.FbaSaleShipment();
|
||||
getFile.GetReport(requestStart, requestEnd);
|
||||
|
||||
if (getFile.ReportDoneNoData)
|
||||
{
|
||||
// continue
|
||||
}
|
||||
else if (getFile.ReportFilePathIsSet)
|
||||
{
|
||||
db.InsertByFlatFile(getFile.ReportFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("no report returned");
|
||||
}
|
||||
if (getFile.ReportDoneNoData)
|
||||
{
|
||||
// continue
|
||||
}
|
||||
else if (getFile.IsSetReportFilePath)
|
||||
{
|
||||
db.InsertByFlatFile(getFile.ReportFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("no report returned");
|
||||
}
|
||||
|
||||
// increment requests times and test for end
|
||||
if (requestEnd == dataEnd)
|
||||
{
|
||||
doLoop = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
requestStart = requestEnd;
|
||||
requestEnd = requestStart.AddDays(maxTimePeriodDay);
|
||||
if (requestEnd > dataEnd)
|
||||
requestEnd = dataEnd;
|
||||
if (requestStart == requestEnd)
|
||||
// increment requests times and test for end
|
||||
if (requestEnd == dataEnd)
|
||||
{
|
||||
doLoop = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
requestStart = requestEnd;
|
||||
requestEnd = requestStart.AddDays(maxTimePeriodDay);
|
||||
if (requestEnd > dataEnd)
|
||||
requestEnd = dataEnd;
|
||||
if (requestStart == requestEnd)
|
||||
doLoop = false;
|
||||
}
|
||||
|
||||
dateLog.SetDateTimeUtc(reportName, requestEnd);
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
while (doLoop);
|
||||
log.LogInformation("Amazon report '" + reportName + "' sync with database comlpete.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,19 @@ namespace bnhtrade.Core.Logic.Import
|
||||
{
|
||||
public class AmazonSettlement
|
||||
{
|
||||
Data.Amazon.Report.SettlementReport amazonReport;
|
||||
private Data.Amazon.Report.SettlementReport amazonReport;
|
||||
private Logic.Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
public AmazonSettlement(Model.Credentials.AmazonSPAPI spapiCredentials)
|
||||
|
||||
public AmazonSettlement()
|
||||
{
|
||||
amazonReport = new Data.Amazon.Report.SettlementReport();
|
||||
}
|
||||
|
||||
public void SyncDatabase(string sqlConnectionString)
|
||||
public void SyncDatabase()
|
||||
{
|
||||
string operation = "Import Amazon Settlement Reports";
|
||||
|
||||
new Logic.Log.LogEvent().EventLogInsert("Started '" + operation + "' operation.");
|
||||
log.LogInformation("Started '" + operation + "' operation.");
|
||||
|
||||
// get avaiable reports from amazon api
|
||||
var spapiReportIdList = amazonReport.ListAvaliableReports();
|
||||
@@ -23,7 +24,7 @@ namespace bnhtrade.Core.Logic.Import
|
||||
|
||||
if (reportCount == 0)
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert("Exiting '" + operation + "' operation. No settlement reports availble on Amazon SP-API.");
|
||||
log.LogInformation("Exiting '" + operation + "' operation. No settlement reports availble on Amazon SP-API.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -47,7 +48,7 @@ namespace bnhtrade.Core.Logic.Import
|
||||
|
||||
if (!spapiReportIdList.Any())
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert("Exiting '" + operation + "' operation. No new reports to import (" + reportCount + " avaibale).");
|
||||
log.LogInformation("Exiting '" + operation + "' operation. No new reports to import (" + reportCount + " avaibale).");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,7 +59,7 @@ namespace bnhtrade.Core.Logic.Import
|
||||
UI.Console.WriteLine("Importing settlement report " + (i + 1) + " of " + spapiReportIdList.Count() + " (ReportID:" + spapiReportIdList[i] + ").");
|
||||
var filePath = amazonReport.GetFile(spapiReportIdList[i]);
|
||||
bool ack = dbImport.ByFlatFile(filePath, spapiReportIdList[i]);
|
||||
new Logic.Log.LogEvent().EventLogInsert("Settlment Report imported (ReportID:" + spapiReportIdList[i] + ").");
|
||||
log.LogInformation("Settlment Report imported (ReportID:" + spapiReportIdList[i] + ").");
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -74,22 +74,6 @@ namespace bnhtrade.Core.Logic.Log
|
||||
{ eventDateTimeUtc = null; }
|
||||
}
|
||||
|
||||
public void LogAuditFailure(string detailShort, string detailLong = null)
|
||||
{
|
||||
eventType = 5;
|
||||
DetailShort = detailShort;
|
||||
DetailLong = detailLong;
|
||||
Execute();
|
||||
}
|
||||
|
||||
public void LogAuditSuccess(string detailShort, string detailLong = null)
|
||||
{
|
||||
eventType = 4;
|
||||
DetailShort = detailShort;
|
||||
DetailLong = detailLong;
|
||||
Execute();
|
||||
}
|
||||
|
||||
public void LogError(string detailShort, string detailLong = null)
|
||||
{
|
||||
eventType = 1;
|
||||
@@ -114,22 +98,6 @@ namespace bnhtrade.Core.Logic.Log
|
||||
Execute();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Depreciated, do not use!
|
||||
/// </summary>
|
||||
public void EventLogInsert(string detailShort = "", int eventType = 3, string detailLong = "", DateTime eventDateTime = default(DateTime), bool consolePrint = true)
|
||||
{
|
||||
this.eventType = eventType;
|
||||
DetailShort = detailShort;
|
||||
if (!string.IsNullOrEmpty(detailLong))
|
||||
DetailLong = detailLong;
|
||||
if (!(eventDateTime == default(DateTime)))
|
||||
this.eventDateTimeUtc = eventDateTime;
|
||||
this.printToConsole = consolePrint;
|
||||
Execute();
|
||||
Initialise();
|
||||
}
|
||||
|
||||
public void Initialise()
|
||||
{
|
||||
eventDateTimeUtc = null;
|
||||
|
||||
36
src/bnhtrade.Core/Logic/Sku/GetSkuId.cs
Normal file
36
src/bnhtrade.Core/Logic/Sku/GetSkuId.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Sku
|
||||
{
|
||||
public class GetSkuId
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for retriving an SKU ID by parameters. If no match, can create a new SKU if required.
|
||||
/// </summary>
|
||||
/// <param name="productId">The product Id for the SKU</param>
|
||||
/// <param name="conditionId">The condition Id for the SKU</param>
|
||||
/// <param name="accountTaxCodeId">The tax code Id for the SKU</param>
|
||||
/// <param name="noMatchCreateNew">When set to true, if no match is made, function will create a new sku and return the id for that</param>
|
||||
/// <returns>Return the id for the new or existing sku or, dependant on set parameters, 0 if not found</returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public int Request(int productId, int conditionId, int accountTaxCodeId, bool noMatchCreateNew)
|
||||
{
|
||||
using (TransactionScope scope = new TransactionScope())
|
||||
{
|
||||
int? skuId = new Data.Database.Sku.GetSkuId().ByParameters(productId, conditionId, accountTaxCodeId);
|
||||
if (skuId != null)
|
||||
{
|
||||
return (int)skuId;
|
||||
}
|
||||
else if (noMatchCreateNew == false)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new Data.Database.Sku.InsertSku().InsertNew(productId, conditionId, accountTaxCodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Sku
|
||||
{
|
||||
class GetSkuIdByType
|
||||
{
|
||||
// used for retriving SKU that matched parameters, creates new if required, returns 0 if not found
|
||||
public static int Request(string sqlConnectionString, int productId, int conditionId, int accountTaxCodeId, bool noMatchInsertNew)
|
||||
{
|
||||
using (TransactionScope scope = new TransactionScope())
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
// look for existing entry
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
SELECT
|
||||
tblSku.skuSkuID
|
||||
FROM
|
||||
tblSku
|
||||
WHERE
|
||||
(((tblSku.skuProductID)=@productId) AND ((tblSku.skuSkuConditionID)=@conditionId) AND ((tblSku.AccountTaxCodeID)=@accountTaxCodeId));
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@productId", productId);
|
||||
cmd.Parameters.AddWithValue("@conditionId", conditionId);
|
||||
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
|
||||
|
||||
object obj = cmd.ExecuteScalar();
|
||||
if (obj != null)
|
||||
{
|
||||
return (int)obj;
|
||||
}
|
||||
}
|
||||
|
||||
// value check insert bool
|
||||
if (noMatchInsertNew == false)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get this far, check tax code id is a valid for SKU
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
SELECT tblAccountTaxCode.InvoiceSales
|
||||
FROM tblAccountTaxCode
|
||||
WHERE (((tblAccountTaxCode.AccountTaxCodeID)=@accountTaxCodeId));
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
|
||||
|
||||
object obj = cmd.ExecuteScalar();
|
||||
|
||||
if (obj == null)
|
||||
{
|
||||
throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " doesn't exist!");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool result = (bool)obj;
|
||||
if (result == false)
|
||||
{
|
||||
throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " is not a valid type for an SKU.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get info to create sku number
|
||||
int skuCount;
|
||||
int skuSuffix;
|
||||
using (SqlCommand cmd = new SqlCommand("SELECT NEXT VALUE FOR SkuCountSequence;", conn))
|
||||
{
|
||||
skuCount = (int)cmd.ExecuteScalar();
|
||||
}
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
SELECT tblSkuCondition.scnSkuNumberSuffix
|
||||
FROM tblSkuCondition
|
||||
WHERE (((tblSkuCondition.scnSkuConditionID)=@conditionId));
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@conditionId", conditionId);
|
||||
|
||||
try
|
||||
{
|
||||
skuSuffix = (int)cmd.ExecuteScalar();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Error retriving SKU number suffix for SkuConditionID=" + conditionId + "." +
|
||||
System.Environment.NewLine + "Error Message: " + ex.Message);
|
||||
}
|
||||
}
|
||||
string skuNumber = skuCount.ToString("D6") + "-" + skuSuffix.ToString("D2");
|
||||
|
||||
// insert new sku
|
||||
int skuId;
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
INSERT INTO tblSku
|
||||
(skuSkuNumber, skuProductID, skuSkuConditionID, AccountTaxCodeID)
|
||||
OUTPUT INSERTED.skuSkuID
|
||||
VALUES
|
||||
(@skuNumber, @productId, @conditionId, @accountTaxCodeId)
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@skuNumber", skuNumber);
|
||||
cmd.Parameters.AddWithValue("@productId", productId);
|
||||
cmd.Parameters.AddWithValue("@conditionId", conditionId);
|
||||
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
|
||||
|
||||
skuId = (int)cmd.ExecuteScalar();
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
return skuId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace bnhtrade.Core.Logic.Sku.Price
|
||||
private Logic.Account.TaxCalculation taxCalc;
|
||||
private decimal marginSchemeMargin;
|
||||
|
||||
public FbaPricing(string sqlConnectionString)
|
||||
public FbaPricing()
|
||||
{
|
||||
// was part of a fba repricing feature, that, for now, is being abandoned
|
||||
throw new NotImplementedException();
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
using System;
|
||||
using bnhtrade.Core.Data.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
public class SkuTransactionPersistance
|
||||
public class SkuTransactionCrud
|
||||
{
|
||||
private string err = "Sku Transaction Persistance Error; ";
|
||||
private string sqlConnectionString;
|
||||
private Data.Database.Stock.DeleteSkuTransaction dbSkuTransDelete;
|
||||
private Data.Database.Stock.CreateSkuTransaction dbSkuTransCreate;
|
||||
private Data.Database.Stock.InsertSkuTransaction dbSkuTransCreate;
|
||||
private Data.Database.Stock.ReadSkuTransaction dbSkuTransRead;
|
||||
private Data.Database.Stock.UpdateSkuTransaction dbSkuTransUpdate;
|
||||
private Logic.Validate.SkuTransaction validateSkuTrans;
|
||||
private Logic.Log.LogEvent log;
|
||||
private Logic.Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
public SkuTransactionPersistance(string sqlConnectionString)
|
||||
public SkuTransactionCrud()
|
||||
{
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
log = new Log.LogEvent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,11 +58,11 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
return dbSkuTransDelete;
|
||||
}
|
||||
|
||||
private Data.Database.Stock.CreateSkuTransaction DatabaseSkuTransInsert(bool forceNew = false)
|
||||
private Data.Database.Stock.InsertSkuTransaction DatabaseSkuTransInsert(bool forceNew = false)
|
||||
{
|
||||
if (dbSkuTransCreate == null || forceNew)
|
||||
{
|
||||
dbSkuTransCreate = new Data.Database.Stock.CreateSkuTransaction();
|
||||
dbSkuTransCreate = new Data.Database.Stock.InsertSkuTransaction();
|
||||
}
|
||||
return dbSkuTransCreate;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
int? journalId = DatabaseSkuTransRead().GetJournalId(skuTransactionId);
|
||||
if (journalId != null)
|
||||
{
|
||||
Core.Stock.StockJournal.StockJournalDelete(sqlConnectionString, (int)journalId);
|
||||
new Data.Database.Stock.JournalCrud().StockJournalDelete((int)journalId);
|
||||
}
|
||||
|
||||
DatabaseSkuTransDelete().ByTransactionId(skuTransactionId);
|
||||
@@ -118,25 +118,116 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Stock SKU Transaction. Implements validation check.
|
||||
/// </summary>
|
||||
/// <param name="skuTransaction">Input data/object</param>
|
||||
/// <returns>Stock SKU Transaction Id of new record</returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
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");
|
||||
}
|
||||
|
||||
Validate().Init();
|
||||
if (!Validate().DatabaseInsert(skuTransaction))
|
||||
{
|
||||
log.LogWarning(err + "Validation failed", Validate().ValidationResultListToString());
|
||||
throw new Exception(err + "Validation failed");
|
||||
}
|
||||
|
||||
// write to database
|
||||
return DatabaseSkuTransInsert().Insert(skuTransaction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an attached journal entry, if one is present.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="skuTransactionId">Stock SKU Transaction ID</param>
|
||||
public void DeleteJournalEntry(int skuTransactionId)
|
||||
/// <param name="retriveTransactionTypeInfo">Retrive and include transaction type model class</param>
|
||||
public List<Model.Stock.SkuTransaction> Read()
|
||||
{
|
||||
var dbRead = DatabaseSkuTransRead();
|
||||
dbRead.Init();
|
||||
dbRead.IsReconciled = IsReconciled;
|
||||
dbRead.StockTransactionTypeCode = StockTransactionTypeCode;
|
||||
dbRead.StockTransactionTypeName = StockTransactionTypeName;
|
||||
var resultList = dbRead.Read();
|
||||
dbRead.Init();
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a transaction quantity (must be less than) and creates a new transaction with the remaining quantity
|
||||
/// </summary>
|
||||
/// <param name="skuTransactionId">Stock SKU Transaction Id of the transaction to split</param>
|
||||
/// <param name="newQuantity">Required quantity of the existing transaction</param>
|
||||
/// <returns>Stock SKU Transaction Id of the newly created transaction</returns>
|
||||
/// <exception cref="ArgumentException">Incorrect parameters passed to function</exception>
|
||||
/// <exception cref="InvalidOperationException">transaction isProcessed error</exception>
|
||||
public int SplitTransaction(int skuTransactionId, int newQuantity)
|
||||
{
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
try
|
||||
{
|
||||
// comfirm there is a journal entry attached
|
||||
int? journalId = DatabaseSkuTransRead().GetJournalId(skuTransactionId);
|
||||
if (journalId != null)
|
||||
// get transaction
|
||||
var transList = DatabaseSkuTransRead().Read(new List<int> { skuTransactionId });
|
||||
if (!transList.Any())
|
||||
throw new ArgumentException("sku transaction id:" + skuTransactionId + "does appear to exist");
|
||||
|
||||
// Checks and new quanatity calculation
|
||||
int quantity2 = 0;
|
||||
var trans = transList[0];
|
||||
|
||||
if (trans.IsProcessed)
|
||||
throw new InvalidOperationException("Invalid operation: SKU Transaction is set to IsProcessed");
|
||||
|
||||
if (newQuantity == 0)
|
||||
throw new ArgumentException("Quantity parameter cannot be zero");
|
||||
|
||||
if (trans.Quantity == newQuantity)
|
||||
throw new ArgumentException("The new quanity is equal to the existing quantity");
|
||||
|
||||
if (trans.Quantity < 0 )
|
||||
{
|
||||
DatabaseSkuTransUpdate().Update(skuTransactionId, null);
|
||||
Core.Stock.StockJournal.StockJournalDelete(sqlConnectionString, (int)journalId);
|
||||
// -ve <------ no transaction is less than 0, negative number are converted to posistive before entry to the table
|
||||
throw new Exception("sku transaction quantity cannot be negative");
|
||||
|
||||
if (newQuantity > 0)
|
||||
throw new ArgumentException("Quantity parameter is +ve when it should be -ve");
|
||||
if (newQuantity < trans.Quantity)
|
||||
throw new ArgumentException("Quantity parameter is greater than transaction quantity");
|
||||
|
||||
quantity2 = trans.Quantity - newQuantity;
|
||||
}
|
||||
else if (trans.Quantity > 0)
|
||||
{
|
||||
// +ve
|
||||
if (newQuantity < 0)
|
||||
throw new ArgumentException("Quantity parameter is -ve when it should be +ve");
|
||||
if (newQuantity > trans.Quantity)
|
||||
throw new ArgumentException("Quantity parameter is greater than transaction quantity");
|
||||
|
||||
quantity2 = trans.Quantity - newQuantity;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("sku transaction quantity is zero");
|
||||
}
|
||||
|
||||
// clone transaction, add to database and update quantities
|
||||
var newTrans = trans.Clone();
|
||||
int NewTransId = DatabaseSkuTransInsert().Insert(newTrans);
|
||||
UpdateQuanitity(skuTransactionId, newQuantity);
|
||||
UpdateQuanitity(NewTransId, quantity2);
|
||||
|
||||
scope.Complete();
|
||||
return NewTransId;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -146,66 +237,18 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates and then creates a Stock SKU Tranaction
|
||||
/// </summary>
|
||||
/// <param name="skuTransaction">'Stock SKU Transaction' model</param>
|
||||
public void Create(Model.Stock.SkuTransaction skuTransaction)
|
||||
{
|
||||
if (skuTransaction == null)
|
||||
{
|
||||
throw new Exception(err + "Object was null");
|
||||
}
|
||||
|
||||
Validate().Innit();
|
||||
if (!Validate().DatabaseInsert(skuTransaction))
|
||||
{
|
||||
log.LogWarning(err + "Validation failed", Validate().ValidationResultListToString());
|
||||
throw new Exception(err + "Validation failed");
|
||||
}
|
||||
|
||||
// write to database
|
||||
DatabaseSkuTransInsert().Create(skuTransaction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="retriveTransactionTypeInfo">Retrive and include transaction type model class</param>
|
||||
public List<Model.Stock.SkuTransaction> Read(bool retriveTransactionTypeInfo = true)
|
||||
{
|
||||
var dbRead = new Data.Database.Stock.ReadSkuTransaction();
|
||||
dbRead.IsReconciled = IsReconciled;
|
||||
dbRead.StockTransactionTypeCode = StockTransactionTypeCode;
|
||||
dbRead.StockTransactionTypeName = StockTransactionTypeName;
|
||||
var resultList = dbRead.Read();
|
||||
|
||||
if (retriveTransactionTypeInfo)
|
||||
{
|
||||
var dbReadType = new Logic.Stock.SkuTransactionTypePersistance(sqlConnectionString);
|
||||
dbReadType.GetBySkuTransaction(resultList);
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrive SKU Transaction by ID
|
||||
/// </summary>
|
||||
/// <param name="SkuTransactionId">SKU Transaction ID</param>
|
||||
/// <param name="retriveTransactionTypeInfo"></param>
|
||||
/// <returns></returns>
|
||||
public List<Model.Stock.SkuTransaction> Read(List<int> SkuTransactionId, bool retriveTransactionTypeInfo = true)
|
||||
public List<Model.Stock.SkuTransaction> Read(List<int> SkuTransactionId)
|
||||
{
|
||||
var dbRead = new Data.Database.Stock.ReadSkuTransaction();
|
||||
var dbRead = DatabaseSkuTransRead();
|
||||
dbRead.Init();
|
||||
var resultList = dbRead.Read(SkuTransactionId);
|
||||
|
||||
if (retriveTransactionTypeInfo)
|
||||
{
|
||||
var dbReadType = new Logic.Stock.SkuTransactionTypePersistance(sqlConnectionString);
|
||||
dbReadType.GetBySkuTransaction(resultList);
|
||||
}
|
||||
|
||||
dbRead.Init();
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@@ -220,27 +263,26 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
throw new Exception(err + "Object was null");
|
||||
}
|
||||
|
||||
Validate().Innit();
|
||||
Validate().Init();
|
||||
if (!Validate().DatabaseUpdate(skuTransaction))
|
||||
{
|
||||
log.LogWarning(err + "Validation failed", Validate().ValidationResultListToString());
|
||||
throw new Exception(err + "Validation failed");
|
||||
}
|
||||
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
// is there an existing journal id that is changing
|
||||
int? journalId = DatabaseSkuTransRead().GetJournalId(skuTransaction.SkuTransactionId);
|
||||
if (journalId != null && skuTransaction.IsSetStockJournalId)
|
||||
{
|
||||
if (journalId != skuTransaction.StockJournalId)
|
||||
{
|
||||
DeleteJournalEntry(skuTransaction.SkuTransactionId);
|
||||
}
|
||||
}
|
||||
DatabaseSkuTransUpdate().Update(skuTransaction);
|
||||
scope.Complete();
|
||||
}
|
||||
DatabaseSkuTransUpdate().Update(skuTransaction);
|
||||
}
|
||||
|
||||
public void UpdateIsProcessed(int skuTransactionId, bool isProcessed, int? stockJournalId, bool enableJournalDelete = false)
|
||||
{
|
||||
// consistancy logic done on data level
|
||||
DatabaseSkuTransUpdate().UpdateIsProcessed(skuTransactionId, isProcessed, stockJournalId, enableJournalDelete);
|
||||
}
|
||||
|
||||
public void UpdateQuanitity(int skuTransactionId, int quantity)
|
||||
{
|
||||
// consistancy logic done on data level
|
||||
DatabaseSkuTransUpdate().UpdateQuanitity(skuTransactionId, quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
395
src/bnhtrade.Core/Logic/Stock/SkuTransactionImport.cs
Normal file
395
src/bnhtrade.Core/Logic/Stock/SkuTransactionImport.cs
Normal file
@@ -0,0 +1,395 @@
|
||||
using Amazon.Runtime.Internal.Transform;
|
||||
using bnhtrade.Core.Model.Stock;
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.Restrictions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
public class SkuTransactionImport
|
||||
{
|
||||
private Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
private string ConstructTransactionTypeCode(Model.Import.FbaReimbursementReport record, bool isPositive)
|
||||
{
|
||||
if (string.IsNullOrEmpty(record.Reason))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string transactionCode = "<AmazonReport><_GET_FBA_REIMBURSEMENTS_DATA_>";
|
||||
|
||||
if (isPositive)
|
||||
{
|
||||
transactionCode = transactionCode + "<+ve>";
|
||||
}
|
||||
else
|
||||
{
|
||||
transactionCode = transactionCode + "<-ve>";
|
||||
}
|
||||
|
||||
transactionCode = transactionCode + "<" + record.Reason + ">";
|
||||
return transactionCode;
|
||||
}
|
||||
|
||||
private string ConstructTransactionTypeCode(Model.Import.AmazonFbaInventoryLedgerDetail record)
|
||||
{
|
||||
if (string.IsNullOrEmpty(record.Reason))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string transactionCode = "<AmazonReport><GET_LEDGER_DETAIL_VIEW_DATA><" + record.EventType + ">";
|
||||
|
||||
if (!string.IsNullOrEmpty(record.Reason))
|
||||
{
|
||||
transactionCode = transactionCode + "<" + record.Reason + ">";
|
||||
}
|
||||
|
||||
if (record.Quantity < 0)
|
||||
{
|
||||
transactionCode = transactionCode + "<-ve>";
|
||||
}
|
||||
else
|
||||
{
|
||||
transactionCode = transactionCode + "<+ve>";
|
||||
}
|
||||
|
||||
transactionCode = transactionCode + "<" + record.Disposition + ">";
|
||||
|
||||
return transactionCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports/Transaposes all data required for reconcilation, into the sku transaction table.
|
||||
/// </summary>
|
||||
public void ImportAll()
|
||||
{
|
||||
bool inventoryLedgerDetail = false;
|
||||
bool reimbursement = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports/Transaposes data from the Amazon FBA Reimbursement report table, into the SKU transaction table, ready for reconcilation.
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void ImportAmazonFbaReimbursement()
|
||||
{
|
||||
throw new NotImplementedException("Needs testing");
|
||||
|
||||
/*
|
||||
* Not to be used for stock reconciliation! A single stock item can have multiple reimburesements aginst it.
|
||||
* Only use to move lost inventory to Amazon ownership (even then, with some caveats!)
|
||||
*
|
||||
* generally any lost or damaged stock goes to lost and found (and is hence written off)
|
||||
* once amazon have reimbursed (confitmation via this report) the stock is then moved to amazon owvership
|
||||
* and also the 'Cost of goods' amounts moved to the appropreate account id
|
||||
*/
|
||||
|
||||
log.LogInformation("Starting TransposeFbaRemovalOrderReport()");
|
||||
int transposeCount = 0;
|
||||
int transposeSkip = 0;
|
||||
var dbAmznReport = new Data.Database.Import.AmazonFbaReimbursement();
|
||||
var dbTransType = new Logic.Stock.SkuTransactionTypeCrud();
|
||||
|
||||
try
|
||||
{
|
||||
var importList = dbAmznReport.Read(false);
|
||||
|
||||
// we need to retrive the transaction-types from the database
|
||||
|
||||
// run through the returned records and build list of transaction-type codes
|
||||
var transTypeCodeList = new List<string>();
|
||||
foreach (var item in importList)
|
||||
{
|
||||
transTypeCodeList.Add(ConstructTransactionTypeCode(item, false));
|
||||
// any that reimburse inventory, will have two entries
|
||||
if(item.QuantityReimbursedInventory > 0)
|
||||
{
|
||||
transTypeCodeList.Add(ConstructTransactionTypeCode(item, true));
|
||||
}
|
||||
}
|
||||
transTypeCodeList = transTypeCodeList.Distinct().ToList();
|
||||
|
||||
// get transaction-type objects from db
|
||||
var transTypeDict = dbTransType.GetByTypeCode(transTypeCodeList);
|
||||
|
||||
// new transaction-type check
|
||||
var foundNewType = false;
|
||||
foreach (var transTypeCode in transTypeCodeList)
|
||||
{
|
||||
// if a transaction-type code did not exist in the db, we need to create it
|
||||
if (transTypeDict.ContainsKey(transTypeCode) == false)
|
||||
{
|
||||
dbTransType.Create(
|
||||
transTypeCode,
|
||||
(int)Data.Database.Constants.StockJournalType.SkuReconciliationFbaReimbursement
|
||||
);
|
||||
var newItem = dbTransType.GetByTypeCode(transTypeCode);
|
||||
if (newItem == null)
|
||||
{
|
||||
throw new Exception("Createing new transaction-type returned null");
|
||||
}
|
||||
transTypeDict.Add(newItem.TypeCode, newItem);
|
||||
foundNewType = true;
|
||||
}
|
||||
|
||||
// also check existing transaction-type for 'is new'
|
||||
if (transTypeDict[transTypeCode].IsNewReviewRequired)
|
||||
{
|
||||
foundNewType = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 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/");
|
||||
return;
|
||||
}
|
||||
|
||||
// we're all setup, time to transpose the report into the transaction table
|
||||
using (TransactionScope scope = new TransactionScope())
|
||||
{
|
||||
var dbTrans = new Logic.Stock.SkuTransactionCrud();
|
||||
foreach (var item in importList)
|
||||
{
|
||||
int? transId = null;
|
||||
// always added
|
||||
if (true)
|
||||
{
|
||||
string typeCode = ConstructTransactionTypeCode(item, false);
|
||||
var transType = transTypeDict[typeCode];
|
||||
|
||||
if (transType.IsNewReviewRequired)
|
||||
{
|
||||
throw new Exception("Fail safe: Buggy code, should not get here!");
|
||||
}
|
||||
else if (transType.TransactionImportEnabled)
|
||||
{
|
||||
var newTransaction = new Model.Stock.SkuTransactionCreate(
|
||||
item.ApprovalDate,
|
||||
typeCode,
|
||||
item.FbaReimbursementReportID,
|
||||
item.ReimbursementId,
|
||||
item.Reason,
|
||||
item.Sku,
|
||||
item.QuantityReimbursedInventory
|
||||
);
|
||||
|
||||
transId = dbTrans.Create(newTransaction);
|
||||
}
|
||||
}
|
||||
// double transaction added if true
|
||||
if (item.QuantityReimbursedInventory > 0)
|
||||
{
|
||||
string typeCode = ConstructTransactionTypeCode(item, true);
|
||||
var transType = transTypeDict[typeCode];
|
||||
|
||||
if (transType.IsNewReviewRequired)
|
||||
{
|
||||
throw new Exception("Fail safe: Buggy code, should not get here!");
|
||||
}
|
||||
else if (transType.TransactionImportEnabled)
|
||||
{
|
||||
var newTransaction = new Model.Stock.SkuTransactionCreate(
|
||||
item.ApprovalDate,
|
||||
typeCode,
|
||||
item.FbaReimbursementReportID,
|
||||
item.ReimbursementId,
|
||||
item.Reason,
|
||||
item.Sku,
|
||||
item.QuantityReimbursedInventory
|
||||
);
|
||||
|
||||
transId = dbTrans.Create(newTransaction);
|
||||
}
|
||||
}
|
||||
// update the amazon report table
|
||||
dbAmznReport.UpdateIsProcessed(item.FbaReimbursementReportID, true, transId);
|
||||
transposeCount = transposeCount + 1;
|
||||
}
|
||||
// drop out of loop
|
||||
scope.Complete();
|
||||
}
|
||||
Console.Write("\r");
|
||||
log.LogInformation("ProcessFbaReimbursementData() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.LogError("Exception catch, aborting ProcessFbaReimbursementData(), see detailed info. "
|
||||
+ transposeCount + " total records completed, " + transposeSkip + " records skipped.", ex.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports/Transaposes data from the Amazon FBA Ledger Detail report table, into the SKU transaction table, ready for reconcilation.
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public void ImportAmazonFbaLedgerDetail()
|
||||
{
|
||||
// Done but needs testing!!
|
||||
throw new NotImplementedException("Done but needs testing!!");
|
||||
|
||||
log.LogInformation("Starting TransposeFbaAdustmentReport()");
|
||||
int transposeCount = 0;
|
||||
int transposeSkip = 0;
|
||||
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
try
|
||||
{
|
||||
// get unprocessed amazon ledger report items
|
||||
var dbImport = new Data.Database.Import.AmazonFbaInventoryLedgerDetail();
|
||||
var reportDict = dbImport.Read(null, null, false);
|
||||
|
||||
// create transaction list to insert into transaction table
|
||||
var transactionList = new List<SkuTransactionCreate>();
|
||||
var transCodeToJournalTypeId = new Dictionary<string, int>();
|
||||
foreach (var item in reportDict)
|
||||
{
|
||||
// test for internal Amazon stuff that we don't care about and mark as processed
|
||||
if (item.Value.EventType == "WhseTransfers")
|
||||
{
|
||||
dbImport.UpdateIsProcessed(item.Key, true);
|
||||
}
|
||||
// add the the transaction list
|
||||
else
|
||||
{
|
||||
// build the transaction code
|
||||
string transactionCode = ConstructTransactionTypeCode(item.Value);
|
||||
|
||||
// load the report item into parameter
|
||||
DateTime transactionDate = item.Value.DateAndTime;
|
||||
|
||||
int foreignKey = item.Key;
|
||||
|
||||
string reference = null;
|
||||
if (!string.IsNullOrEmpty(item.Value.ReferenceId))
|
||||
{ reference = item.Value.ReferenceId; }
|
||||
|
||||
string detail = "Fulfillment Center: " + item.Value.FulfillmentCenter;
|
||||
|
||||
string skuNumber = item.Value.Msku;
|
||||
|
||||
// quanity in the transaction table is always be +ve
|
||||
int quantity = item.Value.Quantity;
|
||||
if (quantity < 0)
|
||||
quantity = quantity * -1;
|
||||
|
||||
// create the objet class and add to the list
|
||||
var transaction = new Model.Stock.SkuTransactionCreate(
|
||||
transactionDate
|
||||
, transactionCode
|
||||
, foreignKey
|
||||
, reference
|
||||
, detail
|
||||
, skuNumber
|
||||
, quantity
|
||||
);
|
||||
transactionList.Add(transaction);
|
||||
|
||||
// add transtypecode to dictionary to 'stock journal type' dictionary. Needed if there's a new transaction type
|
||||
if (transCodeToJournalTypeId.ContainsKey(transactionCode) == false)
|
||||
{
|
||||
int journalTypeId = 0;
|
||||
if (item.Value.EventType == "Receipts")
|
||||
{ journalTypeId = (int)Data.Database.Constants.StockJournalType.SkuReconciliationFbaReceipt; }
|
||||
else if (item.Value.EventType == "Shipments")
|
||||
{ journalTypeId = (int)Data.Database.Constants.StockJournalType.SkuReconciliationFbaShipment; }
|
||||
else if (item.Value.EventType == "Adjustments")
|
||||
{ journalTypeId = (int)Data.Database.Constants.StockJournalType.SkuReconciliationFbaAdjustment; }
|
||||
else if (item.Value.EventType == "CustomerReturns")
|
||||
{ journalTypeId = (int)Data.Database.Constants.StockJournalType.SkuReconciliationFbaCustomerReturn; }
|
||||
else if (item.Value.EventType == "VendorReturns")
|
||||
{ journalTypeId = (int)Data.Database.Constants.StockJournalType.SkuReconciliationFbaVendorReturn; }
|
||||
else if (item.Value.EventType == "WhseTransfers")
|
||||
{ journalTypeId = -1; }
|
||||
else
|
||||
{ throw new Exception("New event-type " + item.Value.EventType + " in the GET_LEDGER_DETAIL_VIEW_DATA report"); }
|
||||
|
||||
transCodeToJournalTypeId.Add(transactionCode, journalTypeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (transCodeToJournalTypeId.ContainsKey(transType.Key))
|
||||
{
|
||||
transCodeToJournalTypeId.Remove(transType.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var newItem in transCodeToJournalTypeId)
|
||||
{
|
||||
dbTransType.Create(newItem.Key, newItem.Value);
|
||||
}
|
||||
|
||||
// finally, add the transction list to the table
|
||||
var dbTransaction = new Logic.Stock.SkuTransactionCrud();
|
||||
foreach (var item in transactionList)
|
||||
{
|
||||
int id = dbTransaction.Create(item);
|
||||
dbImport.UpdateIsProcessed((int)item.ForeignKey, id);
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
|
||||
log.LogInformation(
|
||||
"TransposeFbaAdustmentReport() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped."
|
||||
);
|
||||
|
||||
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."
|
||||
, ex.ToString()
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,31 @@
|
||||
using System;
|
||||
using bnhtrade.Core.Data.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
using System.Web.UI;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
public class SkuTransactionReconcile
|
||||
{
|
||||
private string sqlConnectionString;
|
||||
private Data.Database.AmazonShipment.ReadShipmentInfo readShipmentInfo;
|
||||
private Logic.Stock.SkuTransactionPersistance dbSkuTransaction;
|
||||
private Logic.Stock.SkuTransactionTypePersistance dbSkuTransactionType;
|
||||
private Logic.Stock.SkuTransactionCrud dbSkuTransaction;
|
||||
private Logic.Validate.SkuTransaction validateSkuTrans;
|
||||
private Logic.Stock.StatusReallocate stockReallocate;
|
||||
private Logic.Log.LogEvent logEvent;
|
||||
private Logic.Log.LogEvent log;
|
||||
private string err = "Reconcile Sku Transaction Exception: ";
|
||||
|
||||
public SkuTransactionReconcile(string sqlConnectionString)
|
||||
public SkuTransactionReconcile()
|
||||
{
|
||||
Innit();
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
dbSkuTransaction = new SkuTransactionPersistance(sqlConnectionString);
|
||||
dbSkuTransactionType = new SkuTransactionTypePersistance(sqlConnectionString);
|
||||
dbSkuTransaction = new SkuTransactionCrud();
|
||||
readShipmentInfo = new Data.Database.AmazonShipment.ReadShipmentInfo();
|
||||
validateSkuTrans = new Validate.SkuTransaction();
|
||||
stockReallocate = new Logic.Stock.StatusReallocate(sqlConnectionString);
|
||||
logEvent = new Log.LogEvent();
|
||||
stockReallocate = new Logic.Stock.StatusReallocate();
|
||||
log = new Log.LogEvent();
|
||||
}
|
||||
|
||||
public int ItemsCompleted { get; private set; }
|
||||
@@ -58,12 +56,14 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through the stock transaction table and inserts stock journal entries, where applicable
|
||||
/// N.B. This function does not make allowances for status' that can create stock (i.e. if a status does not have stock available, this function will halt processing rows)
|
||||
/// Iterates through the stock transaction table and creates stock journal entries, if required
|
||||
/// N.B. This function does not make allowances for status' that can create stock (i.e. if a status does not have stock available,
|
||||
/// this function will halt processing rows)
|
||||
/// </summary>
|
||||
/// <param name="updateTransactions">Download and process Amazon reports before starting process</param>
|
||||
/// <param name="updateTransactions">Process Amazon reports before starting process</param>
|
||||
/// <param name="downloadAmaozn">Download reports from Amazon before starting process</param>
|
||||
/// <returns></returns>
|
||||
public void ReconcileStockTransactions(bool updateTransactions)
|
||||
public void ReconcileStockTransactions(bool updateTransactions, bool downloadAmazon = false)
|
||||
{
|
||||
Innit();
|
||||
string currentMethodName = nameof(ReconcileStockTransactions);
|
||||
@@ -73,8 +73,12 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
try
|
||||
{
|
||||
var preCheck = new bnhtrade.Core.Stock.StockReconciliation();
|
||||
preCheck.ProcessFbaStockImportData(sqlConnectionString);
|
||||
if (downloadAmazon)
|
||||
{
|
||||
new bnhtrade.Core.Logic.Import.AmazonFbaReimbursement().SyncDatabaseWithAmazon();
|
||||
new bnhtrade.Core.Logic.Import.AmazonFbaInventoryLedgerDetail().SyncDatabaseWithAmazon();
|
||||
}
|
||||
new bnhtrade.Core.Logic.Stock.SkuTransactionImport().ImportAll();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -83,10 +87,10 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
}
|
||||
}
|
||||
|
||||
logEvent.LogInformation("Starting ReconcileStockTransactions()");
|
||||
log.LogInformation("Starting ReconcileStockTransactions()");
|
||||
int recordSkip = 0;
|
||||
|
||||
ReconcileLostAndFound();
|
||||
ReconcileFoundAndLost();
|
||||
|
||||
// get list of sku transactions to reconcile
|
||||
dbSkuTransaction.Init();
|
||||
@@ -96,27 +100,37 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
ItemsRemaining = transList.Count;
|
||||
ItemsCompleted = 0;
|
||||
|
||||
// get list of sku transaction types
|
||||
var codeList = new List<string>();
|
||||
foreach(var item in transList)
|
||||
{
|
||||
codeList.Add(item.SkuTransactionTypeCode);
|
||||
}
|
||||
var transTypeDict = new Logic.Stock.SkuTransactionTypeCrud().GetByTypeCode(codeList);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// loop through transaction list
|
||||
for (int i = 0; i < transList.Count; i++)
|
||||
//for (int i = 0; i < transList.Count; i++)
|
||||
foreach (var transaction in transList)
|
||||
{
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
|
||||
Console.Write("\rProcessing record: {0} ({1} skipped)", (i + 1 + recordSkip), recordSkip);
|
||||
Console.Write("\rProcessing record: {0} ({1} skipped)", (ItemsCompleted + 1 + recordSkip), recordSkip);
|
||||
|
||||
// setup return values
|
||||
CurrentSkuTransaction = transList[i];
|
||||
CurrentTransactionId = transList[i].SkuTransactionId;
|
||||
CurrentTransactionTypeCode = transList[i].SkuTransactionType.TypeCode;
|
||||
LastItemDateTime = transList[i].TransactionDate;
|
||||
CurrentSkuTransaction = transaction;
|
||||
CurrentTransactionId = transaction.SkuTransactionId;
|
||||
CurrentTransactionTypeCode = transaction.SkuTransactionTypeCode;
|
||||
LastItemDateTime = transaction.TransactionDate;
|
||||
|
||||
// load type into variable
|
||||
//var transType = dbSkuTransactionType.GetByTypeName(transList[i].SkuTransactionTypeName);
|
||||
// setup variables
|
||||
var transactionType = transTypeDict[transaction.SkuTransactionTypeCode].Clone();
|
||||
|
||||
// stop if a new transactiontype is encountered
|
||||
if (transList[i].SkuTransactionType.IsNewReviewRequired)
|
||||
if (transactionType.IsNewReviewRequired)
|
||||
{
|
||||
ProgressMessage = "New 'Transaction-Type' encountered";
|
||||
//Console.Write("\r");
|
||||
@@ -124,51 +138,52 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
break;
|
||||
}
|
||||
|
||||
else if (transList[i].SkuTransactionType.StockJournalEntryEnabled == false)
|
||||
else if (transactionType.StockJournalEntryEnabled == false)
|
||||
{
|
||||
transList[i].IsProcessed = true;
|
||||
dbSkuTransaction.Update(transList[i]);
|
||||
//transList[i].IsProcessed = true;
|
||||
ReconcileTransaction(transaction.SkuTransactionId);
|
||||
}
|
||||
|
||||
// stock journal entry is enabled
|
||||
else
|
||||
{
|
||||
// check debit/credits
|
||||
if (transList[i].SkuTransactionType.DebitStockStatusId.GetValueOrDefault() == 0
|
||||
|| transList[i].SkuTransactionType.CreditStockStatusId.GetValueOrDefault() == 0)
|
||||
if (transactionType.DebitStockStatusId.GetValueOrDefault() == 0
|
||||
|| transactionType.CreditStockStatusId.GetValueOrDefault() == 0)
|
||||
{
|
||||
// special case FBA Shipment Receipt +ve
|
||||
if (transList[i].SkuTransactionType.TypeCode == "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><+ve>"
|
||||
|| transList[i].SkuTransactionType.TypeCode == "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><-ve>")
|
||||
if (transactionType.StockJournalTypeId == (int)Constants.StockJournalType.SkuReconciliationFbaReceipt)
|
||||
//transactionType.TypeCode == "<AmazonReport><GET_LEDGER_DETAIL_VIEW_DATA><Receipt><+ve>"
|
||||
//|| transactionType.TypeCode == "<AmazonReport><GET_LEDGER_DETAIL_VIEW_DATA><Receipt><-ve>")
|
||||
{
|
||||
Model.AmazonFba.ShipmentInfo shipmentInfo = null;
|
||||
if (!shipmentInfoDic.ContainsKey(transList[i].Reference))
|
||||
if (!shipmentInfoDic.ContainsKey(transaction.Reference))
|
||||
{
|
||||
shipmentInfo = readShipmentInfo.HeaderByFbaShipmentId(transList[i].Reference);
|
||||
shipmentInfo = readShipmentInfo.HeaderByFbaShipmentId(transaction.Reference);
|
||||
if (shipmentInfo == null)
|
||||
{
|
||||
throw new Exception("Unable to retrive shipment info for reference '" + transList[i].Reference + "'.");
|
||||
throw new Exception("Unable to retrive shipment info for reference '" + transaction.Reference + "'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
shipmentInfoDic.Add(transList[i].Reference, shipmentInfo);
|
||||
shipmentInfoDic.Add(transaction.Reference, shipmentInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (shipmentInfo.IsSetShipmentStockStatusId())
|
||||
{
|
||||
// +ve shipment receipt
|
||||
if (transList[i].SkuTransactionType.CreditStockStatusId == null
|
||||
&& transList[i].SkuTransactionType.DebitStockStatusId > 0)
|
||||
if (transactionType.CreditStockStatusId == null
|
||||
&& transactionType.DebitStockStatusId > 0)
|
||||
{
|
||||
transList[i].SkuTransactionType.CreditStockStatusId = shipmentInfo.ShipmentStockStatusId;
|
||||
transactionType.CreditStockStatusId = shipmentInfo.ShipmentStockStatusId;
|
||||
}
|
||||
|
||||
// -ve shipment receipt
|
||||
else if (transList[i].SkuTransactionType.DebitStockStatusId == null
|
||||
&& transList[i].SkuTransactionType.CreditStockStatusId > 0)
|
||||
else if (transactionType.DebitStockStatusId == null
|
||||
&& transactionType.CreditStockStatusId > 0)
|
||||
{
|
||||
transList[i].SkuTransactionType.DebitStockStatusId = shipmentInfo.ShipmentStockStatusId;
|
||||
transactionType.DebitStockStatusId = shipmentInfo.ShipmentStockStatusId;
|
||||
}
|
||||
|
||||
// something went wrong, raise error
|
||||
@@ -195,28 +210,28 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
|
||||
// make the journal entries
|
||||
var journalList = new List<(int StockJournalId, int Quantity)>();
|
||||
if (transList[i].SkuTransactionType.FilterStockOnDateTime)
|
||||
if (transactionType.FilterStockOnDateTime)
|
||||
{
|
||||
journalList = stockReallocate.BySkuNumber(
|
||||
transList[i].TransactionDate,
|
||||
transList[i].SkuTransactionType.StockJournalTypeId,
|
||||
transList[i].SkuNumber,
|
||||
transList[i].Quantity,
|
||||
transList[i].SkuTransactionType.DebitStockStatusId.GetValueOrDefault(),
|
||||
transList[i].SkuTransactionType.CreditStockStatusId.GetValueOrDefault(),
|
||||
transList[i].SkuTransactionType.FirstInFirstOut,
|
||||
transaction.TransactionDate,
|
||||
transactionType.StockJournalTypeId,
|
||||
transaction.SkuNumber,
|
||||
transaction.Quantity,
|
||||
transactionType.DebitStockStatusId.GetValueOrDefault(),
|
||||
transactionType.CreditStockStatusId.GetValueOrDefault(),
|
||||
transactionType.FirstInFirstOut,
|
||||
true);
|
||||
}
|
||||
else
|
||||
{
|
||||
journalList = stockReallocate.BySkuNumber(
|
||||
DateTime.UtcNow,
|
||||
transList[i].SkuTransactionType.StockJournalTypeId,
|
||||
transList[i].SkuNumber,
|
||||
transList[i].Quantity,
|
||||
transList[i].SkuTransactionType.DebitStockStatusId.GetValueOrDefault(),
|
||||
transList[i].SkuTransactionType.CreditStockStatusId.GetValueOrDefault(),
|
||||
transList[i].SkuTransactionType.FirstInFirstOut,
|
||||
transactionType.StockJournalTypeId,
|
||||
transaction.SkuNumber,
|
||||
transaction.Quantity,
|
||||
transactionType.DebitStockStatusId.GetValueOrDefault(),
|
||||
transactionType.CreditStockStatusId.GetValueOrDefault(),
|
||||
transactionType.FirstInFirstOut,
|
||||
true);
|
||||
}
|
||||
|
||||
@@ -224,7 +239,8 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
if (!journalList.Any())
|
||||
{
|
||||
// in special case (found inventory), continue
|
||||
if (transList[i].SkuTransactionType.TypeCode.Contains("<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><F>"))
|
||||
if (transactionType.TypeCode.Contains("<AmazonReport><GET_LEDGER_DETAIL_VIEW_DATA><Adjustment><F>")
|
||||
|| transactionType.TypeCode.Contains("<AmazonReport><GET_LEDGER_DETAIL_VIEW_DATA><Adjustment><N>"))
|
||||
{
|
||||
ItemsCompleted++;
|
||||
ItemsRemaining--;
|
||||
@@ -239,56 +255,61 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
}
|
||||
|
||||
// fail safe
|
||||
int qtyAllocated = journalList.Sum(c => c.Quantity);
|
||||
if (qtyAllocated > transList[i].Quantity)
|
||||
int qtyUnallocated = journalList.Sum(c => c.Quantity);
|
||||
if (qtyUnallocated > transaction.Quantity)
|
||||
{
|
||||
throw new Exception(
|
||||
currentMethodName + ": StockReallocateBySkuId() returned greater quantity than passed to function"
|
||||
+ transList[i].SkuTransactionId);
|
||||
+ transaction.SkuTransactionId);
|
||||
}
|
||||
|
||||
// update sku transaction table
|
||||
int qtyRemain = qtyAllocated;
|
||||
var newRecordList = new List<Model.Stock.SkuTransaction>();
|
||||
for (int j = 0; j < journalList.Count; j++)
|
||||
{
|
||||
// update existing record
|
||||
// update existing record to reconciled
|
||||
if (j == 0)
|
||||
{
|
||||
transList[i].Quantity = (short)journalList[j].Quantity;
|
||||
transList[i].StockJournalId = journalList[j].StockJournalId;
|
||||
transList[i].IsProcessed = true;
|
||||
dbSkuTransaction.UpdateQuanitity(transaction.SkuTransactionId, journalList[j].Quantity);
|
||||
dbSkuTransaction.UpdateIsProcessed(transaction.SkuTransactionId, true, journalList[j].StockJournalId);
|
||||
|
||||
dbSkuTransaction.Update(transList[i]);
|
||||
}
|
||||
// new record
|
||||
// create new reconciled record
|
||||
else
|
||||
{
|
||||
var newRecord = transList[i].Clone();
|
||||
newRecord.Quantity = (short)journalList[j].Quantity;
|
||||
newRecord.IsProcessed = true;
|
||||
newRecord.StockJournalId = journalList[j].StockJournalId;
|
||||
|
||||
newRecordList.Add(newRecord);
|
||||
var newTransaction = new Model.Stock.SkuTransactionCreate(
|
||||
transaction.TransactionDate
|
||||
, transaction.SkuTransactionTypeCode
|
||||
, transaction.ForeignKey
|
||||
, transaction.Reference
|
||||
, transaction.Detail
|
||||
, transaction.SkuNumber
|
||||
, journalList[j].Quantity
|
||||
);
|
||||
int newId = dbSkuTransaction.Create(newTransaction);
|
||||
dbSkuTransaction.UpdateIsProcessed(newId, true, journalList[j].StockJournalId);
|
||||
}
|
||||
|
||||
qtyRemain = qtyRemain - journalList[j].Quantity;
|
||||
qtyUnallocated = qtyUnallocated - journalList[j].Quantity;
|
||||
}
|
||||
|
||||
// new record for unallocated quantity
|
||||
if (qtyRemain > 0)
|
||||
// create new record for unreconciled quantity
|
||||
if (qtyUnallocated > 0)
|
||||
{
|
||||
var newRecord = transList[i].Clone();
|
||||
newRecord.Quantity = (short)qtyRemain;
|
||||
newRecord.IsProcessed = false;
|
||||
var newTransaction = new Model.Stock.SkuTransactionCreate(
|
||||
transaction.TransactionDate
|
||||
, transaction.SkuTransactionTypeCode
|
||||
, transaction.ForeignKey
|
||||
, transaction.Reference
|
||||
, transaction.Detail
|
||||
, transaction.SkuNumber
|
||||
, qtyUnallocated
|
||||
);
|
||||
int newId = dbSkuTransaction.Create(newTransaction);
|
||||
|
||||
newRecordList.Add(newRecord);
|
||||
}
|
||||
|
||||
// add new transactions to table
|
||||
for (int j = 0; j < newRecordList.Count; j++)
|
||||
{
|
||||
dbSkuTransaction.Create(newRecordList[j]);
|
||||
ProgressMessage = "Transaction could not be fully reconcoiled. Unallocated quanity remaing:" + qtyUnallocated;
|
||||
recordSkip = recordSkip + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,144 +346,146 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void ReconcileLostAndFound()
|
||||
public void ReconcileFoundAndLost()
|
||||
{
|
||||
/* Amazon can find a item before they lost it. In this senario the found item will not reconcile. Even when the lost transaction comes
|
||||
* though, it will be dated after the found transaction, so it also will not reconcile.
|
||||
*
|
||||
* This method tackles this. Instead of journal entries for found before lost, just cancel then out (set IsProcessed=true) for
|
||||
* both transactions.
|
||||
*
|
||||
* In the main reconcile method, if the porcdure hits an unreconciable found transaction, it will ignore it and carry on. Everything will still
|
||||
* tally at my end, even if Amazon thinks i've got more than I actually have
|
||||
*/
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
// need to loop though table and cancel out any found before they are lost (in reality they were never
|
||||
// lost, therefore should not be entered into journal as lost)
|
||||
string lost = "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><M><-ve><InventoryMisplaced><SELLABLE>";
|
||||
string found = "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><F><+ve><InventoryFound><SELLABLE>";
|
||||
|
||||
var codeList = new List<string>();
|
||||
codeList.Add(lost);
|
||||
codeList.Add(found);
|
||||
|
||||
// get list of sku transactions to reconcile
|
||||
dbSkuTransaction.Init();
|
||||
dbSkuTransaction.IsReconciled = false;
|
||||
dbSkuTransaction.StockTransactionTypeCode = codeList;
|
||||
var transList = dbSkuTransaction.Read();
|
||||
|
||||
ItemsRemaining = transList.Count;
|
||||
ItemsCompleted = 0;
|
||||
|
||||
for (int i = 0; i < transList.Count; i++)
|
||||
try
|
||||
{
|
||||
if (transList[i].SkuTransactionTypeCode == found && !transList[i].IsProcessed)
|
||||
var lostQueryString = new List<string>();
|
||||
lostQueryString.Add("<AmazonReport><GET_LEDGER_DETAIL_VIEW_DATA><Adjustments><M><-ve><SELLABLE>");
|
||||
|
||||
var foundQueryString = new List<string>();
|
||||
foundQueryString.Add("<AmazonReport><GET_LEDGER_DETAIL_VIEW_DATA><Adjustments><F><+ve><SELLABLE>");
|
||||
|
||||
dbSkuTransaction.Init();
|
||||
dbSkuTransaction.IsReconciled = false;
|
||||
dbSkuTransaction.StockTransactionTypeCode = lostQueryString;
|
||||
var lostList = dbSkuTransaction.Read();
|
||||
|
||||
dbSkuTransaction.Init();
|
||||
dbSkuTransaction.IsReconciled = false;
|
||||
dbSkuTransaction.StockTransactionTypeCode = foundQueryString;
|
||||
var foundList = dbSkuTransaction.Read();
|
||||
|
||||
|
||||
ItemsRemaining = foundList.Count;
|
||||
ItemsCompleted = 0;
|
||||
|
||||
for (int i = 0; i < foundList.Count; i++)
|
||||
{
|
||||
string sku = transList[i].SkuNumber;
|
||||
int foundQty = transList[i].Quantity;
|
||||
int foundQtyUnAllocated = foundQty;
|
||||
|
||||
// loop though list and find matching missing
|
||||
for (int j = 0; j < transList.Count; j++)
|
||||
for (int j = 0; j < lostList.Count; j++)
|
||||
{
|
||||
// update the 'lost' transaction
|
||||
if (transList[j].SkuNumber == sku
|
||||
&& transList[j].IsProcessed == false
|
||||
&& transList[j].SkuTransactionTypeCode == lost)
|
||||
if (foundList[i].SkuNumber == lostList[j].SkuNumber)
|
||||
{
|
||||
// split 'lost' transaction
|
||||
if (foundQtyUnAllocated - transList[j].Quantity < 0)
|
||||
// notes. isProcessed items need to be removed from the 'lost' list as we'll be looping over this multiple times, the
|
||||
// 'found' list we only loop though once
|
||||
//
|
||||
// when an sku match is found there is only 3 possible routes
|
||||
// 1. Lost == Found
|
||||
if (foundList[i].Quantity == lostList[j].Quantity)
|
||||
{
|
||||
// create 'reconciled' clone
|
||||
var clone = transList[j].Clone();
|
||||
clone.IsProcessed = true;
|
||||
clone.Quantity = (short)foundQtyUnAllocated;
|
||||
// mark reconciled transaction as isProcessed
|
||||
dbSkuTransaction.UpdateIsProcessed(foundList[i].SkuTransactionId, true, null);
|
||||
dbSkuTransaction.UpdateIsProcessed(lostList[j].SkuTransactionId, true, null);
|
||||
|
||||
// modifiy and validate existing record
|
||||
transList[j].IsProcessed = false;
|
||||
transList[j].Quantity = (short)(transList[j].Quantity - foundQtyUnAllocated);
|
||||
// delete reconciled from 'lost' list
|
||||
lostList.RemoveAt(j);
|
||||
|
||||
// fail safe check
|
||||
if (clone.IsProcessed)
|
||||
{
|
||||
foundQtyUnAllocated -= clone.Quantity;
|
||||
}
|
||||
if (transList[j].IsProcessed)
|
||||
{
|
||||
foundQtyUnAllocated -= transList[j].Quantity;
|
||||
}
|
||||
if (foundQtyUnAllocated != 0)
|
||||
{
|
||||
throw new Exception("Unallocated quantity should equal zero.");
|
||||
}
|
||||
|
||||
// submitt to database
|
||||
dbSkuTransaction.Create(clone);
|
||||
dbSkuTransaction.Update(transList[j]);
|
||||
}
|
||||
// set as isprocessed and continue
|
||||
else
|
||||
{
|
||||
foundQtyUnAllocated = foundQtyUnAllocated - transList[j].Quantity;
|
||||
transList[j].IsProcessed = true;
|
||||
|
||||
dbSkuTransaction.Update(transList[j]);
|
||||
}
|
||||
|
||||
// break?
|
||||
if (foundQtyUnAllocated == 0)
|
||||
{
|
||||
ItemsCompleted++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// drop out of the 'find lost' loop
|
||||
// 2. Lost < Found
|
||||
else if (foundList[i].Quantity < lostList[j].Quantity)
|
||||
{
|
||||
// split the lost transaction
|
||||
int newTransId = dbSkuTransaction.SplitTransaction(lostList[j].SkuTransactionId, foundList[i].Quantity);
|
||||
|
||||
// update the 'found' record
|
||||
if (foundQty != foundQtyUnAllocated)
|
||||
{
|
||||
// set isprocess = true
|
||||
if (foundQtyUnAllocated == 0)
|
||||
{
|
||||
transList[i].IsProcessed = true;
|
||||
dbSkuTransaction.Update(transList[i]);
|
||||
}
|
||||
// split record
|
||||
else if (foundQtyUnAllocated > 0)
|
||||
{
|
||||
// create 'reconciled' clone
|
||||
var clone = transList[i].Clone();
|
||||
clone.IsProcessed = true;
|
||||
clone.Quantity = (short)(clone.Quantity - foundQtyUnAllocated);
|
||||
// mark reconciled transaction as isProcessed
|
||||
dbSkuTransaction.UpdateIsProcessed(foundList[i].SkuTransactionId, true, null);
|
||||
dbSkuTransaction.UpdateIsProcessed(lostList[j].SkuTransactionId, true, null);
|
||||
|
||||
// modifiy existing record
|
||||
transList[i].IsProcessed = false;
|
||||
transList[i].Quantity = (short)foundQtyUnAllocated;
|
||||
// delete reconciled from 'lost' list
|
||||
lostList.RemoveAt(j);
|
||||
|
||||
// submitt to database
|
||||
dbSkuTransaction.Create(clone);
|
||||
dbSkuTransaction.Update(transList[i]);
|
||||
}
|
||||
// this shouldn't happen
|
||||
else
|
||||
{
|
||||
throw new Exception("Quantity unallocated is negative number");
|
||||
// retrieve the new split transaction
|
||||
var newTransactionList = dbSkuTransaction.Read(new List<int> { newTransId });
|
||||
if (!newTransactionList.Any())
|
||||
throw new Exception("Something went wrong, this should not happen.");
|
||||
var newTransaction = newTransactionList[0];
|
||||
|
||||
// insert new split 'lost' record into the list
|
||||
lostList.Insert(j, newTransaction);
|
||||
|
||||
ItemsCompleted++;
|
||||
break;
|
||||
}
|
||||
// 3. Lost > Found
|
||||
else if (foundList[i].Quantity > lostList[j].Quantity)
|
||||
{
|
||||
// split the found transaction
|
||||
int newTransId = dbSkuTransaction.SplitTransaction(lostList[i].SkuTransactionId, foundList[j].Quantity);
|
||||
|
||||
// mark reconciled transaction as isProcessed
|
||||
dbSkuTransaction.UpdateIsProcessed(foundList[i].SkuTransactionId, true, null);
|
||||
dbSkuTransaction.UpdateIsProcessed(lostList[j].SkuTransactionId, true, null);
|
||||
|
||||
// delete reconciled from 'lost' list
|
||||
lostList.RemoveAt(j);
|
||||
|
||||
// retrive the new split transaction
|
||||
var newTransactionList = dbSkuTransaction.Read(new List<int> { newTransId });
|
||||
if (!newTransactionList.Any())
|
||||
throw new Exception("Something went wrong, this should not happen.");
|
||||
var newTransaction = newTransactionList[0];
|
||||
|
||||
// // insert new split 'found' record into the list, in the next position
|
||||
foundList.Insert((i + 1), newTransaction);
|
||||
|
||||
ItemsCompleted++;
|
||||
ItemsRemaining++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Something went wrong, this should not happen.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// drop out of the 'find found' loop
|
||||
scope.Complete();
|
||||
scope.Complete();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
scope.Dispose();
|
||||
Console.Write("\r");
|
||||
ProgressMessage = ex.Message;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the transaction as reconciled/isprocessed with no stock journal entry required
|
||||
/// </summary>
|
||||
/// <param name="skuTransactionId"></param>
|
||||
public void ReconcileTransaction(int skuTransactionId)
|
||||
{
|
||||
new Data.Database.Stock.UpdateSkuTransaction().UpdateIsProcessed(skuTransactionId, true, null);
|
||||
}
|
||||
|
||||
public void UnReconcileTransaction(int skuTransactionId)
|
||||
{
|
||||
var trans = dbSkuTransaction.Read(new List<int> { skuTransactionId }, false).FirstOrDefault();
|
||||
if (trans == null) { return; }
|
||||
|
||||
// test if journal entry needs deleting, or just set to isprocessed = false
|
||||
if (trans.IsProcessed == true && trans.IsSetStockJournalId)
|
||||
{
|
||||
dbSkuTransaction.DeleteJournalEntry(skuTransactionId);
|
||||
}
|
||||
else if (trans.IsProcessed == true)
|
||||
{
|
||||
new Data.Database.Stock.UpdateSkuTransaction().Update(skuTransactionId, false);
|
||||
}
|
||||
new Data.Database.Stock.UpdateSkuTransaction().UpdateIsProcessed(skuTransactionId, false, null, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
106
src/bnhtrade.Core/Logic/Stock/SkuTransactionTypeCrud.cs
Normal file
106
src/bnhtrade.Core/Logic/Stock/SkuTransactionTypeCrud.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using bnhtrade.Core.Data.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
public class SkuTransactionTypeCrud : Connection // this inheritance can be removed when old code is removed below
|
||||
{
|
||||
private Data.Database.Stock.ReadSkuTransactionType dbRead;
|
||||
|
||||
public SkuTransactionTypeCrud()
|
||||
{
|
||||
dbRead = new Data.Database.Stock.ReadSkuTransactionType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SKU Transaction Type with default attributes and 'New' status.
|
||||
/// </summary>
|
||||
/// <param name="skuTransactionTypeCode">New identifier to be created</param>
|
||||
/// <param name="stockJournalTypeId"></param>
|
||||
/// <returns>Id for new record entry</returns>
|
||||
/// <exception cref="InvalidOperationException">Transaction type code already exists</exception>
|
||||
public int Create(string skuTransactionTypeCode, int stockJournalTypeId)
|
||||
{
|
||||
//check to see if type already exists
|
||||
var result = dbRead.ByTypeCode(new List<string> { skuTransactionTypeCode });
|
||||
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);
|
||||
return id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="typeCode"></param>
|
||||
/// <returns>The object, or null</returns>
|
||||
public Model.Stock.SkuTransactionType GetByTypeCode(string typeCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(typeCode))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = dbRead.ByTypeCode(new List<string> { typeCode });
|
||||
|
||||
if (result.Any())
|
||||
{
|
||||
return result[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrives transaction-type object from database
|
||||
/// </summary>
|
||||
/// <param name="typeCodeList">list of transaction type codes</param>
|
||||
/// <returns>DIctionary key=transactionTypeCode, value=transactionType object</returns>
|
||||
public Dictionary<string, Model.Stock.SkuTransactionType> GetByTypeCode(List<string> typeCodeList)
|
||||
{
|
||||
var returnDict = new Dictionary<string, Model.Stock.SkuTransactionType>();
|
||||
if (!typeCodeList.Any())
|
||||
{
|
||||
return returnDict;
|
||||
}
|
||||
|
||||
var dbResult = dbRead.ByTypeCode(typeCodeList);
|
||||
|
||||
foreach(var item in dbResult)
|
||||
{
|
||||
returnDict.Add(item.TypeCode, item);
|
||||
}
|
||||
|
||||
return returnDict;
|
||||
}
|
||||
|
||||
public Model.Stock.SkuTransactionType GetByTypeName(string typeName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(typeName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = dbRead.ByTypeName(new List<string> { typeName });
|
||||
|
||||
if (result.Any())
|
||||
{
|
||||
return result[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
public class SkuTransactionTypePersistance
|
||||
{
|
||||
private string sqlConnectionString;
|
||||
private List<Model.Stock.SkuTransactionType> cache;
|
||||
private Data.Database.Stock.ReadSkuTransactionType dbRead;
|
||||
|
||||
public SkuTransactionTypePersistance(string sqlConnectionString)
|
||||
{
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
dbRead = new Data.Database.Stock.ReadSkuTransactionType();
|
||||
CacheInnit();
|
||||
}
|
||||
|
||||
public void CacheInnit()
|
||||
{
|
||||
cache = new List<Model.Stock.SkuTransactionType>();
|
||||
}
|
||||
|
||||
public void CacheFillByTypeName(List<string> typeNameList)
|
||||
{
|
||||
CacheInnit();
|
||||
|
||||
if (typeNameList == null || !typeNameList.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//fill cache
|
||||
cache = dbRead.ByTypeName(typeNameList.Distinct().ToList());
|
||||
}
|
||||
|
||||
public void CacheFillByTypeCode(List<string> typeCodeList)
|
||||
{
|
||||
CacheInnit();
|
||||
|
||||
typeCodeList.RemoveAll(string.IsNullOrWhiteSpace);
|
||||
|
||||
if (typeCodeList == null || !typeCodeList.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//fill cache
|
||||
cache = dbRead.ByTypeCode(typeCodeList.Distinct().ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Using 'SKU Transaction Type Code', adds Sku Transaction Type info to a list of Stock SKU Transactions.
|
||||
/// </summary>
|
||||
/// <param name="skuTransactionList">Stock SKU Transaction list</param>
|
||||
/// <param name="clearCache">Force database read</param>
|
||||
/// <returns>Returns false if a 'Type Code' is not found, otherwise true</returns>
|
||||
public bool GetBySkuTransaction(List<Model.Stock.SkuTransaction> skuTransactionList)
|
||||
{
|
||||
bool allCodesFound = true;
|
||||
|
||||
if (skuTransactionList == null || !skuTransactionList.Any())
|
||||
{
|
||||
return allCodesFound;
|
||||
}
|
||||
|
||||
CacheFillByTypeCode(skuTransactionList.Select(x => x.SkuTransactionTypeCode).Distinct().ToList());
|
||||
for (int i = 0; i < skuTransactionList.Count(); i++)
|
||||
{
|
||||
if (skuTransactionList[i].IsSetSkuTransactionTypeCode)
|
||||
{
|
||||
var transType = GetByTypeCode(skuTransactionList[i].SkuTransactionTypeCode);
|
||||
if (transType == null)
|
||||
{
|
||||
allCodesFound = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
skuTransactionList[i].SkuTransactionType = transType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allCodesFound;
|
||||
}
|
||||
|
||||
public Model.Stock.SkuTransactionType GetByTypeCode(string typeCode, bool clearCache = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(typeCode))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (clearCache)
|
||||
{
|
||||
CacheInnit();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < cache.Count; i++)
|
||||
{
|
||||
if (cache[i].TypeCode == typeCode)
|
||||
{
|
||||
return cache[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result = dbRead.ByTypeCode(new List<string> { typeCode });
|
||||
|
||||
if (result.Any())
|
||||
{
|
||||
cache.Add(result[0]);
|
||||
return result[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Model.Stock.SkuTransactionType GetByTypeName(string typeName, bool clearCache = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(typeName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (clearCache)
|
||||
{
|
||||
CacheInnit();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < cache.Count; i++)
|
||||
{
|
||||
if (cache[i].TypeName == typeName)
|
||||
{
|
||||
return cache[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result = dbRead.ByTypeName(new List<string> { typeName });
|
||||
|
||||
if (result.Any())
|
||||
{
|
||||
cache.Add(result[0]);
|
||||
return result[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,8 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
public class StatusBalance
|
||||
{
|
||||
private string sqlConnectionString;
|
||||
|
||||
public StatusBalance(string sqlConnectionString)
|
||||
public StatusBalance()
|
||||
{
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,11 +9,8 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
public class StatusReallocate
|
||||
{
|
||||
private string sqlConnectionString;
|
||||
|
||||
public StatusReallocate(string sqlConnectionString)
|
||||
public StatusReallocate()
|
||||
{
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -25,7 +22,7 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
/// <param name="debitStatusId"></param>
|
||||
/// <param name="creditStatusId"></param>
|
||||
/// <param name="entryDate"></param>
|
||||
/// <returns>Return newly created stock journal Id</returns>
|
||||
/// <returns>Returns newly created stock journal Id</returns>
|
||||
public int ByStockId(DateTime entryDate, int journalTypeId, int stockId, int quantity, int debitStatusId, int creditStatusId)
|
||||
{
|
||||
if (entryDate == default(DateTime))
|
||||
@@ -39,7 +36,8 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
posts.Add((creditStatusId, (quantity * -1)));
|
||||
|
||||
// execute
|
||||
return Core.Stock.StockJournal.StockJournalInsert(sqlConnectionString, journalTypeId, stockId, posts, entryDate, false);
|
||||
// return Core.Stock.StockJournal.StockJournalInsert(sqlConnectionString, journalTypeId, stockId, posts, entryDate, false);
|
||||
return new Data.Database.Stock.JournalCrud().StockJournalInsert(journalTypeId, stockId, posts, entryDate, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,14 +51,14 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
/// <param name="creditStatusId">Status to move SKU from</param>
|
||||
/// <param name="firstInFirstOut">Move stock on first in first out basis</param>
|
||||
/// <param name="reallocatePartialQuantity">Reallocate patial quantity if the full quantity is not available</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>List of StockJournalId and quantity</returns>
|
||||
public List<(int StockJournalId, int Quantity)> BySkuNumber(DateTime entryDate, int journalTypeId, string skuNumber, int quantity, int debitStatusId, int creditStatusId,
|
||||
bool firstInFirstOut = true, bool reallocatePartialQuantity = false)
|
||||
{
|
||||
var returnList = new List<(int StockJournalId, int Quantity)>();
|
||||
|
||||
// get balance of status and check for avaliable quantity
|
||||
var statusBalance = new Logic.Stock.StatusBalance(sqlConnectionString).GetBySku(skuNumber, creditStatusId);
|
||||
var statusBalance = new Logic.Stock.StatusBalance().GetBySku(skuNumber, creditStatusId);
|
||||
|
||||
if (statusBalance.GetAvaliableQuantity(entryDate) <= 0
|
||||
|| (statusBalance.CheckAvaliableQuantity(quantity, entryDate) == false && reallocatePartialQuantity == false
|
||||
@@ -71,7 +69,6 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
|
||||
// temp code start
|
||||
// until use of stockId is designed out of application
|
||||
var getStockId = new Data.Database.Stock.ReadStockId();
|
||||
var stockIdDictionary = new Dictionary<int, int>();
|
||||
foreach (var item in statusBalance.ByDateList)
|
||||
{
|
||||
@@ -80,6 +77,7 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
stockIdDictionary.Add(item.StockNumber, 0);
|
||||
}
|
||||
}
|
||||
var getStockId = new Data.Database.Stock.ReadStockId();
|
||||
stockIdDictionary = getStockId.ByStockNumber(stockIdDictionary.Keys.ToList());
|
||||
// temp code finish
|
||||
|
||||
|
||||
115
src/bnhtrade.Core/Logic/Utilities/File.cs
Normal file
115
src/bnhtrade.Core/Logic/Utilities/File.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.Finances;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Utilities
|
||||
{
|
||||
public class File
|
||||
{
|
||||
public static string DecryptString(byte[] key, byte[] iv, byte[] cipherText)
|
||||
{
|
||||
byte[] buffer = cipherText;
|
||||
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.Key = key;
|
||||
aes.IV = iv;
|
||||
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||
|
||||
using (MemoryStream memoryStream = new MemoryStream(buffer))
|
||||
{
|
||||
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
|
||||
{
|
||||
using (StreamReader streamReader = new StreamReader((Stream)cryptoStream))
|
||||
{
|
||||
return streamReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] DecryptByte(byte[] key, byte[] iv, byte[] cipherText)
|
||||
{
|
||||
// untested, don't know if this works
|
||||
|
||||
byte[] buffer = cipherText;
|
||||
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.Key = key;
|
||||
aes.IV = iv;
|
||||
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||
|
||||
using (MemoryStream memoryStream = new MemoryStream(buffer))
|
||||
{
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(cipherText, 0, cipherText.Length);
|
||||
|
||||
return memoryStream.ToArray();
|
||||
//return decryptedData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string Decompress(string fileName)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(fileName);
|
||||
|
||||
using (FileStream originalFileStream = fileInfo.OpenRead())
|
||||
{
|
||||
string currentFileName = fileInfo.FullName;
|
||||
string newFileName = currentFileName.Remove(currentFileName.Length - fileInfo.Extension.Length);
|
||||
|
||||
using (FileStream decompressedFileStream = System.IO.File.Create(newFileName))
|
||||
{
|
||||
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
|
||||
{
|
||||
decompressionStream.CopyTo(decompressedFileStream);
|
||||
Console.WriteLine($"Decompressed: {fileInfo.Name}");
|
||||
}
|
||||
return decompressedFileStream.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Decompress(byte[] data)
|
||||
{
|
||||
using (var compressedStream = new MemoryStream(data))
|
||||
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
|
||||
using (var resultStream = new MemoryStream())
|
||||
{
|
||||
zipStream.CopyTo(resultStream);
|
||||
return resultStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static string DecompressString(string fileName)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(fileName);
|
||||
|
||||
using (FileStream originalFileStream = fileInfo.OpenRead())
|
||||
{
|
||||
string currentFileName = fileInfo.FullName;
|
||||
string newFileName = currentFileName.Remove(currentFileName.Length - fileInfo.Extension.Length);
|
||||
|
||||
using (FileStream decompressedFileStream = System.IO.File.Create(newFileName))
|
||||
{
|
||||
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
|
||||
{
|
||||
decompressionStream.CopyTo(decompressedFileStream);
|
||||
Console.WriteLine($"Decompressed: {fileInfo.Name}");
|
||||
}
|
||||
return decompressedFileStream.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Utilities
|
||||
{
|
||||
public class FileTransform
|
||||
{
|
||||
public static string DecryptString(byte[] key, byte[] iv, byte[] cipherText)
|
||||
{
|
||||
byte[] buffer = cipherText;
|
||||
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.Key = key;
|
||||
aes.IV = iv;
|
||||
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
|
||||
|
||||
using (MemoryStream memoryStream = new MemoryStream(buffer))
|
||||
{
|
||||
using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read))
|
||||
{
|
||||
using (StreamReader streamReader = new StreamReader((Stream)cryptoStream))
|
||||
{
|
||||
return streamReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static string Decompress(string fileName)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(fileName);
|
||||
|
||||
using (FileStream originalFileStream = fileInfo.OpenRead())
|
||||
{
|
||||
string currentFileName = fileInfo.FullName;
|
||||
string newFileName = currentFileName.Remove(currentFileName.Length - fileInfo.Extension.Length);
|
||||
|
||||
using (FileStream decompressedFileStream = File.Create(newFileName))
|
||||
{
|
||||
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
|
||||
{
|
||||
decompressionStream.CopyTo(decompressedFileStream);
|
||||
Console.WriteLine($"Decompressed: {fileInfo.Name}");
|
||||
}
|
||||
return decompressedFileStream.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,35 +8,27 @@ namespace bnhtrade.Core.Logic.Utilities
|
||||
{
|
||||
public class NightlyRoutine
|
||||
{
|
||||
private Model.Credentials.AmazonSPAPI amznCredentials;
|
||||
private Model.Credentials.bnhtradeDB dbCredentials;
|
||||
private Logic.Log.LogEvent log = new Log.LogEvent();
|
||||
|
||||
public NightlyRoutine(Model.Credentials.AmazonSPAPI amznCredentials, Model.Credentials.bnhtradeDB dbCredentials)
|
||||
public NightlyRoutine()
|
||||
{
|
||||
this.amznCredentials = amznCredentials;
|
||||
this.dbCredentials = dbCredentials;
|
||||
}
|
||||
|
||||
public void DownloadAll()
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert("Nightly scheduled tasks started.");
|
||||
log.LogInformation("Nightly scheduled tasks started.");
|
||||
|
||||
var stock = new bnhtrade.Core.Stock.StockReconciliation();
|
||||
var export = new bnhtrade.Core.Logic.Export.AmazonSettlement(dbCredentials.ConnectionString);
|
||||
var export = new bnhtrade.Core.Logic.Export.AmazonSettlement();
|
||||
|
||||
bool accountUpdate = false;
|
||||
bool stockUpdate = false;
|
||||
|
||||
bool accountProcess = false;
|
||||
bool stockProcess = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (accountUpdate == false) { accountUpdate = true; new Logic.Import.AmazonSettlement(amznCredentials).SyncDatabase(dbCredentials.ConnectionString); }
|
||||
if (stockUpdate == false) { stockUpdate = true; new bnhtrade.Core.Logic.Import.Amazon().SyncAllWithDatabase(); ; }
|
||||
if (accountProcess == false) { accountProcess = true; export.ToInvoice(); }
|
||||
if (stockUpdate == false) { stockUpdate = true; stock.UpdateFbaStockImportData(dbCredentials.ConnectionString); }
|
||||
|
||||
// if (stockProcess == false) { stockProcess = true; stock.ProcessFbaStockImportData(); }
|
||||
// ^^^^^^ best to process manually, case, fba inventory recepts, if a correction is made days later (ie -1) the already incorrect value
|
||||
@@ -46,14 +38,13 @@ namespace bnhtrade.Core.Logic.Utilities
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
new Logic.Log.LogEvent().EventLogInsert(
|
||||
log.LogInformation(
|
||||
"Exception caught running all report get method, see for further details",
|
||||
1,
|
||||
ex.ToString()
|
||||
);
|
||||
}
|
||||
}
|
||||
new Logic.Log.LogEvent().EventLogInsert("Nightly scheduled tasks finished.");
|
||||
log.LogInformation("Nightly scheduled tasks finished.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace bnhtrade.Core.Logic.Utilities
|
||||
public bool AllowWhiteSpace { get; set; } = false;
|
||||
public void ResetToDefault()
|
||||
{
|
||||
Innit();
|
||||
Init();
|
||||
AllowEmpty = false;
|
||||
AllowWhiteSpace = false;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace bnhtrade.Core.Logic.Validate
|
||||
|
||||
public new void Innit()
|
||||
{
|
||||
base.Innit();
|
||||
base.Init();
|
||||
stringCheck = new Logic.Utilities.StringCheck();
|
||||
}
|
||||
public bool IsValidAccountCodeId(int accountCode)
|
||||
|
||||
@@ -22,11 +22,11 @@ namespace bnhtrade.Core.Logic.Validate
|
||||
|
||||
public new void Innit()
|
||||
{
|
||||
base.Innit();
|
||||
timeCheck.Innit();
|
||||
stringCheck.Innit();
|
||||
base.Init();
|
||||
timeCheck.Init();
|
||||
stringCheck.Init();
|
||||
currencyCheck.Innit();
|
||||
decimalCheck.Innit();
|
||||
decimalCheck.Init();
|
||||
}
|
||||
|
||||
public bool IsValid(Model.Import.AmazonSettlement settlement)
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace bnhtrade.Core.Logic.Validate
|
||||
private Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck();
|
||||
public new void Innit()
|
||||
{
|
||||
base.Innit();
|
||||
base.Init();
|
||||
stringCheck = new Logic.Utilities.StringCheck();
|
||||
}
|
||||
public bool IsValidCurrencyCode(string currencyCode)
|
||||
|
||||
60
src/bnhtrade.Core/Logic/Validate/Format.cs
Normal file
60
src/bnhtrade.Core/Logic/Validate/Format.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Validate
|
||||
{
|
||||
public static class Format
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates that an sku number string is the correct format i.e. 000000-00
|
||||
/// </summary>
|
||||
/// <param name="skuNumber"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SkuNumber(string skuNumber)
|
||||
{
|
||||
if (string.IsNullOrEmpty(skuNumber)) { return false;}
|
||||
|
||||
int count = 0;
|
||||
foreach (char c in skuNumber)
|
||||
{
|
||||
count++;
|
||||
if (count == 7)
|
||||
{
|
||||
string hyphen = "-";
|
||||
if (c != hyphen[0])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (count > 9)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!char.IsNumber(c))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks the datetime is not default and is utc
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
/// <returns></returns>
|
||||
public static bool DateTime(DateTime dateTime)
|
||||
{
|
||||
if (dateTime == default(DateTime))
|
||||
{ return false; }
|
||||
else if (dateTime.Kind != DateTimeKind.Utc)
|
||||
{ return false; }
|
||||
else
|
||||
{ return true; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,12 @@ namespace bnhtrade.Core.Logic.Validate
|
||||
{
|
||||
public SkuPriceInfo()
|
||||
{
|
||||
Innit();
|
||||
Init();
|
||||
}
|
||||
|
||||
public bool IsValidDatabaseCreate(List<Model.Sku.Price.PriceInfo> priceInfoList)
|
||||
{
|
||||
Innit();
|
||||
Init();
|
||||
|
||||
if (!IsValid(priceInfoList))
|
||||
{
|
||||
|
||||
@@ -19,24 +19,15 @@ namespace bnhtrade.Core.Logic.Validate
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < skuTransactionList.Count; i++)
|
||||
{
|
||||
if (!skuTransactionList[i].IsSetSkuTransactionId)
|
||||
{
|
||||
ValidationResultAdd("StockTransactionId is required");
|
||||
}
|
||||
}
|
||||
|
||||
return IsValidResult;
|
||||
}
|
||||
|
||||
public bool DatabaseInsert(Model.Stock.SkuTransaction skuTransaction)
|
||||
public bool DatabaseInsert(Model.Stock.SkuTransactionCreate skuTransaction)
|
||||
{
|
||||
return IsValid(new List<Model.Stock.SkuTransaction> { skuTransaction });
|
||||
return IsValid(new List<Model.Stock.SkuTransactionCreate> { skuTransaction });
|
||||
}
|
||||
|
||||
public bool DatabaseInsert(List<Model.Stock.SkuTransaction> skuTransactionList)
|
||||
public bool DatabaseInsert(List<Model.Stock.SkuTransactionCreate> skuTransactionList)
|
||||
{
|
||||
return IsValid(skuTransactionList);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace bnhtrade.Core.Logic.Validate
|
||||
}
|
||||
}
|
||||
|
||||
public void Innit()
|
||||
public void Init()
|
||||
{
|
||||
ValidationResult = new List<ValidationResult>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user