using bnhtrade.Core.Data.Database; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Transactions; namespace bnhtrade.Core.Logic.Stock { public class SkuTransactionCrud { private string err = "Sku Transaction Persistance Error; "; private Data.Database.Stock.DeleteSkuTransaction dbSkuTransDelete; private Data.Database.Stock.InsertSkuTransaction dbSkuTransCreate; private Data.Database.Stock.ReadSkuTransaction dbSkuTransRead; private Data.Database.Stock.UpdateSkuTransaction dbSkuTransUpdate; private Logic.Validate.SkuTransaction validateSkuTrans; private Logic.Log.LogEvent log = new Log.LogEvent(); public SkuTransactionCrud() { } /// /// Initialise result filters /// public void Init() { IsReconciled = null; StockTransactionTypeName = null; StockTransactionTypeCode = null; } /// /// Read result filter /// public bool? IsReconciled { get; set; } /// /// Read result filter /// public List StockTransactionTypeName { get; set; } /// /// Read result filter /// public List StockTransactionTypeCode { get; set; } private Data.Database.Stock.DeleteSkuTransaction DatabaseSkuTransDelete(bool forceNew = false) { if (dbSkuTransDelete == null || forceNew) { dbSkuTransDelete = new Data.Database.Stock.DeleteSkuTransaction(); } return dbSkuTransDelete; } private Data.Database.Stock.InsertSkuTransaction DatabaseSkuTransInsert(bool forceNew = false) { if (dbSkuTransCreate == null || forceNew) { dbSkuTransCreate = new Data.Database.Stock.InsertSkuTransaction(); } return dbSkuTransCreate; } private Data.Database.Stock.ReadSkuTransaction DatabaseSkuTransRead(bool forceNew = false) { if (dbSkuTransRead == null || forceNew) { dbSkuTransRead = new Data.Database.Stock.ReadSkuTransaction(); } return dbSkuTransRead; } private Data.Database.Stock.UpdateSkuTransaction DatabaseSkuTransUpdate(bool forceNew = false) { if (dbSkuTransUpdate == null || forceNew) { dbSkuTransUpdate = new Data.Database.Stock.UpdateSkuTransaction(); } return dbSkuTransUpdate; } private Logic.Validate.SkuTransaction Validate() { if (validateSkuTrans == null) { validateSkuTrans = new Validate.SkuTransaction(); } return validateSkuTrans; } public void Delete(int skuTransactionId) { using (var scope = new TransactionScope()) { try { // is there a journal entry attached? int? journalId = DatabaseSkuTransRead().GetJournalId(skuTransactionId); if (journalId != null) { new Data.Database.Stock.JournalCrud().StockJournalDelete((int)journalId); } DatabaseSkuTransDelete().ByTransactionId(skuTransactionId); scope.Complete(); } catch (Exception ex) { scope.Dispose(); throw ex; } } } /// /// Creates a Stock SKU Transaction. Implements validation check. /// /// Input data/object /// Stock SKU Transaction Id of new record /// public int Create(Model.Stock.SkuTransactionCreate skuTransaction) { if (skuTransaction == null) { throw new Exception(err + "Object was null"); } Validate().Init(); if (!Validate().DatabaseInsert(skuTransaction)) { log.LogWarning(err + "Validation failed", Validate().ValidationResultListToString()); throw new Exception(err + "Validation failed"); } // write to database return DatabaseSkuTransInsert().Insert(skuTransaction); } /// /// /// /// Retrive and include transaction type model class public List Read() { var dbRead = DatabaseSkuTransRead(); dbRead.Init(); dbRead.IsReconciled = IsReconciled; dbRead.StockTransactionTypeCode = StockTransactionTypeCode; dbRead.StockTransactionTypeName = StockTransactionTypeName; var resultList = dbRead.Read(); dbRead.Init(); return resultList; } /// /// Updates a transaction quantity (must be less than) and creates a new transaction with the remaining quantity /// /// Stock SKU Transaction Id of the transaction to split /// Required quantity of the existing transaction /// Stock SKU Transaction Id of the newly created transaction /// Incorrect parameters passed to function /// transaction isProcessed error public int SplitTransaction(int skuTransactionId, int newQuantity) { using (var scope = new TransactionScope()) { try { // get transaction var transList = DatabaseSkuTransRead().Read(new List { skuTransactionId }); if (!transList.Any()) throw new ArgumentException("sku transaction id:" + skuTransactionId + "does appear to exist"); // Checks and new quanatity calculation int quantity2 = 0; var trans = transList[0]; if (trans.IsProcessed) throw new InvalidOperationException("Invalid operation: SKU Transaction is set to IsProcessed"); if (newQuantity == 0) throw new ArgumentException("Quantity parameter cannot be zero"); if (trans.Quantity == newQuantity) throw new ArgumentException("The new quanity is equal to the existing quantity"); if (trans.Quantity < 0 ) { // -ve <------ no transaction is less than 0, negative number are converted to posistive before entry to the table throw new Exception("sku transaction quantity cannot be negative"); if (newQuantity > 0) throw new ArgumentException("Quantity parameter is +ve when it should be -ve"); if (newQuantity < trans.Quantity) throw new ArgumentException("Quantity parameter is greater than transaction quantity"); quantity2 = trans.Quantity - newQuantity; } else if (trans.Quantity > 0) { // +ve if (newQuantity < 0) throw new ArgumentException("Quantity parameter is -ve when it should be +ve"); if (newQuantity > trans.Quantity) throw new ArgumentException("Quantity parameter is greater than transaction quantity"); quantity2 = trans.Quantity - newQuantity; } else { throw new ArgumentException("sku transaction quantity is zero"); } // clone transaction, add to database and update quantities var newTrans = trans.Clone(); int NewTransId = DatabaseSkuTransInsert().Insert(newTrans); UpdateQuanitity(skuTransactionId, newQuantity); UpdateQuanitity(NewTransId, quantity2); scope.Complete(); return NewTransId; } catch (Exception ex) { scope.Dispose(); throw ex; } } } /// /// Retrive SKU Transaction by ID /// /// SKU Transaction ID /// /// public List Read(List SkuTransactionId) { var dbRead = DatabaseSkuTransRead(); dbRead.Init(); var resultList = dbRead.Read(SkuTransactionId); dbRead.Init(); return resultList; } /// /// Validates and then updates a Stock SKU Tranaction /// /// 'Stock SKU Transaction' model public void Update(Model.Stock.SkuTransaction skuTransaction) { if (skuTransaction == null) { throw new Exception(err + "Object was null"); } Validate().Init(); if (!Validate().DatabaseUpdate(skuTransaction)) { log.LogWarning(err + "Validation failed", Validate().ValidationResultListToString()); throw new Exception(err + "Validation failed"); } DatabaseSkuTransUpdate().Update(skuTransaction); } public void UpdateIsProcessed(int skuTransactionId, bool isProcessed, int? stockJournalId, bool enableJournalDelete = false) { // consistancy logic done on data level DatabaseSkuTransUpdate().UpdateIsProcessed(skuTransactionId, isProcessed, stockJournalId, enableJournalDelete); } public void UpdateQuanitity(int skuTransactionId, int quantity) { // consistancy logic done on data level DatabaseSkuTransUpdate().UpdateQuanitity(skuTransactionId, quantity); } } }