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; } /// /// 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). /// /// SKU number /// Status ID /// Balance as quantity private int GetAvailableBalanceBySku(string sku, int statusId) { return new Data.Database.Stock.ReadStatusBalance(sqlConnectionString).BySku(sku, statusId); } /// /// Return the avaliable balance of a status at a specified date and time. Useful for checking availability before /// moving stock/sku retrospectivly /// /// SKU number /// Status ID /// Date and time you would like to know the balance at /// 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(sqlConnectionString); var transList = stockTransaction.BySku(statusId, sku); // create quantity list List qtyList = new List(); 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; } } }