mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-05-18 19:48:23 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e6c784fccf | |||
| fccf2190cd |
@@ -35,13 +35,13 @@ namespace bnhtrade.ComTypeLib
|
|||||||
public int AccountJournalInsert(ConnectionCredential sqlConnCred, int journalTypeId, DateTime entryDate,
|
public int AccountJournalInsert(ConnectionCredential sqlConnCred, int journalTypeId, DateTime entryDate,
|
||||||
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false)
|
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false)
|
||||||
{
|
{
|
||||||
return new Core.Logic.Account.AccountJournalService().JournalInsert(journalTypeId, entryDate,
|
return new Core.Logic.Account.Journal().AccountJournalInsert(journalTypeId, entryDate,
|
||||||
currencyCode, amount, debitAccountId, creditAccountId, lockEntry);
|
currencyCode, amount, debitAccountId, creditAccountId, lockEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AccountJournalDelete(ConnectionCredential sqlConnCred, int accountJournalId)
|
public bool AccountJournalDelete(ConnectionCredential sqlConnCred, int accountJournalId)
|
||||||
{
|
{
|
||||||
return new Core.Logic.Account.AccountJournalService().DeleteJournal(accountJournalId);
|
return new Core.Logic.Account.Journal().AccountJournalDelete(accountJournalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[return: MarshalAs(UnmanagedType.Currency)]
|
[return: MarshalAs(UnmanagedType.Currency)]
|
||||||
|
|||||||
@@ -35,30 +35,32 @@ namespace bnhtrade.ComTypeLib.Purchase
|
|||||||
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet,
|
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet,
|
||||||
DateTime entryDate)
|
DateTime entryDate)
|
||||||
{
|
{
|
||||||
new Core.Logic.Purchase.PurchaseService().WIP_PurchaseLineTransactionNetInsert(purchaseLineId, currencyCode, amountNet, entryDate);
|
Core.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionNetInsert(sqlConnCred.ConnectionString,
|
||||||
|
purchaseLineId, currencyCode, amountNet, entryDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PurchaseLineTransactionNetUpdate(ConnectionCredential sqlConnCred, int accountJouranlId,
|
public void PurchaseLineTransactionNetUpdate(ConnectionCredential sqlConnCred, int accountJouranlId,
|
||||||
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet, int debitAccountId)
|
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet, int debitAccountId)
|
||||||
{
|
{
|
||||||
new Core.Logic.Purchase.PurchaseService().WIP_PurchaseLineTransactionNetUpdate(accountJouranlId, currencyCode, amountNet, debitAccountId);
|
Core.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionNetUpdate(sqlConnCred.ConnectionString,
|
||||||
|
accountJouranlId, currencyCode, amountNet, debitAccountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PurchaseLineTransactionDelete(ConnectionCredential sqlConnCred, int purchaseLineId, int accountJournalId)
|
public void PurchaseLineTransactionDelete(ConnectionCredential sqlConnCred, int purchaseLineId, int accountJournalId)
|
||||||
{
|
{
|
||||||
new Core.Logic.Purchase.PurchaseService().WIP_PurchaseLineTransactionDelete(purchaseLineId, accountJournalId);
|
Core.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionDelete(sqlConnCred.ConnectionString, purchaseLineId, accountJournalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int PurchaseLineTransactionStockInsert(ConnectionCredential sqlConnCred, int accountJournalId,
|
public int PurchaseLineTransactionStockInsert(ConnectionCredential sqlConnCred, int accountJournalId,
|
||||||
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId,
|
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId,
|
||||||
int accountTaxCodeId, int stockDebitStatusId)
|
int accountTaxCodeId, int stockDebitStatusId)
|
||||||
{
|
{
|
||||||
return new Core.Logic.Inventory.StockService().WIP_StockInsertPurchase(productId, conditionId, accountTaxCodeId, accountJournalId, quantity, stockDebitStatusId);
|
return Core.Stock.StockCreate.WIP_StockInsertPurchase(sqlConnCred.ConnectionString, productId, conditionId, accountTaxCodeId, accountJournalId, quantity, stockDebitStatusId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PurchaseLineTransactionStockDelete(ConnectionCredential sqlConnCred, int stockId)
|
public void PurchaseLineTransactionStockDelete(ConnectionCredential sqlConnCred, int stockId)
|
||||||
{
|
{
|
||||||
new Core.Logic.Inventory.StockService().WIP_StockDeletePurchase(stockId);
|
Core.Stock.StockCreate.WIP_StockDeletePurchase(sqlConnCred.ConnectionString, stockId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,22 +43,22 @@ namespace bnhtrade.ComTypeLib
|
|||||||
{
|
{
|
||||||
public int StockInsertPurchase(ConnectionCredential sqlConnCred, int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId)
|
public int StockInsertPurchase(ConnectionCredential sqlConnCred, int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId)
|
||||||
{
|
{
|
||||||
return new Core.Logic.Inventory.StockService().WIP_StockInsertPurchase(productId, conditionId, accountTaxCodeId, accountJournalId, quantity, statusDebitId);
|
return Core.Stock.StockCreate.WIP_StockInsertPurchase(sqlConnCred.ConnectionString, productId, conditionId, accountTaxCodeId, accountJournalId, quantity, statusDebitId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int StockInsertOwnerIntroduced(ConnectionCredential sqlConnCred, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
|
public int StockInsertOwnerIntroduced(ConnectionCredential sqlConnCred, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
|
||||||
{
|
{
|
||||||
return new Core.Logic.Inventory.StockService().WIP_StockInsertOwnerIntroduced(amount, quantity, productId, conditionId, accountTaxCodeId, entryDate, debitStatusId);
|
return Core.Stock.StockCreate.WIP_StockInsertOwnerIntroduced(sqlConnCred.ConnectionString, amount, quantity, productId, conditionId, accountTaxCodeId, entryDate, debitStatusId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StockDeletePurchase(ConnectionCredential sqlConnCred, int stockId)
|
public void StockDeletePurchase(ConnectionCredential sqlConnCred, int stockId)
|
||||||
{
|
{
|
||||||
new Core.Logic.Inventory.StockService().WIP_StockDeletePurchase(stockId);
|
Core.Stock.StockCreate.WIP_StockDeletePurchase(sqlConnCred.ConnectionString, stockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StockDeleteOwnerIntroduced(ConnectionCredential sqlConnCred, int stockId)
|
public void StockDeleteOwnerIntroduced(ConnectionCredential sqlConnCred, int stockId)
|
||||||
{
|
{
|
||||||
new Core.Logic.Inventory.StockService().WIP_StockDeleteOwnerIntroduced(stockId);
|
Core.Stock.StockCreate.WIP_StockDeleteOwnerIntroduced(sqlConnCred.ConnectionString, stockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int StockReallocate(ConnectionCredential sqlConnCred, int stockId, int quantity, int debitStatusId, int creditStatusId, DateTime entryDate)
|
public int StockReallocate(ConnectionCredential sqlConnCred, int stockId, int quantity, int debitStatusId, int creditStatusId, DateTime entryDate)
|
||||||
@@ -70,7 +70,7 @@ namespace bnhtrade.ComTypeLib
|
|||||||
|
|
||||||
public void StockJournalDelete(ConnectionCredential sqlConnCred, int stockJournalId)
|
public void StockJournalDelete(ConnectionCredential sqlConnCred, int stockJournalId)
|
||||||
{
|
{
|
||||||
new Core.Logic.Inventory.StockJournalService().StockJournalDelete(stockJournalId);
|
Core.Stock.StockJournal.StockJournalDelete(sqlConnCred.ConnectionString, stockJournalId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object ReconcileStockTransactions(ConnectionCredential sqlConnCred)
|
public object ReconcileStockTransactions(ConnectionCredential sqlConnCred)
|
||||||
@@ -128,7 +128,7 @@ namespace bnhtrade.ComTypeLib
|
|||||||
|
|
||||||
public bool StockJournalConsistencyCheck(ConnectionCredential sqlConnCred, int stockId)
|
public bool StockJournalConsistencyCheck(ConnectionCredential sqlConnCred, int stockId)
|
||||||
{
|
{
|
||||||
return new Core.Logic.Inventory.StockJournalService().WIP_StockJournalConsistencyCheck(stockId, null);
|
return Core.Stock.StockJournal.WIP_StockJournalConsistencyCheck(sqlConnCred.ConnectionString, stockId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SkuTransactionAdd(ConnectionCredential sqlConnCred, int quantity, string skuNumber, string transactionTypeCode, DateTime transactionDate)
|
public void SkuTransactionAdd(ConnectionCredential sqlConnCred, int quantity, string skuNumber, string transactionTypeCode, DateTime transactionDate)
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Data.SqlClient;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Transactions;
|
||||||
|
|
||||||
|
namespace bnhtrade.Core.Data.Database.Account
|
||||||
|
{
|
||||||
|
internal class CreateJournal : Connection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Old code needs sorting
|
||||||
|
/// </summary>
|
||||||
|
public int AccountJournalInsert(int journalTypeId, DateTime entryDate, string currencyCode,
|
||||||
|
decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false)
|
||||||
|
{
|
||||||
|
int defaultDebit = 0;
|
||||||
|
int defaultCredit = 0;
|
||||||
|
|
||||||
|
// ensure date is UTC
|
||||||
|
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
// debit and credit locks are checked in journal post method
|
||||||
|
using (TransactionScope scope = new TransactionScope())
|
||||||
|
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
|
||||||
|
// insert the journal entry
|
||||||
|
int journalId;
|
||||||
|
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
INSERT INTO tblAccountJournal
|
||||||
|
(AccountJournalTypeID, EntryDate, IsLocked)
|
||||||
|
OUTPUT INSERTED.AccountJournalID
|
||||||
|
VALUES
|
||||||
|
(@journalTypeId, @entryDate, @lockEntry)
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
// add parameters
|
||||||
|
cmd.Parameters.AddWithValue("@journalTypeId", journalTypeId);
|
||||||
|
cmd.Parameters.AddWithValue("@entryDate", entryDate.ToUniversalTime());
|
||||||
|
cmd.Parameters.AddWithValue("@lockEntry", lockEntry);
|
||||||
|
|
||||||
|
//execute
|
||||||
|
journalId = (int)cmd.ExecuteScalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert journal entries
|
||||||
|
//bool postResult = AccountJournalPostInsert(sqlConnectionString, journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
|
||||||
|
bool postResult = AccountJournalPostInsert(journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
|
||||||
|
|
||||||
|
scope.Complete();
|
||||||
|
return journalId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Old code needs sorting
|
||||||
|
/// </summary>
|
||||||
|
internal bool AccountJournalPostInsert(int journalId, DateTime entryDate,
|
||||||
|
string currencyCode, decimal amount, int debitAccountId = 0, int creditAccountId = 0)
|
||||||
|
{
|
||||||
|
int defaultDebit;
|
||||||
|
int defaultCredit;
|
||||||
|
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
using (TransactionScope scope = new TransactionScope())
|
||||||
|
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
|
||||||
|
// ensure their are no other entries
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
SELECT
|
||||||
|
Count(tblAccountJournalPost.AccountJournalPostID) AS CountOfAccountJournalPostID
|
||||||
|
FROM
|
||||||
|
tblAccountJournalPost
|
||||||
|
WHERE
|
||||||
|
(((tblAccountJournalPost.AccountJournalID)=@AccountJournalID));
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
cmd.Parameters.AddWithValue("@AccountJournalID", journalId);
|
||||||
|
|
||||||
|
int count = (int)cmd.ExecuteScalar();
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Unable the insert journal posts, post already present AccountJournalID=" + journalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//checks
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
SELECT
|
||||||
|
tblAccountJournalType.ChartOfAccountID_Debit, tblAccountJournalType.ChartOfAccountID_Credit
|
||||||
|
FROM
|
||||||
|
tblAccountJournal
|
||||||
|
INNER JOIN tblAccountJournalType
|
||||||
|
ON tblAccountJournal.AccountJournalTypeID = tblAccountJournalType.AccountJournalTypeID
|
||||||
|
WHERE
|
||||||
|
(((tblAccountJournal.AccountJournalID)=@journalId));
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
cmd.Parameters.AddWithValue("@journalId", journalId);
|
||||||
|
|
||||||
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
// debit check
|
||||||
|
if (reader.IsDBNull(0))
|
||||||
|
{
|
||||||
|
if (debitAccountId == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Debit Account ID required, default not set for journal type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
defaultDebit = reader.GetInt32(0);
|
||||||
|
if (debitAccountId == 0)
|
||||||
|
{
|
||||||
|
debitAccountId = defaultDebit;
|
||||||
|
}
|
||||||
|
else if (debitAccountId != defaultDebit)
|
||||||
|
{
|
||||||
|
throw new Exception("Debit Account ID supplied does not match default set for journal type");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// credit check
|
||||||
|
if (reader.IsDBNull(1))
|
||||||
|
{
|
||||||
|
if (creditAccountId == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Credit Account ID required, default not set for journal type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
defaultCredit = reader.GetInt32(1);
|
||||||
|
if (creditAccountId == 0)
|
||||||
|
{
|
||||||
|
creditAccountId = defaultCredit;
|
||||||
|
}
|
||||||
|
else if (creditAccountId != defaultCredit)
|
||||||
|
{
|
||||||
|
throw new Exception("Credit Account ID supplied does not match default set for journal type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("AccountJournalID '" + journalId + "' does not exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// currency conversion
|
||||||
|
if (currencyCode != "GBP")
|
||||||
|
{
|
||||||
|
amount = new Logic.Account.CurrencyService().CurrencyConvertToGbp(currencyCode, amount, entryDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure decimal is rounded
|
||||||
|
amount = Math.Round(amount, 2);
|
||||||
|
|
||||||
|
// insert debit post
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
INSERT INTO tblAccountJournalPost
|
||||||
|
(AccountJournalID, AccountChartOfID, AmountGbp)
|
||||||
|
VALUES
|
||||||
|
(@AccountJournalId, @AccountChartOfId, @AmountGbp)
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
// add parameters
|
||||||
|
cmd.Parameters.AddWithValue("@AccountJournalId", journalId);
|
||||||
|
cmd.Parameters.AddWithValue("@AccountChartOfId", debitAccountId);
|
||||||
|
cmd.Parameters.AddWithValue("@AmountGbp", amount);
|
||||||
|
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert credit post
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
INSERT INTO tblAccountJournalPost
|
||||||
|
(AccountJournalID, AccountChartOfID, AmountGbp)
|
||||||
|
VALUES
|
||||||
|
(@AccountJournalId, @AccountChartOfId, @AmountGbp)
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
// add parameters
|
||||||
|
cmd.Parameters.AddWithValue("@AccountJournalId", journalId);
|
||||||
|
cmd.Parameters.AddWithValue("@AccountChartOfId", creditAccountId);
|
||||||
|
cmd.Parameters.AddWithValue("@AmountGbp", (amount * -1));
|
||||||
|
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.Complete();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Data.SqlClient;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Transactions;
|
||||||
|
|
||||||
|
namespace bnhtrade.Core.Data.Database.Account
|
||||||
|
{
|
||||||
|
internal class UpdateJournal : Connection
|
||||||
|
{
|
||||||
|
public bool AccountJournalPostUpdate(int journalId, string currencyCode, decimal amount, int debitAccountId = 0, int creditAccountId = 0)
|
||||||
|
{
|
||||||
|
using (TransactionScope scope = new TransactionScope())
|
||||||
|
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
|
||||||
|
// retrive journal entry date
|
||||||
|
DateTime entryDate;
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
SELECT
|
||||||
|
tblAccountJournal.EntryDate
|
||||||
|
FROM
|
||||||
|
tblAccountJournal
|
||||||
|
WHERE
|
||||||
|
(((tblAccountJournal.AccountJournalID)=@accountJournalId));
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
|
||||||
|
|
||||||
|
entryDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the original posts
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
DELETE FROM
|
||||||
|
tblAccountJournalPost
|
||||||
|
WHERE
|
||||||
|
(((tblAccountJournalPost.AccountJournalID)=@accountJournalId));
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
|
||||||
|
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
//insert new posts
|
||||||
|
//bool postResult = AccountJournalPostInsert(sqlConnectionString, journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
|
||||||
|
bool postResult = new Data.Database.Account.CreateJournal().AccountJournalPostInsert(journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
|
||||||
|
|
||||||
|
// update modified date on journal
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
UPDATE
|
||||||
|
tblAccountJournal
|
||||||
|
SET
|
||||||
|
tblAccountJournal.LastModified=@utcNow
|
||||||
|
WHERE
|
||||||
|
(((tblAccountJournal.AccountJournalID)=@accountJournalId));
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
|
||||||
|
cmd.Parameters.AddWithValue("@utcNow", DateTime.UtcNow);
|
||||||
|
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.Complete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
-488
@@ -1,488 +0,0 @@
|
|||||||
using bnhtrade.Core.Data.Database._BoilerPlate;
|
|
||||||
using bnhtrade.Core.Data.Database.Repository.Interface;
|
|
||||||
using bnhtrade.Core.Model.Account;
|
|
||||||
using Microsoft.Data.SqlClient;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Transactions;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
|
||||||
{
|
|
||||||
internal class AccountJournalRepository : _Base, IAccountJournalRepository
|
|
||||||
{
|
|
||||||
public AccountJournalRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// create
|
|
||||||
//
|
|
||||||
|
|
||||||
public int InsertJournalHeader(int accountJournalTypeId, DateTime entryDate, bool lockEntry = false)
|
|
||||||
{
|
|
||||||
// ensure date is UTC
|
|
||||||
if (entryDate.Kind != DateTimeKind.Utc)
|
|
||||||
{
|
|
||||||
throw new Exception("DateTime kind must be utc");
|
|
||||||
}
|
|
||||||
|
|
||||||
// debit and credit locks are checked in journal post method
|
|
||||||
// insert the journal entry
|
|
||||||
int journalId;
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
INSERT INTO tblAccountJournal
|
|
||||||
(AccountJournalTypeID, EntryDate, IsLocked)
|
|
||||||
OUTPUT INSERTED.AccountJournalID
|
|
||||||
VALUES
|
|
||||||
(@journalTypeId, @entryDate, @lockEntry);";
|
|
||||||
|
|
||||||
// add parameters
|
|
||||||
cmd.Parameters.AddWithValue("@journalTypeId", accountJournalTypeId);
|
|
||||||
cmd.Parameters.AddWithValue("@entryDate", entryDate.ToUniversalTime());
|
|
||||||
cmd.Parameters.AddWithValue("@lockEntry", lockEntry);
|
|
||||||
|
|
||||||
//execute
|
|
||||||
journalId = (int)cmd.ExecuteScalar();
|
|
||||||
}
|
|
||||||
|
|
||||||
return journalId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int InsertJournalPost(int accountJournalId, int accountChartOfId, decimal amountGbp)
|
|
||||||
{
|
|
||||||
if (accountJournalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid journal ID provided.", nameof(accountJournalId));
|
|
||||||
}
|
|
||||||
if (accountChartOfId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid account chart of ID provided.", nameof(accountChartOfId));
|
|
||||||
}
|
|
||||||
if (amountGbp == 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Amount cannot be zero.", nameof(amountGbp));
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
INSERT INTO tblAccountJournalPost
|
|
||||||
(AccountJournalID, AccountChartOfID, AmountGbp)
|
|
||||||
OUTPUT INSERTED.AccountJournalPostID
|
|
||||||
VALUES
|
|
||||||
(@accountJournalId, @accountChartOfId, @amountGbp);";
|
|
||||||
|
|
||||||
// add parameters
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
cmd.Parameters.AddWithValue("@accountChartOfId", accountChartOfId);
|
|
||||||
cmd.Parameters.AddWithValue("@amountGbp", amountGbp);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
return (int)cmd.ExecuteScalar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// read
|
|
||||||
//
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Account.JournalBuilder> ReadJournalBuilder(List<int> journalIdList)
|
|
||||||
{
|
|
||||||
var sqlBuilder = new SqlWhereBuilder();
|
|
||||||
var returnDict = new Dictionary<int, Model.Account.JournalBuilder>();
|
|
||||||
|
|
||||||
//build sql query
|
|
||||||
string sql = @"
|
|
||||||
SELECT tblAccountJournal.AccountJournalID
|
|
||||||
,tblAccountJournal.AccountJournalTypeID
|
|
||||||
,tblAccountJournal.EntryDate
|
|
||||||
,tblAccountJournal.PostDate
|
|
||||||
,tblAccountJournal.LastModified
|
|
||||||
,tblAccountJournal.IsLocked
|
|
||||||
,tblAccountJournalPost.AccountJournalPostID
|
|
||||||
,tblAccountJournalPost.AccountChartOfID
|
|
||||||
,tblAccountJournalPost.AmountGbp
|
|
||||||
FROM tblAccountJournal
|
|
||||||
INNER JOIN tblAccountJournalPost ON tblAccountJournal.AccountJournalID = tblAccountJournalPost.AccountJournalID
|
|
||||||
WHERE 1 = 1 ";
|
|
||||||
|
|
||||||
// build the where statments
|
|
||||||
if (journalIdList.Any())
|
|
||||||
{
|
|
||||||
sqlBuilder.In("tblAccountJournal.AccountJournalID", journalIdList, "AND");
|
|
||||||
}
|
|
||||||
|
|
||||||
// append where string to the sql
|
|
||||||
if (sqlBuilder.IsSetSqlWhereString)
|
|
||||||
{
|
|
||||||
sql = sql + sqlBuilder.SqlWhereString;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
|
|
||||||
if (sqlBuilder.ParameterListIsSet)
|
|
||||||
{
|
|
||||||
sqlBuilder.AddParametersToSqlCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
int journalId = reader.GetInt32(0);
|
|
||||||
if (returnDict.ContainsKey(journalId) == false)
|
|
||||||
{
|
|
||||||
var journalBuilder = new Model.Account.JournalBuilder();
|
|
||||||
journalBuilder.JournalId = journalId;
|
|
||||||
journalBuilder.JournalTypeId = reader.GetInt32(1);
|
|
||||||
journalBuilder.EntryDate = DateTime.SpecifyKind(reader.GetDateTime(2), DateTimeKind.Utc);
|
|
||||||
journalBuilder.PostDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc);
|
|
||||||
journalBuilder.LastModified = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc);
|
|
||||||
journalBuilder.IsLocked = reader.GetBoolean(5);
|
|
||||||
journalBuilder.JournalBuilderPosts = new List<Model.Account.JournalBuilder.JournalPostBuilder>();
|
|
||||||
|
|
||||||
returnDict.Add(journalId, journalBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
var journalBuilderLine = new Model.Account.JournalBuilder.JournalPostBuilder();
|
|
||||||
journalBuilderLine.PostId = reader.GetInt32(6);
|
|
||||||
journalBuilderLine.AccountId = reader.GetInt32(7);
|
|
||||||
journalBuilderLine.AmountGbp = reader.GetDecimal(8);
|
|
||||||
|
|
||||||
returnDict[journalId].JournalBuilderPosts.Add(journalBuilderLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DateTime ReadJournalEntryDate(int journalId)
|
|
||||||
{
|
|
||||||
if (journalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid journal ID provided.", nameof(journalId));
|
|
||||||
}
|
|
||||||
|
|
||||||
string sql = @"
|
|
||||||
SELECT tblAccountJournal.EntryDate
|
|
||||||
FROM tblAccountJournal
|
|
||||||
WHERE (((tblAccountJournal.AccountJournalID)=@accountJournalId));";
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
|
|
||||||
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Journal entry not found for AccountJournalID=" + journalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DateTime.SpecifyKind((DateTime)obj, DateTimeKind.Utc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CountJournalPosts(int accountJournalId)
|
|
||||||
{
|
|
||||||
if (accountJournalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid journal ID provided.", nameof(accountJournalId));
|
|
||||||
}
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT
|
|
||||||
Count(tblAccountJournalPost.AccountJournalPostID) AS CountOfAccountJournalPostID
|
|
||||||
FROM
|
|
||||||
tblAccountJournalPost
|
|
||||||
WHERE
|
|
||||||
(((tblAccountJournalPost.AccountJournalID)=@AccountJournalID));";
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
return (int)cmd.ExecuteScalar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsJournalDebitAssetType(int accountJournalId)
|
|
||||||
{
|
|
||||||
if (accountJournalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid journal ID provided.", nameof(accountJournalId));
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
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;";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
|
|
||||||
if ((int)cmd.ExecuteScalar() < 1)
|
|
||||||
{
|
|
||||||
return false; // no debit posts of type Asset found
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Test for locked journal entry
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True/False or null on no records found</returns>
|
|
||||||
public bool? IsJournalLocked(int accountJournalId)
|
|
||||||
{
|
|
||||||
if (accountJournalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid journal ID provided.", nameof(accountJournalId));
|
|
||||||
}
|
|
||||||
|
|
||||||
string sql = @"
|
|
||||||
SELECT
|
|
||||||
tblAccountJournal.IsLocked
|
|
||||||
FROM
|
|
||||||
tblAccountJournal
|
|
||||||
WHERE
|
|
||||||
tblAccountJournal.AccountJournalID=@accountJournalId;";
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
if (obj == null || obj == DBNull.Value)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (bool)obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<(int, string, int?, int?)> ReadJournalType(List<int> accountJournalTypeIds = null, List<string> typeTitles = null)
|
|
||||||
{
|
|
||||||
var returnList = new List<(int, string, int?, int?)>();
|
|
||||||
var sqlBuilder = new SqlWhereBuilder();
|
|
||||||
|
|
||||||
//build sql query
|
|
||||||
string sql = @"
|
|
||||||
SELECT [AccountJournalTypeID]
|
|
||||||
,[TypeTitle]
|
|
||||||
,[ChartOfAccountID_Debit]
|
|
||||||
,[ChartOfAccountID_Credit]
|
|
||||||
FROM [e2A].[dbo].[tblAccountJournalType]
|
|
||||||
WHERE 1 = 1 ";
|
|
||||||
|
|
||||||
// build the where statments
|
|
||||||
if (accountJournalTypeIds.Any())
|
|
||||||
{
|
|
||||||
sqlBuilder.In("AccountJournalTypeID", accountJournalTypeIds, "AND");
|
|
||||||
}
|
|
||||||
if (typeTitles.Any())
|
|
||||||
{
|
|
||||||
sqlBuilder.In("TypeTitle", typeTitles, "AND");
|
|
||||||
}
|
|
||||||
|
|
||||||
// append where string to the sql
|
|
||||||
if (sqlBuilder.IsSetSqlWhereString)
|
|
||||||
{
|
|
||||||
sql = sql + sqlBuilder.SqlWhereString;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
|
|
||||||
if (sqlBuilder.ParameterListIsSet)
|
|
||||||
{
|
|
||||||
sqlBuilder.AddParametersToSqlCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
// read from db and create object
|
|
||||||
int journalTypeId = reader.GetInt32(0);
|
|
||||||
string title = reader.GetString(1);
|
|
||||||
int? debitAccountId = null;
|
|
||||||
if (!reader.IsDBNull(2))
|
|
||||||
debitAccountId = reader.GetInt32(2);
|
|
||||||
int? creditAccountId = null;
|
|
||||||
if (!reader.IsDBNull(3))
|
|
||||||
creditAccountId = reader.GetInt32(3);
|
|
||||||
|
|
||||||
returnList.Add((journalTypeId, title, debitAccountId, creditAccountId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieves the default debit and credit account IDs associated with a specific account journal.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>This method queries the database to retrieve the default debit and credit account IDs
|
|
||||||
/// for the specified account journal. If the account journal does not exist, an exception is thrown. Ensure
|
|
||||||
/// that the provided <paramref name="accountJournalId"/> is valid.</remarks>
|
|
||||||
/// <param name="accountJournalId">The unique identifier of the account journal for which to retrieve the default debit and credit account IDs.</param>
|
|
||||||
/// <returns>A tuple containing two nullable integers: <list type="bullet"> <item><description>The first value represents
|
|
||||||
/// the default debit account ID, or <see langword="null"/> if no debit account is set.</description></item>
|
|
||||||
/// <item><description>The second value represents the default credit account ID, or <see langword="null"/> if
|
|
||||||
/// no credit account is set.</description></item> </list></returns>
|
|
||||||
/// <exception cref="Exception">Thrown if the specified <paramref name="accountJournalId"/> does not exist in the database.</exception>
|
|
||||||
public (int?, int?) ReadJournalTypeDefaultDebitCredit(int accountJournalId)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT
|
|
||||||
tblAccountJournalType.ChartOfAccountID_Debit, tblAccountJournalType.ChartOfAccountID_Credit
|
|
||||||
FROM
|
|
||||||
tblAccountJournal
|
|
||||||
INNER JOIN tblAccountJournalType
|
|
||||||
ON tblAccountJournal.AccountJournalTypeID = tblAccountJournalType.AccountJournalTypeID
|
|
||||||
WHERE
|
|
||||||
(((tblAccountJournal.AccountJournalID)=@journalId));";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@journalId", accountJournalId);
|
|
||||||
|
|
||||||
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
if (reader.Read())
|
|
||||||
{
|
|
||||||
int? defaultDebit = null;
|
|
||||||
int? defaultCredit = null;
|
|
||||||
|
|
||||||
// debit check
|
|
||||||
if (reader.IsDBNull(0) == false)
|
|
||||||
{
|
|
||||||
defaultDebit = reader.GetInt32(0);
|
|
||||||
}
|
|
||||||
// credit check
|
|
||||||
if (reader.IsDBNull(1) == false)
|
|
||||||
{
|
|
||||||
defaultCredit = reader.GetInt32(1);
|
|
||||||
}
|
|
||||||
return (defaultDebit, defaultCredit);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("AccountJournalID '" + accountJournalId + "' does not exist.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// update
|
|
||||||
//
|
|
||||||
|
|
||||||
public bool UpdateJournalEntryModifiedDate(int accountJournalId)
|
|
||||||
{
|
|
||||||
if (accountJournalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid journal ID provided.", nameof(accountJournalId));
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
UPDATE
|
|
||||||
tblAccountJournal
|
|
||||||
SET
|
|
||||||
tblAccountJournal.LastModified=@utcNow
|
|
||||||
WHERE
|
|
||||||
(((tblAccountJournal.AccountJournalID)=@accountJournalId));";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
cmd.Parameters.AddWithValue("@utcNow", DateTime.UtcNow);
|
|
||||||
|
|
||||||
if (cmd.ExecuteNonQuery() == 1)
|
|
||||||
{
|
|
||||||
return true; // update successful
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false; // update failed, journal ID may not exist
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// delete
|
|
||||||
//
|
|
||||||
|
|
||||||
public int DeleteJournalHeader(int accountJournalId)
|
|
||||||
{
|
|
||||||
if (accountJournalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid journal ID provided.", nameof(accountJournalId));
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
DELETE FROM
|
|
||||||
tblAccountJournal
|
|
||||||
WHERE
|
|
||||||
AccountJournalID=@accountJournalId;";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
return cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int DeleteJournalPostAll(int accountJournalId)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
DELETE FROM
|
|
||||||
tblAccountJournalPost
|
|
||||||
WHERE
|
|
||||||
tblAccountJournalPost.AccountJournalID = @accountJournalId;";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
return cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,372 @@
|
|||||||
|
using bnhtrade.Core.Data.Database._BoilerPlate;
|
||||||
|
using bnhtrade.Core.Data.Database.Repository.Interface;
|
||||||
|
using Microsoft.Data.SqlClient;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Transactions;
|
||||||
|
|
||||||
|
namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
||||||
|
{
|
||||||
|
internal class JournalRepository : _Base, IJournalRepository
|
||||||
|
{
|
||||||
|
public JournalRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<int, Core.Model.Account.Journal> ReadJournal(List<int> journalIdList)
|
||||||
|
{
|
||||||
|
var sqlBuilder = new SqlWhereBuilder();
|
||||||
|
|
||||||
|
//build sql query
|
||||||
|
string sql = @"
|
||||||
|
SELECT tblAccountJournal.AccountJournalID
|
||||||
|
,tblAccountJournal.AccountJournalTypeID
|
||||||
|
,tblAccountJournal.EntryDate
|
||||||
|
,tblAccountJournal.PostDate
|
||||||
|
,tblAccountJournal.LastModified
|
||||||
|
,tblAccountJournal.IsLocked
|
||||||
|
,tblAccountJournalPost.AccountJournalPostID
|
||||||
|
,tblAccountJournalPost.AccountChartOfID
|
||||||
|
,tblAccountJournalPost.AmountGbp
|
||||||
|
FROM tblAccountJournal
|
||||||
|
INNER JOIN tblAccountJournalPost ON tblAccountJournal.AccountJournalID = tblAccountJournalPost.AccountJournalID
|
||||||
|
WHERE 1 = 1 ";
|
||||||
|
|
||||||
|
// build the where statments
|
||||||
|
if (journalIdList.Any())
|
||||||
|
{
|
||||||
|
sqlBuilder.In("tblAccountJournal.AccountJournalID", journalIdList, "AND");
|
||||||
|
}
|
||||||
|
|
||||||
|
// append where string to the sql
|
||||||
|
if (sqlBuilder.IsSetSqlWhereString)
|
||||||
|
{
|
||||||
|
sql = sql + sqlBuilder.SqlWhereString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build tuple list
|
||||||
|
var dbJournalList = new List<(
|
||||||
|
int AccountJournalId
|
||||||
|
, int AccountJournalTypeId
|
||||||
|
, DateTime EntryDate
|
||||||
|
, DateTime PostDate
|
||||||
|
, DateTime LastModified
|
||||||
|
, bool IsLocked
|
||||||
|
)>();
|
||||||
|
|
||||||
|
var dbJournalPostList = new List<(
|
||||||
|
int AccountJournalId
|
||||||
|
, int AccountJournalPostId
|
||||||
|
, int AccountChartOfId
|
||||||
|
, decimal AmountGbp
|
||||||
|
)>();
|
||||||
|
|
||||||
|
|
||||||
|
bool hasRows = false;
|
||||||
|
|
||||||
|
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
||||||
|
{
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
cmd.Transaction = _transaction as SqlTransaction;
|
||||||
|
|
||||||
|
if (sqlBuilder.ParameterListIsSet)
|
||||||
|
{
|
||||||
|
sqlBuilder.AddParametersToSqlCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
if (reader.HasRows)
|
||||||
|
{
|
||||||
|
hasRows = true;
|
||||||
|
int lastJournalId = 0;
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
// read journal header
|
||||||
|
int journalId = reader.GetInt32(0);
|
||||||
|
if (journalId != lastJournalId)
|
||||||
|
{
|
||||||
|
lastJournalId = journalId;
|
||||||
|
|
||||||
|
(int AccountJournalId
|
||||||
|
, int AccountJournalTypeId
|
||||||
|
, DateTime EntryDate
|
||||||
|
, DateTime PostDate
|
||||||
|
, DateTime LastModified
|
||||||
|
, bool IsLocked
|
||||||
|
)
|
||||||
|
journal =
|
||||||
|
(journalId
|
||||||
|
, reader.GetInt32(1)
|
||||||
|
, DateTime.SpecifyKind(reader.GetDateTime(2), DateTimeKind.Utc)
|
||||||
|
, DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc)
|
||||||
|
, DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc)
|
||||||
|
, reader.GetBoolean(5)
|
||||||
|
);
|
||||||
|
|
||||||
|
dbJournalList.Add(journal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read journal posts
|
||||||
|
(int AccountJournalId
|
||||||
|
, int AccountJournalPostId
|
||||||
|
, int AccountChartOfId
|
||||||
|
, decimal AmountGbp
|
||||||
|
)
|
||||||
|
journalPost =
|
||||||
|
(journalId
|
||||||
|
, reader.GetInt32(6)
|
||||||
|
, reader.GetInt32(7)
|
||||||
|
, reader.GetDecimal(8)
|
||||||
|
);
|
||||||
|
|
||||||
|
dbJournalPostList.Add(journalPost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var returnList = new Dictionary<int, Core.Model.Account.Journal>();
|
||||||
|
if (hasRows)
|
||||||
|
{
|
||||||
|
// build lists to filter db results by
|
||||||
|
var journalTypeIdList = new List<int>();
|
||||||
|
var accountIdList = new List<int>();
|
||||||
|
foreach (var item in dbJournalList)
|
||||||
|
{
|
||||||
|
journalTypeIdList.Add(item.AccountJournalTypeId);
|
||||||
|
}
|
||||||
|
foreach (var item in dbJournalPostList)
|
||||||
|
{
|
||||||
|
accountIdList.Add(item.AccountChartOfId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get journalTypes from db
|
||||||
|
var journalTypeDict = new JournalRepository(_connection, _transaction).ReadJournalType(journalTypeIdList);
|
||||||
|
|
||||||
|
// get accounts from db
|
||||||
|
var accountDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIdList);
|
||||||
|
|
||||||
|
// build final return dictionary
|
||||||
|
foreach (var dbJournal in dbJournalList)
|
||||||
|
{
|
||||||
|
// build posts
|
||||||
|
var newPosts = new List<Core.Model.Account.Journal.Post>();
|
||||||
|
foreach (var dbJournalPost in dbJournalPostList)
|
||||||
|
{
|
||||||
|
if (dbJournalPost.AccountJournalId == dbJournal.AccountJournalId)
|
||||||
|
{
|
||||||
|
var newPost = new Core.Model.Account.Journal.Post(
|
||||||
|
dbJournalPost.AccountJournalPostId
|
||||||
|
, accountDict[dbJournalPost.AccountChartOfId]
|
||||||
|
, dbJournalPost.AmountGbp);
|
||||||
|
|
||||||
|
newPosts.Add(newPost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the journal
|
||||||
|
var newJournal = new Core.Model.Account.Journal(
|
||||||
|
dbJournal.AccountJournalId
|
||||||
|
, journalTypeDict[dbJournal.AccountJournalTypeId]
|
||||||
|
, newPosts
|
||||||
|
, dbJournal.EntryDate
|
||||||
|
, dbJournal.PostDate
|
||||||
|
, dbJournal.LastModified
|
||||||
|
, dbJournal.IsLocked);
|
||||||
|
|
||||||
|
returnList.Add(dbJournal.AccountJournalId, newJournal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// all done, return the list herevar
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test for locked journal entry
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>False on locked journal entry</returns>
|
||||||
|
public bool ReadJournalIsLocked(int journalId)
|
||||||
|
{
|
||||||
|
string sql = @"
|
||||||
|
SELECT
|
||||||
|
tblAccountJournal.IsLocked
|
||||||
|
FROM
|
||||||
|
tblAccountJournal
|
||||||
|
WHERE
|
||||||
|
tblAccountJournal.AccountJournalID=@accountJournalId;";
|
||||||
|
|
||||||
|
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
||||||
|
{
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
cmd.Transaction = _transaction as SqlTransaction;
|
||||||
|
|
||||||
|
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
|
||||||
|
|
||||||
|
object obj = cmd.ExecuteScalar();
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Journal entry not found for AccountJournalID=" + journalId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (bool)obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Dictionary<int, Model.Account.JournalType> ReadJournalType(List<int> journalTypeIds = null, List<string> typeTitles = null)
|
||||||
|
{
|
||||||
|
var sqlBuilder = new SqlWhereBuilder();
|
||||||
|
|
||||||
|
// create the return (emptyP list) here
|
||||||
|
var returnList = new Dictionary<int, Model.Account.JournalType>();
|
||||||
|
sqlBuilder.Init();
|
||||||
|
|
||||||
|
//build sql query
|
||||||
|
string sql = @"
|
||||||
|
SELECT [AccountJournalTypeID]
|
||||||
|
,[TypeTitle]
|
||||||
|
,[ChartOfAccountID_Debit]
|
||||||
|
,[ChartOfAccountID_Credit]
|
||||||
|
FROM [e2A].[dbo].[tblAccountJournalType]
|
||||||
|
WHERE 1 = 1 ";
|
||||||
|
|
||||||
|
// build the where statments
|
||||||
|
if (journalTypeIds.Any())
|
||||||
|
{
|
||||||
|
sqlBuilder.In("AccountJournalTypeID", journalTypeIds, "AND");
|
||||||
|
}
|
||||||
|
if (typeTitles.Any())
|
||||||
|
{
|
||||||
|
sqlBuilder.In("TypeTitle", typeTitles, "AND");
|
||||||
|
}
|
||||||
|
|
||||||
|
// append where string to the sql
|
||||||
|
if (sqlBuilder.IsSetSqlWhereString)
|
||||||
|
{
|
||||||
|
sql = sql + sqlBuilder.SqlWhereString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create dictionary to add credit/debit accounts on after db read
|
||||||
|
var creditDict = new Dictionary<int, int>();
|
||||||
|
var debitDict = new Dictionary<int, int>();
|
||||||
|
|
||||||
|
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
||||||
|
{
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
cmd.Transaction = _transaction as SqlTransaction;
|
||||||
|
|
||||||
|
if (sqlBuilder.ParameterListIsSet)
|
||||||
|
{
|
||||||
|
sqlBuilder.AddParametersToSqlCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
if (reader.HasRows)
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
// read from db and create object
|
||||||
|
int journalTypeId = reader.GetInt32(0);
|
||||||
|
string title = reader.GetString(1);
|
||||||
|
int? debitAccountId = null;
|
||||||
|
if (!reader.IsDBNull(2)) { debitAccountId = reader.GetInt32(2); }
|
||||||
|
int? creditAccountId = null;
|
||||||
|
if (!reader.IsDBNull(3)) { creditAccountId = reader.GetInt32(3); }
|
||||||
|
|
||||||
|
// build return list
|
||||||
|
var item = new Model.Account.JournalType(journalTypeId, title);
|
||||||
|
returnList.Add(journalTypeId, item);
|
||||||
|
|
||||||
|
// build dictionaries
|
||||||
|
if (debitAccountId != null)
|
||||||
|
{
|
||||||
|
debitDict.Add(journalTypeId, debitAccountId.Value);
|
||||||
|
}
|
||||||
|
if (creditAccountId != null)
|
||||||
|
{
|
||||||
|
creditDict.Add(journalTypeId, creditAccountId.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// get account objects from db
|
||||||
|
var accountIdList = debitDict.Values.ToList();
|
||||||
|
accountIdList.AddRange(creditDict.Values.ToList());
|
||||||
|
var dbDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIdList);
|
||||||
|
|
||||||
|
// add to the returnlist
|
||||||
|
foreach (var account in returnList.Values)
|
||||||
|
{
|
||||||
|
Model.Account.Account debitAccount = null;
|
||||||
|
if (debitDict.ContainsKey(account.JournalTypeId))
|
||||||
|
{
|
||||||
|
debitAccount = dbDict[debitDict[account.JournalTypeId]];
|
||||||
|
}
|
||||||
|
|
||||||
|
Model.Account.Account creditAccount = null;
|
||||||
|
if (creditDict.ContainsKey(account.JournalTypeId))
|
||||||
|
{
|
||||||
|
creditAccount = dbDict[creditDict[account.JournalTypeId]]; // key of 59 needed
|
||||||
|
}
|
||||||
|
|
||||||
|
account.AddDefaultAccounts(creditAccount, debitAccount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// all done, return the list here
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Old code needs sorting
|
||||||
|
/// </summary>
|
||||||
|
public bool DeleteJournal(int accountJournalId)
|
||||||
|
{
|
||||||
|
bool IsLocked = ReadJournalIsLocked(accountJournalId);
|
||||||
|
if (IsLocked == true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the delete
|
||||||
|
|
||||||
|
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
||||||
|
{
|
||||||
|
cmd.CommandText = @"
|
||||||
|
DELETE FROM tblAccountJournalPost
|
||||||
|
WHERE AccountJournalID=@accountJournalId;";
|
||||||
|
cmd.Transaction = _transaction as SqlTransaction;
|
||||||
|
|
||||||
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
||||||
|
|
||||||
|
int rows = cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
|
if (rows == 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Journal entry and/or entry posts do not exist for AccountJournalId=" + accountJournalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
||||||
|
{
|
||||||
|
cmd.CommandText = @"
|
||||||
|
DELETE FROM tblAccountJournal
|
||||||
|
WHERE AccountJournalID=@accountJournalId;";
|
||||||
|
cmd.Transaction = _transaction as SqlTransaction;
|
||||||
|
|
||||||
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
||||||
|
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
using bnhtrade.Core.Data.Database.Repository.Interface;
|
|
||||||
using bnhtrade.Core.Model.Account;
|
|
||||||
using Microsoft.Data.SqlClient;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Transactions;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
|
||||||
{
|
|
||||||
internal class PurchaseRepository : _Base, IPurchaseRepository
|
|
||||||
{
|
|
||||||
private static int accountJournalTypeIdNet = 1;
|
|
||||||
private static int accountJournalTypeIdTax = 2;
|
|
||||||
private static int stockJournalTypeId = 1;
|
|
||||||
private static int creditAccountId = 59;
|
|
||||||
private static int creditStatusId = 13;
|
|
||||||
private static int defaultAccountId = 138;
|
|
||||||
|
|
||||||
public PurchaseRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public int DeletePurchaseLineTransaction(int accountJournalId)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
DELETE FROM tblPurchaseLineTransaction
|
|
||||||
WHERE AccountJournalID=@accountJournalId;";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalID", accountJournalId);
|
|
||||||
|
|
||||||
return cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void InsertPurchaseLineTransaction(int accountJournalId, int purchaseLineId)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
INSERT INTO
|
|
||||||
tblPurchaseLineTransaction
|
|
||||||
( PurchaseLineID, AccountJournalID )
|
|
||||||
VALUES
|
|
||||||
( @purchaseLineID, @accountJournalID );";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@purchaseLineID", purchaseLineId);
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalID", accountJournalId);
|
|
||||||
|
|
||||||
int count = cmd.ExecuteNonQuery();
|
|
||||||
|
|
||||||
if (count != 1)
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to insert record to tblPurchaseLineTransaction table");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WIP_PurchaseLineTransactionNetUpdate(int accountJouranlId, string currencyCode, decimal amountNet, int debitAccountId)
|
|
||||||
{
|
|
||||||
// stock accountId check
|
|
||||||
if (debitAccountId == 86)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT Count(tblStock.StockID) AS CountOfStockID
|
|
||||||
FROM tblStock
|
|
||||||
WHERE (((tblStock.AccountJournalID)=@accountJournalId));
|
|
||||||
";
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJouranlId);
|
|
||||||
|
|
||||||
count = (int)cmd.ExecuteScalar();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
throw new Exception("Add account journal entry to stock before attempting this operation.");
|
|
||||||
}
|
|
||||||
else if (count > 1)
|
|
||||||
{
|
|
||||||
throw new Exception("Houston we have a problem! An account journal entry is assigned to " + count + " stock lines.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete after testing....
|
|
||||||
|
|
||||||
//public void WIP_PurchaseLineTransactionStockDelete(string sqlConnectionString, int accountJournalId, int stockId)
|
|
||||||
//{
|
|
||||||
// using (TransactionScope scope = new TransactionScope())
|
|
||||||
// using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
||||||
// {
|
|
||||||
// conn.Open();
|
|
||||||
|
|
||||||
// // get stock cost
|
|
||||||
// (int quantity, decimal totalCost) result = Stock.StockJournal.StockGetTotalQuantityAndCost(sqlConnectionString, stockId);
|
|
||||||
// decimal amount = result.totalCost;
|
|
||||||
|
|
||||||
// // delete accountJournalId from stock table
|
|
||||||
// using (SqlCommand cmd = new SqlCommand(@"
|
|
||||||
// UPDATE tblStock
|
|
||||||
// SET AccountJournalID=Null
|
|
||||||
// WHERE StockID=@stockId AND AccountJournalID=@accountJournalId;
|
|
||||||
// ", conn))
|
|
||||||
// {
|
|
||||||
// cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
// cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
|
|
||||||
// int count = cmd.ExecuteNonQuery();
|
|
||||||
|
|
||||||
// if (count != 1)
|
|
||||||
// {
|
|
||||||
// throw new Exception("Integrity check failure! StockID=" + stockId + ", AccountJournalID=" + accountJournalId +
|
|
||||||
// " combination not found on stock table.");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // reset the account journal to default
|
|
||||||
// Account.AccountQuery.AccountJournalPostUpdate(sqlConnectionString, accountJournalId, "GBP", amount, defaultAccountId, creditAccountId);
|
|
||||||
|
|
||||||
// // delete the stock entry
|
|
||||||
// Stock.StockCreate.WIP_StockDeleteSub(sqlConnectionString, stockId);
|
|
||||||
|
|
||||||
// scope.Complete();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,552 +0,0 @@
|
|||||||
using bnhtrade.Core.Data.Database._BoilerPlate;
|
|
||||||
using bnhtrade.Core.Data.Database.Repository.Interface;
|
|
||||||
using bnhtrade.Core.Model.Account;
|
|
||||||
using bnhtrade.Core.Model.Stock;
|
|
||||||
using Microsoft.Data.SqlClient;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Transactions;
|
|
||||||
using static bnhtrade.Core.Data.Database.Constants;
|
|
||||||
using static bnhtrade.Core.Model.Account.Journal;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
|
||||||
{
|
|
||||||
internal class StockJournalRepository : _Base, IStockJournalRepository
|
|
||||||
{
|
|
||||||
public StockJournalRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> ConvertStockNumbers(List<int> stockNumbers)
|
|
||||||
{
|
|
||||||
if (stockNumbers == null || stockNumbers.Count == 0)
|
|
||||||
{
|
|
||||||
return new List<string>();
|
|
||||||
}
|
|
||||||
return stockNumbers.Select(sn => "STK#" + sn.ToString("D6")).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<int> ConvertStockNumbers(List<string> stockNumbers)
|
|
||||||
{
|
|
||||||
if (stockNumbers == null || stockNumbers.Count == 0)
|
|
||||||
{
|
|
||||||
return new List<int>();
|
|
||||||
}
|
|
||||||
return stockNumbers.Select(sn => int.Parse(sn.Substring(4))).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Create
|
|
||||||
//
|
|
||||||
|
|
||||||
public int InsertStockJournalHeader(int stockId, int journalTypeId, DateTime entryDate, bool isLocked)
|
|
||||||
{
|
|
||||||
if (entryDate.Kind != DateTimeKind.Utc)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Entry date must be in UTC format.", nameof(entryDate));
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
INSERT INTO tblStockJournal ( EntryDate, StockJournalTypeID, StockID, IsLocked )
|
|
||||||
OUTPUT INSERTED.StockJournalID
|
|
||||||
VALUES ( @EntryDate, @journalTypeId, @stockID, @isLocked );";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockID", stockId);
|
|
||||||
cmd.Parameters.AddWithValue("@journalTypeId", journalTypeId);
|
|
||||||
cmd.Parameters.AddWithValue("@EntryDate", entryDate.ToUniversalTime());
|
|
||||||
cmd.Parameters.AddWithValue("@isLocked", isLocked);
|
|
||||||
|
|
||||||
//execute
|
|
||||||
return (int)cmd.ExecuteScalar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int InsertStockJournalPost(int stockJournalId, int stockStatusId, int quantity)
|
|
||||||
{
|
|
||||||
if (quantity == 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Quantity must be non-zero.", nameof(quantity));
|
|
||||||
}
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
INSERT INTO tblStockJournalPost ( StockJournalID, StockStatusID, Quantity )
|
|
||||||
OUTPUT INSERTED.StockJournalPostID
|
|
||||||
VALUES ( @StockJournalId, @stockStatudId, @quantity );";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@StockJournalId", stockJournalId);
|
|
||||||
cmd.Parameters.AddWithValue("@stockStatudId", stockStatusId);
|
|
||||||
cmd.Parameters.AddWithValue("@quantity", quantity);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
return cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Read
|
|
||||||
//
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Stock.StockJournalBuilder> ReadStockJournal(bool lockRecords = false,
|
|
||||||
List<int> stockJournalIds = null, List<int> stockIds = null, List<string> stockNumbers = null
|
|
||||||
, DateTime? minEntryDate = null, DateTime? maxEntryDate = null, List<int> stockStatusIds = null)
|
|
||||||
{
|
|
||||||
var returnDict = new Dictionary<int, Model.Stock.StockJournalBuilder>();
|
|
||||||
var sqlWhere = new SqlWhereBuilder();
|
|
||||||
|
|
||||||
string lockClause = "";
|
|
||||||
if (lockRecords)
|
|
||||||
{
|
|
||||||
lockClause = "WITH (UPDLOCK, HOLDLOCK)";
|
|
||||||
}
|
|
||||||
|
|
||||||
string sql = $@"
|
|
||||||
SELECT tblStockJournal.StockJournalID,
|
|
||||||
tblStockJournal.StockJournalTypeID,
|
|
||||||
tblStockJournal.StockID,
|
|
||||||
tblStock.StockNumber
|
|
||||||
tblStockJournal.EntryDate,
|
|
||||||
tblStockJournal.PostDate,
|
|
||||||
tblStockJournal.LastModified,
|
|
||||||
tblStockJournal.IsLocked,
|
|
||||||
tblStockJournal.AccountIsProcessed,
|
|
||||||
tblStockJournalPost.StockJournalPostID,
|
|
||||||
tblStockJournalPost.StockStatusID,
|
|
||||||
tblStockJournalPost.Quantity,
|
|
||||||
FROM tblStockJournal {lockClause}
|
|
||||||
LEFT OUTER JOIN tblStock {lockClause} ON tblStockJournal.StockID = tblStock.StockID
|
|
||||||
LEFT OUTER JOIN tblStockJournalPost {lockClause} ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
||||||
WHERE 1=1 ";
|
|
||||||
|
|
||||||
// build where clause based on provided filters
|
|
||||||
bool noFilter = true;
|
|
||||||
if (stockJournalIds != null && stockJournalIds.Any())
|
|
||||||
{
|
|
||||||
sql += sqlWhere.InClause("tblStockJournal.StockJournalID", stockJournalIds, "AND");
|
|
||||||
noFilter = false;
|
|
||||||
}
|
|
||||||
if (stockIds != null && stockIds.Any())
|
|
||||||
{
|
|
||||||
sql += sqlWhere.InClause("tblStockJournal.StockID", stockIds, "AND");
|
|
||||||
noFilter = false;
|
|
||||||
}
|
|
||||||
if (stockNumbers != null && stockNumbers.Any())
|
|
||||||
{
|
|
||||||
List<int> stockNumbersInt = ConvertStockNumbers(stockNumbers);
|
|
||||||
sql += sqlWhere.InClause("tblStock.StockNumber", stockNumbersInt, "AND");
|
|
||||||
noFilter = false;
|
|
||||||
}
|
|
||||||
if (minEntryDate.HasValue)
|
|
||||||
{
|
|
||||||
sql += sqlWhere.IsEqualToOrGreaterThanClause("tblStockJournal.EntryDate", minEntryDate.Value.ToUniversalTime(), "AND");
|
|
||||||
noFilter = false;
|
|
||||||
}
|
|
||||||
if (maxEntryDate.HasValue)
|
|
||||||
{
|
|
||||||
sql += sqlWhere.IsEqualToOrLessThanClause("tblStockJournal.EntryDate", maxEntryDate.Value.ToUniversalTime(), "AND");
|
|
||||||
noFilter = false;
|
|
||||||
}
|
|
||||||
if (stockStatusIds != null && stockStatusIds.Any())
|
|
||||||
{
|
|
||||||
sql += sqlWhere.InClause(
|
|
||||||
"StockStatusID"
|
|
||||||
, stockStatusIds
|
|
||||||
, " AND tblStockJournal.StockJournalID IN (SELECT StockJournalID FROM tblStockJournalPost WHERE "
|
|
||||||
, " ) "
|
|
||||||
);
|
|
||||||
noFilter = false;
|
|
||||||
}
|
|
||||||
if (noFilter)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("At least one filter must be provided for stock journal retrieval.");
|
|
||||||
}
|
|
||||||
|
|
||||||
sql += " ORDER BY tblStockJournal.EntryDate, tblStockJournal.StockJournalID, tblStockJournalPost.StockJournalPostID;";
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
|
|
||||||
if (sqlWhere.ParameterListIsSet)
|
|
||||||
{
|
|
||||||
sqlWhere.AddParametersToSqlCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
int stockJournalId = reader.GetInt32(0);
|
|
||||||
|
|
||||||
// add header information, if not already in dictionary
|
|
||||||
if (returnDict.ContainsKey(stockJournalId) == false)
|
|
||||||
{
|
|
||||||
// create new StockJournalBuilder
|
|
||||||
var stockJournalBuilder = new Model.Stock.StockJournalBuilder
|
|
||||||
{
|
|
||||||
StockJournalId = stockJournalId,
|
|
||||||
StockJournalTypeId = reader.GetInt32(1),
|
|
||||||
StockId = reader.GetInt32(2),
|
|
||||||
StockNumber = "STK#" + reader.GetInt32(3).ToString("D6"),
|
|
||||||
EntryDate = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc),
|
|
||||||
PostDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc),
|
|
||||||
LastModified = DateTime.SpecifyKind(reader.GetDateTime(6), DateTimeKind.Utc),
|
|
||||||
IsLocked = reader.GetBoolean(7),
|
|
||||||
AccountIsProcessed = reader.GetBoolean(8),
|
|
||||||
StockJournalBuilderPosts = new List<Model.Stock.StockJournalBuilder.StockJournalBuilderPost>()
|
|
||||||
};
|
|
||||||
returnDict.Add(stockJournalId, stockJournalBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
var stockJournalBuilderPost = new Model.Stock.StockJournalBuilder.StockJournalBuilderPost
|
|
||||||
{
|
|
||||||
StockJournalPostId = reader.GetInt32(9),
|
|
||||||
StatusId = reader.GetInt32(10),
|
|
||||||
Quantity = reader.GetInt32(11)
|
|
||||||
};
|
|
||||||
|
|
||||||
returnDict[stockJournalId].StockJournalBuilderPosts.Add(stockJournalBuilderPost);
|
|
||||||
}
|
|
||||||
return returnDict;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<int, (int id, string title, int? stockStatusIdDebit, int? stockStatusIdCredit)> ReadStockJournalType(List<int> stockJournalTypeIdList)
|
|
||||||
{
|
|
||||||
var returnDict = new Dictionary<int, (int id, string title, int? stockStatusIdDebit, int? stockStatusIdCredit)>();
|
|
||||||
var sqlWhere = new SqlWhereBuilder();
|
|
||||||
|
|
||||||
string sql = @"
|
|
||||||
SELECT StockJournalTypeID, TypeTitle, StockStatusID_Debit, StockStatusID_Credit
|
|
||||||
FROM tblStockJournalType
|
|
||||||
WHERE 1=1 ";
|
|
||||||
|
|
||||||
if (stockJournalTypeIdList != null && stockJournalTypeIdList.Any())
|
|
||||||
{
|
|
||||||
sql += sqlWhere.InClause("StockJournalTypeID", stockJournalTypeIdList, "AND");
|
|
||||||
}
|
|
||||||
|
|
||||||
sql += ";";
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
|
|
||||||
if (sqlWhere.ParameterListIsSet)
|
|
||||||
{
|
|
||||||
sqlWhere.AddParametersToSqlCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
int stockJournalTypeId = reader.GetInt32(0);
|
|
||||||
returnDict.Add(stockJournalTypeId, (
|
|
||||||
id: stockJournalTypeId,
|
|
||||||
title: reader.GetString(1),
|
|
||||||
stockStatusIdDebit: reader.IsDBNull(2) ? (int?)null : reader.GetInt32(2),
|
|
||||||
stockStatusIdCredit: reader.IsDBNull(3) ? (int?)null : reader.GetInt32(3)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
public (int, DateTime) ReadJournalStockIdAndEntryDate(int stockJournalId)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT tblStockJournal.EntryDate, StockID
|
|
||||||
FROM tblStockJournal
|
|
||||||
WHERE (((tblStockJournal.StockJournalID)=@stockJournalId));";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockJournalId", stockJournalId);
|
|
||||||
|
|
||||||
using (var reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
if (reader.Read())
|
|
||||||
{
|
|
||||||
return (reader.GetInt32(1), DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("StockJournalID=" + stockJournalId + " does not exist!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadJournalTypeIdByStockId(int stockId)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT tblStockJournal.StockJournalTypeID
|
|
||||||
FROM tblStock INNER JOIN
|
|
||||||
tblStockJournal ON tblStock.StockJournalID = tblStockJournal.StockJournalID
|
|
||||||
WHERE (tblStock.StockID = @stockId);";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
|
|
||||||
if (obj == null || obj == DBNull.Value)
|
|
||||||
{
|
|
||||||
throw new Exception("No stock journal type found for StockID=" + stockId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int)obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadStatusBalanceBySku(string sku, int statusId)
|
|
||||||
{
|
|
||||||
int statusBalance = new int();
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT SUM(tblStockJournalPost.Quantity) AS Balance
|
|
||||||
FROM tblStockJournal INNER JOIN
|
|
||||||
tblStockJournalPost ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID INNER JOIN
|
|
||||||
tblStock ON tblStockJournal.StockID = tblStock.StockID INNER JOIN
|
|
||||||
tblSku ON tblStock.SkuID = tblSku.skuSkuID
|
|
||||||
WHERE (tblStockJournalPost.StockStatusID = @statusId) AND (tblSku.skuSkuNumber = @sku);";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@sku", sku);
|
|
||||||
cmd.Parameters.AddWithValue("@statusId", statusId);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
if (obj == null || obj == DBNull.Value)
|
|
||||||
{
|
|
||||||
statusBalance = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
statusBalance = (int)obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return statusBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadStatusBalanceByStockNumber(int stockNumber, int statusId)
|
|
||||||
{
|
|
||||||
int statusBalance = new int();
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT SUM(tblStockJournalPost.Quantity) AS Balance
|
|
||||||
FROM tblStockJournal INNER JOIN
|
|
||||||
tblStockJournalPost ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID INNER JOIN
|
|
||||||
tblStock ON tblStockJournal.StockID = tblStock.StockID
|
|
||||||
WHERE (tblStockJournalPost.StockStatusID = @statusId) AND (tblStock.StockNumber = @stockNumber);";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockNumber", stockNumber);
|
|
||||||
cmd.Parameters.AddWithValue("@statusId", statusId);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
if (obj == null || obj == DBNull.Value)
|
|
||||||
{
|
|
||||||
statusBalance = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
statusBalance = (int)obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return statusBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadStatusBalanceByStockId(int stockId, int statusId)
|
|
||||||
{
|
|
||||||
int statusBalance = new int();
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT
|
|
||||||
SUM(tblStockJournalPost.Quantity) AS Balance
|
|
||||||
FROM
|
|
||||||
tblStockJournal
|
|
||||||
INNER JOIN tblStockJournalPost
|
|
||||||
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
||||||
WHERE
|
|
||||||
(tblStockJournal.StockID = @stockId )
|
|
||||||
AND (tblStockJournalPost.StockStatusID = @statusId );";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
cmd.Parameters.AddWithValue("@statusId", statusId);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
if (obj == null || obj == DBNull.Value)
|
|
||||||
{
|
|
||||||
statusBalance = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
statusBalance = (int)obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return statusBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadJournalEntryCountByStockId(int stockId)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT Count(tblStockJournal.StockJournalID) AS CountOfStockJournalID
|
|
||||||
FROM tblStockJournal
|
|
||||||
WHERE (((tblStockJournal.StockID)=@stockId));";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
|
|
||||||
return (int)cmd.ExecuteScalar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int? ReadTypeIdStatusCreditId(int stockJournalTypeId)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT
|
|
||||||
tblStockJournalType.StockStatusID_Credit
|
|
||||||
FROM
|
|
||||||
tblStockJournalType
|
|
||||||
WHERE
|
|
||||||
tblStockJournalType.StockJournalTypeID=@stockJournalTypeId
|
|
||||||
AND tblStockJournalType.StockStatusID_Credit Is Not Null;";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockJournalTypeId", stockJournalTypeId);
|
|
||||||
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
|
|
||||||
if (obj == null || obj == DBNull.Value)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (int)obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public DateTime? ReadMostRecentEntryDateForStatusDebit(int stockId, List<int> stockStatusIdList)
|
|
||||||
{
|
|
||||||
if (stockId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Stock ID must be greater than zero.", nameof(stockId));
|
|
||||||
}
|
|
||||||
if (stockStatusIdList == null || stockStatusIdList.Count == 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Stock status ID list cannot be null or empty.", nameof(stockStatusIdList));
|
|
||||||
}
|
|
||||||
|
|
||||||
var sqlWhere = new SqlWhereBuilder();
|
|
||||||
|
|
||||||
// build sql string
|
|
||||||
string stringSql = @"
|
|
||||||
MAX (tblStockJournal.EntryDate) AS MostRecentEntryDate
|
|
||||||
FROM
|
|
||||||
tblStockJournal
|
|
||||||
INNER JOIN tblStockJournalPost
|
|
||||||
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
||||||
WHERE
|
|
||||||
tblStockJournal.StockID=@stockId
|
|
||||||
AND tblStockJournalPost.Quantity>0 ";
|
|
||||||
|
|
||||||
stringSql += sqlWhere.InClause("tblStockJournalPost.StockStatusID", stockStatusIdList, "AND") + ";";
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.CommandText = stringSql;
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
sqlWhere.AddParametersToSqlCommand(cmd);
|
|
||||||
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
if (obj == null || obj == DBNull.Value)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return DateTime.SpecifyKind((DateTime)obj, DateTimeKind.Utc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// update
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Delete
|
|
||||||
//
|
|
||||||
|
|
||||||
public void StockJournalDelete(int stockJournalId)
|
|
||||||
{
|
|
||||||
// delete posts
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
DELETE FROM tblStockJournalPost
|
|
||||||
WHERE StockJournalID=@stockJournalId;";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@StockJournalId", stockJournalId);
|
|
||||||
|
|
||||||
// execute
|
|
||||||
cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete journal entry
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
DELETE FROM tblStockJournal
|
|
||||||
WHERE StockJournalID=@stockJournalId;";
|
|
||||||
|
|
||||||
// add parameters
|
|
||||||
cmd.Parameters.AddWithValue("@stockJournalId", stockJournalId);
|
|
||||||
|
|
||||||
int count = cmd.ExecuteNonQuery();
|
|
||||||
|
|
||||||
if (count != 1)
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to delete stock journal header.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
using bnhtrade.Core.Data.Database.Repository.Interface;
|
using bnhtrade.Core.Data.Database._BoilerPlate;
|
||||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
using bnhtrade.Core.Data.Database.Repository.Interface;
|
||||||
using Microsoft.Data.SqlClient;
|
using Microsoft.Data.SqlClient;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -7,8 +7,6 @@ using System.Data;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Transactions;
|
|
||||||
using static System.Formats.Asn1.AsnWriter;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
||||||
{
|
{
|
||||||
@@ -18,254 +16,126 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
public List<Model.Stock.Status> ReadStatus(List<int> statusIds = null, List<int> statusTypeIds = null)
|
||||||
// create
|
|
||||||
//
|
|
||||||
|
|
||||||
public int InsertNewStock(int skuId, int accountJournalId)
|
|
||||||
{
|
{
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
var sqlBuilder = new SqlWhereBuilder();
|
||||||
{
|
var returnList = new List<Model.Stock.Status>();
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
INSERT INTO tblStock
|
|
||||||
(SkuID, AccountJournalID)
|
|
||||||
OUTPUT INSERTED.StockID
|
|
||||||
VALUES
|
|
||||||
(@skuId, @accountJournalId);";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@skuId", skuId);
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
|
|
||||||
return (int)cmd.ExecuteScalar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// read
|
|
||||||
//
|
|
||||||
|
|
||||||
public int CountStockTableRecords(List<int> accountJournalId = null)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("This needs testing before use");
|
|
||||||
|
|
||||||
var sqlWhere = new SqlWhereBuilder();
|
|
||||||
|
|
||||||
|
//build sql query
|
||||||
string sql = @"
|
string sql = @"
|
||||||
SELECT Count(tblStock.StockID) AS CountOfID
|
SELECT [StockStatusID]
|
||||||
FROM tblStock
|
,[StatusCode]
|
||||||
|
,[StockStatus]
|
||||||
|
,[StockStatusTypeID]
|
||||||
|
,[Reference]
|
||||||
|
,[ForeignKeyID]
|
||||||
|
,[IsCreditOnly]
|
||||||
|
,[IsClosed]
|
||||||
|
,[RecordCreated]
|
||||||
|
FROM [e2A].[dbo].[tblStockStatus]
|
||||||
WHERE 1=1 ";
|
WHERE 1=1 ";
|
||||||
|
|
||||||
if (accountJournalId != null)
|
// build the where statments
|
||||||
|
if (statusIds.Any())
|
||||||
{
|
{
|
||||||
sqlWhere.In("AccountJournalID", accountJournalId, "AND");
|
sqlBuilder.In("StockStatusID", statusIds, "AND");
|
||||||
|
}
|
||||||
|
if (statusTypeIds.Any())
|
||||||
|
{
|
||||||
|
sqlBuilder.In("StockStatusTypeID", statusTypeIds, "AND");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sqlWhere.IsSetSqlWhereString)
|
// append where string to the sql
|
||||||
|
if (sqlBuilder.IsSetSqlWhereString)
|
||||||
{
|
{
|
||||||
sql += sqlWhere.SqlWhereString;
|
sql = sql + sqlBuilder.SqlWhereString;
|
||||||
}
|
}
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
|
|
||||||
if (sqlWhere.ParameterListIsSet)
|
|
||||||
{
|
|
||||||
sqlWhere.AddParametersToSqlCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int)cmd.ExecuteScalar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int? ReadStockIdByAccountJournalId(int accountJournalId)
|
|
||||||
{
|
|
||||||
if (accountJournalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Account Journal ID must be greater than zero", nameof(accountJournalId));
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT StockID
|
|
||||||
FROM tblStock
|
|
||||||
WHERE AccountJournalID = @accountJournalId;
|
|
||||||
";
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
||||||
|
|
||||||
object obj = cmd.ExecuteScalar();
|
|
||||||
|
|
||||||
// unique index on tblStock.AccountJournalID ensures that this will return at most one row
|
|
||||||
if (obj == null)
|
|
||||||
{
|
|
||||||
throw new Exception("AccountJournalID=" + accountJournalId + " does not exist.");
|
|
||||||
}
|
|
||||||
else if (obj == DBNull.Value)
|
|
||||||
{
|
|
||||||
return null; // no stock entry found
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (int)obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
||||||
{
|
{
|
||||||
cmd.CommandText = sql;
|
cmd.CommandText = sql;
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
cmd.Transaction = _transaction as SqlTransaction;
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
if (accountJournalID == null)
|
if (sqlBuilder.ParameterListIsSet)
|
||||||
{
|
{
|
||||||
cmd.Parameters.AddWithValue("@accountJournalID", DBNull.Value);
|
sqlBuilder.AddParametersToSqlCommand(cmd);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@accountJournalID", accountJournalID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd.ExecuteNonQuery();
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
var typeDict = new StockRepository(_connection, _transaction).ReadStatusType();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
int statusId = reader.GetInt32(0);
|
||||||
|
int? statusCode = null;
|
||||||
|
if (!reader.IsDBNull(1)) { statusCode = reader.GetInt32(1); }
|
||||||
|
string stockStatus = reader.GetString(2);
|
||||||
|
int typeId = reader.GetInt32(3);
|
||||||
|
string reference = null;
|
||||||
|
if (!reader.IsDBNull(4)) { reference = reader.GetString(4); }
|
||||||
|
int? foreignKeyId = null;
|
||||||
|
if (!reader.IsDBNull(5)) { foreignKeyId = reader.GetInt32(5); }
|
||||||
|
bool isCreditOnly = reader.GetBoolean(6);
|
||||||
|
bool isClosed = reader.GetBoolean(7);
|
||||||
|
DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc);
|
||||||
|
|
||||||
|
var newItem = new Model.Stock.Status(statusId
|
||||||
|
, statusCode
|
||||||
|
, stockStatus
|
||||||
|
, typeDict[typeId]
|
||||||
|
, reference
|
||||||
|
, foreignKeyId
|
||||||
|
, isCreditOnly
|
||||||
|
, isClosed
|
||||||
|
, recordCreated
|
||||||
|
);
|
||||||
|
|
||||||
|
returnList.Add(newItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int UpdateStockJournalId(int stockId, int? stockJournalId)
|
public Dictionary<int, Model.Stock.StatusType> ReadStatusType()
|
||||||
{
|
{
|
||||||
if (stockId <= 0)
|
var returnDict = new Dictionary<int, Model.Stock.StatusType>();
|
||||||
{
|
|
||||||
throw new ArgumentException("Stock ID must be greater than zero", nameof(stockId));
|
|
||||||
}
|
|
||||||
|
|
||||||
string sql = @"
|
// get all account info before we start
|
||||||
UPDATE
|
var accountDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode();
|
||||||
tblStock
|
|
||||||
SET
|
|
||||||
StockJournalID = @stockJournalId
|
|
||||||
WHERE
|
|
||||||
StockID = @stockId;";
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
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 DeleteStock(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 = @"
|
cmd.CommandText = @"
|
||||||
DELETE FROM tblStock
|
SELECT [StockStatusTypeID]
|
||||||
WHERE StockID=@stockId;";
|
,[StatusTypeName]
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
,[ForeignKeyType]
|
||||||
return cmd.ExecuteNonQuery();
|
,[ReferenceType]
|
||||||
|
,[AccountChartOfID]
|
||||||
|
FROM [e2A].[dbo].[tblStockStatusType]";
|
||||||
|
cmd.Transaction = _transaction as SqlTransaction;
|
||||||
|
|
||||||
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
var accountIdDict = new Dictionary<int, int>();
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
int statusTypeId = reader.GetInt32(0);
|
||||||
|
string name = reader.GetString(1);
|
||||||
|
string foreignKey = null;
|
||||||
|
if (!reader.IsDBNull(2)) { foreignKey = reader.GetString(2); }
|
||||||
|
string reference = null;
|
||||||
|
if (!reader.IsDBNull(3)) { reference = reader.GetString(3); }
|
||||||
|
uint accountId = (uint)reader.GetInt32(4);
|
||||||
|
|
||||||
|
var statusType = new Model.Stock.StatusType(statusTypeId, name, foreignKey, reference, accountDict[(int)accountId]);
|
||||||
|
returnDict.Add(statusTypeId, statusType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return returnDict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,131 +0,0 @@
|
|||||||
using Amazon.Runtime.Internal.Transform;
|
|
||||||
using bnhtrade.Core.Data.Database._BoilerPlate;
|
|
||||||
using bnhtrade.Core.Data.Database.Repository.Interface;
|
|
||||||
using Microsoft.Data.SqlClient;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
|
||||||
{
|
|
||||||
internal class StockStatusRepository : _Base, IStockStatusRepository
|
|
||||||
{
|
|
||||||
public StockStatusRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Stock.StatusBuilder> ReadStatus(List<int> statusIds = null, List<int> statusTypeIds = null)
|
|
||||||
{
|
|
||||||
var sqlBuilder = new SqlWhereBuilder();
|
|
||||||
var returnList = new Dictionary<int, Model.Stock.StatusBuilder>();
|
|
||||||
|
|
||||||
//build sql query
|
|
||||||
string sql = @"
|
|
||||||
SELECT [StockStatusID]
|
|
||||||
,[StatusCode]
|
|
||||||
,[StockStatus]
|
|
||||||
,[StockStatusTypeID]
|
|
||||||
,[Reference]
|
|
||||||
,[ForeignKeyID]
|
|
||||||
,[IsCreditOnly]
|
|
||||||
,[IsClosed]
|
|
||||||
,[RecordCreated]
|
|
||||||
FROM [e2A].[dbo].[tblStockStatus]
|
|
||||||
WHERE 1=1 ";
|
|
||||||
|
|
||||||
// build the where statments
|
|
||||||
if (statusIds.Any())
|
|
||||||
{
|
|
||||||
sqlBuilder.In("StockStatusID", statusIds, "AND");
|
|
||||||
}
|
|
||||||
if (statusTypeIds.Any())
|
|
||||||
{
|
|
||||||
sqlBuilder.In("StockStatusTypeID", statusTypeIds, "AND");
|
|
||||||
}
|
|
||||||
|
|
||||||
// append where string to the sql
|
|
||||||
if (sqlBuilder.IsSetSqlWhereString)
|
|
||||||
{
|
|
||||||
sql = sql + sqlBuilder.SqlWhereString;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
|
|
||||||
if (sqlBuilder.ParameterListIsSet)
|
|
||||||
{
|
|
||||||
sqlBuilder.AddParametersToSqlCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
var statusBuilder = new Model.Stock.StatusBuilder
|
|
||||||
{
|
|
||||||
StatusId = reader.GetInt32(0),
|
|
||||||
StatusCode = reader.IsDBNull(1) ? (int?)null : reader.GetInt32(1),
|
|
||||||
StatusTitle = reader.GetString(2),
|
|
||||||
StatusTypeId = reader.GetInt32(3),
|
|
||||||
Reference = reader.IsDBNull(4) ? null : reader.GetString(4),
|
|
||||||
ForeignKeyID = reader.IsDBNull(5) ? (int?)null : reader.GetInt32(5),
|
|
||||||
IsCreditOnly = reader.GetBoolean(6),
|
|
||||||
IsClosed = reader.GetBoolean(7),
|
|
||||||
RecordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc)
|
|
||||||
};
|
|
||||||
|
|
||||||
returnList.Add(statusBuilder.StatusId, statusBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Stock.StatusTypeBuilder> ReadStatusType(List<int> stockStatusTypeIds = null)
|
|
||||||
{
|
|
||||||
var returnDict = new Dictionary<int, Model.Stock.StatusTypeBuilder>();
|
|
||||||
var sqlWhere = new SqlWhereBuilder();
|
|
||||||
|
|
||||||
string sql = @"
|
|
||||||
SELECT [StockStatusTypeID]
|
|
||||||
,[StatusTypeName]
|
|
||||||
,[ForeignKeyType]
|
|
||||||
,[ReferenceType]
|
|
||||||
,[AccountChartOfID]
|
|
||||||
FROM [e2A].[dbo].[tblStockStatusType]
|
|
||||||
WHERE 1=1 ";
|
|
||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
if (sqlWhere.ParameterListIsSet)
|
|
||||||
{
|
|
||||||
sqlWhere.AddParametersToSqlCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
var statusTypeBuilder = new Model.Stock.StatusTypeBuilder
|
|
||||||
{
|
|
||||||
StockStatusTypeID = reader.GetInt32(0),
|
|
||||||
StatusTypeName = reader.GetString(1),
|
|
||||||
ForeignKeyType = reader.IsDBNull(2) ? null : reader.GetString(2),
|
|
||||||
ReferenceType = reader.IsDBNull(3) ? null : reader.GetString(3),
|
|
||||||
AccountId = reader.GetInt32(4)
|
|
||||||
};
|
|
||||||
returnDict.Add(statusTypeBuilder.StockStatusTypeID, statusTypeBuilder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnDict;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -44,8 +44,8 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
|
|||||||
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
||||||
{
|
{
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = sql;
|
cmd.CommandText = sql;
|
||||||
|
cmd.Transaction = _transaction as SqlTransaction;
|
||||||
|
|
||||||
sqlwhere.AddParametersToSqlCommand(cmd);
|
sqlwhere.AddParametersToSqlCommand(cmd);
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Interface
|
|
||||||
{
|
|
||||||
internal interface IAccountJournalRepository
|
|
||||||
{
|
|
||||||
int InsertJournalHeader(int journalTypeId, DateTime entryDate, bool lockEntry = false);
|
|
||||||
int InsertJournalPost(int accountJournalId, int accountChartOfId, decimal amountGbp);
|
|
||||||
Dictionary<int, Model.Account.JournalBuilder> ReadJournalBuilder(List<int> journalIdList);
|
|
||||||
DateTime ReadJournalEntryDate(int journalId);
|
|
||||||
int CountJournalPosts(int accountJournalId);
|
|
||||||
bool IsJournalDebitAssetType(int accountJournalId);
|
|
||||||
bool? IsJournalLocked(int journalId);
|
|
||||||
List<(int, string, int?, int?)> ReadJournalType(List<int> accountJournalTypeIds = null, List<string> typeTitles = null);
|
|
||||||
(int?, int?) ReadJournalTypeDefaultDebitCredit(int accountJournalId);
|
|
||||||
bool UpdateJournalEntryModifiedDate(int accountJournalId);
|
|
||||||
int DeleteJournalHeader(int accountJournalId);
|
|
||||||
int DeleteJournalPostAll(int accountJournalId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace bnhtrade.Core.Data.Database.Repository.Interface
|
||||||
|
{
|
||||||
|
internal interface IJournalRepository
|
||||||
|
{
|
||||||
|
Dictionary<int, Core.Model.Account.Journal> ReadJournal(List<int> journalIdList);
|
||||||
|
bool ReadJournalIsLocked(int journalId);
|
||||||
|
Dictionary<int, Model.Account.JournalType> ReadJournalType(List<int> journalTypeIds = null, List<string> typeTitles = null);
|
||||||
|
bool DeleteJournal(int accountJournalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Interface
|
|
||||||
{
|
|
||||||
internal interface IPurchaseRepository
|
|
||||||
{
|
|
||||||
int DeletePurchaseLineTransaction(int accountJournalId);
|
|
||||||
void InsertPurchaseLineTransaction(int accountJournalId, int purchaseLineId);
|
|
||||||
void WIP_PurchaseLineTransactionNetUpdate(int accountJouranlId, string currencyCode, decimal amountNet, int debitAccountId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Interface
|
|
||||||
{
|
|
||||||
internal interface IStockJournalRepository
|
|
||||||
{
|
|
||||||
int InsertStockJournalHeader(int stockId, int journalTypeId, DateTime entryDate, bool isLocked);
|
|
||||||
int InsertStockJournalPost(int stockJournalId, int stockStatusId, int quantity);
|
|
||||||
Dictionary<int, Model.Stock.StockJournalBuilder> ReadStockJournal(bool lockRecords = false,
|
|
||||||
List<int> stockJournalIds = null, List<int> stockIds = null, List<string> stockNumbers = null
|
|
||||||
, DateTime? minEntryDate = null, DateTime? maxEntryDate = null, List<int> stockStatusIds = null);
|
|
||||||
Dictionary<int, (int id, string title, int? stockStatusIdDebit, int? stockStatusIdCredit)> ReadStockJournalType(List<int> stockJournalTypeIdList);
|
|
||||||
(int, DateTime) ReadJournalStockIdAndEntryDate(int stockJournalId);
|
|
||||||
int ReadJournalTypeIdByStockId(int stockId);
|
|
||||||
int ReadStatusBalanceBySku(string sku, int statusId);
|
|
||||||
int ReadStatusBalanceByStockNumber(int stockNumber, int statusId);
|
|
||||||
int ReadStatusBalanceByStockId(int stockId, int statusId);
|
|
||||||
int ReadJournalEntryCountByStockId(int stockId);
|
|
||||||
int? ReadTypeIdStatusCreditId(int stockJournalTypeId);
|
|
||||||
DateTime? ReadMostRecentEntryDateForStatusDebit(int stockId, List<int> stockStatusIdList);
|
|
||||||
void StockJournalDelete(int stockJournalId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,13 +8,7 @@ namespace bnhtrade.Core.Data.Database.Repository.Interface
|
|||||||
{
|
{
|
||||||
internal interface IStockRepository
|
internal interface IStockRepository
|
||||||
{
|
{
|
||||||
int InsertNewStock(int skuId, int accountJournalId);
|
List<Model.Stock.Status> ReadStatus(List<int> statusIds = null, List<int> statusTypeIds = null);
|
||||||
int CountStockTableRecords(List<int> accountJournalId = null);
|
Dictionary<int, Model.Stock.StatusType> ReadStatusType();
|
||||||
int? ReadStockIdByAccountJournalId(int accountJournalId);
|
|
||||||
int? ReadAccountJournalId(int stockId);
|
|
||||||
int? ReadStockJournalId(int stockId);
|
|
||||||
int UpdateAccountJournalId(int stockId, int? accountJournalID);
|
|
||||||
int UpdateStockJournalId(int stockId, int? stockJournalID);
|
|
||||||
int DeleteStock(int stockId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Data.Database.Repository.Interface
|
|
||||||
{
|
|
||||||
internal interface IStockStatusRepository
|
|
||||||
{
|
|
||||||
Dictionary<int, Model.Stock.StatusBuilder> ReadStatus(List<int> statusIds = null, List<int> statusTypeIds = null);
|
|
||||||
Dictionary<int, Model.Stock.StatusTypeBuilder> ReadStatusType(List<int> stockStatusTypeIds = null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,15 +8,17 @@ using Microsoft.IdentityModel.Tokens;
|
|||||||
namespace bnhtrade.Core.Data.Database
|
namespace bnhtrade.Core.Data.Database
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sep 1: Call each Where_____ method in this class as needed, the method returns a string that can be appended to your SQL statement and builds
|
/// Step 1: Call the methods for each where clause you want to create. This can be done multiple times to create an sql where string. Pay attention
|
||||||
/// a parameter list.
|
/// to the prefixes that you'll require between each where clause, as each time a method is called the sql statement will be appended to the previous sql
|
||||||
|
/// string.
|
||||||
///
|
///
|
||||||
/// Step 2: Once you've created your sql command object, add the parameters to it using the method contained within this class.
|
/// Step 2: Appened the created sql string to your sql statement, NB the WHERE statemet is not included by default.
|
||||||
|
///
|
||||||
|
/// Step 3: Once you've created your sql command object, add the parameters to it using the method contained within this class.
|
||||||
///
|
///
|
||||||
/// Step 4: exceute your sql commend.
|
/// Step 4: exceute your sql commend.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
public class SqlWhereBuilder
|
||||||
internal class SqlWhereBuilder
|
|
||||||
{
|
{
|
||||||
private int parameterCount = 0;
|
private int parameterCount = 0;
|
||||||
|
|
||||||
@@ -25,10 +27,8 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
|
||||||
public string SqlWhereString { get; private set; }
|
public string SqlWhereString { get; private set; }
|
||||||
|
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
|
||||||
public bool IsSetSqlWhereString
|
public bool IsSetSqlWhereString
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -115,7 +115,6 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
||||||
/// <param name="phraseList">List of phrases to test in condition statement</param>
|
/// <param name="phraseList">List of phrases to test in condition statement</param>
|
||||||
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
|
||||||
public void LikeAnd(string columnReference, IEnumerable<string> phraseList, string wherePrefix = null)
|
public void LikeAnd(string columnReference, IEnumerable<string> phraseList, string wherePrefix = null)
|
||||||
{
|
{
|
||||||
Like(columnReference, phraseList, true, wherePrefix);
|
Like(columnReference, phraseList, true, wherePrefix);
|
||||||
@@ -127,13 +126,11 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
||||||
/// <param name="phraseList">List of phrases to test in condition statement</param>
|
/// <param name="phraseList">List of phrases to test in condition statement</param>
|
||||||
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
|
||||||
public void LikeOr(string columnReference, IEnumerable<string> phraseList, string wherePrefix = null)
|
public void LikeOr(string columnReference, IEnumerable<string> phraseList, string wherePrefix = null)
|
||||||
{
|
{
|
||||||
Like(columnReference, phraseList, false, wherePrefix);
|
Like(columnReference, phraseList, false, wherePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
|
||||||
private void Like(string columnReference, IEnumerable<string> phraseList, bool isAnd, string wherePrefix = null)
|
private void Like(string columnReference, IEnumerable<string> phraseList, bool isAnd, string wherePrefix = null)
|
||||||
{
|
{
|
||||||
if (phraseList == null || !phraseList.Any())
|
if (phraseList == null || !phraseList.Any())
|
||||||
@@ -193,62 +190,35 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//public void IsEqualTo(string columnReference, bool booleanValue, string wherePrefix = null)
|
public void IsEqualTo(string columnReference, bool booleanValue, string wherePrefix = null)
|
||||||
//{
|
|
||||||
// string sqlWhereString = @"
|
|
||||||
// ";
|
|
||||||
|
|
||||||
// if (wherePrefix != null)
|
|
||||||
// {
|
|
||||||
// sqlWhereString += wherePrefix;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// sqlWhereString += " ( " + columnReference + " = ";
|
|
||||||
|
|
||||||
// if (booleanValue)
|
|
||||||
// {
|
|
||||||
// sqlWhereString += "1 ) ";
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// sqlWhereString += "0 ) ";
|
|
||||||
// }
|
|
||||||
|
|
||||||
// SqlWhereString = SqlWhereString + sqlWhereString;
|
|
||||||
//}
|
|
||||||
|
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
|
||||||
public void IsEqualTo(string columnReference, object whereArgument, string wherePrefix = null)
|
|
||||||
{
|
{
|
||||||
IsEqualSub(columnReference, whereArgument, "=", wherePrefix);
|
string sqlWhereString = @"
|
||||||
}
|
";
|
||||||
|
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
if (wherePrefix != null)
|
||||||
public void IsEqualToOrLessThan(string columnReference, object whereArgument, string wherePrefix = null)
|
|
||||||
{
|
|
||||||
IsEqualSub(columnReference, whereArgument, "<=", wherePrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
|
||||||
public void IsEqualToOrGreaterThan(string columnReference, object whereArgument, string wherePrefix = null)
|
|
||||||
{
|
|
||||||
IsEqualSub(columnReference, whereArgument, ">=", wherePrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
|
||||||
private void IsEqualSub(string columnReference, object whereArgument, string operatorString, string wherePrefix = null)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(columnReference))
|
|
||||||
{
|
{
|
||||||
throw new Exception(wherePrefix + " IsEqual method requires a valid column reference.");
|
sqlWhereString += wherePrefix;
|
||||||
}
|
}
|
||||||
if (whereArgument == null)
|
|
||||||
|
sqlWhereString += " ( " + columnReference + " = ";
|
||||||
|
|
||||||
|
if (booleanValue)
|
||||||
{
|
{
|
||||||
throw new Exception(wherePrefix + " IsEqual method requires a valid where argument.");
|
sqlWhereString += "1 ) ";
|
||||||
}
|
}
|
||||||
if (whereArgument is string && string.IsNullOrEmpty(whereArgument.ToString()))
|
else
|
||||||
{
|
{
|
||||||
throw new Exception(wherePrefix + " IsEqual method requires a valid where argument.");
|
sqlWhereString += "0 ) ";
|
||||||
|
}
|
||||||
|
|
||||||
|
SqlWhereString = SqlWhereString + sqlWhereString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IsEqualTo(string columnReference, string stringValue, string wherePrefix = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(stringValue) || string.IsNullOrEmpty(columnReference))
|
||||||
|
{
|
||||||
|
throw new Exception(wherePrefix + " IsEqualTo method requires a valid column reference and string value.");
|
||||||
}
|
}
|
||||||
|
|
||||||
string sqlWhereString = @"
|
string sqlWhereString = @"
|
||||||
@@ -258,26 +228,27 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
{
|
{
|
||||||
sqlWhereString += wherePrefix;
|
sqlWhereString += wherePrefix;
|
||||||
}
|
}
|
||||||
sqlWhereString += " ( " + columnReference + " " + operatorString + " " + GetSetParameter(whereArgument) + " ) ";
|
|
||||||
|
sqlWhereString += " ( " + columnReference + " = " + GetSetParameter(stringValue) + " ) ";
|
||||||
|
|
||||||
SqlWhereString = SqlWhereString + sqlWhereString;
|
SqlWhereString = SqlWhereString + sqlWhereString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Append an 'In' statement and parameter list to the class properties
|
/// Append an 'In' statement and parameter list to the class properties
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
||||||
/// <param name="orArgumentList">List of values to test in condition statement</param>
|
/// <param name="orValueList">List of values to test in condition statement</param>
|
||||||
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
public void In(string columnReference, IEnumerable<object> orValueList, string wherePrefix = null)
|
||||||
public void In(string columnReference, IEnumerable<object> orArgumentList, string wherePrefix = null)
|
|
||||||
{
|
{
|
||||||
if (orArgumentList == null || !orArgumentList.Any())
|
if (orValueList == null || !orValueList.Any())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var distinctList = orArgumentList.Distinct().ToList();
|
var distinctList = orValueList.Distinct().ToList();
|
||||||
|
|
||||||
string sqlWhere = @"
|
string sqlWhere = @"
|
||||||
";
|
";
|
||||||
@@ -308,16 +279,15 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
/// Append an 'In' statement and parameter list to the class properties
|
/// Append an 'In' statement and parameter list to the class properties
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
||||||
/// <param name="orArgumentList">List of values to test in condition statement</param>
|
/// <param name="orValueList">List of values to test in condition statement</param>
|
||||||
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
public void In(string columnReference, IEnumerable<string> orValueList, string wherePrefix = null)
|
||||||
public void In(string columnReference, IEnumerable<string> orArgumentList, string wherePrefix = null)
|
|
||||||
{
|
{
|
||||||
var objectList = new List<object>();
|
var objectList = new List<object>();
|
||||||
|
|
||||||
if (orArgumentList != null && orArgumentList.Any())
|
if (orValueList != null && orValueList.Any())
|
||||||
{
|
{
|
||||||
foreach (string value in orArgumentList)
|
foreach (string value in orValueList)
|
||||||
{
|
{
|
||||||
objectList.Add(value.ToString());
|
objectList.Add(value.ToString());
|
||||||
}
|
}
|
||||||
@@ -330,16 +300,15 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
/// Append an 'In' statement and parameter list to the class properties
|
/// Append an 'In' statement and parameter list to the class properties
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
||||||
/// <param name="orArgumentList">List of values to test in condition statement</param>
|
/// <param name="orValueList">List of values to test in condition statement</param>
|
||||||
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
public void In(string columnReference, IEnumerable<int> orValueList, string wherePrefix = null)
|
||||||
public void In(string columnReference, IEnumerable<int> orArgumentList, string wherePrefix = null)
|
|
||||||
{
|
{
|
||||||
var objectList = new List<object>();
|
var objectList = new List<object>();
|
||||||
|
|
||||||
if (orArgumentList != null && orArgumentList.Any())
|
if (orValueList != null && orValueList.Any())
|
||||||
{
|
{
|
||||||
foreach (var value in orArgumentList)
|
foreach (var value in orValueList)
|
||||||
{
|
{
|
||||||
objectList.Add(value.ToString());
|
objectList.Add(value.ToString());
|
||||||
}
|
}
|
||||||
@@ -352,16 +321,15 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
/// Append an 'In' statement and parameter list to the class properties
|
/// Append an 'In' statement and parameter list to the class properties
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
||||||
/// <param name="orArgumentList">List of values to test in condition statement</param>
|
/// <param name="orValueList">List of values to test in condition statement</param>
|
||||||
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
public void In(string columnReference, IEnumerable<uint> orValueList, string wherePrefix = null)
|
||||||
public void In(string columnReference, IEnumerable<uint> orArgumentList, string wherePrefix = null)
|
|
||||||
{
|
{
|
||||||
var objectList = new List<object>();
|
var objectList = new List<object>();
|
||||||
|
|
||||||
if (orArgumentList != null && orArgumentList.Any())
|
if (orValueList != null && orValueList.Any())
|
||||||
{
|
{
|
||||||
foreach (var value in orArgumentList)
|
foreach (var value in orValueList)
|
||||||
{
|
{
|
||||||
objectList.Add(value.ToString());
|
objectList.Add(value.ToString());
|
||||||
}
|
}
|
||||||
@@ -370,14 +338,13 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
In(columnReference, objectList, wherePrefix);
|
In(columnReference, objectList, wherePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Deprecated. Use the new methods.")]
|
public void In(string columnReference, IEnumerable<DateTime> orValueList, string wherePrefix = null)
|
||||||
public void In(string columnReference, IEnumerable<DateTime> orArgumentList, string wherePrefix = null)
|
|
||||||
{
|
{
|
||||||
var objectList = new List<object>();
|
var objectList = new List<object>();
|
||||||
|
|
||||||
if (orArgumentList != null && orArgumentList.Any())
|
if (orValueList != null && orValueList.Any())
|
||||||
{
|
{
|
||||||
foreach(var value in orArgumentList)
|
foreach(var value in orValueList)
|
||||||
{
|
{
|
||||||
objectList.Add(value.ToString());
|
objectList.Add(value.ToString());
|
||||||
}
|
}
|
||||||
@@ -386,188 +353,17 @@ namespace bnhtrade.Core.Data.Database
|
|||||||
In(columnReference, objectList, wherePrefix);
|
In(columnReference, objectList, wherePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// new code below, going to change everything over to these methods, it returns the sql string instead of appending it to the class property
|
|
||||||
// which is more versatile and more intuitive to use
|
|
||||||
//
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Append an 'Like' statement (with AND between each like string) and parameter list to the class properties
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
|
||||||
/// <param name="arguments">List of phrases to test in condition statement</param>
|
|
||||||
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
|
||||||
public string LikeAndClause(string columnReference, IEnumerable<string> arguments, string clausePrefix = null, string clausePostfix = null)
|
|
||||||
{
|
|
||||||
return LikeClause(columnReference, arguments, true, clausePrefix, clausePostfix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Append an 'Like' statement (with OR between each like string) and parameter list to the class properties
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
|
|
||||||
/// <param name="phraseList">List of phrases to test in condition statement</param>
|
|
||||||
/// <param name="wherePrefix">Optional prefix that gets added to the sql string result</param>
|
|
||||||
public string LikeOrClause(string columnReference, IEnumerable<string> arguments, string clausePrefix = null, string clausePostfix = null)
|
|
||||||
{
|
|
||||||
return LikeClause(columnReference, arguments, false, clausePrefix, clausePostfix);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string LikeClause(string columnReference, IEnumerable<string> arguments, bool isAnd, string clausePrefix = null, string clausePostfix = null)
|
|
||||||
{
|
|
||||||
if (arguments == null || !arguments.Any())
|
|
||||||
{
|
|
||||||
throw new ArgumentException("The arguments cannot be null or empty.", nameof(arguments));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure no values are repeated
|
|
||||||
var distinctList = arguments.Distinct().ToList();
|
|
||||||
|
|
||||||
// clean the list
|
|
||||||
for (int i = 0; i < distinctList.Count; i++)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(distinctList[i]))
|
|
||||||
{
|
|
||||||
distinctList.RemoveAt(i);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check again
|
|
||||||
if (distinctList == null || !distinctList.Any())
|
|
||||||
{
|
|
||||||
throw new ArgumentException("The arguments must contain at least one valid value.", nameof(arguments));
|
|
||||||
}
|
|
||||||
|
|
||||||
string sqlWhere = Environment.NewLine + clausePrefix + " ";
|
|
||||||
|
|
||||||
|
|
||||||
int listCount = distinctList.Count();
|
|
||||||
for (int i = 0; i < listCount; i++)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
if (isAnd)
|
|
||||||
{
|
|
||||||
sqlWhere += " AND ";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sqlWhere += " OR ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlWhere += " ( " + columnReference + " LIKE '%' + ";
|
|
||||||
|
|
||||||
|
|
||||||
sqlWhere = sqlWhere + GetSetParameter(distinctList[i]) + " + '%' ) ";
|
|
||||||
}
|
|
||||||
return sqlWhere + clausePostfix;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string IsEqualToClause(string columnReference, object whereArgument, string clausePrefix = null, string clausePostfix = null)
|
|
||||||
{
|
|
||||||
return IsEqualSubClause(columnReference, whereArgument, "=", clausePrefix, clausePostfix);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string IsEqualToOrLessThanClause(string columnReference, object whereArgument, string clausePrefix = null, string clausePostfix = null)
|
|
||||||
{
|
|
||||||
return IsEqualSubClause(columnReference, whereArgument, "<=", clausePrefix, clausePostfix);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string IsEqualToOrGreaterThanClause(string columnReference, object whereArgument, string clausePrefix = null, string clausePostfix = null)
|
|
||||||
{
|
|
||||||
return IsEqualSubClause(columnReference, whereArgument, ">=", clausePrefix, clausePostfix);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string IsEqualSubClause(string columnReference, object whereArgument, string operatorString, string clausePrefix = null, string clausePostfix = null)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(columnReference))
|
|
||||||
{
|
|
||||||
throw new Exception(" WhereIsEqual* method requires a valid column reference.");
|
|
||||||
}
|
|
||||||
if (whereArgument == null)
|
|
||||||
{
|
|
||||||
throw new Exception(" WhereIsEqual* method requires a valid where argument.");
|
|
||||||
}
|
|
||||||
if (whereArgument is string && string.IsNullOrEmpty(whereArgument.ToString()))
|
|
||||||
{
|
|
||||||
throw new Exception(" WhereIsEqual* method requires a valid where argument.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// build the SQL WHERE clause and parameter list
|
|
||||||
string sqlWhere = Environment.NewLine + clausePrefix + " ( " + columnReference + " " + operatorString + " " + GetSetParameter(whereArgument) + " ) ";
|
|
||||||
|
|
||||||
return sqlWhere + clausePostfix;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a SQL WHERE clause with an IN condition for the specified column and a list of values and adds to the parameter list.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="columnReference">The name of the column to be used in the IN condition</param>
|
|
||||||
/// <param name="orArgumentList">A collection of values to include in the IN condition.</param>
|
|
||||||
/// <param name="lineReturn">A boolean value indicating whether to prefix the returned SQL clause with a line return</param>
|
|
||||||
/// <returns>A string representing the SQL WHERE clause with the specified column and values in the IN condition.</returns>
|
|
||||||
public string InClause<T>(string columnReference, IEnumerable<T> orArgumentList, string clausePrefix = null, string clausePostfix = null)
|
|
||||||
{
|
|
||||||
// new code, going to change everything over to this method, it returns the sql string instead of appending it to the class property
|
|
||||||
// which is more versatile and more intuitive to use
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(columnReference))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Column reference cannot be null or empty.", nameof(columnReference));
|
|
||||||
}
|
|
||||||
if (orArgumentList == null || !orArgumentList.Any())
|
|
||||||
{
|
|
||||||
throw new ArgumentException("The orArgumentList cannot be null or empty.", nameof(orArgumentList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure no values are repeated, null, or empty
|
|
||||||
var distinctList = orArgumentList
|
|
||||||
.Where(x =>
|
|
||||||
x is not null && // not null
|
|
||||||
(!(x.GetType().IsGenericType && x.GetType().GetGenericTypeDefinition() == typeof(Nullable<>)) // not a nullable type
|
|
||||||
|| x.GetType().GetProperty("HasValue")?.GetValue(x) as bool? == true) // or, if nullable, HasValue is true
|
|
||||||
&& (!(x is string s) || !string.IsNullOrEmpty(s)) // not an empty string
|
|
||||||
)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (!distinctList.Any())
|
|
||||||
{
|
|
||||||
throw new ArgumentException("The orArgumentList must contain at least one valid value.", nameof(orArgumentList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// build the SQL WHERE clause and parameter list
|
|
||||||
string sqlWhere = Environment.NewLine + clausePrefix + " " + columnReference + " IN ( ";
|
|
||||||
|
|
||||||
int listCount = distinctList.Count();
|
|
||||||
for (int i = 0; i < listCount; i++)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
sqlWhere += ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlWhere = sqlWhere + GetSetParameter(distinctList[i]);
|
|
||||||
}
|
|
||||||
sqlWhere += " ) ";
|
|
||||||
|
|
||||||
return sqlWhere + clausePostfix;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a string value to the ParameterList and returns '@parameterN' that is then appended to the SQL statement
|
/// Adds a string value to the ParameterList and returns '@parameterN' that is then appended to the SQL statement
|
||||||
/// i.e. @parameter1, @parameter2, etc.
|
/// i.e. @parameter1, @parameter2, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="argument">parameter string that is then appended to the SQL statement</param>
|
/// <param name="value">parameter string that is then appended to the SQL statement</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private string GetSetParameter(object argument)
|
private string GetSetParameter(string value)
|
||||||
{
|
{
|
||||||
parameterCount++;
|
parameterCount++;
|
||||||
string parameterString = "@parameter" + parameterCount;
|
string parameterString = "@parameter" + parameterCount;
|
||||||
ParameterList.Add(parameterString, argument);
|
ParameterList.Add(parameterString, value);
|
||||||
return parameterString;
|
return parameterString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ namespace bnhtrade.Core.Data.Database.Stock
|
|||||||
{
|
{
|
||||||
if (item.Value < 0 && dicStatusIsCreditOnly[item.Key] == false)
|
if (item.Value < 0 && dicStatusIsCreditOnly[item.Key] == false)
|
||||||
{
|
{
|
||||||
int quantity = new Data.Database.Stock.ReadStatusBalance().ReadStatusBalanceByStockId(stockId, item.Key);
|
int quantity = new Data.Database.Stock.ReadStatusBalance().ByStockId(stockId, item.Key);
|
||||||
|
|
||||||
if (quantity + item.Value < 0)
|
if (quantity + item.Value < 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,7 +13,76 @@ namespace bnhtrade.Core.Data.Database.Stock
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ReadStatusBalanceByStockId(int stockId, int statusId)
|
public int BySku(string sku, int statusId)
|
||||||
|
{
|
||||||
|
int statusBalance = new int();
|
||||||
|
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
SELECT SUM(tblStockJournalPost.Quantity) AS Balance
|
||||||
|
FROM tblStockJournal INNER JOIN
|
||||||
|
tblStockJournalPost ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID INNER JOIN
|
||||||
|
tblStock ON tblStockJournal.StockID = tblStock.StockID INNER JOIN
|
||||||
|
tblSku ON tblStock.SkuID = tblSku.skuSkuID
|
||||||
|
WHERE (tblStockJournalPost.StockStatusID = @statusId) AND (tblSku.skuSkuNumber = @sku)
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
// add parameters
|
||||||
|
cmd.Parameters.AddWithValue("@sku", sku);
|
||||||
|
cmd.Parameters.AddWithValue("@statusId", statusId);
|
||||||
|
|
||||||
|
// execute
|
||||||
|
object obj = cmd.ExecuteScalar();
|
||||||
|
if (obj == null || obj == DBNull.Value)
|
||||||
|
{
|
||||||
|
statusBalance = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
statusBalance = (int)obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return statusBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ByStockNumber(int stockNumber, int statusId)
|
||||||
|
{
|
||||||
|
int statusBalance = new int();
|
||||||
|
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
|
||||||
|
using (SqlCommand cmd = new SqlCommand(@"
|
||||||
|
SELECT SUM(tblStockJournalPost.Quantity) AS Balance
|
||||||
|
FROM tblStockJournal INNER JOIN
|
||||||
|
tblStockJournalPost ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID INNER JOIN
|
||||||
|
tblStock ON tblStockJournal.StockID = tblStock.StockID
|
||||||
|
WHERE (tblStockJournalPost.StockStatusID = @statusId) AND (tblStock.StockNumber = @stockNumber)
|
||||||
|
", conn))
|
||||||
|
{
|
||||||
|
// add parameters
|
||||||
|
cmd.Parameters.AddWithValue("@stockNumber", stockNumber);
|
||||||
|
cmd.Parameters.AddWithValue("@statusId", statusId);
|
||||||
|
|
||||||
|
// execute
|
||||||
|
object obj = cmd.ExecuteScalar();
|
||||||
|
if (obj == null || obj == DBNull.Value)
|
||||||
|
{
|
||||||
|
statusBalance = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
statusBalance = (int)obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return statusBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ByStockId(int stockId, int statusId)
|
||||||
{
|
{
|
||||||
int statusBalance = new int();
|
int statusBalance = new int();
|
||||||
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
|
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
|
||||||
@@ -56,7 +125,7 @@ namespace bnhtrade.Core.Data.Database.Stock
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="statusId">The stock status id</param>
|
/// <param name="statusId">The stock status id</param>
|
||||||
/// <returns>Dictionary of SKUs and the balance of each</returns>
|
/// <returns>Dictionary of SKUs and the balance of each</returns>
|
||||||
public Dictionary<string, int> ReadStatusBalanceByStatusId(int statusId)
|
public Dictionary<string, int> ByStatusId(int statusId)
|
||||||
{
|
{
|
||||||
var returnList = new Dictionary<string, int>();
|
var returnList = new Dictionary<string, int>();
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,10 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
|
|||||||
IExportInvoiceRepository ExportInvoiceRepository { get; }
|
IExportInvoiceRepository ExportInvoiceRepository { get; }
|
||||||
IAmazonSettlementRepository AmazonSettlementRepository { get; }
|
IAmazonSettlementRepository AmazonSettlementRepository { get; }
|
||||||
IInvoiceRepository InvoiceRepository { get; }
|
IInvoiceRepository InvoiceRepository { get; }
|
||||||
IPurchaseRepository PurchaseRepository { get; }
|
IJournalRepository JournalRepository { get; }
|
||||||
IAccountJournalRepository AccountJournalRepository { get; }
|
|
||||||
ISequenceGenerator SequenceGenerator { get; }
|
ISequenceGenerator SequenceGenerator { get; }
|
||||||
ISkuRepository SkuRepository { get; }
|
ISkuRepository SkuRepository { get; }
|
||||||
IStockRepository StockRepository { get; }
|
IStockRepository StockRepository { get; }
|
||||||
IStockJournalRepository StockJournalRepository { get; }
|
|
||||||
IStockStatusRepository StockStatusRepository { get; }
|
|
||||||
|
|
||||||
// Methods to manage the transaction
|
// Methods to manage the transaction
|
||||||
void Commit();
|
void Commit();
|
||||||
|
|||||||
@@ -19,18 +19,15 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
|
|||||||
|
|
||||||
// Private field for lazy loading, add here for each repository
|
// Private field for lazy loading, add here for each repository
|
||||||
private IAccountCodeRepository _accountCodeRepository;
|
private IAccountCodeRepository _accountCodeRepository;
|
||||||
private IAccountJournalRepository _accountJournalRepository;
|
|
||||||
private IAccountTaxRepository _accountTaxRepository;
|
private IAccountTaxRepository _accountTaxRepository;
|
||||||
private IAmazonSettlementRepository _amazonSettlementRepository;
|
private IAmazonSettlementRepository _amazonSettlementRepository;
|
||||||
private ICurrencyRepository _currencyRepository;
|
private ICurrencyRepository _currencyRepository;
|
||||||
private IExportInvoiceRepository _exportInvoiceRepository;
|
private IExportInvoiceRepository _exportInvoiceRepository;
|
||||||
private IInvoiceRepository _invoiceRepository;
|
private IInvoiceRepository _invoiceRepository;
|
||||||
private IPurchaseRepository _purchaseRepository;
|
private IJournalRepository _journalRepository;
|
||||||
private ISequenceGenerator _sequenceGenerator;
|
private ISequenceGenerator _sequenceGenerator;
|
||||||
private ISkuRepository _skuRepository;
|
private ISkuRepository _skuRepository;
|
||||||
private IStockRepository _stockRepository;
|
private IStockRepository _stockRepository;
|
||||||
private IStockJournalRepository _stockJournalRespository;
|
|
||||||
private IStockStatusRepository _stockStatusRepository;
|
|
||||||
|
|
||||||
internal UnitOfWork()
|
internal UnitOfWork()
|
||||||
{
|
{
|
||||||
@@ -51,18 +48,6 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAccountJournalRepository AccountJournalRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_accountJournalRepository == null)
|
|
||||||
{
|
|
||||||
_accountJournalRepository = new AccountJournalRepository(_connection, _transaction);
|
|
||||||
}
|
|
||||||
return _accountJournalRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IAccountTaxRepository AccountTaxRepository
|
public IAccountTaxRepository AccountTaxRepository
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -123,15 +108,15 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPurchaseRepository PurchaseRepository
|
public IJournalRepository JournalRepository
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_purchaseRepository == null)
|
if (_journalRepository == null)
|
||||||
{
|
{
|
||||||
_purchaseRepository = new PurchaseRepository(_connection, _transaction);
|
_journalRepository = new JournalRepository(_connection, _transaction);
|
||||||
}
|
}
|
||||||
return _purchaseRepository;
|
return _journalRepository;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,30 +156,6 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IStockJournalRepository StockJournalRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_stockJournalRespository == null)
|
|
||||||
{
|
|
||||||
_stockJournalRespository = new StockJournalRepository(_connection, _transaction);
|
|
||||||
}
|
|
||||||
return _stockJournalRespository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IStockStatusRepository StockStatusRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_stockStatusRepository == null)
|
|
||||||
{
|
|
||||||
_stockStatusRepository = new StockStatusRepository(_connection, _transaction);
|
|
||||||
}
|
|
||||||
return _stockStatusRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Commit()
|
public void Commit()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -13,16 +12,52 @@ namespace bnhtrade.Core.Logic.Account
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AccountCodeService(IUnitOfWork unitOfWork) : base(unitOfWork)
|
public Dictionary<int, Model.Account.Account> GetAll()
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Account.Account> GetAccountCode(List<int> accountIdList = null, List<int> accountCodeList = null)
|
|
||||||
{
|
{
|
||||||
return WithUnitOfWork(uow =>
|
return WithUnitOfWork(uow =>
|
||||||
{
|
{
|
||||||
return uow.AccountCodeRepository.ReadAccountCode(accountIdList, accountCodeList);
|
return uow.AccountCodeRepository.ReadAccountCode();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Model.Account.Account ByAccountCode(int accountCode)
|
||||||
|
{
|
||||||
|
var list = ByAccountCode(new List<int> { accountCode });
|
||||||
|
if (list.Any())
|
||||||
|
{
|
||||||
|
return list[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Model.Account.Account> ByAccountCode(List<int> accountCodeList)
|
||||||
|
{
|
||||||
|
return WithUnitOfWork(uow =>
|
||||||
|
{
|
||||||
|
return uow.AccountCodeRepository.ReadAccountCode(null, accountCodeList).Values.ToList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<int, Model.Account.Account> ConvertToDictionary(List<Model.Account.Account> accountCodeList)
|
||||||
|
{
|
||||||
|
var returnDict = new Dictionary<int, Model.Account.Account>();
|
||||||
|
|
||||||
|
if (accountCodeList == null)
|
||||||
|
{
|
||||||
|
return returnDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var accountCode in accountCodeList)
|
||||||
|
{
|
||||||
|
if (!returnDict.ContainsKey((int)accountCode.AccountCode))
|
||||||
|
{
|
||||||
|
returnDict.Add((int)accountCode.AccountCode, accountCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnDict;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,300 +0,0 @@
|
|||||||
using bnhtrade.Core.Data.Database;
|
|
||||||
using bnhtrade.Core.Data.Database.Repository.Implementation;
|
|
||||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
|
||||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data.Common;
|
|
||||||
using System.Data.SqlClient;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Transactions;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Logic.Account
|
|
||||||
{
|
|
||||||
public class AccountJournalService : UnitOfWorkBase
|
|
||||||
{
|
|
||||||
public AccountJournalService()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
internal AccountJournalService(IUnitOfWork unitOfWork) : base(unitOfWork)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public int JournalInsert(int journalTypeId, DateTime entryDate, string currencyCode,
|
|
||||||
decimal amount, int? debitAccountId = null, int? creditAccountId = null, bool lockEntry = false)
|
|
||||||
{
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
// insert header record
|
|
||||||
int journalId = uow.AccountJournalRepository.InsertJournalHeader(journalTypeId, entryDate, lockEntry);
|
|
||||||
|
|
||||||
// ensure their are no other entries (not sure why this is needed, but it was in the old code)
|
|
||||||
int count = uow.AccountJournalRepository.CountJournalPosts(journalId);
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
throw new Exception("Unable the insert journal posts, post already present AccountJournalID=" + journalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check defaults for debit and credit accounts
|
|
||||||
var result = uow.AccountJournalRepository.ReadJournalTypeDefaultDebitCredit(journalId);
|
|
||||||
int? defaultDebit = result.Item1;
|
|
||||||
int? defaultCredit = result.Item2;
|
|
||||||
|
|
||||||
if (defaultDebit == null)
|
|
||||||
{
|
|
||||||
if (debitAccountId == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Debit Account ID required, default not set for journal type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (debitAccountId == null)
|
|
||||||
{
|
|
||||||
debitAccountId = defaultDebit.Value;
|
|
||||||
}
|
|
||||||
else if (debitAccountId.Value != defaultDebit)
|
|
||||||
{
|
|
||||||
throw new Exception("Debit Account ID supplied does not match default set for journal type");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defaultCredit == null)
|
|
||||||
{
|
|
||||||
if (creditAccountId == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Credit Account ID required, default not set for journal type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (creditAccountId == null)
|
|
||||||
{
|
|
||||||
creditAccountId = defaultCredit.Value;
|
|
||||||
}
|
|
||||||
else if (creditAccountId.Value != defaultCredit)
|
|
||||||
{
|
|
||||||
throw new Exception("Credit Account ID supplied does not match default set for journal type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// currency conversion
|
|
||||||
if (currencyCode != "GBP")
|
|
||||||
{
|
|
||||||
amount = new Logic.Account.CurrencyService(uow).CurrencyConvertToGbp(currencyCode, amount, entryDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure decimal is rounded
|
|
||||||
amount = Math.Round(amount, 2);
|
|
||||||
|
|
||||||
// insert posts
|
|
||||||
int debitPostId = uow.AccountJournalRepository.InsertJournalPost(journalId, debitAccountId.Value, amount);
|
|
||||||
int creditPostId = uow.AccountJournalRepository.InsertJournalPost(journalId, creditAccountId.Value, amount * -1);
|
|
||||||
|
|
||||||
// need to add verification here to ensure the entry is correct
|
|
||||||
|
|
||||||
// finished
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
return journalId;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<int, Core.Model.Account.Journal> ReadJournal(List<int> journalIdList)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("done, but needs testing");
|
|
||||||
|
|
||||||
var returnDict = new Dictionary<int, Core.Model.Account.Journal>();
|
|
||||||
|
|
||||||
WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
var builderDict = uow.AccountJournalRepository.ReadJournalBuilder(journalIdList);
|
|
||||||
if (builderDict.Any())
|
|
||||||
{
|
|
||||||
// build list of journal types and accounts from the builderDict
|
|
||||||
var journalTypeIdList = new List<int>();
|
|
||||||
var accountIdList = new List<int>();
|
|
||||||
|
|
||||||
foreach (var journal in builderDict.Values)
|
|
||||||
{
|
|
||||||
journalTypeIdList.Add(journal.JournalTypeId);
|
|
||||||
foreach (var post in journal.JournalBuilderPosts)
|
|
||||||
{
|
|
||||||
accountIdList.Add(post.AccountId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
journalTypeIdList = journalTypeIdList.Distinct().ToList();
|
|
||||||
accountIdList = accountIdList.Distinct().ToList();
|
|
||||||
|
|
||||||
// get object dictionaries
|
|
||||||
var journalTypeDict = ReadJournalType(journalTypeIdList);
|
|
||||||
var accountDict = uow.AccountCodeRepository.ReadAccountCode(accountIdList);
|
|
||||||
|
|
||||||
// build final return dictionary
|
|
||||||
foreach (var item in builderDict)
|
|
||||||
{
|
|
||||||
var journal = item.Value.Build(journalTypeDict, accountDict);
|
|
||||||
returnDict.Add(journal.JournalId, journal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return returnDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DateTime ReadJournalEntryDate(int journalId)
|
|
||||||
{
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
return uow.AccountJournalRepository.ReadJournalEntryDate(journalId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Account.JournalType> ReadJournalType(List<int> journalTypeIdList)
|
|
||||||
{
|
|
||||||
var returnDict = new Dictionary<int, Model.Account.JournalType>();
|
|
||||||
|
|
||||||
WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
// get base info from db
|
|
||||||
var dbJournalTypeList = uow.AccountJournalRepository.ReadJournalType(journalTypeIdList);
|
|
||||||
|
|
||||||
// build list of account object to retrieve
|
|
||||||
var accountIdList = new List<int>();
|
|
||||||
foreach (var dbJournalType in dbJournalTypeList)
|
|
||||||
{
|
|
||||||
if (dbJournalType.Item3.HasValue)
|
|
||||||
{
|
|
||||||
accountIdList.Add(dbJournalType.Item3.Value);
|
|
||||||
}
|
|
||||||
if (dbJournalType.Item4.HasValue)
|
|
||||||
{
|
|
||||||
accountIdList.Add(dbJournalType.Item4.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
accountIdList = accountIdList.Distinct().ToList();
|
|
||||||
|
|
||||||
// retieve account objects from db
|
|
||||||
var accountDict = uow.AccountCodeRepository.ReadAccountCode(accountIdList);
|
|
||||||
|
|
||||||
// build the return dictionary
|
|
||||||
foreach (var dbJournalType in dbJournalTypeList)
|
|
||||||
{
|
|
||||||
var journalType = new Model.Account.JournalType(
|
|
||||||
dbJournalType.Item1, // JournalTypeId
|
|
||||||
dbJournalType.Item2, // Name
|
|
||||||
dbJournalType.Item3.HasValue ? accountDict[dbJournalType.Item3.Value] : null, // DebitAccount
|
|
||||||
dbJournalType.Item4.HasValue ? accountDict[dbJournalType.Item4.Value] : null // CreditAccount
|
|
||||||
);
|
|
||||||
returnDict.Add(journalType.JournalTypeId, journalType);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return returnDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes all posts associated with an entry and replaces the posts for a journal entry with two new posts
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="twoPostCheck">Raise exception if journal entry has more than two associated posts</param>
|
|
||||||
internal bool AccountJournalPostReplace(int accountJournalId, string currencyCode, decimal amountGbp, int debitAccountId = 0, int creditAccountId = 0, bool twoPostCheck = true)
|
|
||||||
{
|
|
||||||
if (amountGbp <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Amount must be greater than zero", nameof(amountGbp));
|
|
||||||
}
|
|
||||||
if ( amountGbp.Scale > 2)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Amount must have a maximum of two decimal places", nameof(amountGbp));
|
|
||||||
}
|
|
||||||
if (debitAccountId <= 0 || creditAccountId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Debit and Credit Account IDs must be greater than zero", nameof(debitAccountId));
|
|
||||||
}
|
|
||||||
|
|
||||||
WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
// check if the journal entry is locked
|
|
||||||
bool? isLocked = uow.AccountJournalRepository.IsJournalLocked(accountJournalId);
|
|
||||||
if (isLocked == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Journal entry does not exist for AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
else if (isLocked.Value)
|
|
||||||
{
|
|
||||||
throw new Exception("Cannot replace posts for locked journal entry AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrive journal entry date
|
|
||||||
DateTime entryDate = uow.AccountJournalRepository.ReadJournalEntryDate(accountJournalId);
|
|
||||||
|
|
||||||
// delete the original posts
|
|
||||||
var rowsDeleted = uow.AccountJournalRepository.DeleteJournalPostAll(accountJournalId);
|
|
||||||
if (rowsDeleted == 0)
|
|
||||||
{
|
|
||||||
throw new Exception("No posts found for AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
if (twoPostCheck && rowsDeleted > 2)
|
|
||||||
{
|
|
||||||
throw new Exception("More than two posts found for AccountJournalID=" + accountJournalId + ", cannot replace posts with two new posts.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//insert new posts
|
|
||||||
var rowsInserted = uow.AccountJournalRepository.InsertJournalPost(accountJournalId, debitAccountId, amountGbp);
|
|
||||||
rowsInserted += uow.AccountJournalRepository.InsertJournalPost(accountJournalId, creditAccountId, amountGbp * -1);
|
|
||||||
if (rowsInserted != 2)
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to insert two posts for AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update modified date on journal
|
|
||||||
if (uow.AccountJournalRepository.UpdateJournalEntryModifiedDate(accountJournalId) == false)
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to update LastModified date for AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Old code needs sorting
|
|
||||||
/// </summary>
|
|
||||||
public bool DeleteJournal(int accountJournalId)
|
|
||||||
{
|
|
||||||
WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
if (accountJournalId <= 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Account journal ID must be greater than zero", nameof(accountJournalId));
|
|
||||||
}
|
|
||||||
// check if the journal entry is locked
|
|
||||||
bool? isLocked = uow.AccountJournalRepository.IsJournalLocked(accountJournalId);
|
|
||||||
if (isLocked == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Journal entry does not exist for AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
else if (isLocked.Value)
|
|
||||||
{
|
|
||||||
throw new Exception("Cannot replace posts for locked journal entry AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete posts first
|
|
||||||
uow.AccountJournalRepository.DeleteJournalPostAll(accountJournalId);
|
|
||||||
|
|
||||||
// then delete header record
|
|
||||||
uow.AccountJournalRepository.DeleteJournalHeader(accountJournalId);
|
|
||||||
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Data.SqlClient;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Transactions;
|
||||||
|
|
||||||
|
namespace bnhtrade.Core.Logic.Account
|
||||||
|
{
|
||||||
|
public class Journal : UnitOfWorkBase
|
||||||
|
{
|
||||||
|
public int AccountJournalInsert(int journalTypeId, DateTime entryDate, string currencyCode,
|
||||||
|
decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false)
|
||||||
|
{
|
||||||
|
return new Data.Database.Account.CreateJournal().AccountJournalInsert(journalTypeId, entryDate, currencyCode,
|
||||||
|
amount, debitAccountId, creditAccountId, lockEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AccountJournalDelete(int accountJournalId)
|
||||||
|
{
|
||||||
|
return WithUnitOfWork(uow =>
|
||||||
|
{
|
||||||
|
bool result = uow.JournalRepository.DeleteJournal(accountJournalId);
|
||||||
|
CommitIfOwned(uow);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,570 +0,0 @@
|
|||||||
using Amazon.Runtime.Internal.Transform;
|
|
||||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
|
||||||
using bnhtrade.Core.Logic.Account;
|
|
||||||
using bnhtrade.Core.Model.Account;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using static System.Formats.Asn1.AsnWriter;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Logic.Inventory
|
|
||||||
{
|
|
||||||
public class StockJournalService : UnitOfWorkBase
|
|
||||||
{
|
|
||||||
public StockJournalService() { }
|
|
||||||
|
|
||||||
internal StockJournalService(IUnitOfWork unitOfWork) : base(unitOfWork) { }
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Stock.StockJournal> ReadStockJournal(List<int> stockJournalIds)
|
|
||||||
{
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
return ReadStockJournal(uow, false, stockJournalIds);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Dictionary<int, Model.Stock.StockJournal> ReadStockJournal(IUnitOfWork uow, bool lockJournalEntries, List<int> stockJournalIds)
|
|
||||||
{
|
|
||||||
if (stockJournalIds == null || stockJournalIds.Count == 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Stock journal IDs cannot be null or empty.", nameof(stockJournalIds));
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the stock journal entries from the repository
|
|
||||||
var builderList = uow.StockJournalRepository.ReadStockJournal(lockJournalEntries, stockJournalIds);
|
|
||||||
|
|
||||||
// get the stock status for the journal posts
|
|
||||||
var statusIds = new List<int>();
|
|
||||||
foreach (var journal in builderList.Values)
|
|
||||||
{
|
|
||||||
foreach (var post in journal.StockJournalBuilderPosts)
|
|
||||||
{
|
|
||||||
if (!statusIds.Contains(post.StatusId))
|
|
||||||
{
|
|
||||||
statusIds.Add(post.StatusId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var statusDict = new StockStatusService(uow).GetStatus(statusIds);
|
|
||||||
|
|
||||||
// get the stock journal types for the journal entries
|
|
||||||
var journalTypeIds = new List<int>();
|
|
||||||
foreach (var journal in builderList.Values)
|
|
||||||
{
|
|
||||||
if (!journalTypeIds.Contains(journal.StockJournalTypeId))
|
|
||||||
{
|
|
||||||
journalTypeIds.Add(journal.StockJournalTypeId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var journalTypeDict = ReadStockJournalType(uow, journalTypeIds);
|
|
||||||
|
|
||||||
// build the stock journal objects and return them in a dictionary
|
|
||||||
var returnDict = new Dictionary<int, Model.Stock.StockJournal>();
|
|
||||||
foreach (var journal in builderList.Values)
|
|
||||||
{
|
|
||||||
returnDict.Add(journal.StockJournalId, journal.Build(journalTypeDict, statusDict));
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Stock.StockJournalType> ReadStockJournalType(List<int> stockJournalTypeIds = null)
|
|
||||||
{
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
return ReadStockJournalType(uow, stockJournalTypeIds);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<int, Model.Stock.StockJournalType> ReadStockJournalType(IUnitOfWork uow, List<int> stockJournalTypeIds = null)
|
|
||||||
{
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
// get the stock journal types from the repository
|
|
||||||
var tupleList = uow.StockJournalRepository.ReadStockJournalType(stockJournalTypeIds);
|
|
||||||
|
|
||||||
// get the accounts for the stock journal types
|
|
||||||
var statusIds = new List<int>();
|
|
||||||
foreach (var type in tupleList.Values)
|
|
||||||
{
|
|
||||||
if (type.stockStatusIdDebit.HasValue)
|
|
||||||
{
|
|
||||||
statusIds.Add(type.stockStatusIdDebit.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.stockStatusIdCredit.HasValue)
|
|
||||||
{
|
|
||||||
statusIds.Add(type.stockStatusIdCredit.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
statusIds = statusIds.Distinct().ToList();
|
|
||||||
var statusDict = new StockStatusService(uow).GetStatus(statusIds);
|
|
||||||
|
|
||||||
// build the stock journal type objects and return them in a dictionary
|
|
||||||
var returnDict = new Dictionary<int, Model.Stock.StockJournalType>();
|
|
||||||
foreach (var type in tupleList.Values)
|
|
||||||
{
|
|
||||||
var debitStatus = type.stockStatusIdDebit.HasValue ? statusDict[type.stockStatusIdDebit.Value] : null;
|
|
||||||
var creditStatus = type.stockStatusIdCredit.HasValue ? statusDict[type.stockStatusIdCredit.Value] : null;
|
|
||||||
|
|
||||||
var stockJournalType = new Model.Stock.StockJournalType(
|
|
||||||
type.id,
|
|
||||||
type.title,
|
|
||||||
debitStatus,
|
|
||||||
creditStatus
|
|
||||||
);
|
|
||||||
|
|
||||||
returnDict.Add(stockJournalType.StockJournalTypeID, stockJournalType);
|
|
||||||
}
|
|
||||||
return returnDict;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public int StockJournalInsert(int journalTypeId, int stockId, List<(int statusId, int quantity)> journalPosts,
|
|
||||||
DateTime entryDate, bool isNewStock = false)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* TODO: currently the consistancy check checks the journal after the entry has been inserted to the db, if the check fails
|
|
||||||
* the transaction scope is disposed, and the ne journal entries roll back. However, if this is done within a higher
|
|
||||||
* level transaction scope, this nested dispose() also rolls back the all transacopes scopes it is a child of.
|
|
||||||
*
|
|
||||||
* Therefore, a consistancy check needs to be simulated in code to negate the need to rollback/dispose of a db transaction.
|
|
||||||
* This would also have some slight performance benefits.
|
|
||||||
*
|
|
||||||
* Once you've done this, fix the SkuTransactionReconcile class: Currently it's transactionscope only covers updates.
|
|
||||||
* Need to set the scope to cover the intial table read (to lock the records). The issue above restricts this.
|
|
||||||
*
|
|
||||||
* Future me here, refactored the code to use a UnitOfWork pattern, wil need to check that this is still the case.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// balance and status IsCredit checks made by post insert function
|
|
||||||
|
|
||||||
//consitancy check is required?
|
|
||||||
bool consistencyRequired = true;
|
|
||||||
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
// get date of most recent debit for status' that I will be crediting
|
|
||||||
if (isNewStock == false)
|
|
||||||
{
|
|
||||||
var debitStatusIds = new List<int>();
|
|
||||||
foreach (var post in journalPosts)
|
|
||||||
{
|
|
||||||
if (post.quantity > 0)
|
|
||||||
{
|
|
||||||
debitStatusIds.Add(post.statusId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var mostRecentDebitDate = uow.StockJournalRepository.ReadMostRecentEntryDateForStatusDebit(stockId, debitStatusIds);
|
|
||||||
if (mostRecentDebitDate.HasValue && mostRecentDebitDate >= entryDate)
|
|
||||||
{
|
|
||||||
consistencyRequired = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
consistencyRequired = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create journal entry
|
|
||||||
int stockJournalId = uow.StockJournalRepository.InsertStockJournalHeader(stockId, journalTypeId, entryDate, isNewStock);
|
|
||||||
|
|
||||||
// insert journal posts into database
|
|
||||||
//new Data.Database.Stock
|
|
||||||
var insertCount = StockJournalPostInsert(uow, stockId, stockJournalId, journalPosts, isNewStock);
|
|
||||||
|
|
||||||
// consistency check
|
|
||||||
bool consistencyResult = true;
|
|
||||||
if (consistencyRequired)
|
|
||||||
{
|
|
||||||
consistencyResult = false;
|
|
||||||
// build list of effected status'
|
|
||||||
var statusIdEffected = new List<int>();
|
|
||||||
foreach (var item in journalPosts)
|
|
||||||
{
|
|
||||||
if (item.quantity < 0)
|
|
||||||
{
|
|
||||||
statusIdEffected.Add(item.statusId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// run check
|
|
||||||
consistencyResult = WIP_StockJournalConsistencyCheck(uow, stockId, statusIdEffected);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (consistencyResult)
|
|
||||||
{
|
|
||||||
// commit
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
return stockJournalId;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Unable to insert stock journal entry, consistancy check failed.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private int StockJournalPostInsert(IUnitOfWork uow, int stockId, int stockJournalId, List<(int statusId, int quantity)> journalPosts, bool isNewStock = false)
|
|
||||||
{
|
|
||||||
//checks
|
|
||||||
if (journalPosts.Count > 2)
|
|
||||||
{
|
|
||||||
// I have purposely made the code to accept split transaction incase of future requirements, however for now, it's simpler this way
|
|
||||||
throw new Exception("Stock journal does not currently support split transactions (greater than two posts)." + journalPosts.Count + " number posts attempted.");
|
|
||||||
}
|
|
||||||
else if (journalPosts.Count < 2)
|
|
||||||
{
|
|
||||||
// list not long enough
|
|
||||||
throw new Exception("Stock journal entry requires minium of two posts, entry of " + journalPosts.Count + " number posts attempted.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (journalPosts.Sum(item => item.quantity) != 0)
|
|
||||||
{
|
|
||||||
// credits and debits do not match
|
|
||||||
throw new Exception("Sum of credits and debits do not resolve to zero.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// group credits and debits by status
|
|
||||||
var dicStatusQty = new Dictionary<int, int>();
|
|
||||||
foreach (var post in journalPosts)
|
|
||||||
{
|
|
||||||
if (dicStatusQty.ContainsKey(post.statusId) == false)
|
|
||||||
{
|
|
||||||
dicStatusQty.Add(post.statusId, post.quantity);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dicStatusQty[post.statusId] = dicStatusQty[post.statusId] + post.quantity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get isCreditOnly for each status
|
|
||||||
var statusDict = new StockStatusService(uow).GetStatus(dicStatusQty.Keys.ToList());
|
|
||||||
var dicStatusIsCreditOnly = new Dictionary<int, bool>();
|
|
||||||
foreach (var status in statusDict.Values.ToList())
|
|
||||||
{
|
|
||||||
dicStatusIsCreditOnly.Add(status.StatusId, status.IsCreditOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check there is only one IsCreditOnly in list and it is allowed in this instance
|
|
||||||
int isCreditOnlyCount = 0;
|
|
||||||
foreach (var item in dicStatusIsCreditOnly)
|
|
||||||
{
|
|
||||||
if (item.Value)
|
|
||||||
{
|
|
||||||
isCreditOnlyCount = isCreditOnlyCount + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isNewStock == false && isCreditOnlyCount > 0)
|
|
||||||
{
|
|
||||||
throw new Exception("Attempted credit or debit to 'Is Credit Only' status not allowed, in this instance.");
|
|
||||||
}
|
|
||||||
if (isNewStock == true && isCreditOnlyCount != 1)
|
|
||||||
{
|
|
||||||
throw new Exception("StockID=" + stockId + ", each stock line must have only have one IsCreditOnly=True status assigned to it.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure debit (or zero credit) isn't made to credit only status
|
|
||||||
// need to do this check via original post list (i.e. journalPosts)
|
|
||||||
foreach (var post in journalPosts)
|
|
||||||
{
|
|
||||||
// debit check
|
|
||||||
if (post.quantity >= 0)
|
|
||||||
{
|
|
||||||
if (dicStatusIsCreditOnly[post.statusId] == true)
|
|
||||||
{
|
|
||||||
throw new Exception("Cannot make debit, or zero quantity credit, to credit only status. StatusID=" + post.statusId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// balance check for any credits (that are not isCreditOnly=true)
|
|
||||||
foreach (var item in dicStatusQty)
|
|
||||||
{
|
|
||||||
if (item.Value < 0 && dicStatusIsCreditOnly[item.Key] == false)
|
|
||||||
{
|
|
||||||
int quantity = new Data.Database.Stock.ReadStatusBalance().ReadStatusBalanceByStockId(stockId, item.Key);
|
|
||||||
|
|
||||||
if (quantity + item.Value < 0)
|
|
||||||
{
|
|
||||||
throw new Exception("Credit status balance check failed. Available balance " + quantity + ", attempted credit " + item.Value * -1 + ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get this far...
|
|
||||||
// insert journal posts into database
|
|
||||||
var postIdList = new List<int>();
|
|
||||||
foreach (var post in journalPosts)
|
|
||||||
{
|
|
||||||
postIdList.Add(uow.StockJournalRepository.InsertStockJournalPost(stockJournalId, post.statusId, post.quantity));
|
|
||||||
}
|
|
||||||
return postIdList.Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool StockJournalDelete(int stockJournalId)
|
|
||||||
{
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
var result = StockJournalDelete(uow, stockJournalId);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// To be used internally (private). Deletes a stock journal entry and performs a consistency check, does not roll back transaction on fail.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>consistantcy check result, true=good, false=bad</returns>
|
|
||||||
private bool StockJournalDelete(IUnitOfWork uow, int stockJournalId)
|
|
||||||
{
|
|
||||||
// get journal entry
|
|
||||||
var stockJournalDict = uow.StockJournalRepository.ReadStockJournal(true, new List<int> { stockJournalId });
|
|
||||||
if (stockJournalDict.Count == 0)
|
|
||||||
{
|
|
||||||
throw new Exception("StockJournalID=" + stockJournalId + " does not exist!");
|
|
||||||
}
|
|
||||||
var stockJournal = stockJournalDict[stockJournalId];
|
|
||||||
|
|
||||||
// build list of debits to check
|
|
||||||
var debitStatusIds = new List<int>();
|
|
||||||
foreach (var post in stockJournal.StockJournalBuilderPosts)
|
|
||||||
{
|
|
||||||
if (post.IsDebit)
|
|
||||||
{
|
|
||||||
debitStatusIds.Add(post.StatusId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get all journal entries for stockId and debit status combination where entryDate >= stockJournal.EntryDate
|
|
||||||
var journalList = uow.StockJournalRepository.ReadStockJournal(
|
|
||||||
true, null, new List<int> { stockJournal.StockId }, null, stockJournal.EntryDate, null, debitStatusIds
|
|
||||||
);
|
|
||||||
|
|
||||||
// check no credits for stockId & debit status combination have been made since delete entry
|
|
||||||
bool consistancyCheckRequired = false;
|
|
||||||
foreach (var item in journalList.Values)
|
|
||||||
{
|
|
||||||
foreach (var post in item.StockJournalBuilderPosts)
|
|
||||||
{
|
|
||||||
if (post.Quantity < 0 && debitStatusIds.Contains(post.StatusId))
|
|
||||||
{
|
|
||||||
consistancyCheckRequired = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make the delete
|
|
||||||
uow.StockJournalRepository.StockJournalDelete(stockJournalId);
|
|
||||||
|
|
||||||
// consistanct check
|
|
||||||
bool consistencyResult = true;
|
|
||||||
if (consistancyCheckRequired)
|
|
||||||
{
|
|
||||||
// run check
|
|
||||||
consistencyResult = WIP_StockJournalConsistencyCheck(uow, stockJournal.StockId, debitStatusIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (consistencyResult)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// can be used before commiting an sql insert, update or delete to the stock journal to ensure a status does not fall below 0
|
|
||||||
// (unless the status is enabled to do so)
|
|
||||||
// set empty list or statusIdEffected to null to check entier stock entries for consistency
|
|
||||||
internal bool WIP_StockJournalConsistencyCheck(int stockId, List<int> statusIdsEffected = null)
|
|
||||||
{
|
|
||||||
if (statusIdsEffected == null)
|
|
||||||
{
|
|
||||||
statusIdsEffected = new List<int>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no list supplied, build list of all used status' for stockId
|
|
||||||
if (statusIdsEffected.Count == 0)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT
|
|
||||||
tblStockJournalPost.StockStatusID
|
|
||||||
FROM
|
|
||||||
tblStockJournal
|
|
||||||
INNER JOIN tblStockJournalPost
|
|
||||||
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
||||||
WHERE
|
|
||||||
tblStockJournal.StockID=@stockId
|
|
||||||
GROUP BY
|
|
||||||
tblStockJournalPost.StockStatusID;";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
|
|
||||||
using (var reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
if (reader.HasRows)
|
|
||||||
{
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
statusIdsEffected.Add(reader.GetInt32(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("No stock journal entries exist for StockID=" + stockId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// build the sql string to build creditCreate bool
|
|
||||||
var dicStatusCreditOnly = new Dictionary<int, bool>();
|
|
||||||
string sqlString = @"
|
|
||||||
SELECT
|
|
||||||
tblStockStatus.StockStatusID, tblStockStatus.IsCreditOnly
|
|
||||||
FROM
|
|
||||||
tblStockStatus ";
|
|
||||||
|
|
||||||
for (var i = 0; i < statusIdsEffected.Count; i++)
|
|
||||||
{
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
sqlString = sqlString + " WHERE tblStockStatus.StockStatusID=" + statusIdsEffected[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sqlString = sqlString + " OR tblStockStatus.StockStatusID=" + statusIdsEffected[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (i == (statusIdEffected.Count - 1))
|
|
||||||
//{
|
|
||||||
// sqlString = sqlString + ";";
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
sqlString = sqlString + " GROUP BY tblStockStatus.StockStatusID, tblStockStatus.IsCreditOnly;";
|
|
||||||
|
|
||||||
// run query & build dictionaries
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = sqlString;
|
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
|
|
||||||
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
if (reader.Read())
|
|
||||||
{
|
|
||||||
dicStatusCreditOnly.Add(reader.GetInt32(0), reader.GetBoolean(1));
|
|
||||||
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
dicStatusCreditOnly.Add(reader.GetInt32(0), reader.GetBoolean(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Error, no journal entries found for StockID=" + stockId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check integrity of supplied statusIds
|
|
||||||
foreach (int statusId in statusIdsEffected)
|
|
||||||
{
|
|
||||||
if (!dicStatusCreditOnly.ContainsKey(statusId))
|
|
||||||
{
|
|
||||||
throw new Exception("Supplied StatusId (" + statusId + ") doesn't exist for StockId=" + stockId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop through each statudId and check integrity, if createdEnabled=false
|
|
||||||
foreach (int statudId in statusIdsEffected)
|
|
||||||
{
|
|
||||||
if (dicStatusCreditOnly[statudId] == false)
|
|
||||||
{
|
|
||||||
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
||||||
{
|
|
||||||
cmd.Transaction = _transaction as SqlTransaction;
|
|
||||||
cmd.CommandText = @"
|
|
||||||
SELECT
|
|
||||||
tblStockJournal.EntryDate, tblStockJournalPost.Quantity
|
|
||||||
FROM
|
|
||||||
tblStockJournal
|
|
||||||
INNER JOIN tblStockJournalPost
|
|
||||||
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
||||||
WHERE
|
|
||||||
tblStockJournal.StockID=@stockId
|
|
||||||
AND tblStockJournalPost.StockStatusID=@statudId
|
|
||||||
ORDER BY
|
|
||||||
tblStockJournal.EntryDate;";
|
|
||||||
|
|
||||||
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
||||||
cmd.Parameters.AddWithValue("@statudId", statudId);
|
|
||||||
|
|
||||||
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
||||||
{
|
|
||||||
// read first line into variables
|
|
||||||
reader.Read();
|
|
||||||
int quantity = reader.GetInt32(1);
|
|
||||||
DateTime entryDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
// compare to next values
|
|
||||||
if (reader.Read())
|
|
||||||
{
|
|
||||||
DateTime nextEntryDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc);
|
|
||||||
// don't check quantites for transactions on same date
|
|
||||||
if (entryDate == nextEntryDate)
|
|
||||||
{
|
|
||||||
entryDate = nextEntryDate;
|
|
||||||
quantity = quantity + reader.GetInt32(1);
|
|
||||||
}
|
|
||||||
// check if dates are different
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (quantity < 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entryDate = nextEntryDate;
|
|
||||||
quantity = quantity + reader.GetInt32(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// end if no records, check quantity
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (quantity < 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get this far, all good
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
|
||||||
using bnhtrade.Core.Logic.Account;
|
|
||||||
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) { }
|
|
||||||
|
|
||||||
public int WIP_StockInsertPurchase(int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId)
|
|
||||||
{
|
|
||||||
DateTime stockJournalEntryDate;
|
|
||||||
int stockJournalTypeId = 1;
|
|
||||||
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
stockJournalEntryDate = new AccountJournalService(uow).ReadJournalEntryDate(accountJournalId);
|
|
||||||
int result = WIP_StockInsertSub(
|
|
||||||
uow, productId, conditionId, accountTaxCodeId, accountJournalId, stockJournalTypeId, stockJournalEntryDate, quantity, statusDebitId);
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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.AccountJournalService(uow).JournalInsert(accountJournalType, entryDate, currencyCode, amount);
|
|
||||||
|
|
||||||
// make the stock insert
|
|
||||||
int stockId = WIP_StockInsertSub(uow, productId, conditionId, accountTaxCodeId,
|
|
||||||
accountJournalId, stockJournalType, entryDate, quantity, debitStatusId);
|
|
||||||
|
|
||||||
return stockId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int WIP_StockInsertSub(IUnitOfWork uow, 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 = uow.StockRepository.CountStockTableRecords(new List<int> { accountJournalId });
|
|
||||||
|
|
||||||
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
|
|
||||||
bool isIt = uow.AccountJournalRepository.IsJournalDebitAssetType(accountJournalId);
|
|
||||||
if (!isIt)
|
|
||||||
{
|
|
||||||
throw new Exception("Supplied AccountJournal entry must debit an 'Asset' account type.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// get statusCreditId for stock journal type
|
|
||||||
int? statusCreditId = uow.StockJournalRepository.ReadTypeIdStatusCreditId(stockJournalTypeId);
|
|
||||||
|
|
||||||
if (statusCreditId == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Default credit status not set for StockJournalTypeID=" + stockJournalTypeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get/set an skuId
|
|
||||||
int skuId = new Logic.Inventory.SkuService(uow).GetSkuId(productId, conditionId, accountTaxCodeId, true);
|
|
||||||
|
|
||||||
// add the entry to the stock table (minus stockJournalId)
|
|
||||||
int stockId = uow.StockRepository.InsertNewStock(skuId, accountJournalId);
|
|
||||||
|
|
||||||
// insert stock journal entry
|
|
||||||
var journalPosts = new List<(int statusId, int quantity)>();
|
|
||||||
journalPosts.Add((statusDebitId, quantity));
|
|
||||||
journalPosts.Add((statusCreditId.Value, (quantity * -1)));
|
|
||||||
int stockJournalId = new StockJournalService(uow).StockJournalInsert(stockJournalTypeId, stockId, journalPosts, stockJournalEntryDate, true);
|
|
||||||
|
|
||||||
// update the stock table
|
|
||||||
count = uow.StockRepository.UpdateStockJournalId(stockId, stockJournalId);
|
|
||||||
if (count < 1)
|
|
||||||
{
|
|
||||||
throw new Exception("New stock insert cancelled, failed to update StockJournalID");
|
|
||||||
}
|
|
||||||
|
|
||||||
return stockId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WIP_StockDeletePurchase(int 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)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
new StockJournalService(uow).StockJournalDelete(stockJournalId);
|
|
||||||
|
|
||||||
// delete stock table entry
|
|
||||||
count = uow.StockRepository.DeleteStock(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
|
|
||||||
new AccountJournalService(uow).DeleteJournal(accountJournalId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Logic.Inventory
|
|
||||||
{
|
|
||||||
public class StockStatusService : UnitOfWorkBase
|
|
||||||
{
|
|
||||||
public StockStatusService() : base() { }
|
|
||||||
|
|
||||||
internal StockStatusService(IUnitOfWork unitOfWork) : base(unitOfWork) { }
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Stock.Status> GetStatus(List<int> statusIds = null, List<int> statusTypeIds = null)
|
|
||||||
{
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
var builderList = uow.StockStatusRepository.ReadStatus(statusIds, statusTypeIds).Values.ToList();
|
|
||||||
|
|
||||||
var satusTypeIdList = new List<int>();
|
|
||||||
foreach (var status in builderList)
|
|
||||||
{
|
|
||||||
satusTypeIdList.Add(status.StatusTypeId);
|
|
||||||
}
|
|
||||||
satusTypeIdList = satusTypeIdList.Distinct().ToList();
|
|
||||||
var statusTypeDict = GetStatusType(uow, satusTypeIdList);
|
|
||||||
|
|
||||||
var retrunDict = new Dictionary<int, Model.Stock.Status>();
|
|
||||||
foreach (var status in builderList)
|
|
||||||
{
|
|
||||||
retrunDict.Add(status.StatusId, status.Build(statusTypeDict));
|
|
||||||
}
|
|
||||||
return retrunDict;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<int, Model.Stock.StatusType> GetStatusType(IUnitOfWork uow, List<int> statusTypeIds = null)
|
|
||||||
{
|
|
||||||
// get the status types from the repository
|
|
||||||
var typeBuilderList = uow.StockStatusRepository.ReadStatusType(statusTypeIds);
|
|
||||||
|
|
||||||
// get the accounts for the status types
|
|
||||||
var accountIds = new List<int>();
|
|
||||||
foreach (var type in typeBuilderList.Values)
|
|
||||||
{
|
|
||||||
accountIds.Add(type.AccountId);
|
|
||||||
}
|
|
||||||
accountIds = accountIds.Distinct().ToList();
|
|
||||||
var accountDict = uow.AccountCodeRepository.ReadAccountCode(accountIds);
|
|
||||||
|
|
||||||
// build the status type objects and return them in a dictionary
|
|
||||||
var returnDict = new Dictionary<int, Model.Stock.StatusType>();
|
|
||||||
foreach (var type in typeBuilderList.Values)
|
|
||||||
{
|
|
||||||
returnDict.Add(type.StockStatusTypeID, type.Build(accountDict));
|
|
||||||
}
|
|
||||||
return returnDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dictionary<int, Model.Stock.StatusType> GetStatusType(List<int> statusTypeIds = null)
|
|
||||||
{
|
|
||||||
return WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
return GetStatusType(uow, statusTypeIds);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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 WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(sku))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("SKU number is null, empty, or whitespace", nameof(sku));
|
|
||||||
}
|
|
||||||
|
|
||||||
return uow.StockJournalRepository.ReadStatusBalanceBySku(sku, statusId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
using bnhtrade.Core.Data.Database.Repository.Implementation;
|
|
||||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
|
||||||
using bnhtrade.Core.Logic.Account;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Transactions;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Logic.Purchase
|
|
||||||
{
|
|
||||||
public class PurchaseService : UnitOfWorkBase
|
|
||||||
{
|
|
||||||
private static int accountJournalTypeIdNet = 1;
|
|
||||||
private static int accountJournalTypeIdTax = 2;
|
|
||||||
private static int stockJournalTypeId = 1;
|
|
||||||
private static int creditAccountId = 59;
|
|
||||||
private static int creditStatusId = 13;
|
|
||||||
private static int defaultAccountId = 138;
|
|
||||||
|
|
||||||
public PurchaseService() : base() { }
|
|
||||||
|
|
||||||
internal PurchaseService(IUnitOfWork unitOfWork) : base(unitOfWork) { }
|
|
||||||
|
|
||||||
public void WIP_PurchaseLineTransactionNetInsert(int purchaseLineId, string currencyCode, decimal amountNet, DateTime entryDate, int? debitAccountId = null)
|
|
||||||
{
|
|
||||||
// default to 'Inventory, Receivable/Processing'
|
|
||||||
if (debitAccountId == null)
|
|
||||||
{
|
|
||||||
debitAccountId = defaultAccountId;
|
|
||||||
}
|
|
||||||
|
|
||||||
WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
int journalId = new AccountJournalService(uow).JournalInsert(accountJournalTypeIdNet, entryDate, currencyCode, amountNet, debitAccountId.Value);
|
|
||||||
uow.PurchaseRepository.InsertPurchaseLineTransaction(journalId, purchaseLineId);
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WIP_PurchaseLineTransactionNetUpdate(int accountJouranlId, string currencyCode, decimal amountNet, int debitAccountId)
|
|
||||||
{
|
|
||||||
WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
// stock accountId check
|
|
||||||
if (debitAccountId == 86)
|
|
||||||
{
|
|
||||||
int? stockId = uow.StockRepository.ReadStockIdByAccountJournalId(accountJouranlId);
|
|
||||||
|
|
||||||
if (stockId.HasValue == false)
|
|
||||||
{
|
|
||||||
throw new Exception("Add account journal entry to stock before attempting this operation.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make the update
|
|
||||||
new AccountJournalService(uow).AccountJournalPostReplace(accountJouranlId, currencyCode, amountNet, debitAccountId, creditAccountId);
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WIP_PurchaseLineTransactionDelete(int purchaseLineId, int accountJournalId)
|
|
||||||
{
|
|
||||||
WithUnitOfWork(uow =>
|
|
||||||
{
|
|
||||||
// check accountJournalId does not exist in stock table
|
|
||||||
int? stockId = uow.StockRepository.ReadStockIdByAccountJournalId(accountJournalId);
|
|
||||||
if (stockId.HasValue)
|
|
||||||
{
|
|
||||||
throw new Exception("Delete stock first before proceeding, AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete line in purchase line transaction table
|
|
||||||
int deleted = uow.PurchaseRepository.DeletePurchaseLineTransaction(accountJournalId);
|
|
||||||
|
|
||||||
if (deleted != 1)
|
|
||||||
{
|
|
||||||
throw new Exception("Operation cancelled, failed to delete entry in tblPurchaseLineTransaction WHERE AccountJournalID=" + accountJournalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete account journal entry
|
|
||||||
new AccountJournalService(uow).DeleteJournal(accountJournalId);
|
|
||||||
|
|
||||||
CommitIfOwned(uow);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-7
@@ -1,16 +1,11 @@
|
|||||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Transactions;
|
using System.Transactions;
|
||||||
|
|
||||||
namespace bnhtrade.Core.Logic.Inventory
|
namespace bnhtrade.Core.Logic.Sku
|
||||||
{
|
{
|
||||||
public class SkuService : UnitOfWorkBase
|
public class SkuService : UnitOfWorkBase
|
||||||
{
|
{
|
||||||
public SkuService() : base() { }
|
|
||||||
|
|
||||||
internal SkuService(IUnitOfWork unitOfWork) : base(unitOfWork) { }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for retriving an SKU ID by parameters. If no match, can create a new SKU if required.
|
/// Used for retriving an SKU ID by parameters. If no match, can create a new SKU if required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -12,9 +12,22 @@ namespace bnhtrade.Core.Logic.Stock
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
/// <summary>
|
||||||
/// Return the avaliable balance of a status, includes datetime that each stockNumber became avaiable.
|
/// Return the avaliable balance of a status, includes datetime that each stockNumber became avaiable.
|
||||||
/// Useful for checking availability before moving stock/sku retrospectivly
|
/// Useful for checking availability before moving stock/sku retrospectivly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="skuNumber">SKU number</param>
|
/// <param name="skuNumber">SKU number</param>
|
||||||
/// <param name="statusId">Status ID</param>
|
/// <param name="statusId">Status ID</param>
|
||||||
@@ -100,7 +113,7 @@ namespace bnhtrade.Core.Logic.Stock
|
|||||||
var sku = readSku.BySkuNumber(statusTransaction.SkuNumber);
|
var sku = readSku.BySkuNumber(statusTransaction.SkuNumber);
|
||||||
|
|
||||||
// get the status obj
|
// get the status obj
|
||||||
var status = new Logic.Inventory.StockStatusService(uow).GetStatus(new List<int> { statusTransaction.StockStatusId }).Values.First();
|
var status = uow.StockRepository.ReadStatus(new List<int> { statusTransaction.StockStatusId })[0];
|
||||||
|
|
||||||
return new Model.Stock.StatusBalance(status, sku, entryList);
|
return new Model.Stock.StatusBalance(status, sku, entryList);
|
||||||
}
|
}
|
||||||
@@ -118,7 +131,7 @@ namespace bnhtrade.Core.Logic.Stock
|
|||||||
/// <returns>Dictionary of SKUs and the repective balance of each</returns>
|
/// <returns>Dictionary of SKUs and the repective balance of each</returns>
|
||||||
public Dictionary<string, int> GetSkuQuantity(int statusId)
|
public Dictionary<string, int> GetSkuQuantity(int statusId)
|
||||||
{
|
{
|
||||||
return new Data.Database.Stock.ReadStatusBalance().ReadStatusBalanceByStatusId(statusId);
|
return new Data.Database.Stock.ReadStatusBalance().ByStatusId(statusId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,20 +45,6 @@ namespace bnhtrade.Core.Logic.Validate
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Validates that a stock number string is in the format 'STK#000000' (six digits).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stockNumber"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static bool StockNumber(string stockNumber)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(stockNumber))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check for exact match: STK# followed by 6 digits
|
|
||||||
return System.Text.RegularExpressions.Regex.IsMatch(stockNumber, @"^STK#\d{6}$");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks the datetime is not default and is utc
|
/// Checks the datetime is not default and is utc
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace bnhtrade.Core.Model.Account
|
|||||||
{
|
{
|
||||||
public Account(int id, int accountCode, string accountName, string description, string type, string basicType, int multiplier)
|
public Account(int id, int accountCode, string accountName, string description, string type, string basicType, int multiplier)
|
||||||
{
|
{
|
||||||
AccountId = id;
|
Id = id;
|
||||||
AccountCode = accountCode;
|
AccountCode = accountCode;
|
||||||
AccountName = accountName;
|
AccountName = accountName;
|
||||||
Description = description;
|
Description = description;
|
||||||
@@ -23,18 +23,18 @@ namespace bnhtrade.Core.Model.Account
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Database record id
|
/// Database record id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int AccountId { get; }
|
public int Id { get; private set; }
|
||||||
|
|
||||||
public int AccountCode { get; }
|
public int AccountCode { get; private set; }
|
||||||
|
|
||||||
public string AccountName { get; }
|
public string AccountName { get; private set; }
|
||||||
|
|
||||||
public string Description { get; }
|
public string Description { get; private set; }
|
||||||
|
|
||||||
public string Type { get; }
|
public string Type { get; private set; }
|
||||||
|
|
||||||
public string BasicType { get; }
|
public string BasicType { get; private set; }
|
||||||
|
|
||||||
public int Multiplier { get; }
|
public int Multiplier { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Model.Account
|
|
||||||
{
|
|
||||||
public class JournalBuilder
|
|
||||||
{
|
|
||||||
// Setters for each property
|
|
||||||
public int JournalId { get; set; }
|
|
||||||
public int JournalTypeId { get; set; }
|
|
||||||
public List<JournalPostBuilder> JournalBuilderPosts { get; set; }
|
|
||||||
public DateTime EntryDate { get; set; }
|
|
||||||
public DateTime PostDate { get; set; }
|
|
||||||
public DateTime LastModified { get; set; }
|
|
||||||
public bool IsLocked { get; set; }
|
|
||||||
|
|
||||||
public class JournalPostBuilder
|
|
||||||
{
|
|
||||||
public int AccountId { get; set; }
|
|
||||||
public int PostId { get; set; }
|
|
||||||
public decimal AmountGbp { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Journal Build(Dictionary<int, Model.Account.JournalType> journalTypeDict, Dictionary<int, Model.Account.Account> accountDict)
|
|
||||||
{
|
|
||||||
if (journalTypeDict == null || !journalTypeDict.ContainsKey(JournalTypeId))
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Journal type with ID {JournalTypeId} does not exist.");
|
|
||||||
}
|
|
||||||
if (JournalBuilderPosts == null || JournalBuilderPosts.Count == 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Journal posts cannot be null or empty.");
|
|
||||||
}
|
|
||||||
if (accountDict == null || accountDict.Any() == false)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Account dictionary cannot be null or empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
// build lines
|
|
||||||
var journalPosts = new List<Journal.Post>();
|
|
||||||
foreach (var post in JournalBuilderPosts)
|
|
||||||
{
|
|
||||||
if (!accountDict.ContainsKey(post.AccountId))
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Account with ID {post.AccountId} does not exist.");
|
|
||||||
}
|
|
||||||
journalPosts.Add(new Journal.Post(post.PostId, accountDict[post.AccountId], post.AmountGbp));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Journal(
|
|
||||||
JournalId
|
|
||||||
, journalTypeDict[JournalTypeId]
|
|
||||||
, journalPosts
|
|
||||||
, EntryDate
|
|
||||||
, PostDate
|
|
||||||
, LastModified
|
|
||||||
, IsLocked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,18 +16,24 @@ namespace bnhtrade.Core.Model.Account
|
|||||||
DefaultDebitAccount = defaultDebitAccount;
|
DefaultDebitAccount = defaultDebitAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int JournalTypeId { get; }
|
internal void AddDefaultAccounts(Model.Account.Account defaultCreditAccount = null, Model.Account.Account defaultDebitAccount = null)
|
||||||
|
{
|
||||||
|
DefaultCreditAccount = defaultCreditAccount;
|
||||||
|
DefaultDebitAccount = defaultDebitAccount;
|
||||||
|
}
|
||||||
|
|
||||||
public string Title { get; }
|
public int JournalTypeId { get ; private set; }
|
||||||
|
|
||||||
public Model.Account.Account DefaultDebitAccount { get; }
|
public string Title { get; private set; }
|
||||||
|
|
||||||
|
public Model.Account.Account DefaultDebitAccount { get; private set; }
|
||||||
|
|
||||||
public bool IsSetDefaultDebitAccount
|
public bool IsSetDefaultDebitAccount
|
||||||
{
|
{
|
||||||
get { return DefaultDebitAccount != null; }
|
get { return DefaultDebitAccount != null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Model.Account.Account DefaultCreditAccount { get; }
|
public Model.Account.Account DefaultCreditAccount { get; private set; }
|
||||||
|
|
||||||
public bool IsSetDefaultCreditAccount
|
public bool IsSetDefaultCreditAccount
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace bnhtrade.Core.Model.Stock
|
||||||
|
{
|
||||||
|
public class JournalEntry : IValidatableObject
|
||||||
|
{
|
||||||
|
public string TypeTitle { get; set; }
|
||||||
|
|
||||||
|
public int StockNumber { get; set; }
|
||||||
|
|
||||||
|
public DateTime EntryDate { get; set; }
|
||||||
|
|
||||||
|
public DateTime PostDate { get; set; }
|
||||||
|
|
||||||
|
public DateTime LastModified { get; set; }
|
||||||
|
|
||||||
|
public bool IsLocked { get; set; }
|
||||||
|
|
||||||
|
public List<JournalEntryPost> JournalPosts { get; set; } = new List<JournalEntryPost>();
|
||||||
|
|
||||||
|
public class JournalEntryPost
|
||||||
|
{
|
||||||
|
public int JournalPostId { get; set; }
|
||||||
|
|
||||||
|
public int StockStatusId { get; set; }
|
||||||
|
|
||||||
|
[Required()]
|
||||||
|
public string StockStatus { get; set; }
|
||||||
|
|
||||||
|
[Required()]
|
||||||
|
public int Quantity { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,32 +21,22 @@ namespace bnhtrade.Core.Model.Stock
|
|||||||
RecordCreated = recordCreated;
|
RecordCreated = recordCreated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int StatusId { get; }
|
public int StatusId { get; private set; }
|
||||||
|
|
||||||
public int? StatusCode { get; }
|
public int? StatusCode { get; private set; }
|
||||||
|
|
||||||
public bool StatusCodeIsSet
|
public string StatusTitle { get; private set; }
|
||||||
{
|
|
||||||
get { return StatusCode.HasValue; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public string StatusTitle { get; }
|
public Model.Stock.StatusType StatusType { get; private set; }
|
||||||
|
|
||||||
public Model.Stock.StatusType StatusType { get; }
|
public string Reference { get; private set; }
|
||||||
|
|
||||||
public string Reference { get; }
|
public int? ForeignKeyID { get; private set; }
|
||||||
|
|
||||||
public int? ForeignKeyID { get; }
|
public bool IsCreditOnly { get; private set; }
|
||||||
|
|
||||||
public bool ForeignKeyIDIsSet
|
public bool IsClosed { get; private set; }
|
||||||
{
|
|
||||||
get { return ForeignKeyID.HasValue; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsCreditOnly { get; }
|
public DateTime RecordCreated { get; private set; }
|
||||||
|
|
||||||
public bool IsClosed { get; }
|
|
||||||
|
|
||||||
public DateTime RecordCreated { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Model.Stock
|
|
||||||
{
|
|
||||||
internal class StatusBuilder
|
|
||||||
{
|
|
||||||
public int StatusId { get; set; }
|
|
||||||
|
|
||||||
public int? StatusCode { get; set; }
|
|
||||||
|
|
||||||
public string StatusTitle { get; set; }
|
|
||||||
|
|
||||||
public int StatusTypeId { get; set; }
|
|
||||||
|
|
||||||
public string Reference { get; set; }
|
|
||||||
|
|
||||||
public int? ForeignKeyID { get; set; }
|
|
||||||
|
|
||||||
public bool IsCreditOnly { get; set; }
|
|
||||||
|
|
||||||
public bool IsClosed { get; set; }
|
|
||||||
|
|
||||||
public DateTime RecordCreated { get; set; }
|
|
||||||
|
|
||||||
public Status Build(Dictionary<int, StatusType> statusTypeDict)
|
|
||||||
{
|
|
||||||
if (!statusTypeDict.ContainsKey(StatusTypeId))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Status type with ID {StatusTypeId} does not exist.");
|
|
||||||
}
|
|
||||||
return new Status(
|
|
||||||
StatusId,
|
|
||||||
StatusCode,
|
|
||||||
StatusTitle,
|
|
||||||
statusTypeDict[StatusTypeId],
|
|
||||||
Reference,
|
|
||||||
ForeignKeyID,
|
|
||||||
IsCreditOnly,
|
|
||||||
IsClosed,
|
|
||||||
RecordCreated
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,10 +17,10 @@ namespace bnhtrade.Core.Model.Stock
|
|||||||
ReferenceType = referenceType;
|
ReferenceType = referenceType;
|
||||||
Account = account;
|
Account = account;
|
||||||
}
|
}
|
||||||
public int StockStatusTypeID { get; }
|
public int StockStatusTypeID { get; private set; }
|
||||||
public string StatusTypeName { get; }
|
public string StatusTypeName { get; private set; }
|
||||||
public string ForeignKeyType { get; }
|
public string ForeignKeyType { get; private set; }
|
||||||
public string ReferenceType { get; }
|
public string ReferenceType { get; private set; }
|
||||||
public Model.Account.Account Account { get; }
|
public Model.Account.Account Account { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Model.Stock
|
|
||||||
{
|
|
||||||
internal class StatusTypeBuilder
|
|
||||||
{
|
|
||||||
public int StockStatusTypeID { get; set; }
|
|
||||||
public string StatusTypeName { get; set; }
|
|
||||||
public string ForeignKeyType { get; set; }
|
|
||||||
public string ReferenceType { get; set; }
|
|
||||||
public int AccountId { get; set; }
|
|
||||||
|
|
||||||
public StatusType Build(Dictionary<int, Model.Account.Account> accountDict)
|
|
||||||
{
|
|
||||||
if (!accountDict.ContainsKey(AccountId))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Account with ID {AccountId} does not exist.");
|
|
||||||
}
|
|
||||||
return new StatusType(
|
|
||||||
StockStatusTypeID,
|
|
||||||
StatusTypeName,
|
|
||||||
ForeignKeyType,
|
|
||||||
ReferenceType,
|
|
||||||
accountDict[AccountId]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,153 +0,0 @@
|
|||||||
using bnhtrade.Core.Logic.Validate;
|
|
||||||
using bnhtrade.Core.Model.Account;
|
|
||||||
using FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInboundv20240320;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Model.Stock
|
|
||||||
{
|
|
||||||
public class StockJournal : IValidatableObject
|
|
||||||
{
|
|
||||||
public StockJournal(int stockJournalId, StockJournalType stockJournalType, int stockId, string stockNumber, DateTime entryDate, DateTime postDate, DateTime lastModified, bool isLocked, List<StockJournalPost> journalPosts)
|
|
||||||
{
|
|
||||||
StockJournalId = stockJournalId;
|
|
||||||
StockJournalType = stockJournalType;
|
|
||||||
StockId = stockId;
|
|
||||||
StockNumber = stockNumber;
|
|
||||||
EntryDate = entryDate;
|
|
||||||
PostDate = postDate;
|
|
||||||
LastModified = lastModified;
|
|
||||||
IsLocked = isLocked;
|
|
||||||
StockJournalPosts = journalPosts ?? throw new ArgumentNullException(nameof(journalPosts), "Journal posts cannot be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[Required()]
|
|
||||||
[Range(1, int.MaxValue, ErrorMessage = "StockJournalId must be greater than 0.")]
|
|
||||||
public int StockJournalId { get; }
|
|
||||||
|
|
||||||
public StockJournalType StockJournalType { get; }
|
|
||||||
|
|
||||||
[Required()]
|
|
||||||
[Range(1, int.MaxValue, ErrorMessage = "StockId must be greater than 0.")]
|
|
||||||
public int StockId { get; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Stock number is required.")]
|
|
||||||
public string StockNumber { get; }
|
|
||||||
|
|
||||||
public DateTime EntryDate { get; }
|
|
||||||
|
|
||||||
public DateTime PostDate { get; }
|
|
||||||
|
|
||||||
public DateTime LastModified { get; }
|
|
||||||
|
|
||||||
public bool IsLocked { get; }
|
|
||||||
|
|
||||||
public List<StockJournalPost> StockJournalPosts { get; }
|
|
||||||
|
|
||||||
public class StockJournalPost : IValidatableObject
|
|
||||||
{
|
|
||||||
public StockJournalPost(int journalPostId, Status status, int quantity)
|
|
||||||
{
|
|
||||||
StockJournalPostId = journalPostId;
|
|
||||||
Status = status;
|
|
||||||
Quantity = quantity;
|
|
||||||
}
|
|
||||||
public int StockJournalPostId { get; }
|
|
||||||
|
|
||||||
[Required()]
|
|
||||||
public Status Status { get; }
|
|
||||||
|
|
||||||
[Required()]
|
|
||||||
public int Quantity { get; }
|
|
||||||
|
|
||||||
public bool IsCredit
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Quantity < 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (Quantity > 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Quantity cannot be zero for a journal post.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsDebit
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !IsCredit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
|
||||||
{
|
|
||||||
var validationResults = new List<ValidationResult>();
|
|
||||||
|
|
||||||
if (Quantity == 0)
|
|
||||||
{
|
|
||||||
validationResults.Add(new ValidationResult("Quantity cannot be zero for a journal post.", new[] { nameof(Quantity) }));
|
|
||||||
}
|
|
||||||
|
|
||||||
return validationResults;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
|
||||||
{
|
|
||||||
var validationResults = new List<ValidationResult>();
|
|
||||||
|
|
||||||
// dates are in UTC format
|
|
||||||
if (EntryDate.Kind != DateTimeKind.Utc || EntryDate == default(DateTime))
|
|
||||||
{
|
|
||||||
validationResults.Add(new ValidationResult("Entry Date must be in UTC format and not a default value.", new[] { nameof(EntryDate) }));
|
|
||||||
}
|
|
||||||
if (PostDate.Kind != DateTimeKind.Utc || PostDate == default(DateTime))
|
|
||||||
{
|
|
||||||
validationResults.Add(new ValidationResult("PostDate must be in UTC format and not a default value.", new[] { nameof(PostDate) }));
|
|
||||||
}
|
|
||||||
if (LastModified.Kind != DateTimeKind.Utc || LastModified == default(DateTime))
|
|
||||||
{
|
|
||||||
validationResults.Add(new ValidationResult("LastModified must be in UTC format and not a default value.", new[] { nameof(LastModified) }));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Format.StockNumber(StockNumber) == false)
|
|
||||||
{
|
|
||||||
validationResults.Add(new ValidationResult("StockNumber must be in the format 'STK#000000'.", new[] { nameof(StockNumber) }));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate each StockJournalPost using its own context and Validate method
|
|
||||||
int sum = 0;
|
|
||||||
for (int i = 0; i < StockJournalPosts.Count; i++)
|
|
||||||
{
|
|
||||||
sum += StockJournalPosts[i].Quantity;
|
|
||||||
|
|
||||||
var post = StockJournalPosts[i];
|
|
||||||
var postContext = new ValidationContext(post, validationContext, validationContext.Items);
|
|
||||||
foreach (var result in post.Validate(postContext))
|
|
||||||
{
|
|
||||||
// Prefix property name with the index for clarity
|
|
||||||
var memberNames = result.MemberNames.Select(name => $"StockJournalPosts[{i}].{name}");
|
|
||||||
validationResults.Add(new ValidationResult(result.ErrorMessage, memberNames));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sum != 0)
|
|
||||||
{
|
|
||||||
validationResults.Add(new ValidationResult("The sum of all journal posts must equal zero.", new[] { nameof(StockJournalPosts) }));
|
|
||||||
}
|
|
||||||
|
|
||||||
return validationResults;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using static bnhtrade.Core.Data.Database.Constants;
|
|
||||||
using static bnhtrade.Core.Model.Stock.StockJournal;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Model.Stock
|
|
||||||
{
|
|
||||||
internal class StockJournalBuilder
|
|
||||||
{
|
|
||||||
public int StockJournalId { get; set; }
|
|
||||||
|
|
||||||
public int StockJournalTypeId { get; set; }
|
|
||||||
|
|
||||||
public int StockId { get; set; }
|
|
||||||
|
|
||||||
public string StockNumber { get; set; }
|
|
||||||
|
|
||||||
public DateTime EntryDate { get; set; }
|
|
||||||
|
|
||||||
public DateTime PostDate { get; set; }
|
|
||||||
|
|
||||||
public DateTime LastModified { get; set; }
|
|
||||||
|
|
||||||
public bool IsLocked { get; set; }
|
|
||||||
|
|
||||||
public bool AccountIsProcessed { get; set; }
|
|
||||||
|
|
||||||
public List<StockJournalBuilderPost> StockJournalBuilderPosts { get; set; }
|
|
||||||
|
|
||||||
public class StockJournalBuilderPost
|
|
||||||
{
|
|
||||||
public int StockJournalPostId { get; set; }
|
|
||||||
|
|
||||||
public int StatusId { get; set; }
|
|
||||||
|
|
||||||
public int Quantity { get; set; }
|
|
||||||
|
|
||||||
public bool IsCredit
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Quantity < 0)
|
|
||||||
{
|
|
||||||
return true; // Negative quantity indicates a credit post
|
|
||||||
}
|
|
||||||
else if (Quantity > 0)
|
|
||||||
{
|
|
||||||
return false; // Positive quantity indicates a debit post
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Quantity cannot be zero for a stock journal post.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsDebit
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !IsCredit; // Debit is the opposite of credit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StockJournal Build(Dictionary<int, StockJournalType> stockJournalTypeDict, Dictionary<int, Status> stockStatusDict)
|
|
||||||
{
|
|
||||||
if (StockJournalBuilderPosts == null || !StockJournalBuilderPosts.Any())
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("At least one journal post is required.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var posts = new List<StockJournalPost>();
|
|
||||||
foreach (var builderPost in StockJournalBuilderPosts)
|
|
||||||
{
|
|
||||||
var post = new StockJournalPost(
|
|
||||||
builderPost.StockJournalPostId,
|
|
||||||
stockStatusDict[builderPost.StockJournalPostId],
|
|
||||||
builderPost.Quantity
|
|
||||||
);
|
|
||||||
posts.Add(post);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new StockJournal(
|
|
||||||
StockJournalId,
|
|
||||||
stockJournalTypeDict[StockJournalTypeId],
|
|
||||||
StockId,
|
|
||||||
StockNumber,
|
|
||||||
EntryDate,
|
|
||||||
PostDate,
|
|
||||||
LastModified,
|
|
||||||
IsLocked,
|
|
||||||
posts
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace bnhtrade.Core.Model.Stock
|
|
||||||
{
|
|
||||||
public class StockJournalType
|
|
||||||
{
|
|
||||||
public StockJournalType(int stockJournalTypeId, string stockJournalTypeTitle, Status defaultDebitStatus, Status defaultCreditStatus)
|
|
||||||
{
|
|
||||||
StockJournalTypeID = stockJournalTypeId;
|
|
||||||
StockJournalTypeTitle = stockJournalTypeTitle ?? throw new ArgumentNullException(nameof(stockJournalTypeTitle), "Stock journal type title cannot be null.");
|
|
||||||
DefaultDebitStatus = defaultDebitStatus;
|
|
||||||
DefaultCreditStatus = defaultCreditStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int StockJournalTypeID { get; }
|
|
||||||
|
|
||||||
public string StockJournalTypeTitle { get; }
|
|
||||||
|
|
||||||
public Status DefaultDebitStatus { get; }
|
|
||||||
|
|
||||||
public bool DefaultDebitStatusIsSet
|
|
||||||
{
|
|
||||||
get { return DefaultDebitStatus != null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Status DefaultCreditStatus { get; }
|
|
||||||
|
|
||||||
public bool DefaultCreditStatusIsSet
|
|
||||||
{
|
|
||||||
get { return DefaultCreditStatus != null; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1288
-2
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user