mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-03-19 22:47:15 +00:00
444 lines
18 KiB
C#
444 lines
18 KiB
C#
using bnhtrade.Core.Data.Database.UnitOfWork;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Transactions;
|
|
using static System.Formats.Asn1.AsnWriter;
|
|
|
|
namespace bnhtrade.Core.Logic.Inventory
|
|
{
|
|
public class StockService : UnitOfWorkBase
|
|
{
|
|
public StockService() : base() { }
|
|
|
|
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)
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// add account journal entry
|
|
int accountJournalId = new Logic.Account.JournalService().JournalInsert(accountJournalType, entryDate, currencyCode, amount);
|
|
|
|
// make the stock insert
|
|
int stockId = WIP_StockInsertSub(sqlConnectionString, productId, conditionId, accountTaxCodeId,
|
|
accountJournalId, stockJournalType, entryDate, quantity, debitStatusId);
|
|
|
|
scope.Complete();
|
|
return stockId;
|
|
}
|
|
}
|
|
|
|
private int WIP_StockInsertSub(int productId, int conditionId, int accountTaxCodeId,
|
|
int accountJournalId, int stockJournalTypeId, DateTime stockJournalEntryDate, int quantity, int statusDebitId)
|
|
{
|
|
stockJournalEntryDate = DateTime.SpecifyKind(stockJournalEntryDate, DateTimeKind.Utc);
|
|
|
|
// ensure account journal id hasn't already been added to stock table
|
|
int count = 0;
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT Count(tblStock.StockID) AS CountOfID
|
|
FROM tblStock
|
|
WHERE (((tblStock.AccountJournalID)=@accountJouranlId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJouranlId", accountJournalId);
|
|
|
|
count = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
if (count == 1)
|
|
{
|
|
throw new Exception("Add account journal entry already assigned to stock line.");
|
|
}
|
|
else if (count > 1)
|
|
{
|
|
throw new Exception("Houston we have a problem! An account journal entry is assigned to " + count + " stock lines.");
|
|
}
|
|
|
|
// ensure the debit for the account journal transaction is to an 'Asset' account type
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
Count(tblAccountJournalPost.AccountJournalPostID) AS CountOfAccountJournalPostID
|
|
FROM
|
|
(tblAccountJournalPost
|
|
INNER JOIN tblAccountChartOf
|
|
ON tblAccountJournalPost.AccountChartOfID = tblAccountChartOf.AccountChartOfID)
|
|
INNER JOIN tblAccountChartOfType
|
|
ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID
|
|
WHERE
|
|
tblAccountJournalPost.AmountGbp>=0
|
|
AND tblAccountChartOfType.BasicType='Asset'
|
|
AND tblAccountJournalPost.AccountJournalID=@accountJournalId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
if ((int)cmd.ExecuteScalar() < 1)
|
|
{
|
|
throw new Exception("Supplied AccountJournal entry must debit an 'Asset' account type.");
|
|
}
|
|
}
|
|
|
|
// get statusCreditId for stock journal type
|
|
int statusCreditId;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblStockJournalType.StockStatusID_Credit
|
|
FROM
|
|
tblStockJournalType
|
|
WHERE
|
|
tblStockJournalType.StockJournalTypeID=@stockJournalTypeId
|
|
AND tblStockJournalType.StockStatusID_Credit Is Not Null;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockJournalTypeId", stockJournalTypeId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
|
|
if (obj == null)
|
|
{
|
|
throw new Exception("Default credit status not set for StockJournalTypeID=" + stockJournalTypeId);
|
|
}
|
|
else
|
|
{
|
|
statusCreditId = (int)obj;
|
|
}
|
|
}
|
|
|
|
// get/set an skuId
|
|
int skuId = new Logic.Inventory.SkuService().GetSkuId(productId, conditionId, accountTaxCodeId, true);
|
|
|
|
// add the entry to the stock table (minus stockJournalId)
|
|
int stockId = 0;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblStock
|
|
(SkuID, AccountJournalID)
|
|
OUTPUT INSERTED.StockID
|
|
VALUES
|
|
(@skuId, @accountJournalId);
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@skuId", skuId);
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
stockId = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
// insert stock journal entry
|
|
var journalPosts = new List<(int statusId, int quantity)>();
|
|
journalPosts.Add((statusDebitId, quantity));
|
|
journalPosts.Add((statusCreditId, (quantity * -1)));
|
|
int stockJournalId = Stock.StockJournal.StockJournalInsert(sqlConnectionString, stockJournalTypeId, stockId, journalPosts, stockJournalEntryDate, true);
|
|
|
|
// update the stock table
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
UPDATE tblStock
|
|
SET StockJournalID=@stockJournalId
|
|
WHERE StockID=@stockId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockJournalId", stockJournalId);
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
count = cmd.ExecuteNonQuery();
|
|
|
|
if (count < 1)
|
|
{
|
|
throw new Exception("New stock insert cancelled, failed to update StockJournalID");
|
|
}
|
|
}
|
|
|
|
scope.Complete();
|
|
return stockId;
|
|
}
|
|
|
|
private void WIP_StockDelete(int stockId)
|
|
{
|
|
int accountJournalType = 0;
|
|
int stockJournalType = 0;
|
|
|
|
// get stock and account types
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// ensure stockId is owner-introduced
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblStockJournal.StockJournalTypeID, tblAccountJournal.AccountJournalTypeID
|
|
FROM
|
|
(tblStock INNER JOIN tblAccountJournal
|
|
ON tblStock.AccountJournalID = tblAccountJournal.AccountJournalID)
|
|
INNER JOIN tblStockJournal
|
|
ON tblStock.StockJournalID = tblStockJournal.StockJournalID
|
|
WHERE
|
|
(((tblStock.StockID)=@stockId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
accountJournalType = reader.GetInt32(1);
|
|
stockJournalType = reader.GetInt32(0);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Integrity check failed, cancelling StockDeleteOwnerIntroduced");
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT Count(tblStockJournal.StockJournalID) AS CountOfStockJournalID
|
|
FROM tblStockJournal
|
|
WHERE (((tblStockJournal.StockID)=@stockId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
int count = (int)cmd.ExecuteScalar();
|
|
|
|
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
|
|
Core.Stock.StockJournal.StockJournalDelete(sqlConnectionString, 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;
|
|
int stockJournalTypeId = 1;
|
|
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// retrive info from purchase invoice line/transaction
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblAccountJournal.EntryDate
|
|
FROM tblAccountJournal
|
|
WHERE (((tblAccountJournal.AccountJournalID)=@accountJournalId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
stockJournalEntryDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc);
|
|
}
|
|
}
|
|
return WIP_StockInsertSub(productId, conditionId, accountTaxCodeId, accountJournalId, stockJournalTypeId, stockJournalEntryDate, quantity, statusDebitId);
|
|
}
|
|
|
|
public int WIP_StockInsertOwnerIntroduced(decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
|
|
{
|
|
int accountJournalType = 3;
|
|
int stockJournalType = 2;
|
|
string currencyCode = "GBP";
|
|
|
|
return WIP_StockInsert(accountJournalType, stockJournalType, currencyCode, amount, quantity, productId, conditionId, accountTaxCodeId, entryDate, debitStatusId);
|
|
}
|
|
|
|
public void WIP_StockDeletePurchase(int stockId)
|
|
{
|
|
WIP_StockDeleteSub(sqlConnectionString, stockId);
|
|
}
|
|
|
|
public void WIP_StockDeleteOwnerIntroduced(int stockId)
|
|
{
|
|
WIP_StockDelete(sqlConnectionString, stockId);
|
|
}
|
|
|
|
}
|
|
}
|