This commit is contained in:
2025-07-09 16:47:37 +01:00
parent eb959dd6e2
commit e2af1e4f99
6 changed files with 288 additions and 251 deletions

View File

@@ -1,5 +1,6 @@
using bnhtrade.Core.Data.Database.Repository.Interface;
using bnhtrade.Core.Data.Database.UnitOfWork;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
@@ -183,14 +184,160 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
// read
//
public int? ReadStockJournalId(int stockId)
{
if (stockId <= 0)
{
throw new ArgumentException("Stock ID must be greater than zero", nameof(stockId));
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Transaction = _transaction as SqlTransaction;
cmd.CommandText = @"
SELECT StockJournalID
FROM tblStock
WHERE StockID=@stockId;;";
cmd.Parameters.AddWithValue("@stockId", stockId);
object obj = cmd.ExecuteScalar();
if (obj == null )
{
throw new Exception("StockID=" + stockId + " does not exist.");
}
else if (obj == DBNull.Value)
{
return null; // no stock journal entry
}
else
{
return (int)obj;
}
}
}
public int? ReadAccountJournalId(int stockId)
{
if (stockId <= 0)
{
throw new ArgumentException("Stock ID must be greater than zero", nameof(stockId));
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Transaction = _transaction as SqlTransaction;
cmd.CommandText = @"
SELECT AccountJournalID
FROM tblStock
WHERE StockID=@stockId;";
cmd.Parameters.AddWithValue("@stockId", stockId);
object obj = cmd.ExecuteScalar();
if (obj == null)
{
throw new Exception("StockID=" + stockId + " does not exist.");
}
else if (obj == DBNull.Value)
{
return null; // no account journal entry
}
else
{
return (int)obj;
}
}
}
//
// update
//
public int UpdateAccountJournalId(int stockId, int? accountJournalID)
{
if (stockId <= 0)
{
throw new ArgumentException("Stock ID must be greater than zero", nameof(stockId));
}
string sql = @"
UPDATE
tblStock
SET
AccountJournalID = @accountJournalID
WHERE
StockID = @stockId;";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@stockId", stockId);
if (accountJournalID == null)
{
cmd.Parameters.AddWithValue("@accountJournalID", DBNull.Value);
}
else
{
cmd.Parameters.AddWithValue("@accountJournalID", accountJournalID);
}
return cmd.ExecuteNonQuery();
}
}
public int UpdateStockJournalId(int stockId, int? stockJournalId)
{
if (stockId <= 0)
{
throw new ArgumentException("Stock ID must be greater than zero", nameof(stockId));
}
string sql = @"
UPDATE
tblStock
SET
StockJournalID = @stockJournalId
WHERE
StockID = @stockId;";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@stockId", stockId);
if (stockJournalId == null)
{
cmd.Parameters.AddWithValue("@stockJournalId", DBNull.Value);
}
else
{
cmd.Parameters.AddWithValue("@stockJournalId", stockJournalId);
}
return cmd.ExecuteNonQuery();
}
}
//
// delete
//
public int DeleteStockTableLine(int stockId)
{
if (stockId <= 0)
{
throw new ArgumentException("Stock ID must be greater than zero", nameof(stockId));
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Transaction = _transaction as SqlTransaction;
cmd.CommandText = @"
DELETE FROM tblStock
WHERE StockID=@stockId;";
cmd.Parameters.AddWithValue("@stockId", stockId);
return cmd.ExecuteNonQuery();
}
}
private void WIP_StockDelete(int stockId)
{
int accountJournalType = 0;

View File

@@ -12,6 +12,11 @@ namespace bnhtrade.Core.Data.Database.Repository.Interface
int accountJournalId, int stockJournalTypeId, DateTime stockJournalEntryDate, int quantity, int statusDebitId);
int WIP_StockInsertPurchase(int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId);
int WIP_StockInsertOwnerIntroduced(decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId);
int? ReadAccountJournalId(int stockId);
int? ReadStockJournalId(int stockId);
int UpdateAccountJournalId(int stockId, int? accountJournalID);
int UpdateStockJournalId(int stockId, int? stockJournalID);
int DeleteStockTableLine(int stockId);
void WIP_StockDelete(int stockId);
void WIP_StockDeleteSub(int stockId);
void WIP_StockDeleteSubAccountJournalEntry(int stockId);

View File

@@ -17,7 +17,7 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
IAmazonSettlementRepository AmazonSettlementRepository { get; }
IInvoiceRepository InvoiceRepository { get; }
IPurchaseRepository PurchaseRepository { get; }
IAccountJournalRepository JournalRepository { get; }
IAccountJournalRepository AccountJournalRepository { get; }
ISequenceGenerator SequenceGenerator { get; }
ISkuRepository SkuRepository { get; }
IStockRepository StockRepository { get; }

View File

@@ -19,13 +19,13 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
// Private field for lazy loading, add here for each repository
private IAccountCodeRepository _accountCodeRepository;
private IAccountJournalRepository _accountJournalRepository;
private IAccountTaxRepository _accountTaxRepository;
private IAmazonSettlementRepository _amazonSettlementRepository;
private ICurrencyRepository _currencyRepository;
private IExportInvoiceRepository _exportInvoiceRepository;
private IInvoiceRepository _invoiceRepository;
private IPurchaseRepository _purchaseRepository;
private IAccountJournalRepository _journalRepository;
private ISequenceGenerator _sequenceGenerator;
private ISkuRepository _skuRepository;
private IStockRepository _stockRepository;
@@ -51,6 +51,18 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
}
}
public IAccountJournalRepository AccountJournalRepository
{
get
{
if (_accountJournalRepository == null)
{
_accountJournalRepository = new AccountJournalRepository(_connection, _transaction);
}
return _accountJournalRepository;
}
}
public IAccountTaxRepository AccountTaxRepository
{
get
@@ -123,18 +135,6 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
}
}
public IAccountJournalRepository JournalRepository
{
get
{
if (_journalRepository == null)
{
_journalRepository = new AccountJournalRepository(_connection, _transaction);
}
return _journalRepository;
}
}
public ISequenceGenerator SequenceGenerator
{
get

View File

@@ -24,7 +24,7 @@ namespace bnhtrade.Core.Logic.Account
{
return WithUnitOfWork(uow =>
{
int journalId = uow.JournalRepository.AccountJournalInsert(journalTypeId, entryDate, currencyCode,
int journalId = uow.AccountJournalRepository.AccountJournalInsert(journalTypeId, entryDate, currencyCode,
amount, debitAccountId, creditAccountId, lockEntry);
CommitIfOwned(uow);
return journalId;
@@ -35,7 +35,7 @@ namespace bnhtrade.Core.Logic.Account
{
return WithUnitOfWork(uow =>
{
bool result = uow.JournalRepository.DeleteJournal(accountJournalId);
bool result = uow.AccountJournalRepository.DeleteJournal(accountJournalId);
CommitIfOwned(uow);
return result;
});

View File

@@ -15,237 +15,6 @@ namespace bnhtrade.Core.Logic.Inventory
internal StockService(IUnitOfWork unitOfWork) : base(unitOfWork) { }
private int WIP_StockInsert(int accountJournalType, int stockJournalType, string currencyCode, decimal amount,
int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
{
return WithUnitOfWork(uow =>
{
// add account journal entry
int accountJournalId = new Logic.Account.JournalService(uow).JournalInsert(accountJournalType, entryDate, currencyCode, amount);
// make the stock insert
int stockId = uow.StockRepository.WIP_StockInsertSub(productId, conditionId, accountTaxCodeId,
accountJournalId, stockJournalType, entryDate, quantity, debitStatusId);
CommitIfOwned(uow);
return stockId;
});
}
private void WIP_StockDelete(int stockId)
{
int stockJournalType = 0;
WithUnitOfWork(uow =>
{
// ensure stockId is owner-introduced
stockJournalType = uow.StockJournalRepository.ReadJournalTypeIdByStockId(stockId);
// check stock journal type is not restricted
// owner inventory introduced
if (stockJournalType == 2)
{
// no dramas
}
else
{
throw new Exception("Manual delete of this stock type is not supported, use the method that created it!");
}
// check there is only one stock journal entry for stock item (i.e. the source entry)
int count = uow.StockJournalRepository.ReadJournalEntryCountByStockId(stockId);
if (count > 1)
{
throw new Exception("Delete " + count + " stock journal entries (other than source entry), before peforming this operation.");
}
// remove account journal entry
WIP_StockDeleteSubAccountJournalEntry(sqlConnectionString, stockId);
// remove stock
WIP_StockDeleteSub(sqlConnectionString, stockId);
scope.Complete();
});
}
private void WIP_StockDeleteSub(int stockId)
{
using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
// check for accountJournalId on stock table
using (SqlCommand cmd = new SqlCommand(@"
SELECT AccountJournalID
FROM tblStock
WHERE StockID=@stockId;
", conn))
{
cmd.Parameters.AddWithValue("@stockId", stockId);
object obj = cmd.ExecuteScalar();
if (obj == null)
{
throw new Exception("StockID=" + stockId + " does not exist.");
}
else if (obj == DBNull.Value)
{
// nothing to do all is good
}
else
{
int id = (int)obj;
if (id > 0)
{
throw new Exception("StockID=" + stockId + " remove account journal entry using method that created it first.");
}
}
}
// get stockJournalId
int stockJournalId;
using (SqlCommand cmd = new SqlCommand(@"
SELECT StockJournalID
FROM tblStock
WHERE StockID=@stockId;
", conn))
{
cmd.Parameters.AddWithValue("@stockId", stockId);
try
{
stockJournalId = (int)cmd.ExecuteScalar();
}
catch
{
throw new Exception("Could not retrive StockJournalID for StockID=" + stockId);
}
}
// remove stockJournalId from stock table
using (SqlCommand cmd = new SqlCommand(@"
UPDATE tblStock
SET StockJournalID=NULL
WHERE StockID=@stockId;
", conn))
{
cmd.Parameters.AddWithValue("@stockId", stockId);
int count = cmd.ExecuteNonQuery();
if (count != 2) // we need to count the LastUpdated trigger!
{
throw new Exception("Failed to remove StockJournalID from stock table StockID=" + stockId);
}
}
// delete stock journal entry
new Core.Logic.Inventory.StockJournalService().StockJournalDelete(stockJournalId);
// delete stock table entry
using (SqlCommand cmd = new SqlCommand(@"
DELETE FROM tblStock
WHERE StockID=@stockId;
", conn))
{
cmd.Parameters.AddWithValue("@stockId", stockId);
int count = cmd.ExecuteNonQuery();
if (count != 1)
{
throw new Exception("StockID = " + stockId + " delete failed");
}
else
{
scope.Complete();
}
}
}
}
// to be used by other methods within a transaction scope
private void WIP_StockDeleteSubAccountJournalEntry(int stockId)
{
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
conn.Open();
var trans = conn.BeginTransaction();
// get the account journal id
int accountJournalId = 0;
using (SqlCommand cmd = new SqlCommand(@"
SELECT AccountJournalID
FROM tblStock
WHERE StockID=@stockId;
", conn))
{
cmd.Transaction = trans;
cmd.Parameters.AddWithValue("@stockId", stockId);
object obj = cmd.ExecuteScalar();
if (obj == null)
{
throw new Exception("StockID=" + stockId + " does not exist.");
}
else if (obj == DBNull.Value)
{
throw new Exception("AccountJournalID not found for StockID=" + stockId);
}
else
{
accountJournalId = (int)obj;
}
}
// remove entry from stock table
using (SqlCommand cmd = new SqlCommand(@"
UPDATE tblStock
SET AccountJournalID=NULL
WHERE StockID=@stockId;
", conn))
{
cmd.Transaction = trans;
cmd.Parameters.AddWithValue("@stockId", stockId);
int count = cmd.ExecuteNonQuery();
if (count != 2) // must include last modified trigger
{
throw new Exception("Failed to set AccountJournalID to NULL on stock table for StockID=" + stockId);
}
}
// delete account journal entry
new Data.Database.Repository.Implementation.AccountJournalRepository(conn, trans).DeleteJournal(accountJournalId);
trans.Commit();
}
}
public int WIP_StockInsertPurchase(int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId)
{
DateTime stockJournalEntryDate;
@@ -253,7 +22,7 @@ namespace bnhtrade.Core.Logic.Inventory
return WithUnitOfWork(uow =>
{
stockJournalEntryDate = uow.JournalRepository.ReadJournalEntryDate(accountJournalId);
stockJournalEntryDate = uow.AccountJournalRepository.ReadJournalEntryDate(accountJournalId);
int result = uow.StockRepository.WIP_StockInsertSub(
productId, conditionId, accountTaxCodeId, accountJournalId, stockJournalTypeId, stockJournalEntryDate, quantity, statusDebitId);
CommitIfOwned(uow);
@@ -267,17 +36,133 @@ namespace bnhtrade.Core.Logic.Inventory
int stockJournalType = 2;
string currencyCode = "GBP";
return WIP_StockInsert(accountJournalType, stockJournalType, currencyCode, amount, quantity, productId, conditionId, accountTaxCodeId, entryDate, debitStatusId);
return WithUnitOfWork(uow =>
{
int stockId = WIP_StockInsert(uow, accountJournalType, stockJournalType, currencyCode, amount, quantity, productId, conditionId, accountTaxCodeId, entryDate, debitStatusId);
CommitIfOwned(uow);
return stockId;
});
}
private int WIP_StockInsert(IUnitOfWork uow, int accountJournalType, int stockJournalType, string currencyCode, decimal amount,
int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
{
// add account journal entry
int accountJournalId = new Logic.Account.JournalService(uow).JournalInsert(accountJournalType, entryDate, currencyCode, amount);
// make the stock insert
int stockId = uow.StockRepository.WIP_StockInsertSub(productId, conditionId, accountTaxCodeId,
accountJournalId, stockJournalType, entryDate, quantity, debitStatusId);
return stockId;
}
public void WIP_StockDeletePurchase(int stockId)
{
WIP_StockDeleteSub(sqlConnectionString, stockId);
WithUnitOfWork(uow =>
{
if (stockId <= 0)
{
throw new ArgumentException("Stock ID must be greater than zero", nameof(stockId));
}
WIP_StockDelete(uow, stockId);
CommitIfOwned(uow);
});
}
public void WIP_StockDeleteOwnerIntroduced(int stockId)
{
WIP_StockDelete(sqlConnectionString, stockId);
WithUnitOfWork(uow =>
{
if (stockId <= 0)
{
throw new ArgumentException("Stock ID must be greater than zero", nameof(stockId));
}
WIP_StockDelete(uow, stockId);
CommitIfOwned(uow);
});
}
private void WIP_StockDelete(IUnitOfWork uow, int stockId)
{
int stockJournalType = 0;
// ensure stockId is owner-introduced
stockJournalType = uow.StockJournalRepository.ReadJournalTypeIdByStockId(stockId);
// check stock journal type is not restricted
// owner inventory introduced
if (stockJournalType == 2)
{
// no dramas
}
else
{
throw new Exception("Manual delete of this stock type is not supported, use the method that created it!");
}
// check there is only one stock journal entry for stock item (i.e. the source entry)
int count = uow.StockJournalRepository.ReadJournalEntryCountByStockId(stockId);
if (count > 1)
{
throw new Exception("Delete " + count + " stock journal entries (other than source entry), before peforming this operation.");
}
// remove account journal entry
WIP_StockDeleteSubAccountJournalEntry(uow, stockId);
// remove stock
WIP_StockDeleteSub(uow, stockId);
}
private void WIP_StockDeleteSub(IUnitOfWork uow, int stockId)
{
// check for accountJournalId on stock table
int? accountJournalId = uow.StockRepository.ReadAccountJournalId(stockId);
if (accountJournalId.HasValue)
{
throw new Exception("StockID=" + stockId + " remove account journal entry using method that created it first.");
}
// get stockJournalId
int stockJournalId = uow.StockRepository.ReadStockJournalId(stockId) ?? throw new Exception("StockJournalID not found for StockID=" + stockId);
// remove stockJournalId from stock table
int count = uow.StockRepository.UpdateStockJournalId(stockId, null);
if (count != 2) // we need to count the LastUpdated trigger!
{
throw new Exception("Failed to remove StockJournalID from stock table StockID=" + stockId);
}
// delete stock journal entry
uow.StockJournalRepository.StockJournalDelete(stockJournalId);
// delete stock table entry
count = uow.StockRepository.DeleteStockTableLine(stockId);
if (count != 1)
{
throw new Exception("StockID = " + stockId + " delete failed");
}
}
// to be used by other methods within a transaction scope
private void WIP_StockDeleteSubAccountJournalEntry(IUnitOfWork uow, int stockId)
{
// get the account journal id
int accountJournalId = uow.StockRepository.ReadAccountJournalId(stockId) ?? throw new Exception("AccountJournalID not found for StockID=" + stockId);
// remove entry from stock table
int count = uow.StockRepository.UpdateAccountJournalId(stockId, null);
if (count != 2) // must include last modified trigger
{
throw new Exception("Failed to set AccountJournalID to NULL on stock table for StockID=" + stockId);
}
// delete account journal entry
uow.AccountJournalRepository.DeleteJournal(accountJournalId);
}
}