mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-03-19 14:37:16 +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:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user