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:
Bobbie Hodgetts
2024-05-07 08:24:00 +01:00
committed by GitHub
parent 2f919d7b5a
commit 91ef9acc78
1272 changed files with 4944 additions and 2773311 deletions

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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