Migration from Amazon MWS to Selling Partner API

This commit is contained in:
Bobbie Hodgetts
2024-04-11 12:26:13 +01:00
committed by GitHub
parent e054278cdd
commit a7bc00e73a
1318 changed files with 2778105 additions and 5936 deletions

View File

@@ -8,76 +8,53 @@ namespace bnhtrade.Core.Logic.Account
{
public class GetAccountCodeInfo
{
private string sqlConnectionString;
private Data.Database.Account.ReadAccountCode readAccountCode;
private Dictionary<int, Model.Account.AccountCode> cache;
public GetAccountCodeInfo(string sqlConnectionString)
public GetAccountCodeInfo()
{
this.sqlConnectionString = sqlConnectionString;
readAccountCode = new Data.Database.Account.ReadAccountCode(sqlConnectionString);
cache = new Dictionary<int, Model.Account.AccountCode>();
readAccountCode = new Data.Database.Account.ReadAccountCode();
}
public void CacheClear()
public List<Model.Account.AccountCode> GetAll()
{
cache.Clear();
return readAccountCode.All();
}
public void CacheFill()
public Model.Account.AccountCode ByAccountCode(int accountCode)
{
CacheClear();
var resultList = readAccountCode.All();
foreach (var result in resultList)
var list = ByAccountCode(new List<int> { accountCode });
if (list.Any())
{
cache.Add(result.AccountCodeId, result);
}
}
public void CacheFill(List<int> accountCodeList, bool forceDbRead = false)
{
if (accountCodeList == null || !accountCodeList.Any())
{
return;
}
var accountCodeQueryList = new List<int>();
foreach (var code in accountCodeList.Distinct().ToList())
{
if (forceDbRead)
{
cache.Remove(code);
accountCodeQueryList.Add(code);
}
else if (!cache.ContainsKey(code))
{
accountCodeQueryList.Add(code);
}
}
// get db list
var dbList = readAccountCode.ByAccountCode(accountCodeQueryList);
// add to cache
foreach (var item in dbList)
{
cache.Add(item.AccountCodeId, item);
}
}
public Model.Account.AccountCode ByAccountCode(int accountCode, bool forceDbRead = false)
{
CacheFill(new List<int> { accountCode }, forceDbRead);
if (cache.ContainsKey(accountCode))
{
return cache[accountCode];
return list[0];
}
else
{
return null;
}
}
public List<Model.Account.AccountCode> ByAccountCode(List<int> accountCodeList)
{
return readAccountCode.ByAccountCode(accountCodeList);
}
public Dictionary<int, Model.Account.AccountCode> ConvertToDictionary(List<Model.Account.AccountCode> accountCodeList)
{
var returnDict = new Dictionary<int, Model.Account.AccountCode>();
if (accountCodeList == null)
{
return returnDict;
}
foreach (var accountCode in accountCodeList)
{
if (!returnDict.ContainsKey(accountCode.AccountCodeId))
{
returnDict.Add(accountCode.AccountCodeId, accountCode);
}
}
return returnDict;
}
}
}
}

View File

@@ -8,20 +8,18 @@ namespace bnhtrade.Core.Logic.Account
{
public class GetInvoiceLineItem
{
string sqlConnectionString;
private Dictionary<string, Model.Account.InvoiceLineItem> cache;
private Data.Database.Account.ReadInvoiceLineItem dbRead;
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
private Logic.Account.GetTaxCodeInfo getTaxCode;
private Logic.Account.GetAccountCodeInfo getAccountCode;
public GetInvoiceLineItem(string sqlConnectionString)
public GetInvoiceLineItem()
{
this.sqlConnectionString = sqlConnectionString;
CacheInnit();
dbRead = new Data.Database.Account.ReadInvoiceLineItem(sqlConnectionString);
getAccountCode = new GetAccountCodeInfo(sqlConnectionString);
getTaxCode = new GetTaxCodeInfo(sqlConnectionString);
dbRead = new Data.Database.Account.ReadInvoiceLineItem();
getAccountCode = new GetAccountCodeInfo();
getTaxCode = new GetTaxCodeInfo();
}
/// <summary>
@@ -63,21 +61,21 @@ namespace bnhtrade.Core.Logic.Account
// query database
var resultList = dbRead.ByItemCode(itemCodeQueryList);
// fill account & tax codes cache
getAccountCode.CacheFill(dbRead.AccountCodeList.Values.ToList(), forceDbRead);
getTaxCode.CacheFill(dbRead.TaxCodeList.Values.ToList(), forceDbRead);
// get account & tax codes dictionaries
var accountCodeDict = getAccountCode.ConvertToDictionary(getAccountCode.ByAccountCode(dbRead.AccountCodeList.Values.ToList()));
var taxCodeDict = getTaxCode.ConvertToDictionary(getTaxCode.GetByTaxCode(dbRead.TaxCodeList.Values.ToList()));
// build final itemcode object and add to cache
foreach (var result in resultList.Values)
{
if (dbRead.AccountCodeList.ContainsKey(result.ItemCode))
{
result.DefaultAccountCode = getAccountCode.ByAccountCode(dbRead.AccountCodeList[result.ItemCode]);
result.DefaultAccountCode = accountCodeDict[dbRead.AccountCodeList[result.ItemCode]];
}
if (dbRead.TaxCodeList.ContainsKey(result.ItemCode))
{
result.DefaultTaxCode = getTaxCode.GetByTaxCode(dbRead.TaxCodeList[result.ItemCode]);
result.DefaultTaxCode = taxCodeDict[dbRead.TaxCodeList[result.ItemCode]];
}
cache.Add(result.ItemCode, result);
@@ -91,7 +89,7 @@ namespace bnhtrade.Core.Logic.Account
/// <returns></returns>
public Model.Account.InvoiceLineItem CreateDefault(string itemCode)
{
new Data.Database.Account.CreateInvoiceLineItem(sqlConnectionString).CreateDefault(itemCode);
new Data.Database.Account.CreateInvoiceLineItem().CreateDefault(itemCode);
var item = dbRead.ByItemCode(itemCode);
cache.Add(item.ItemCode, item);
return item;

View File

@@ -8,86 +8,29 @@ namespace bnhtrade.Core.Logic.Account
{
public class GetTaxCodeInfo
{
string sqlConnectionString;
private bool allRetrived;
private Dictionary<string, Model.Account.TaxCodeInfo> cache;
private Dictionary<string, Model.Account.TaxCodeInfo> cacheInvoiceItem;
private Data.Database.Account.ReadTaxCode dbRead;
public GetTaxCodeInfo(string sqlConnectionString)
public GetTaxCodeInfo()
{
this.sqlConnectionString = sqlConnectionString;
allRetrived = false;
CacheClear();
dbRead = new Data.Database.Account.ReadTaxCode(sqlConnectionString);
}
private void CacheClear()
{
cache = new Dictionary<string, Model.Account.TaxCodeInfo>();
cacheInvoiceItem = new Dictionary<string, Model.Account.TaxCodeInfo>();
}
public void CacheFill()
{
CacheClear();
var list = dbRead.GetAllActive();
foreach (var item in list)
{
cache.Add(item.TaxCode, item);
}
}
public void CacheFill(List<string> taxCodeList, bool forceDbRead = false)
{
if (taxCodeList == null || !taxCodeList.Any())
{
return;
}
var taxCodeQueryList = new List<string>();
foreach (var code in taxCodeList.Distinct().ToList())
{
if (forceDbRead)
{
cache.Remove(code);
taxCodeQueryList.Add(code);
}
else if (!cache.ContainsKey(code))
{
taxCodeQueryList.Add(code);
}
}
// get db list
var dbList = dbRead.GetByTaxCode(taxCodeQueryList);
// add to cache
foreach (var item in dbList)
{
cache.Add(item.TaxCode, item);
}
dbRead = new Data.Database.Account.ReadTaxCode();
}
public List<Model.Account.TaxCodeInfo> GetAllActive()
{
CacheFill();
return cache.Values.ToList();
return dbRead.GetAllActive();
}
public Model.Account.TaxCodeInfo GetByTaxCode(string taxCode, bool forceDbRead = false)
public List<Model.Account.TaxCodeInfo> GetByTaxCode(List<string> taxCodeList)
{
if (string.IsNullOrWhiteSpace(taxCode))
{
return null;
}
return dbRead.GetByTaxCode(taxCodeList);
}
CacheFill(new List<string> { taxCode }, forceDbRead);
if (cache.ContainsKey(taxCode))
public Model.Account.TaxCodeInfo GetByTaxCode(string taxCode)
{
var temp = GetByTaxCode(new List<string> { taxCode });
if (temp.Any())
{
return cache[taxCode];
return temp[0];
}
else
{
@@ -109,17 +52,9 @@ namespace bnhtrade.Core.Logic.Account
return returnList;
}
// remove any duplicates
var cleanSkuList = skuNumberList.Distinct().ToList();
// get db list
var dbList = dbRead.GetTaxCodeBySkuNumber(skuNumberList);
if (!dbList.Any()) { return returnList; }
// charge the cache
dbRead.GetAllActive();
// build dictionary
foreach (var item in dbList)
{
@@ -133,9 +68,50 @@ namespace bnhtrade.Core.Logic.Account
return returnList;
}
public Dictionary<string, Model.Account.TaxCodeInfo> Get(List<Model.Account.InvoiceLineItem> invoiceLineList)
public bool AddToSkuInfo(List<Model.Sku.Sku> skuList)
{
throw new NotImplementedException();
bool missionSuccess = true;
if (skuList == null || !skuList.Any())
{
return true;
}
// get list of sku numbers to condition codes
var lookupDictionary = GetBySkuNumber(skuList.Select(x => x.SkuNumber).ToList());
for (int i = 0; i < skuList.Count; i++)
{
if (lookupDictionary.ContainsKey(skuList[i].SkuNumber))
{
skuList[i].TaxCodeInfo = lookupDictionary[skuList[i].SkuNumber];
}
else
{
missionSuccess = false;
}
}
return missionSuccess;
}
public Dictionary<string, Model.Account.TaxCodeInfo> ConvertToDictionary(List<Model.Account.TaxCodeInfo> taxCodeList)
{
var returnDict = new Dictionary<string, Model.Account.TaxCodeInfo>();
if (taxCodeList == null)
{
return returnDict;
}
foreach (var taxCode in taxCodeList)
{
if (!returnDict.ContainsKey(taxCode.TaxCode))
{
returnDict.Add(taxCode.TaxCode, taxCode);
}
}
return returnDict;
}
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Amazon.Fba
{
public class Fnsku
{
/// <summary>
/// Gets any Amazon FNSKU numbers that are missing from database
/// </summary>
public void GetFnskus()
{
}
}
}

View File

@@ -10,33 +10,21 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
{
public class ShipmentInfoPersistanceUpdate
{
private string sqlConnectionString;
private readonly string logDateTimeId = "FbaInboundShipmentNewCheck";
public int TotalUpdated { get; private set; } = 0;
public ShipmentInfoPersistanceUpdate(string sqlConnectionString)
{
this.sqlConnectionString = sqlConnectionString;
}
public void GetNew()
{
TotalUpdated = 0;
// get time frame to check
DateTime dateTimeBefore = new Data.AmazonMWS.CurrentDateTime().GetUtc();
DateTime dateTimeAfter = new Data.Database.Log.DateTimeLog(sqlConnectionString).GetDateTimeUtc(logDateTimeId);
DateTime dateTimeBefore = new Data.Amazon.SellingPartnerAPI.Utils.CurrentDateTime().GetUtc();
DateTime dateTimeAfter = new Data.Database.Log.DateTimeLog().GetDateTimeUtc(logDateTimeId);
//var objGetUtc = new Data.AmazonMWS.CurrentDateTime();
//DateTime dateTimeBefore = objGetUtc.GetUtc();
var amazonApi = new Data.Amazon.FulFillmentInbound.GetShipments();
//var objDateTimeCheck = new Data.Database.Log.DateTimeLog(sqlConnectionString);
//DateTime dateTimeAfter = objDateTimeCheck.GetDateTimeUtc(logDateTimeId);
//
var shipmentRequest = new Data.AmazonMWS.FBAInbound.ListInboundShipments();
shipmentRequest.LastUpdatedAfter = dateTimeAfter.AddDays(-14);
shipmentRequest.LastUpdatedBefore = dateTimeBefore;
List<Model.AmazonFba.ShipmentInfo> shipmentInfoList = shipmentRequest.GetShipmentInfo();
var shipmentInfoList = amazonApi.GetByDateRange(dateTimeAfter.AddDays(-14), dateTimeBefore);
// build list of shipments returned from mws
var dicShipExistsInDb = new Dictionary<string, bool>();
@@ -55,7 +43,7 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
var newShipmentId = new List<string>();
// query db for shipment header info
var resultHeader = new Data.Database.AmazonShipment.ReadShipmentInfo(sqlConnectionString)
var resultHeader = new Data.Database.AmazonShipment.ReadShipmentInfo()
.HeaderByFbaShipmentId(dicShipExistsInDb.Keys.ToList());
// compare db and mws result
@@ -71,16 +59,15 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
}
}
// query mws for new shipment info
// query amazon's api for new shipment info
if (newShipmentId.Any())
{
shipmentRequest.ShipmentIdList = newShipmentId;
newShipmentInfoList = shipmentRequest.GetShipmentInfo();
newShipmentInfoList = amazonApi.GetByShipmentIdList(newShipmentId);
foreach (var item in newShipmentInfoList)
{
var shipmentItemInfoRequest = new Data.AmazonMWS.FBAInbound.ListInboundShipmentItems();
item.ShipmentItemInfoList = shipmentItemInfoRequest.GetByAmazonShipmentId(item.FbaShipmentId);
var shipmentItemInfoRequest = new Data.Amazon.FulFillmentInbound.GetShipmentItems();
item.ShipmentItemInfoList = shipmentItemInfoRequest.GetByShipmentId(item.FbaShipmentId);
}
}
@@ -93,7 +80,7 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
item.LastUpdated = dateTimeBefore;
// write to db
var dbWrite = new Data.Database.AmazonShipment.SetShipmentInfo(sqlConnectionString);
var dbWrite = new Data.Database.AmazonShipment.SetShipmentInfo();
dbWrite.Excecute(item);
complete = complete + 1;
}
@@ -101,7 +88,7 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
}
// update datetime log
new Data.Database.Log.DateTimeLog(sqlConnectionString).SetDateTimeUtc(logDateTimeId, dateTimeBefore);
new Data.Database.Log.DateTimeLog().SetDateTimeUtc(logDateTimeId, dateTimeBefore);
//objDateTimeCheck.SetDateTimeUtc(logDateTimeId, dateTimeBefore);
scope.Complete();

View File

@@ -21,16 +21,15 @@ namespace bnhtrade.Core.Logic.Export
public void ToInvoice()
{
var console = new UI.Console.Update();
log.LogInformation("Starting processing of Amazon settlement data into export invoice table...");
// check settlement reports consistancy
var consistencyCheck = new Data.Database.Consistency.ImportAmazonSettlement(sqlConnectionString).PeriodDateGaps();
var consistencyCheck = new Data.Database.Consistency.ImportAmazonSettlement().PeriodDateGaps();
if (consistencyCheck == false)
{ return; }
// get list of unprocssed settlement reports to export
var settlementData = new Data.Database.Import.ReadAmazonSettlement(sqlConnectionString);
var settlementData = new Data.Database.Import.AmazonSettlementRead();
var settlementList = settlementData.AllUnprocessed();
settlementData = null;
@@ -92,7 +91,7 @@ namespace bnhtrade.Core.Logic.Export
}
}
}
var taxCodeBySkuNumer = new Logic.Account.GetTaxCodeInfo(sqlConnectionString).GetBySkuNumber(skuList);
var taxCodeBySkuNumer = new Logic.Account.GetTaxCodeInfo().GetBySkuNumber(skuList);
// loop through each settlement and build list of invoices to export
Console.Write("\rBuilding invoices to export... ");
@@ -190,10 +189,11 @@ namespace bnhtrade.Core.Logic.Export
// add invoice item code data to lines
// also clean invoices of any disabled lines (remove lines and possibly invoices)
var getLineItemInfo = new Logic.Account.GetInvoiceLineItem(sqlConnectionString);
var getLineItemInfo = new Logic.Account.GetInvoiceLineItem();
getLineItemInfo.InsertNewOnNoMatch = true;
getLineItemInfo.CacheFill(lineItemCodeList);
bool newTypeFound = false;
string newTypeText = null;
for (int i = 0; i < invoiceList.Count(); i++)
{
@@ -209,6 +209,14 @@ namespace bnhtrade.Core.Logic.Export
else if (itemCode.IsNewReviewRequired)
{
newTypeFound = true;
if (string.IsNullOrWhiteSpace(itemCode.ItemCode))
{
newTypeText = itemCode.Name;
}
else
{
newTypeText = itemCode.ItemCode;
}
}
// clean invoices of any disabled lines (remove lines and possibly invoices)
else if (itemCode.InvoiceLineEntryEnabled == false)
@@ -243,7 +251,7 @@ namespace bnhtrade.Core.Logic.Export
{
if (newTypeFound)
{
throw new Exception("New line ItemCode found. Add item code default values and then try again.");
throw new Exception("Parameters required for Invoice line item code '"+ newTypeText + "'. Set in tblAccountInvoiceLineItem.");
}
return;
}
@@ -292,7 +300,7 @@ namespace bnhtrade.Core.Logic.Export
saveInv.SaveSalesInvoice(invoiceList);
// set settlements to isprocessed
new Data.Database.Import.UpdateAmazonSettlement(sqlConnectionString).SetIsProcessedTrue(settlementIdList);
new Data.Database.Import.AmazonSettlementUpdate().SetIsProcessedTrue(settlementIdList);
scope.Complete();
}
@@ -319,7 +327,7 @@ namespace bnhtrade.Core.Logic.Export
// add tax info if required
if ((match01 == "Order" || match01 == "Refund")
&& (match02 == "ItemPrice" || match02 == "Promotion"))
&& (match02 == "ItemPrice" || match02 == "Promotion" || match02 == "ItemWithheldTax"))
{
if (taxCodeBySkuNumer.ContainsKey(skuNumber))
{

View File

@@ -24,29 +24,17 @@ namespace bnhtrade.Core.Logic.Export
public void SubmitInventoryLoader(MemoryStream stream)
{
Model.Export.AmazonFeedSubmission result;
int queueId = QueueInventoryLoader(stream, out result);
SubmitQueuedFeedSubmission(queueId, result);
}
public void SubmitInventoryLoader(MemoryStream stream, out Model.Export.AmazonFeedSubmission result)
{
int queueId = QueueInventoryLoader(stream, out result);
SubmitQueuedFeedSubmission(queueId, result);
int queueId = QueueInventoryLoader(stream);
SubmitQueuedFeedSubmission(queueId);
}
public int QueueInventoryLoader(MemoryStream stream)
{
Model.Export.AmazonFeedSubmission result;
return QueueFeedSubbmission("_POST_FLAT_FILE_INVLOADER_DATA_", "txt", stream, out result);
return QueueFeedSubbmission("_POST_FLAT_FILE_INVLOADER_DATA_", "txt", stream);
}
public int QueueInventoryLoader(MemoryStream stream, out Model.Export.AmazonFeedSubmission result)
{
// write file database
return QueueFeedSubbmission("_POST_FLAT_FILE_INVLOADER_DATA_", "txt", stream, out result);
}
private int QueueFeedSubbmission(string feedType, string fileExtention, MemoryStream stream, out Model.Export.AmazonFeedSubmission result)
// adds the file(stream) to the database and returns the queue Id
private int QueueFeedSubbmission(string feedType, string fileExtention, MemoryStream stream)
{
// construct file object
var fileInfo = new Model.Data.DatabaseFileStream();
@@ -63,7 +51,7 @@ namespace bnhtrade.Core.Logic.Export
int queueId = 0;
using (var scope = new TransactionScope())
{
queueId = new Data.Database.Export.CreateAmazonFeedSubmission(sqlConnectionString).Execute(feedType, fileInfo);
queueId = new Data.Database.Export.CreateAmazonFeedSubmission().Execute(feedType, fileInfo);
// validate the result
var validateResults = new List<ValidationResult>();
@@ -83,11 +71,6 @@ namespace bnhtrade.Core.Logic.Export
scope.Complete();
}
// create feed object
result = new Model.Export.AmazonFeedSubmission();
result.FeedType = feedType;
result.File = fileInfo;
return queueId;
}
@@ -95,7 +78,11 @@ namespace bnhtrade.Core.Logic.Export
private void SubmitQueuedFeedSubmission(int queueId, Model.Export.AmazonFeedSubmission feedSubmission)
{
// upload to mws
var feedSubmitt = new Data.AmazonMWS.Feeds.SubmitFeed(feedSubmission);
//var feedSubmitt = new Data.AmazonMWS.Feeds.SubmitFeed(feedSubmission);
// upload to sp-api
var feedSubmitt = new Data.Amazon.Feeds.SubmittFeed();
feedSubmitt.SubmitFeed(feedSubmission);
if (!feedSubmitt.FeedSubmissionRecived)
{
@@ -104,7 +91,7 @@ namespace bnhtrade.Core.Logic.Export
}
// set the amazon feed Id
var dbUpdate = new Data.Database.Export.UpdateAmazonFeedSubmission(sqlConnectionString);
var dbUpdate = new Data.Database.Export.UpdateAmazonFeedSubmission();
dbUpdate.AddAmazonFeedId(queueId, feedSubmission.FeedSubmissionId);
// update progress info

View File

@@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Export
{
public class AmazonSubmitFileStatus
{
private string sqlConnectionString;
private bnhtrade.Core.Logic.Log.LogEvent log = new Log.LogEvent();
public AmazonSubmitFileStatus(string sqlConnectionString)
{
this.sqlConnectionString = sqlConnectionString;
}
public void UpdateStatusInfo()
{
var openList = new Data.Database.Export.ReadAmazonFeedSubmission(sqlConnectionString).GetOpenFeeds();
if (openList.Count == 0)
return;
var getStatus = new Data.AmazonMWS.Feeds.GetFeedSubmissions();
getStatus.FeedSubmissionIdList = openList.Select(x => x.FeedSubmissionId).ToList();
var currentStatus = getStatus.Invoke();
for (int i = 0; i < openList.Count; i++)
{
bool found = false;
for (int j = 0; j < currentStatus.Count; j++)
{
if (openList[i].FeedSubmissionId == currentStatus[j].FeedSubmissionId)
{
found = true;
openList[i].FeedProcessingStatus = currentStatus[j].FeedProcessingStatus;
if (currentStatus[j].IsSetCompletedProcessingDate())
openList[i].CompletedProcessingDate = currentStatus[j].CompletedProcessingDate;
if (currentStatus[j].IsSetStartedProcessingDate())
openList[i].StartedProcessingDate = currentStatus[j].StartedProcessingDate;
if (currentStatus[j].IsSetSubmittedDate())
openList[i].SubmittedDate = DateTime.Parse(currentStatus[j].SubmittedDate);
}
}
if (found == false)
{
log.LogError("FeedSubmissionId '" + openList[i].FeedSubmissionId + "' exists in database but was not returned by Amazon MWS when queried.");
openList.RemoveAt(i);
i = i - 1;
}
}
// update the database
new Data.Database.Export.UpdateAmazonFeedSubmission(sqlConnectionString).UpdateStatusInfo(openList);
}
}
}

View File

@@ -18,7 +18,7 @@ namespace bnhtrade.Core.Logic.Export
public string GetNextTempInvoiceNumber()
{
var sequence = new Data.Database.Programmability.Sequence(sqlConnectionString);
var sequence = new Data.Database.Programmability.Sequence();
return "_tmp" + sequence.GetNext("ExportTempInvoiceNumber").ToString("00000000");
}
@@ -47,7 +47,7 @@ namespace bnhtrade.Core.Logic.Export
validateInvoice = null;
// save to database
new Data.Database.Export.CreateSalesInvoice(sqlConnectionString).Execute(invoiceList);
new Data.Database.Export.CreateSalesInvoice().Execute(invoiceList);
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonFbaCustomerReturn
{
public void SyncDatabaseWithAmazon()
{
/*
* flat file lines/rows maybe unique
* Overlap reports by 3 days.
* To disambiguate duplicate row, I will use combination of date, orderid, fnsku, quantity, LPN#, disposition, and reason.
*/
// get most recent record from db
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);
if (!getFile.ReportFilePathIsSet)
{
MiscFunction.EventLogInsert(
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
2
);
return;
}
db.UpdateByFlatFile(getFile.ReportFilePath);
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonFbaInventory
{
public void SyncDatabaseWithAmazon()
{
var getFile = new Data.Amazon.Report.FbaInventory();
getFile.GetReport();
if (!getFile.ReportFilePathIsSet)
{
MiscFunction.EventLogInsert(
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
2
);
return;
}
new Data.Database.Import.AmazonFbaInventoryData().InsertByFlatFile(getFile.ReportFilePath);
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonFbaInventoryAdjustment
{
public void SyncDatabaseWithAmazon()
{
// get most recent record from db
var db = new Data.Database.Import.AmazonFbaInventoryAdjustment();
var startDate = db.ReadRecentDate().AddDays(-3);
var getFile = new Data.Amazon.Report.FbaInventoryAdustment();
getFile.GetReport(startDate, DateTime.UtcNow);
if (!getFile.ReportFilePathIsSet)
{
MiscFunction.EventLogInsert(
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
2
);
return;
}
db.InsertByFlatFile(getFile.ReportFilePath);
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonFbaInventoryAge
{
public void SyncDatabaseWithAmazon()
{
var getFile = new Data.Amazon.Report.FbaInventoryAge();
getFile.GetReport();
if (!getFile.ReportFilePathIsSet)
{
MiscFunction.EventLogInsert(
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
2
);
return;
}
new Data.Database.Import.AmazonFbaInventoryAgeData().InsertByFlatFile(getFile.ReportFilePath);
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonFbaInventoryReceipt
{
public void SyncDatabaseWithAmazon()
{
// get most recent record from db
var db = new Data.Database.Import.AmazonFbaInventoryReceipt();
var startDate = db.ReadRecentDate().AddSeconds(1);
var getReport = new Data.Amazon.Report.FbaInventoryReceipt();
getReport.GetReport(startDate, DateTime.UtcNow);
if (!getReport.ReportFilePathIsSet)
{
MiscFunction.EventLogInsert(
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
2
);
return;
}
db.InsertByFlatFile(getReport.ReportFilePath, startDate);
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonFbaReimbursement
{
public void SyncDatabaseWithAmazon()
{
// get most recent record from db
var db = new Data.Database.Import.AmazonFbaReimbursement();
var startDate = db.ReadRecentDate().AddDays(-3);
var getFile = new Data.Amazon.Report.FbaReimbursement();
getFile.GetReport(startDate, DateTime.UtcNow);
if (!getFile.ReportFilePathIsSet)
{
MiscFunction.EventLogInsert(
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
2
);
return;
}
db.InsertByFlatFile(getFile.ReportFilePath);
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonFbaRemovalOrder
{
public void SyncDatabaseWithAmazon()
{
/*
* flat file lines/rows are unique
* FROM MWS GUIDANCE
* https://docs.developer.amazonservices.com/en_UK/fba_guide/FBAGuide_TipsShipmentsReport.html
* 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);
var getFile = new Data.Amazon.Report.FbaRemovalOrder();
getFile.GetReport(startDate, DateTime.UtcNow);
if (!getFile.ReportFilePathIsSet)
{
MiscFunction.EventLogInsert(
"Something went wrong retriving report from Amazon SP API. Operation cancelled.",
2
);
return;
}
db.InsertByFlatFile(getFile.ReportFilePath);
}
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonFbaSaleShipment
{
private int maxTimePeriodDay = 30;
public void SyncDatabaseWithAmazon()
{
/*
* flat file lines/rows are unique
* FROM MWS GUIDANCE
* https://docs.developer.amazonservices.com/en_UK/fba_guide/FBAGuide_TipsShipmentsReport.html
* 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.AmazonFbaSaleShipment();
var dataSart = db.ReadRecentDate().AddDays(-3);
var dataEnd = DateTime.UtcNow;
// error check
if (dataSart >= dataEnd)
throw new Exception("Data start time is equal or greater than the end time.");
bool doLoop = true;
var requestStart = dataSart;
var requestEnd = dataSart.AddDays(maxTimePeriodDay);
if (requestEnd > dataEnd)
requestEnd = dataEnd;
do
{
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");
}
// 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;
}
}
while (doLoop);
}
}
}

View File

@@ -0,0 +1,67 @@
using System.Linq;
namespace bnhtrade.Core.Logic.Import
{
public class AmazonSettlement
{
Data.Amazon.Report.SettlementReport amazonReport;
public AmazonSettlement(Model.Credentials.AmazonSPAPI spapiCredentials)
{
amazonReport = new Data.Amazon.Report.SettlementReport();
}
public void SyncDatabase(string sqlConnectionString)
{
string operation = "Import Amazon Settlement Reports";
MiscFunction.EventLogInsert("Started '" + operation + "' operation.");
// get avaiable reports from amazon api
var spapiReportIdList = amazonReport.ListAvaliableReports();
int reportCount = spapiReportIdList.Count();
if (reportCount == 0)
{
MiscFunction.EventLogInsert("Exiting '" + operation + "' operation. No settlement reports availble on Amazon SP-API.");
return;
}
// query db and remove reports that have already been imported
var dbReportList = new Data.Database.Import.AmazonSettlementHeaderRead().BySpapiReportId(spapiReportIdList);
foreach (var dbReport in dbReportList)
{
if (dbReport.SpapiReportIdIsSet)
{
for (int i = 0; i < spapiReportIdList.Count; i++)
{
if (spapiReportIdList[i] == dbReport.SpapiReportId)
{
spapiReportIdList.RemoveAt(i);
i--;
break;
}
}
}
}
if (!spapiReportIdList.Any())
{
MiscFunction.EventLogInsert("Exiting '" + operation + "' operation. No new reports to import (" + reportCount + " avaibale).");
return;
}
// import into database
var dbImport = new Data.Database.Import.AmazonSettlementInsert();
for (int i = 0; i < spapiReportIdList.Count(); i++)
{
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]);
MiscFunction.EventLogInsert("Settlment Report imported (ReportID:" + spapiReportIdList[i] + ").");
}
return;
}
}
}

View File

@@ -11,28 +11,38 @@ namespace bnhtrade.Core.Logic.Log
private DateTime? eventDateTimeUtc;
private int? eventType;
private bool? printToConsole;
public DateTime EventDateTimeUtc
{
get { return (DateTime)eventDateTimeUtc; }
set { eventDateTimeUtc = DateTime.SpecifyKind(value, DateTimeKind.Utc); }
}
private int EventType
{
get { return (int)eventType; }
set { eventType = value; }
}
private string DetailShort { get; set; }
private string DetailLong { get; set; }
/// <summary>
/// Also prints short log entry to console. Default is 'true'
/// </summary>
public bool PrintToConsole
{
get { return (bool)printToConsole; }
set { printToConsole = value; }
}
public LogEvent()
{
EventType = 3;
PrintToConsole = true;
}
private void Execute()
{
// ensure we have enough parameter set
@@ -52,10 +62,9 @@ namespace bnhtrade.Core.Logic.Log
}
// update console
var console = new UI.Console.Update();
if (!IsSetDetailLong)
{ console.WriteLine(DetailShort); }
else { console.WriteLine(DetailShort + Environment.NewLine + DetailLong); }
{ UI.Console.WriteLine(DetailShort); }
else { UI.Console.WriteLine(DetailShort + Environment.NewLine + DetailLong); }
// log in database
DatabaseLogInsert(DetailShort, EventType, DetailLong, EventDateTimeUtc, false); // remove false on end once code is re-writtien
@@ -64,6 +73,7 @@ namespace bnhtrade.Core.Logic.Log
if (resetDateTime)
{ eventDateTimeUtc = null; }
}
public void LogAuditFailure(string detailShort, string detailLong = null)
{
eventType = 5;
@@ -71,6 +81,7 @@ namespace bnhtrade.Core.Logic.Log
DetailLong = detailLong;
Execute();
}
public void LogAuditSuccess(string detailShort, string detailLong = null)
{
eventType = 4;
@@ -78,6 +89,7 @@ namespace bnhtrade.Core.Logic.Log
DetailLong = detailLong;
Execute();
}
public void LogError(string detailShort, string detailLong = null)
{
eventType = 1;
@@ -85,6 +97,7 @@ namespace bnhtrade.Core.Logic.Log
DetailLong = detailLong;
Execute();
}
public void LogWarning(string detailShort, string detailLong = null)
{
eventType = 2;
@@ -92,6 +105,7 @@ namespace bnhtrade.Core.Logic.Log
DetailLong = detailLong;
Execute();
}
public void LogInformation(string detailShort, string detailLong = null)
{
eventType = 3;
@@ -99,6 +113,7 @@ namespace bnhtrade.Core.Logic.Log
DetailLong = detailLong;
Execute();
}
public void Initialise()
{
eventDateTimeUtc = null;
@@ -107,22 +122,27 @@ namespace bnhtrade.Core.Logic.Log
DetailLong = null;
PrintToConsole = true;
}
public bool IsSetEventDateTime
{
get { return eventDateTimeUtc != null; }
}
public bool IsSetEventType
{
get { return eventType != null; }
}
public bool IsSetDetailShort
{
get { return DetailShort != null; }
}
public bool IsSetDetailLong
{
get { return DetailLong != null; }
}
public bool IsSetPrintToConsole
{
get { return printToConsole != null; }

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Product
{
public class AmazonCompetitivePrice
{
private Data.Amazon.ProductPricing.GetCompetitivePricing apiRead;
public AmazonCompetitivePrice()
{
apiRead = new Data.Amazon.ProductPricing.GetCompetitivePricing();
}
/// <summary>
/// Function adapted (for use with SP-API) from VBA to retrive a product price from Amazon MWS and return a competivite price
/// </summary>
/// <param name="asin"></param>
/// <param name="lastPrice"></param>
public void GetForSpreadsheetApplication(string asin, decimal lastPrice = 0m)
{
var result = apiRead.ByAsin(asin);
//result = new Data.Amazon.SellingPartnerAPI.SDK.Models.ProductPricing.Price();
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Product
{
public class AmazonEstimateFee
{
public void UpdateDatabase(List<(string asin, decimal listingPrice)> inputList)
{
int inputCount = inputList.Count;
var log = new Log.LogEvent();
log.LogInformation("Starting update Amazon Fee Estimation, " + inputCount + " ASIN(s) to do...");
//check input list
if (!inputList.Any())
return;
// retrive product ids from db
var asinList = new List<string>();
foreach (var item in inputList)
{
asinList.Add(item.asin);
}
var productList = new Data.Database.Product.ReadProductId().ProductIdByAsin(asinList);
// request info from SP-API and update database
var amazon = new Data.Amazon.ProductFee.GetFeeEstimate();
var db = new Data.Database.Amazon.FeeEstimate();
var progress = new UI.ConsoleProgressBar(productList.Count, "Processing " + productList.Count + " records...");
int doneCount = 0;
try
{
foreach (var item in productList)
{
doneCount++;
progress.Report(doneCount);
string asin = item.Key;
int productId = item.Value;
decimal listingPrice = 0m;
foreach (var input in inputList)
{
if (asin == input.asin)
{
listingPrice = input.listingPrice;
break;
}
}
var result = amazon.GetFba(asin, productId, listingPrice);
db.UpdateProductFeeEstimate(result);
}
}
finally
{
progress.Dispose();
}
log.LogInformation("Completed update Amazon Fee Estimation, " + doneCount + " of " + inputCount + " done.");
}
}
}

View File

@@ -20,7 +20,7 @@ namespace bnhtrade.Core.Logic.Product
public GetCompetitivePrice(string sqlConnectionString)
{
this.sqlConnectionString = sqlConnectionString;
dbRead = new Data.Database.Product.ReadCompetitivePrice(sqlConnectionString);
dbRead = new Data.Database.Product.ReadCompetitivePrice();
newConditionMultipier = new Dictionary<int, decimal>();
}
@@ -39,7 +39,7 @@ namespace bnhtrade.Core.Logic.Product
DistinctResponceCount = 0;
}
public Dictionary<string, Model.Product.CompetitivePrice> Execute(List<Model.Sku.Price.SkuPriceParameter> skuParamList)
public Dictionary<string, Model.Product.CompetitivePrice> Execute(List<Model.Sku.Price.SkuRepriceInfo> skuParamList)
{
var requestList = new List<(int ProductId, int ConditionId)>();
for (int i = 0; i < skuParamList.Count; i++)
@@ -218,44 +218,46 @@ namespace bnhtrade.Core.Logic.Product
else
{
DistinctResponceCount = 1;
return result.First();
return result.First();
}
}
private void UpdateConditionMultipers()
{
var conditionInfo = new List<Model.Sku.SkuConditionInfo>();
throw new NotImplementedException();
if (newConditionMultipier.Any())
{
conditionInfo = new Logic.Sku.GetSkuConditionInfo(sqlConnectionString)
.GetByConditionId(newConditionMultipier.Keys.ToList());
}
else
{
conditionInfo = new Logic.Sku.GetSkuConditionInfo(sqlConnectionString).GetAll();
}
for(int i = 0; i < conditionInfo.Count; i++)
{
if (newConditionMultipier.ContainsKey(conditionInfo[i].SkuConditionId))
{
newConditionMultipier[conditionInfo[i].SkuConditionId] = conditionInfo[i].CompetitivePriceMultiplier;
}
else
{
throw new Exception("Condition Id mismatch");
}
}
//var conditionInfo = new List<Model.Sku.SkuConditionInfo>();
// check all multipilers have been set
for (int i = 0; i < newConditionMultipier.Count; i++)
{
if (newConditionMultipier.ElementAt(i).Value <= 0)
{
throw new Exception("Invalid price multiplier");
}
}
//if (newConditionMultipier.Any())
//{
// conditionInfo = new Logic.Sku.GetSkuConditionInfo(sqlConnectionString)
// .GetByConditionId(newConditionMultipier.Keys.ToList());
//}
//else
//{
// conditionInfo = new Logic.Sku.GetSkuConditionInfo(sqlConnectionString).GetAll();
//}
//for(int i = 0; i < conditionInfo.Count; i++)
//{
// if (newConditionMultipier.ContainsKey(conditionInfo[i].SkuConditionId))
// {
// newConditionMultipier[conditionInfo[i].SkuConditionId] = conditionInfo[i].CompetitivePriceMultiplier;
// }
// else
// {
// throw new Exception("Condition Id mismatch");
// }
//}
//// check all multipilers have been set
//for (int i = 0; i < newConditionMultipier.Count; i++)
//{
// if (newConditionMultipier.ElementAt(i).Value <= 0)
// {
// throw new Exception("Invalid price multiplier");
// }
//}
}
}
}
}

View File

@@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Product
{
public class GetProductInfo
{
private Data.Database.Product.ReadProduct dbRead;
public GetProductInfo()
{
Init();
}
public void Init()
{
dbRead = new Data.Database.Product.ReadProduct();
}
public Model.Product.ProductInfo GetByProductId(int productId)
{
var temp = GetByProductId(new List<int> { productId });
if (temp.Any()) { return temp[0]; }
else { return null; }
}
public List<Model.Product.ProductInfo> GetByProductId(List<int> productIdList)
{
dbRead.Innit();
dbRead.FilterByProductId = productIdList;
return dbRead.ExecuteQuery();
}
public Model.Product.ProductInfo GetBySkuNumber(string skuNumber)
{
var temp = GetBySkuNumber(new List<string> { skuNumber });
if (temp.ContainsKey(skuNumber))
{
return temp[skuNumber];
}
else
{
return null;
}
}
/// <summary>
/// Gets product info for given list of SKU numbers
/// </summary>
/// <param name="skuNumberList">SKU Number list</param>
/// <returns>Dictionary with SKU number as key and Product Info as value</returns>
public Dictionary<string, Model.Product.ProductInfo> GetBySkuNumber(List<string> skuNumberList)
{
var returnDictionary = new Dictionary<string, Model.Product.ProductInfo>();
if (skuNumberList == null || !skuNumberList.Any())
{
return returnDictionary;
}
var skuDictionary = dbRead.ProductIdBySkuNumber(skuNumberList);
var productList = GetByProductId(skuDictionary.Values.ToList());
// build return dictionary
foreach (var skuNumber in skuDictionary)
{
foreach (var product in productList)
{
if (product.ProductID == skuNumber.Value)
{
returnDictionary.Add(skuNumber.Key, product);
break;
}
}
}
return returnDictionary;
}
public bool AddToSkuInfo(List<Model.Sku.Sku> skuList)
{
bool missionSuccess = true;
if (skuList == null || !skuList.Any())
{
return true;
}
// get list of sku numbers to condition codes
var lookupDictionary = GetBySkuNumber(skuList.Select(x => x.SkuNumber).ToList());
for (int i = 0; i < skuList.Count; i++)
{
if (lookupDictionary.ContainsKey(skuList[i].SkuNumber))
{
skuList[i].ProductInfo = lookupDictionary[skuList[i].SkuNumber];
}
else
{
missionSuccess = false;
}
}
return missionSuccess;
}
}
}

View File

@@ -8,23 +8,94 @@ namespace bnhtrade.Core.Logic.Sku
{
public class GetSkuConditionInfo
{
private string sqlConnectionString;
private Data.Database.Sku.ReadSkuConditionInfo dbRead;
public GetSkuConditionInfo(string sqlConnectionString)
public GetSkuConditionInfo()
{
this.sqlConnectionString = sqlConnectionString;
dbRead = new Data.Database.Sku.ReadSkuConditionInfo(sqlConnectionString);
Init();
}
public void Init()
{
dbRead = new Data.Database.Sku.ReadSkuConditionInfo();
}
public List<Model.Sku.SkuConditionInfo> GetAll()
{
return dbRead.Read(new List<int>());
return dbRead.ByConditionCode(null);
}
public List<Model.Sku.SkuConditionInfo> GetByConditionId(List<int> conditionIdList)
public Model.Sku.SkuConditionInfo GetByConditionCode(string conditionCode)
{
return dbRead.Read(conditionIdList);
var temp = dbRead.ByConditionCode(new List<string> { conditionCode });
if (temp.Any())
{
return temp[0];
}
else
{
return null;
}
}
public List<Model.Sku.SkuConditionInfo> GetByConditionCode(List<string> conditionCodeList)
{
return dbRead.ByConditionCode(conditionCodeList);
}
public Dictionary<string, Model.Sku.SkuConditionInfo> GetBySkuNumber(List<string> skuNumberList)
{
var returnDictionary = new Dictionary<string, Model.Sku.SkuConditionInfo>();
if (skuNumberList == null || !skuNumberList.Any())
{
return returnDictionary;
}
var skuDictionary = dbRead.ReadSkuConditionCode(skuNumberList);
var conditionInfoList = dbRead.ByConditionCode(skuDictionary.Values.ToList());
// build return dictionary
foreach (var skuNumber in skuDictionary)
{
foreach (var conditionInfo in conditionInfoList)
{
if (conditionInfo.SkuConditionCode == skuNumber.Value)
{
returnDictionary.Add(skuNumber.Key, conditionInfo);
break;
}
}
}
return returnDictionary;
}
public bool AddToSkuInfo(List<Model.Sku.Sku> skuList)
{
bool missionSuccess = true;
if (skuList == null || !skuList.Any())
{
return true;
}
// get list of sku numbers to condition codes
var lookupDictionary = GetBySkuNumber(skuList.Select(x => x.SkuNumber).ToList());
for (int i = 0; i < skuList.Count; i++)
{
if (lookupDictionary.ContainsKey(skuList[i].SkuNumber))
{
skuList[i].ConditionInfo = lookupDictionary[skuList[i].SkuNumber];
}
else
{
missionSuccess = false;
}
}
return missionSuccess;
}
}
}
}

View File

@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Sku
{
public class GetSkuInfo
{
private string sqlConnectionString;
private Data.Database.Sku.ReadSku dbSkuInfo;
private Logic.Product.GetProductInfo getProductInfo;
private Logic.Sku.GetSkuConditionInfo getConditionInfo;
private Logic.Account.GetTaxCodeInfo getTaxCodeInfo;
public GetSkuInfo(string sqlConnection)
{
this.sqlConnectionString = sqlConnection;
Init();
}
public bool IncludeProductInfo
{
get
{
return getProductInfo != null;
}
set
{
if (value == true)
{
getProductInfo = new Product.GetProductInfo();
}
else
{
getProductInfo = null;
}
}
}
public bool IncludeConditionInfo
{
get
{
return getConditionInfo != null;
}
set
{
if (value == true)
{
getConditionInfo = new Sku.GetSkuConditionInfo();
}
else
{
getConditionInfo = null;
}
}
}
public bool IncludeTaxCodeInfo
{
get
{
return getTaxCodeInfo != null;
}
set
{
if (value == true)
{
getTaxCodeInfo = new Account.GetTaxCodeInfo();
}
else
{
getTaxCodeInfo = null;
}
}
}
protected void Init()
{
dbSkuInfo = new Data.Database.Sku.ReadSku();
if (IncludeProductInfo) { getProductInfo.Init(); }
if (IncludeConditionInfo) { getConditionInfo = new Sku.GetSkuConditionInfo(); }
if (IncludeTaxCodeInfo) { getTaxCodeInfo = new Account.GetTaxCodeInfo(); }
}
public Model.Sku.Sku BySkuNumber(string skuNumber)
{
var skuList = BySkuNumber(new List<string> { skuNumber });
if (skuList.Any())
{
return skuList[0];
}
else
{
return null;
}
}
public List<Model.Sku.Sku> BySkuNumber(List<string> skuNumberList)
{
var returnList = new List<Model.Sku.Sku>();
if (skuNumberList == null || !skuNumberList.Any())
{
return returnList;
}
returnList = dbSkuInfo.BySkuNumber(skuNumberList);
// add pproductInfo
if (IncludeProductInfo)
{
var ack = getProductInfo.AddToSkuInfo(returnList);
if (ack == false)
{
throw new Exception("Unable to load all product info for sku info object");
}
}
// add condition info
if (IncludeConditionInfo)
{
var ack = getConditionInfo.AddToSkuInfo(returnList);
if (ack == false)
{
throw new Exception("Unable to load all condition info for sku info object");
}
}
// add condition info
if (IncludeTaxCodeInfo)
{
var ack = getTaxCodeInfo.AddToSkuInfo(returnList);
if (ack == false)
{
throw new Exception("Unable to load all tax info for sku info object");
}
}
return returnList;
}
public Dictionary<string, Model.Sku.Sku> ConvertToDictionary(List<Model.Sku.Sku> skuInfoList)
{
var returnList = new Dictionary<string, Model.Sku.Sku>();
foreach (var skuInfo in skuInfoList)
{
if (!returnList.ContainsKey(skuInfo.SkuNumber))
{
returnList.Add(skuInfo.SkuNumber, skuInfo);
}
}
return returnList;
}
}
}

View File

@@ -17,9 +17,8 @@ namespace bnhtrade.Core.Logic.Sku.Price
private bnhtrade.Core.Logic.Log.LogEvent log = new Log.LogEvent();
string err = "FbaPricing Error: ";
private string marginSchemeTaxCode = Data.Database.Constants.GetMarginSchemeTaxCode();
int repriceHoldOnSalePeriod = 14; // days
private int newConditionId = Data.Database.Constants.GetProductConditionIdNew();
private List<Model.Sku.Price.SkuPriceParameter> skuInfo;
private List<Model.Sku.Price.SkuRepriceInfo> skuInfo;
private Dictionary<string, Model.Product.CompetitivePrice> competitivePrices;
DateTime newTimeStamp = DateTime.UtcNow;
private int repriceIncrementDivisor = 60;
@@ -35,6 +34,8 @@ namespace bnhtrade.Core.Logic.Sku.Price
marginSchemeMargin = taxCalc.GetMarginMultiplier(newTimeStamp);
}
public int RepriceHoldOnSalePeriod { get; set; } = 14; // days
public void Update(bool overrideDayCheck = false)
{
UpdatePrecheck();
@@ -43,8 +44,29 @@ namespace bnhtrade.Core.Logic.Sku.Price
{
string orderChannel = Data.Database.Constants.GetOrderChannelAmazonUk(); ; // may in future enable other order channels
// get SKU quantities in stock on FBA
var statusTypeList = new List<int> { 3, 4 };
var fbaSkuStock = new Logic.Stock.GetStatusTypeBalance().BySku(statusTypeList);
// retrive SKU info
var getSku = new Logic.Sku.GetSkuInfo(sqlConnectionString);
var skuInfoDict = getSku.ConvertToDictionary(getSku.BySkuNumber(fbaSkuStock.Keys.ToList()));
// get current sku base pricing details (stock quantity, competative price, VAT info, etc.)
skuInfo = new Data.Database.Sku.Price.ReadParameter(sqlConnectionString).Execute();
skuInfo = new Data.Database.Sku.Price.ReadParameter().Execute();
if (skuInfo == null || !skuInfo.Any())
{
err += "Querying the database returned no records.";
@@ -57,10 +79,10 @@ namespace bnhtrade.Core.Logic.Sku.Price
var crDictionary = new Dictionary<string, Model.Sku.Price.PriceInfo>();
// open needed classes
var readAge = new Data.Database.Import.ReadFbaInventoryAge(sqlConnectionString);
var readAge = new Data.Database.Import.AmazonFbaInventoryAgeRead();
// get current db pricing
var dbDictionary = new Data.Database.Sku.Price.ReadPricingDetail(sqlConnectionString).ReadDictionary(skuInfo.Select(o => o.SkuNumber).ToList(), orderChannel);
var dbDictionary = new Data.Database.Sku.Price.ReadPricingDetail().ReadDictionary(skuInfo.Select(o => o.SkuNumber).ToList(), orderChannel);
// get required competivie prices
var readComp = new Logic.Product.GetCompetitivePrice(sqlConnectionString);
@@ -248,7 +270,7 @@ namespace bnhtrade.Core.Logic.Sku.Price
if (skuInfo[i].TaxCode == marginSchemeTaxCode) // taxcodeinfo now has ismarginscheme boolean
{
price = (costPrice + agentFeeFixed - (costPrice * marginSchemeMargin))
price = (costPrice + agentFeeFixed - (costPrice * marginSchemeMargin))
/ (1 - profitMargin - agentFeeMargin - marginSchemeMargin);
}
else
@@ -300,8 +322,8 @@ namespace bnhtrade.Core.Logic.Sku.Price
{
if (!saleCountInPeriod.Any())
{
saleCountInPeriod = new Data.Database.Import.ReadFbaSaleShipment(sqlConnectionString)
.GetSaleCount(skuInfo.Select(x => x.SkuNumber).ToList(), DateTime.Now.AddDays(repriceHoldOnSalePeriod * -1), DateTime.Now);
saleCountInPeriod = new Data.Database.Import.AmazonFbaSaleShipment()
.ReadSaleCount(skuInfo.Select(x => x.SkuNumber).ToList(), DateTime.Now.AddDays(RepriceHoldOnSalePeriod * -1), DateTime.Now);
}
if (saleCountInPeriod.ContainsKey(skuInfo[i].SkuNumber))
{
@@ -313,6 +335,11 @@ namespace bnhtrade.Core.Logic.Sku.Price
}
}
/// <summary>
/// Compares current date and last reprice date to check if SKU can be repriced
/// </summary>
/// <param name="lastPriceUpdate">The date & time the SKU was lasted repriced</param>
/// <returns></returns>
private bool OkayToReprice(DateTime lastPriceUpdate)
{
if (lastPriceUpdate == default(DateTime))
@@ -338,6 +365,10 @@ namespace bnhtrade.Core.Logic.Sku.Price
return update;
}
/// <summary>
/// Saves the pricing info to databse
/// </summary>
/// <param name="crDictionary">Current repricing data in Dictonary form by SKU number</param>
private void SaveToDatabase(Dictionary<string, Model.Sku.Price.PriceInfo> crDictionary)
{
var validate = new Core.Logic.Validate.SkuPriceInfo();
@@ -348,7 +379,7 @@ namespace bnhtrade.Core.Logic.Sku.Price
throw new Exception(err);
}
new Data.Database.Sku.Price.CreatePricingDetail(sqlConnectionString).Executue(crDictionary.Values.ToList());
new Data.Database.Sku.Price.CreatePricingDetail().Executue(crDictionary.Values.ToList());
}
/// <summary>
@@ -409,4 +440,4 @@ namespace bnhtrade.Core.Logic.Sku.Price
submit.SubmitInventoryLoader(stream);
}
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Sku.Price
{
public class SkuRepriceInfo
{
public int SkuId { get; set; }
public string SkuNumber { get; set; }
public int TotalQuantity { get; set; }
public decimal UnitCostAverage { get; set; }
public int ProductId { get; set; }
public int ConditionId { get; set; }
public string TaxCode { get; set; }
public decimal ProfitMargin { get; set; }
/// <summary>
/// Agent fee as ratio of selling price (i.e. 20% = 0.2)
/// </summary>
public decimal AgentFeeMargin { get; set; }
/// <summary>
/// Total of agent fixed fees
/// </summary>
public decimal AgentFeeFixed { get; set; }
/// <summary>
/// Tax margin as a ratio of 1 (i.e. 20% = 0.2)
/// </summary>
public decimal VatMargin { get; set; }
public string TaxRateName { get; set; }
public bool IsFixedPrice { get; set; }
public decimal CompetitivePriceMultiplierNew { get; set; }
public decimal TotalCost { get; set; }
public decimal PriceMinProfit { get; set; }
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Stock
{
public class GetStatusTypeBalance
{
private Core.Data.Database.Stock.ReadStatusTypeBalance dbRead;
public GetStatusTypeBalance()
{
dbRead = new Data.Database.Stock.ReadStatusTypeBalance();
}
/// <summary>
/// Gets total balance of supplied 'Status Type(s)' grouped by SKU
/// </summary>
/// <param name="StatusTypeIdList">List of Status Type Ids</param>
/// <returns>Dictionary where SKU number is key and quantity is value</returns>
public Dictionary<string, int> BySku(List<int> StatusTypeIdList)
{
return dbRead.ReadSku(StatusTypeIdList);
}
}
}

View File

@@ -53,7 +53,7 @@ namespace bnhtrade.Core.Logic.Stock
{
if (dbSkuTransDelete == null || forceNew)
{
dbSkuTransDelete = new Data.Database.Stock.DeleteSkuTransaction(sqlConnectionString);
dbSkuTransDelete = new Data.Database.Stock.DeleteSkuTransaction();
}
return dbSkuTransDelete;
}
@@ -62,7 +62,7 @@ namespace bnhtrade.Core.Logic.Stock
{
if (dbSkuTransCreate == null || forceNew)
{
dbSkuTransCreate = new Data.Database.Stock.CreateSkuTransaction(sqlConnectionString);
dbSkuTransCreate = new Data.Database.Stock.CreateSkuTransaction();
}
return dbSkuTransCreate;
}
@@ -71,7 +71,7 @@ namespace bnhtrade.Core.Logic.Stock
{
if (dbSkuTransRead == null || forceNew)
{
dbSkuTransRead = new Data.Database.Stock.ReadSkuTransaction(sqlConnectionString);
dbSkuTransRead = new Data.Database.Stock.ReadSkuTransaction();
}
return dbSkuTransRead;
}
@@ -80,7 +80,7 @@ namespace bnhtrade.Core.Logic.Stock
{
if (dbSkuTransUpdate == null || forceNew)
{
dbSkuTransUpdate = new Data.Database.Stock.UpdateSkuTransaction(sqlConnectionString);
dbSkuTransUpdate = new Data.Database.Stock.UpdateSkuTransaction();
}
return dbSkuTransUpdate;
}
@@ -174,7 +174,7 @@ namespace bnhtrade.Core.Logic.Stock
/// <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(sqlConnectionString);
var dbRead = new Data.Database.Stock.ReadSkuTransaction();
dbRead.IsReconciled = IsReconciled;
dbRead.StockTransactionTypeCode = StockTransactionTypeCode;
dbRead.StockTransactionTypeName = StockTransactionTypeName;
@@ -197,7 +197,7 @@ namespace bnhtrade.Core.Logic.Stock
/// <returns></returns>
public List<Model.Stock.SkuTransaction> Read(List<int> SkuTransactionId, bool retriveTransactionTypeInfo = true)
{
var dbRead = new Data.Database.Stock.ReadSkuTransaction(sqlConnectionString);
var dbRead = new Data.Database.Stock.ReadSkuTransaction();
var resultList = dbRead.Read(SkuTransactionId);
if (retriveTransactionTypeInfo)

View File

@@ -24,7 +24,7 @@ namespace bnhtrade.Core.Logic.Stock
this.sqlConnectionString = sqlConnectionString;
dbSkuTransaction = new SkuTransactionPersistance(sqlConnectionString);
dbSkuTransactionType = new SkuTransactionTypePersistance(sqlConnectionString);
readShipmentInfo = new Data.Database.AmazonShipment.ReadShipmentInfo(sqlConnectionString);
readShipmentInfo = new Data.Database.AmazonShipment.ReadShipmentInfo();
validateSkuTrans = new Validate.SkuTransaction();
stockReallocate = new Logic.Stock.StatusReallocate(sqlConnectionString);
logEvent = new Log.LogEvent();
@@ -316,8 +316,8 @@ namespace bnhtrade.Core.Logic.Stock
//Stop:
Console.Write("\r");
MiscFunction.ConsoleUpdate("ProcessStockTransactions() compete. " + ItemsCompleted + " total records processed, " + recordSkip + " rows uncompllete due to insurficent stock.");
MiscFunction.ConsoleUpdate("ProcessStockTransactions(), " + recordSkip + " rows skipped due to insurficent stock.");
UI.Console.WriteLine("ProcessStockTransactions() compete. " + ItemsCompleted + " total records processed, " + recordSkip + " rows uncompllete due to insurficent stock.");
UI.Console.WriteLine("ProcessStockTransactions(), " + recordSkip + " rows skipped due to insurficent stock.");
return;
}
@@ -461,7 +461,7 @@ namespace bnhtrade.Core.Logic.Stock
}
else if (trans.IsProcessed == true)
{
new Data.Database.Stock.UpdateSkuTransaction(sqlConnectionString).Update(skuTransactionId, false);
new Data.Database.Stock.UpdateSkuTransaction().Update(skuTransactionId, false);
}
}
}

View File

@@ -15,7 +15,7 @@ namespace bnhtrade.Core.Logic.Stock
public SkuTransactionTypePersistance(string sqlConnectionString)
{
this.sqlConnectionString = sqlConnectionString;
dbRead = new Data.Database.Stock.ReadSkuTransactionType(sqlConnectionString);
dbRead = new Data.Database.Stock.ReadSkuTransactionType();
CacheInnit();
}

View File

@@ -25,7 +25,7 @@ namespace bnhtrade.Core.Logic.Stock
/// <returns>Balance as quantity</returns>
private int GetAvailableBalanceBySku(string sku, int statusId)
{
return new Data.Database.Stock.ReadStatusBalance(sqlConnectionString).BySku(sku, statusId);
return new Data.Database.Stock.ReadStatusBalance().BySku(sku, statusId);
}
/// <summary>
@@ -44,7 +44,7 @@ namespace bnhtrade.Core.Logic.Stock
}
// get list of transactions for availale stock
var stockTransaction = new Data.Database.Stock.ReadStatusTransaction(sqlConnectionString);
var stockTransaction = new Data.Database.Stock.ReadStatusTransaction();
var transList = stockTransaction.BySku(statusId, sku);
// create quantity list

View File

@@ -71,7 +71,7 @@ namespace bnhtrade.Core.Logic.Stock
// temp code start
// until use of stockId is designed out of application
var getStockId = new Data.Database.Stock.ReadStockId(sqlConnectionString);
var getStockId = new Data.Database.Stock.ReadStockId();
var stockIdDictionary = new Dictionary<int, int>();
foreach (var item in statusBalance.ByDateList)
{

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace bnhtrade.Core.Logic.Utilities
{
public class EasyMD5
{
private static string GetMd5Hash(byte[] data)
{
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
sBuilder.Append(data[i].ToString("x2"));
return sBuilder.ToString();
}
private static bool VerifyMd5Hash(byte[] data, string hash)
{
return 0 == StringComparer.OrdinalIgnoreCase.Compare(GetMd5Hash(data), hash);
}
public static string Hash(string data)
{
using (var md5 = MD5.Create())
return GetMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)));
}
public static string Hash(FileStream data)
{
using (var md5 = MD5.Create())
return GetMd5Hash(md5.ComputeHash(data));
}
public static bool Verify(string data, string hash)
{
using (var md5 = MD5.Create())
return VerifyMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)), hash);
}
public static bool Verify(FileStream data, string hash)
{
using (var md5 = MD5.Create())
return VerifyMd5Hash(md5.ComputeHash(data), hash);
}
}
}

View File

@@ -0,0 +1,57 @@
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;
}
}
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Utilities
{
public class NightlyRoutine
{
private Model.Credentials.AmazonSPAPI amznCredentials;
private Model.Credentials.bnhtradeDB dbCredentials;
public NightlyRoutine(Model.Credentials.AmazonSPAPI amznCredentials, Model.Credentials.bnhtradeDB dbCredentials)
{
this.amznCredentials = amznCredentials;
this.dbCredentials = dbCredentials;
}
public void DownloadAll()
{
MiscFunction.EventLogInsert("Nightly scheduled tasks started.");
var stock = new bnhtrade.Core.Stock.StockReconciliation();
var export = new bnhtrade.Core.Logic.Export.AmazonSettlement(dbCredentials.ConnectionString);
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 (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
// will have been entered in the stocktransaction table and maked as processed in the inventoryreceipt table
break;
}
catch (Exception ex)
{
MiscFunction.EventLogInsert(
"Exception caught running all report get method, see for further details",
1,
ex.ToString()
);
}
}
MiscFunction.EventLogInsert("Nightly scheduled tasks finished.");
}
}
}