mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-03-20 06:57:15 +00:00
634 lines
25 KiB
C#
634 lines
25 KiB
C#
using bnhtrade.Core.Data.Database;
|
|
using bnhtrade.Core.Data.Database.Repository.Implementation;
|
|
using bnhtrade.Core.Data.Database.UnitOfWork;
|
|
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 = 0, int creditAccountId = 0, bool lockEntry = false)
|
|
{
|
|
return WithUnitOfWork(uow =>
|
|
{
|
|
// insert header record
|
|
int journalId = uow.AccountJournalRepository.AccountJournalInsert(journalTypeId, entryDate, lockEntry);
|
|
|
|
// insert post record
|
|
int defaultDebit;
|
|
int defaultCredit;
|
|
|
|
// 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();
|
|
}
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CommitIfOwned(uow);
|
|
return journalId;
|
|
});
|
|
}
|
|
|
|
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 AccountJournalRepository(_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;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Old code needs sorting
|
|
/// </summary>
|
|
public bool AccountJournalPostInsert(IUnitOfWork uow, 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;
|
|
}
|
|
|
|
}
|
|
|
|
public bool AccountJournalPostUpdate(int journalId, string currencyCode, decimal amount, int debitAccountId = 0, int creditAccountId = 0)
|
|
{
|
|
// retrive journal entry date
|
|
DateTime entryDate;
|
|
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
|
|
{
|
|
cmd.Transaction = _transaction as SqlTransaction;
|
|
cmd.CommandText = @"
|
|
SELECT
|
|
tblAccountJournal.EntryDate
|
|
FROM
|
|
tblAccountJournal
|
|
WHERE
|
|
(((tblAccountJournal.AccountJournalID)=@accountJournalId));";
|
|
|
|
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
|
|
|
|
entryDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc);
|
|
}
|
|
|
|
// delete the original posts
|
|
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", journalId);
|
|
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
|
|
//insert new posts
|
|
bool postResult = AccountJournalPostInsert(journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
|
|
|
|
// update modified date on journal
|
|
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", journalId);
|
|
cmd.Parameters.AddWithValue("@utcNow", DateTime.UtcNow);
|
|
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <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;
|
|
}
|
|
}
|
|
}
|