Files
bnhtrade/src/bnhtrade.Core/Logic/Stock/StatusBalance.cs
2024-04-11 12:26:13 +01:00

112 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Stock
{
public class StatusBalance
{
private string sqlConnectionString;
public StatusBalance(string sqlConnectionString)
{
this.sqlConnectionString = sqlConnectionString;
}
/// <summary>
/// Return the avaliable balance of a status. Uses a more efficent sql/code. However, balance requests should
/// generally also involve a date/time (i.e. the system does allow a stock transaction in the future, therefore
/// this method may give an available quantity, but transfers before that date wouod not be possible).
/// </summary>
/// <param name="sku">SKU number</param>
/// <param name="statusId">Status ID</param>
/// <returns>Balance as quantity</returns>
private int GetAvailableBalanceBySku(string sku, int statusId)
{
return new Data.Database.Stock.ReadStatusBalance().BySku(sku, statusId);
}
/// <summary>
/// Return the avaliable balance of a status at a specified date and time. Useful for checking availability before
/// moving stock/sku retrospectivly
/// </summary>
/// <param name="sku">SKU number</param>
/// <param name="statusId">Status ID</param>
/// <param name="atDate">Date and time you would like to know the balance at</param>
/// <returns></returns>
public Model.Stock.StatusBalance GetBySku(string sku, int statusId)
{
if (string.IsNullOrWhiteSpace(sku))
{
throw new Exception("SKU number is null, empty, or whitespace");
}
// get list of transactions for availale stock
var stockTransaction = new Data.Database.Stock.ReadStatusTransaction();
var transList = stockTransaction.BySku(statusId, sku);
// create quantity list
List<int> qtyList = new List<int>();
for (int i = 0; i < transList.TransactionList.Count; i++)
{
qtyList.Add(transList.TransactionList[i].Quantity);
}
// tally list
// loop, in reverse, to find credits to tally with debits
for (int iCr = qtyList.Count - 1; iCr > -1; iCr--)
{
if (qtyList[iCr] < 0)
{
int crStockNumber = transList.TransactionList[iCr].StockNumber;
DateTime crDate = transList.TransactionList[iCr].EntryDate;
// loop, in reverse, to find debits
for (int iDr = qtyList.Count - 1; iDr > -1; iDr--)
{
// find debits, last in first out (filter by date)
if (transList.TransactionList[iDr].StockNumber == crStockNumber
&& transList.TransactionList[iDr].EntryDate <= crDate
&& qtyList[iDr] > 0)
{
// credit fully assigned
if ((qtyList[iCr] + qtyList[iDr]) >= 0)
{
qtyList[iDr] = qtyList[iDr] + qtyList[iCr];
qtyList[iCr] = 0;
break;
}
// credit partially assigned
else
{
qtyList[iCr] = qtyList[iDr] + qtyList[iCr];
qtyList[iDr] = 0;
}
}
}
}
}
// build result list from tally results
var result = new Model.Stock.StatusBalance();
result.Sku = transList.Sku;
result.StockStatusId = transList.StockStatusId;
for (int i = 0; i < qtyList.Count; i++)
{
if (qtyList[i] != 0)
{
result.AddBalanceTransaction(
transList.TransactionList[i].EntryDate,
transList.TransactionList[i].StockNumber,
qtyList[i]);
}
}
return result;
}
}
}