Bug fix in ExportSalesInvoice and converted more code over to repository and service pattern

This commit is contained in:
2025-07-07 15:22:21 +01:00
parent 5900a6e6e4
commit 5cd653d700
64 changed files with 2623 additions and 2517 deletions

View File

@@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
//using System.Data.SqlClient;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Account
{
public class CreateInvoiceLineItem : Connection
{
public CreateInvoiceLineItem()
{
}
public int CreateDefault(string itemCode)
{
using (var conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblAccountInvoiceLineItem ( ItemName, ItemCode )
OUTPUT INSERTED.AccountInvoiceLineItemID
VALUES ( @itemName, @itemCode )
", conn))
{
cmd.Parameters.AddWithValue("@itemName", itemCode);
cmd.Parameters.AddWithValue("@itemCode", itemCode);
object obj = cmd.ExecuteScalar();
if (obj == null || obj == DBNull.Value)
{
throw new Exception("Error inserting new defalt invoice line item into database");
}
return (int)obj;
}
}
}
}
}

View File

@@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace bnhtrade.Core.Data.Database.Account
{
internal class DeleteJournal : Connection
{
/// <summary>
/// Old code needs sorting
/// </summary>
public bool AccountJournalDelete(int accountJournalId)
{
// check if journal entry is locked
using (TransactionScope scope = new TransactionScope())
{
bool IsLocked = new Data.Database.Account.ReadJournal().EntryIsLocked(accountJournalId);
if (IsLocked == true)
{
return false;
}
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
// make the delete
using (SqlCommand cmd = new SqlCommand(@"
DELETE FROM tblAccountJournalPost
WHERE AccountJournalID=@accountJournalId;
", conn))
{
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 = new SqlCommand(@"
DELETE FROM tblAccountJournal
WHERE AccountJournalID=@accountJournalId;
", conn))
{
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
cmd.ExecuteNonQuery();
}
scope.Complete();
return true;
}
}
}
}
}

View File

@@ -1,126 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Account
{
public class ReadAccountCode : Connection
{
private Data.Database.SqlWhereBuilder sqlWhere = new SqlWhereBuilder();
public ReadAccountCode()
{
}
/// <summary>
/// Gets the full chart of accounts
/// </summary>
/// <returns>Dictionary where the database record id is the key</returns>
public Dictionary<uint, Model.Account.Account> All()
{
Innit();
var list = Execute(null, null);
var dictionary = new Dictionary<uint, Model.Account.Account>();
foreach (var item in list)
{
dictionary.Add(item.Value.Id, item.Value);
}
return dictionary;
}
public Dictionary<uint, Model.Account.Account> ByAccountId(List<uint> accountIdList)
{
Innit();
var resultDict = new Dictionary<uint, Model.Account.Account>();
if (accountIdList == null || !accountIdList.Any())
{
return resultDict;
}
sqlWhere.In("tblAccountChartOf.AccountChartOfID", accountIdList, " WHERE ");
resultDict = Execute(sqlWhere.SqlWhereString, sqlWhere.ParameterList);
return resultDict;
}
public Dictionary<uint, Model.Account.Account> ByAccountCode(List<int> accountCodeList)
{
Innit();
var resultDict = new Dictionary<uint, Model.Account.Account>();
if (accountCodeList == null || !accountCodeList.Any())
{
return resultDict;
}
sqlWhere.In("tblAccountChartOf.AccountCode", accountCodeList, " WHERE ");
resultDict = Execute(sqlWhere.SqlWhereString, sqlWhere.ParameterList);
return resultDict;
}
private Dictionary<uint, Model.Account.Account> Execute(string sqlWhere, Dictionary<string, object> parameters)
{
var resultDict = new Dictionary<uint, Model.Account.Account>();
//build sql query
string sqlString = @"
SELECT tblAccountChartOf.AccountChartOfID
,tblAccountChartOf.AccountCode
,tblAccountChartOf.AccountName
,tblAccountChartOf.Description
,tblAccountChartOfType.AccountChartOfType
,tblAccountChartOfType.BasicType
,tblAccountChartOfType.Multiplier
FROM tblAccountChartOf
INNER JOIN tblAccountChartOfType ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID
" + sqlWhere;
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
{
if (parameters != null)
{
foreach (var parameter in parameters)
{
cmd.Parameters.AddWithValue(parameter.Key, parameter.Value);
}
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
uint tablePk = (uint)reader.GetInt32(0);
uint accountCode = (uint)reader.GetInt32(1);
string title = reader.GetString(2);
string description = null;
if (!reader.IsDBNull(3)) { description = reader.GetString(3); }
string type = reader.GetString(4);
string basicType = reader.GetString(5);
int multiplier = reader.GetInt32(6);
var result = new Model.Account.Account(tablePk, accountCode, title, description, type, basicType, multiplier);
resultDict.Add(tablePk, result);
}
}
}
}
}
return resultDict;
}
private void Innit()
{
sqlWhere.Init();
}
}
}

View File

@@ -1,123 +0,0 @@
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 ReadInvoiceLineItem : Connection
{
public ReadInvoiceLineItem()
{
}
/// <summary>
/// Reads all invoice line items from the database.
/// </summary>
/// <returns>dictionary where key=id, value=object</returns>
internal Dictionary<int, Model.Account.InvoiceLineItem> All()
{
return Execute();
}
/// <summary>
/// Read list of invoice line items by item code.
/// </summary>
/// <param name="itemCodes">List of item coeds to query db against</param>
/// <returns>dictionary where key=id, value=object</returns>
/// <exception cref="ArgumentException"></exception>
internal Dictionary<int, Model.Account.InvoiceLineItem> ByItemCode(List<string> itemCodes)
{
if (itemCodes == null || !itemCodes.Any())
{
throw new ArgumentException("Item codes list cannot be null or empty.");
}
var sqlwhere = new SqlWhereBuilder();
sqlwhere.In("ItemCode", itemCodes, "AND");
return Execute(sqlwhere);
}
private Dictionary<int, Model.Account.InvoiceLineItem> Execute(SqlWhereBuilder sqlwhere = null)
{
var resultList = new Dictionary<int, Model.Account.InvoiceLineItem>();
var accountCodeIdList = new Dictionary<int, uint>(); // key=LineItemID, value=AccountChartOfID
var taxCodeIdList = new Dictionary<int, int>(); // key=LineItemID, value=AccountTaxCodeID
string sql = @"
SELECT [AccountInvoiceLineItemID]
,[ItemName]
,[ItemCode]
,[ItemDescription]
,[IsNewReviewRequired]
,[InvoiceLineEntryEnable]
,[AccountChartOfID_Default]
,[AccountTaxCodeID_Default]
FROM [e2A].[dbo].[tblAccountInvoiceLineItem]
WHERE 1=1 ";
if (sqlwhere != null)
{
sql += sqlwhere.SqlWhereString;
}
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
if (sqlwhere != null)
{
sqlwhere.AddParametersToSqlCommand(cmd);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var lineItem = new Model.Account.InvoiceLineItem();
int lineItemId = reader.GetInt32(0);
lineItem.Name = reader.GetString(1);
lineItem.ItemCode = reader.GetString(2);
if (!reader.IsDBNull(3)) { lineItem.Description = reader.GetString(3); }
lineItem.IsNewReviewRequired = reader.GetBoolean(4);
lineItem.InvoiceLineEntryEnabled = reader.GetBoolean(5);
if (!reader.IsDBNull(6))
{
accountCodeIdList.Add(lineItemId, (uint)reader.GetInt32(6));
}
if (!reader.IsDBNull(7))
{
taxCodeIdList.Add(lineItemId, reader.GetInt32(7));
}
resultList.Add(lineItemId, lineItem);
}
}
}
// get account codes and add to result list
var accountCodeDictionary = new Data.Database.Account.ReadAccountCode().ByAccountId(accountCodeIdList.Values.ToList());
foreach (var accountCode in accountCodeIdList)
{
resultList[accountCode.Key].DefaultAccountCode = accountCodeDictionary[accountCode.Value];
}
// get tax codes
var taxCodeDictionary = new Data.Database.Account.ReadTaxCode().GetByTaxCodeId(taxCodeIdList.Values.ToList());
foreach (var taxCode in taxCodeIdList)
{
resultList[taxCode.Key].DefaultTaxCode = taxCodeDictionary[taxCode.Value];
}
return resultList;
}
}
}
}

View File

@@ -1,242 +0,0 @@
using FikaAmazonAPI.AmazonSpApiSDK.Models.CatalogItems;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Runtime.InteropServices.Marshalling;
using System.Text;
using System.Threading.Tasks;
using static System.ComponentModel.Design.ObjectSelectorEditor;
namespace bnhtrade.Core.Data.Database.Account
{
internal class ReadJournal : Connection
{
private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder;
/// <summary>
/// Filter the read results
/// </summary>
public List<uint> AccountJournalId { get; set; }
public ReadJournal()
{
Init();
}
public void Init()
{
sqlBuilder = new SqlWhereBuilder();
AccountJournalId = new List<uint>();
}
/// <summary>
///
/// </summary>
/// <returns>Dictionary were key is the table primary key</returns>
public Dictionary<uint, Core.Model.Account.Journal> Read()
{
sqlBuilder.Init();
//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 (AccountJournalId.Any())
{
sqlBuilder.In("tblAccountJournal.AccountJournalID", AccountJournalId, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// build tuple list
var dbJournalList = new List<(
uint AccountJournalId
, uint AccountJournalTypeId
, DateTime EntryDate
, DateTime PostDate
, DateTime LastModified
, bool IsLocked
)>();
var dbJournalPostList = new List<(
uint AccountJournalId
, uint AccountJournalPostId
, uint AccountChartOfId
, decimal AmountGbp
)>();
bool hasRows = false;
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
hasRows = true;
uint lastJournalId = 0;
while (reader.Read())
{
// read journal header
uint journalId = (uint)reader.GetInt32(0);
if (journalId != lastJournalId)
{
lastJournalId = journalId;
(uint AccountJournalId
, uint AccountJournalTypeId
, DateTime EntryDate
, DateTime PostDate
, DateTime LastModified
, bool IsLocked
)
journal =
( journalId
, (uint)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
(uint AccountJournalId
, uint AccountJournalPostId
, uint AccountChartOfId
, decimal AmountGbp
)
journalPost =
( journalId
, (uint)reader.GetInt32(6)
, (uint)reader.GetInt32(7)
, reader.GetDecimal(8)
);
dbJournalPostList.Add(journalPost);
}
}
}
}
}
var returnList = new Dictionary<uint, Core.Model.Account.Journal>();
if (hasRows)
{
// build lists to filter db results by
var journalTypeIdList = new List<uint>();
var accountIdList = new List<uint>();
foreach (var item in dbJournalList)
{
journalTypeIdList.Add(item.AccountJournalTypeId);
}
foreach (var item in dbJournalPostList)
{
accountIdList.Add(item.AccountChartOfId);
}
// get journalTypes from db
var dbJournalType = new Data.Database.Account.ReadJournalType();
dbJournalType.IdList = journalTypeIdList;
var journalTypeDict = dbJournalType.Read();
// get accounts from db
var dbAccount = new Data.Database.Account.ReadAccountCode();
var accountDict = dbAccount.ByAccountId(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 EntryIsLocked(int journalId)
{
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
SELECT
tblAccountJournal.IsLocked
FROM
tblAccountJournal
WHERE
tblAccountJournal.AccountJournalID=@accountJournalId;
", conn))
{
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;
}
}
}
}
}
}

View File

@@ -1,144 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Account
{
internal class ReadJournalType : Connection
{
private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder;
/// <summary>
/// Results filter
/// </summary>
public List<uint> IdList { get; set; }
/// <summary>
/// Searches for the specificed phases within the item description. Uses the LIKE AND sql function
/// </summary>
public List<string> TitleList { get; set; }
public ReadJournalType()
{
Init();
}
public void Init()
{
sqlBuilder = new SqlWhereBuilder();
IdList = new List<uint>();
TitleList = new List<string>();
}
/// <summary>
///
/// </summary>
/// <returns>Dictionary where key is the table primary key</returns>
public Dictionary<uint, Model.Account.JournalType> Read()
{
// create the return (emptyP list) here
var returnList = new Dictionary<uint, 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 (IdList.Any())
{
sqlBuilder.In("AccountJournalTypeID", IdList, "AND");
}
if (TitleList.Any())
{
sqlBuilder.In("TypeTitle", TitleList, "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<uint, uint>();
var debitDict = new Dictionary<uint, uint>();
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
// read from db and create object
uint journalTypeId = (uint)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, (uint)debitAccountId);
}
if (creditAccountId != null)
{
creditDict.Add(journalTypeId, (uint)creditAccountId);
}
}
}
}
}
}
// get account objects from db
var accountIdList = debitDict.Values.ToList();
accountIdList.AddRange(creditDict.Values.ToList());
var dbaccount = new Data.Database.Account.ReadAccountCode();
var dbDict = dbaccount.ByAccountId(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;
}
}
}

View File

@@ -1,178 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.ComponentModel.Design.ObjectSelectorEditor;
namespace bnhtrade.Core.Data.Database.Account
{
internal class ReadPurchaseInvoice : Connection
{
private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder;
public IEnumerable<int> PurchaseInvoiceIdList { get; set; }
public ReadPurchaseInvoice()
{
Init();
}
public void Init()
{
sqlBuilder = new SqlWhereBuilder();
PurchaseInvoiceIdList = new List<int>();
}
public Dictionary<int, Model.Account.PurchaseInvoice> Read()
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoice>();
sqlBuilder.Init();
//build sql query
string sql = @"
SELECT tblPurchase.PurchaseID
,tblPurchase.PurchaseNumber
,tblPurchase.RecordID
,tblPurchase.PurchaseDate
,tblPurchase.ContactID
,tblPurchase.SupplierRef
,tblPurchase.PurchaseTotalAmount
,tblPurchase.VatInclusiveAmounts
,tblPurchase.RecordCreated
,tblPurchase.RecordModified
,tblPurchase.IsActive
,tblAccountCurrency.CurrencyCode
,tblPurchaseChannel.PurchaseChannelName
,tblPurchaseStatus.PurchaseStatus
FROM tblPurchase
LEFT OUTER JOIN tblAccountCurrency ON tblPurchase.AccountCurrencyID = tblAccountCurrency.AccountCurrencyID
LEFT OUTER JOIN tblPurchaseStatus ON tblPurchase.PurchaseStatusID = tblPurchaseStatus.PurchaseStatusID
LEFT OUTER JOIN tblPurchaseChannel ON tblPurchase.PurchaseChannelID = tblPurchaseChannel.PurchaseChannelID
WHERE 1 = 1
";
// build the where statments
if (PurchaseInvoiceIdList.Any())
{
sqlBuilder.In("[PurchaseID]", PurchaseInvoiceIdList, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// dictionary so we can fill in details afterwards
var invoiceContactDict = new Dictionary<int, int>();
var purchaseIdList = new List<int>();
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int purchaseID = reader.GetInt32(0);
int purchaseNumber = reader.GetInt32(1);
int? recordID = null;
if (!reader.IsDBNull(2)) { recordID = reader.GetInt32(2); }
DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc);
int? contactID = null;
if (!reader.IsDBNull(4)) { contactID = reader.GetInt32(4);}
string supplierRef = null;
if (!reader.IsDBNull(5)) { supplierRef = reader.GetString(5);}
decimal? purchaseTotalAmount = null;
if (!reader.IsDBNull(6)) { purchaseTotalAmount = reader.GetDecimal(6);}
bool vatInclusiveAmounts = reader.GetBoolean(7);
DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc);
DateTime recordModified = DateTime.SpecifyKind(reader.GetDateTime(9), DateTimeKind.Utc);
bool isActive = reader.GetBoolean(10);
string currencyCode = reader.GetString(11);
string purchaseChannelName = reader.GetString(12);
string purchaseStatus = null;
if (!reader.IsDBNull(13)) { purchaseStatus = reader.GetString(13);}
var invoice = new Model.Account.PurchaseInvoice();
invoice.PurchaseID = purchaseID;
invoice.PurchaseNumber = purchaseNumber;
invoice.RecordID = recordID;
invoice.PurchaseDate = purchaseDate;
invoice.SupplierRef = supplierRef;
//invoice.PurchaseTotalAmount = purchaseTotalAmount;
invoice.VatInclusiveAmounts = vatInclusiveAmounts;
invoice.RecordCreated = recordCreated;
invoice.RecordModified = recordModified;
invoice.IsActive = isActive;
invoice.CurrencyCode = currencyCode;
invoice.PurchaseChannel = purchaseChannelName;
// is there contact info that needs to be added?
if (contactID != null)
{
invoiceContactDict.Add(purchaseID, (int)contactID);
}
purchaseIdList.Add(purchaseID);
returnList.Add(purchaseID, invoice);
}
}
}
}
}
// add contact info
if (invoiceContactDict.Any())
{
var readContact = new Data.Database.Account.ReadContact();
readContact.ContactIdList = invoiceContactDict.Values.ToList();
var contactDict = readContact.Read();
if (contactDict.Any())
{
foreach ( var invoice in returnList)
{
if (invoiceContactDict.ContainsKey(invoice.Value.PurchaseID))
{
int contactId = invoiceContactDict[invoice.Value.PurchaseID];
invoice.Value.Contact = contactDict[contactId];
}
}
}
}
// add invoice lines
var readLines = new Data.Database.Account.ReadPurchaseInvoiceLine();
readLines.InvoiceIdList = purchaseIdList;
var lines = readLines.Read();
foreach(var invoice in returnList.Values)
{
foreach(var line in lines.Values)
{
if (line.PurchaseId == invoice.PurchaseID)
{
if (invoice.InvoiceLines == null)
{
invoice.InvoiceLines = new List<Model.Account.PurchaseInvoice.Line>();
}
invoice.InvoiceLines.Add(line);
}
}
}
return returnList;
}
}
}

View File

@@ -1,212 +0,0 @@
using Amazon.Runtime.Internal.Transform;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.ComponentModel.Design.ObjectSelectorEditor;
namespace bnhtrade.Core.Data.Database.Account
{
internal class ReadPurchaseInvoiceLine : Connection
{
private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder;
/// <summary>
/// Results filter
/// </summary>
public List<int> InvoiceIdList { get; set; }
/// <summary>
/// Results filter
/// </summary>
public List<int> InvoiceLineIdList { get; set; }
/// <summary>
/// Results filter
/// </summary>
public List<string> StatusList { get; set; }
/// <summary>
/// Searches for the specificed phases within the item description. Uses the LIKE AND sql function
/// </summary>
public List<string> ItemDescription { get; set; }
public ReadPurchaseInvoiceLine()
{
Init();
}
public void Init()
{
sqlBuilder = new SqlWhereBuilder();
InvoiceIdList = new List<int>();
InvoiceLineIdList = new List<int>();
StatusList = new List<string>();
ItemDescription = new List<string>();
}
public Dictionary<int, Model.Account.PurchaseInvoice.Line> Read()
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoice.Line>();
sqlBuilder.Init();
//build sql query
string sql = @"
SELECT tblPurchaseLine.PurchaseLineID
,tblPurchaseLine.PurchaseID
,tblPurchaseLineStatus.PurchaseLineStatus
,tblPurchaseLine.SupplierRef
,tblPurchaseLine.CheckedIn
,tblPurchaseLine.ItemDescription
,tblPurchaseLine.ItemQuantity
,tblPurchaseLine.ItemGross
,tblPurchaseLine.ItemTax
,tblPurchaseLine.ShippingGross
,tblPurchaseLine.ShippingTax
,tblPurchaseLine.OtherGross
,tblPurchaseLine.OtherTax
,tblPurchaseLine.AccountTaxCodeID
,tblPurchaseLine.Tax_AccountTransactionID
,tblPurchaseLine.Net_AccountChartOfID
,tblPurchaseLine.Net_AccountTransactionID
,tblPurchaseLine.RecordCreated
,tblPurchaseLine.RecordModified
,tblPurchaseLine.IsActive
,tblAccountTaxCode.TaxCode
FROM tblPurchaseLine
INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID
LEFT OUTER JOIN tblAccountTaxCode ON tblPurchaseLine.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID
WHERE 1 = 1 ";
// build the where statments
if (InvoiceIdList.Any())
{
sqlBuilder.In("PurchaseID", InvoiceLineIdList, "AND");
}
if (InvoiceLineIdList.Any())
{
sqlBuilder.In("PurchaseLineID", InvoiceLineIdList, "AND");
}
if (StatusList.Any())
{
sqlBuilder.In("PurchaseLineStatus", InvoiceLineIdList, "AND");
}
if (ItemDescription.Any())
{
sqlBuilder.LikeAnd("ItemDescription", ItemDescription, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// catch taxcode to add in after db read
var lineTaxCodeDict = new Dictionary<int, string>();
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int purchaseLineID = reader.GetInt32(0);
int purchaseID = reader.GetInt32(1);
string purchaseLineStatus = reader.GetString(2);
string supplierRef = null;
if (!reader.IsDBNull(3)) { supplierRef = reader.GetString(3); }
DateTime? checkedIn = null;
if (!reader.IsDBNull(4)) { checkedIn = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc); }
string itemDescription = null;
if (!reader.IsDBNull(5)) { itemDescription = reader.GetString(5); }
int itemQuantity = reader.GetInt32(6);
decimal itemGross = 0;
if (!reader.IsDBNull(7)) { itemGross = reader.GetDecimal(7); }
decimal itemTax = 0;
if (!reader.IsDBNull(8)) { itemTax = reader.GetDecimal(8); }
decimal shippingGross = 0;
if (!reader.IsDBNull(9)) { shippingGross = reader.GetDecimal(9); }
decimal shippingTax = 0;
if (!reader.IsDBNull(10)) { shippingTax = reader.GetDecimal(10); }
decimal otherGross = 0;
if (!reader.IsDBNull(11)) { otherGross = reader.GetDecimal(11); }
decimal otherTax = 0;
if (!reader.IsDBNull(12)) { otherTax = reader.GetDecimal(12); }
int accountTaxCodeID = reader.GetInt32(13);
int? tax_AccountTransactionID = null;
if (!reader.IsDBNull(14)) { tax_AccountTransactionID = reader.GetInt32(14); }
int net_AccountChartOfID = reader.GetInt32(15);
int? net_AccountTransactionID = null;
if (!reader.IsDBNull(16)) { net_AccountTransactionID = reader.GetInt32(16); }
DateTime recordModified;
DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(17), DateTimeKind.Utc);
if (reader.IsDBNull(18)) { recordModified = recordCreated; }
else { recordModified = DateTime.SpecifyKind(reader.GetDateTime(18), DateTimeKind.Utc); }
bool isActive = reader.GetBoolean(19);
string accountTaxCode = reader.GetString(20);
var line = new Model.Account.PurchaseInvoice.Line();
line.PurchaseLineId = purchaseLineID;
line.PurchaseId = purchaseID;
line.Status = purchaseLineStatus;
line.SupplierRef = supplierRef;
line.CheckedIn = checkedIn;
line.ItemDescription = itemDescription;
line.ItemQuantity = itemQuantity;
line.ItemGross = itemGross;
line.ItemTax = itemTax;
line.ShippingGross = shippingGross;
line.ShippingTax = shippingTax;
line.OtherGross = otherGross;
line.OtherTax = otherTax;
line.Tax_AccountTransactionId = tax_AccountTransactionID;
line.Net_AccountChartOfId = net_AccountChartOfID;
line.Net_AccountTransactionId = net_AccountTransactionID;
line.RecordModified = recordModified;
line.RecordCreated = recordCreated;
line.IsActive = isActive;
returnList.Add(purchaseLineID, line);
lineTaxCodeDict.Add(purchaseLineID, accountTaxCode);
}
}
}
}
}
// read tax codes form db and add to return object
var taxcodeList = new Data.Database.Account.ReadTaxCode().GetByTaxCode(lineTaxCodeDict.Values.ToList());
foreach (var line in returnList.Values)
{
foreach(var taxcode in taxcodeList)
{
if (taxcode.TaxCode == lineTaxCodeDict[line.PurchaseLineId])
{
line.AccountTaxCode = taxcode;
break;
}
}
if (line.AccountTaxCode == null)
{
throw new Exception("Fail safe, this really shouodn't happen");
}
}
// all done
return returnList;
}
}
}

View File

@@ -1,54 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Account
{
internal class ReadPurchaseInvoiceLineStatus : Connection
{
public Dictionary<int, Model.Account.PurchaseInvoiceLineStatus> Read()
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoiceLineStatus>();
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
SELECT [PurchaseLineStatusID]
,[PurchaseLineStatus]
,[ListSort]
,[TimeStamp]
FROM [e2A].[dbo].[tblPurchaseLineStatus]
ORDER BY [ListSort]
", conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
// do something
}
else
{
while (reader.Read())
{
int id = reader.GetInt32(0);
string name = reader.GetString(1);
int lineSort = reader.GetInt32(2);
var returnItem = new Model.Account.PurchaseInvoiceLineStatus(id, name,lineSort);
returnList.Add(id, returnItem );
}
}
}
}
}
return returnList;
}
}
}

View File

@@ -1,91 +0,0 @@
using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductFees;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.ComponentModel.Design.ObjectSelectorEditor;
namespace bnhtrade.Core.Data.Database.Account
{
internal class ReadPurchaseInvoiceLineSummary : Connection
{
public List<Model.Account.PurchaseInvoiceLineSummary> Read(DateTime periodTo, string lineStatus, List<string> descriptionSearch)
{
var returnList = new List<Model.Account.PurchaseInvoiceLineSummary>();
var sqlBuilder = new bnhtrade.Core.Data.Database.SqlWhereBuilder();
//build sql query
string sql = @"
SELECT tblPurchase.PurchaseDate
,tblPurchase.PurchaseID
,tblPurchase.PurchaseNumber
,tblPurchaseLine.PurchaseLineID
,tblPurchaseLine.ItemDescription
,tblPurchaseLineStatus.PurchaseLineStatus
FROM tblPurchase
INNER JOIN tblPurchaseLine ON tblPurchase.PurchaseID = tblPurchaseLine.PurchaseID
INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID
WHERE tblPurchase.PurchaseDate <= @purchaseDate
";
if (lineStatus != null)
{
sql = sql + " AND PurchaseLineStatus = @purchaseLineStatus ";
}
// build the where statments
if (descriptionSearch.Any())
{
sqlBuilder.LikeAnd("ItemDescription", descriptionSearch, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@purchaseDate", periodTo);
if (lineStatus != null)
{
cmd.Parameters.AddWithValue("@purchaseLineStatus", lineStatus);
}
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc);
int purchaseID = reader.GetInt32(1);
int purchaseNumber = reader.GetInt32(2);
int purchaseLineID = reader.GetInt32(3);
string itemDescription = reader.GetString(4);
string purchaseLineStatus = reader.GetString(5);
var item = new Model.Account.PurchaseInvoiceLineSummary();
item.PurchaseDate = purchaseDate;
item.PurchaseId = purchaseID;
item.PurchaseNumber = purchaseNumber;
item.PurchaseLineId = purchaseLineID;
item.ItemDescription = itemDescription;
item.LineStatus = purchaseLineStatus;
returnList.Add(item);
}
}
}
}
return returnList;
}
}
}

View File

@@ -1,242 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Account
{
internal class ReadTaxCode : Connection
{
private Data.Database.SqlWhereBuilder whereBuilder = new SqlWhereBuilder();
public ReadTaxCode()
{
}
private Dictionary<int, Model.Account.TaxCodeInfo> Execute(string sqlWhere, Dictionary<string, object> parameters)
{
var resultList = new Dictionary<int, Model.Account.TaxCodeInfo>();
//build sql query
string sqlString = @"
SELECT
AccountTaxCodeID
,TaxCode
,TaxCodeName
,TaxCodeDescription
,TaxRatePercent
,IsMarginScheme
,IsValidOnExpense
,IsVailidOnIncome
,IsActive
,TaxType
FROM tblAccountTaxCode";
sqlString += sqlWhere;
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
{
foreach (var paramter in parameters)
{
cmd.Parameters.AddWithValue(paramter.Key, paramter.Value);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int taxCodeId = reader.GetByte(0);
string taxCode = reader.GetString(1);
string name = reader.GetString(2);
string description = null;
if (!reader.IsDBNull(3)) { description = reader.GetString(3); }
decimal rate = reader.GetDecimal(4);
bool isMargin = reader.GetBoolean(5);
bool isValidOnExpense = reader.GetBoolean(6);
bool isValidOnIncome = reader.GetBoolean(7);
bool isActive = reader.GetBoolean(8);
string taxType = reader.GetString(9);
var result = new Model.Account.TaxCodeInfo(
taxCode,
name,
description,
rate,
isMargin,
isValidOnExpense,
isValidOnIncome,
taxType,
isActive);
resultList.Add(taxCodeId, result);
}
}
}
}
}
return resultList;
}
public List<Model.Account.TaxCodeInfo> GetByTaxCode(List<string> taxcodeList)
{
var resultList = new List<Model.Account.TaxCodeInfo>();
if (taxcodeList == null || !taxcodeList.Any())
{
return resultList;
}
taxcodeList = taxcodeList.Distinct().ToList();
whereBuilder.Init();
whereBuilder.In("TaxCode", taxcodeList, "WHERE");
var dic = Execute(whereBuilder.SqlWhereString, whereBuilder.ParameterList);
return dic.Values.ToList();
}
public Dictionary<int, Model.Account.TaxCodeInfo> GetByTaxCodeId(List<int> taxcodeIdList)
{
var resultList = new Dictionary<int, Model.Account.TaxCodeInfo>();
if (taxcodeIdList == null || !taxcodeIdList.Any())
{
return resultList;
}
taxcodeIdList = taxcodeIdList.Distinct().ToList();
whereBuilder.Init();
whereBuilder.In("AccountTaxCodeID", taxcodeIdList, "WHERE");
return Execute(whereBuilder.SqlWhereString, whereBuilder.ParameterList);
}
/// <summary>
/// Gets all active Tax Code objects
/// </summary>
/// <returns>Dictionary where database record ID is the key</returns>
public Dictionary<int, Model.Account.TaxCodeInfo> GetAllActive()
{
string sqlWhere = @"
WHERE IsActive=@isActive;";
var parameters = new Dictionary<string, object>();
parameters.Add("@isActive", true);
return Execute(sqlWhere, parameters);
}
public Dictionary<string, string> GetTaxCodeBySkuNumber(List<string> skuNumberList)
{
var resultList = new Dictionary<string, string>();
if (skuNumberList == null || !skuNumberList.Any())
{
return resultList;
}
skuNumberList = skuNumberList.Distinct().ToList();
string sql = @"
SELECT tblSku.skuSkuNumber
,tblAccountTaxCode.TaxCode
FROM tblSku
INNER JOIN tblAccountTaxCode ON tblSku.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID ";
whereBuilder.Init();
whereBuilder.In("tblSku.skuSkuNumber", skuNumberList, "WHERE");
sql += whereBuilder.SqlWhereString;
using (var conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (var cmd = new SqlCommand(sql, conn))
{
foreach (var param in whereBuilder.ParameterList)
{
cmd.Parameters.AddWithValue(param.Key, param.Value);
}
using (var reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
return resultList;
}
while (reader.Read())
{
resultList.Add(reader.GetString(0), reader.GetString(1));
}
}
}
}
return resultList;
}
public Dictionary<string, string> GetTaxCodeByInvoiceLineItemCode(List<string> lineItemCode)
{
var resultList = new Dictionary<string, string>();
if (lineItemCode == null || !lineItemCode.Any())
{
return resultList;
}
lineItemCode = lineItemCode.Distinct().ToList();
string sql = @"
SELECT tblAccountInvoiceLineItem.ItemCode
,tblAccountTaxCode.TaxCode
FROM tblAccountInvoiceLineItem
LEFT OUTER JOIN tblAccountTaxCode ON tblAccountInvoiceLineItem.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID
";
whereBuilder.Init();
whereBuilder.In("tblAccountInvoiceLineItem.ItemCode", lineItemCode, "WHERE");
sql += whereBuilder.SqlWhereString;
using (var conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (var cmd = new SqlCommand(sql, conn))
{
foreach (var param in whereBuilder.ParameterList)
{
cmd.Parameters.AddWithValue(param.Key, param.Value);
}
using (var reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
return resultList;
}
while (reader.Read())
{
if (reader.IsDBNull(1)) { resultList.Add(reader.GetString(0), null); }
else { resultList.Add(reader.GetString(0), reader.GetString(1)); }
}
}
}
}
return resultList;
}
}
}

View File

@@ -0,0 +1,82 @@
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 AccountCodeRepository : _Base, IAccountCodeRepository
{
public AccountCodeRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public Dictionary<int, Model.Account.Account> ReadAccountCode(List<int> accountIdList = null, List<int> accountCodeList = null)
{
var resultDict = new Dictionary<int, Model.Account.Account>();
var sqlWhere = new SqlWhereBuilder();
//build sql query
string sqlString = @"
SELECT tblAccountChartOf.AccountChartOfID
,tblAccountChartOf.AccountCode
,tblAccountChartOf.AccountName
,tblAccountChartOf.Description
,tblAccountChartOfType.AccountChartOfType
,tblAccountChartOfType.BasicType
,tblAccountChartOfType.Multiplier
FROM tblAccountChartOf
INNER JOIN tblAccountChartOfType ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID
WHERE 1=1 ";
if (accountIdList != null && accountIdList.Any())
{
sqlWhere.In("tblAccountChartOf.AccountChartOfID", accountIdList, " AND ");
}
if (accountCodeList != null && accountCodeList.Any())
{
sqlWhere.In("tblAccountChartOf.AccountCode", accountCodeList, " AND ");
}
if (sqlWhere.IsSetSqlWhereString)
{
sqlString = sqlString + sqlWhere.SqlWhereString;
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sqlString;
cmd.Transaction = _transaction as SqlTransaction;
if (sqlWhere.ParameterListIsSet)
{
sqlWhere.AddParametersToSqlCommand(cmd);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int tablePk = reader.GetInt32(0);
int accountCode = reader.GetInt32(1);
string title = reader.GetString(2);
string description = null;
if (!reader.IsDBNull(3)) { description = reader.GetString(3); }
string type = reader.GetString(4);
string basicType = reader.GetString(5);
int multiplier = reader.GetInt32(6);
var result = new Model.Account.Account(tablePk, accountCode, title, description, type, basicType, multiplier);
resultDict.Add(tablePk, result);
}
}
}
return resultDict;
}
}
}

View File

@@ -0,0 +1,201 @@
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 AccountTaxRepository : _Base, IAccountTaxRepository
{
public AccountTaxRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public Dictionary<int, Model.Account.TaxCodeInfo> ReadTaxCodeInfo(bool? IsActive = null, List<string> taxcodeList = null, List<int> taxcodeIdList = null)
{
var resultList = new Dictionary<int, Model.Account.TaxCodeInfo>();
Data.Database.SqlWhereBuilder whereBuilder = new SqlWhereBuilder();
//build sql query
string sqlString = @"
SELECT
AccountTaxCodeID
,TaxCode
,TaxCodeName
,TaxCodeDescription
,TaxRatePercent
,IsMarginScheme
,IsValidOnExpense
,IsVailidOnIncome
,IsActive
,TaxType
FROM tblAccountTaxCode
WHERE 1=1 ";
// add where clauses
if (IsActive.HasValue)
{
whereBuilder.IsEqualTo("IsActive", IsActive.Value, "AND");
}
if (taxcodeList != null && taxcodeList.Count > 0)
{
whereBuilder.In("TaxCode", taxcodeList, "AND");
}
if (taxcodeIdList != null && taxcodeIdList.Count > 0)
{
whereBuilder.In("AccountTaxCodeID", taxcodeIdList, "AND");
}
if (whereBuilder.IsSetSqlWhereString)
{
sqlString = sqlString + whereBuilder.SqlWhereString;
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sqlString;
cmd.Transaction = _transaction as SqlTransaction;
if (whereBuilder.ParameterListIsSet)
{
whereBuilder.AddParametersToSqlCommand(cmd);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int taxCodeId = reader.GetByte(0);
string taxCode = reader.GetString(1);
string name = reader.GetString(2);
string description = null;
if (!reader.IsDBNull(3)) { description = reader.GetString(3); }
decimal rate = reader.GetDecimal(4);
bool isMargin = reader.GetBoolean(5);
bool isValidOnExpense = reader.GetBoolean(6);
bool isValidOnIncome = reader.GetBoolean(7);
bool isActive = reader.GetBoolean(8);
string taxType = reader.GetString(9);
var result = new Model.Account.TaxCodeInfo(
taxCode,
name,
description,
rate,
isMargin,
isValidOnExpense,
isValidOnIncome,
taxType,
isActive);
resultList.Add(taxCodeId, result);
}
}
}
return resultList;
}
public Dictionary<string, string> GetTaxCodeBySkuNumber(List<string> skuNumberList)
{
var resultList = new Dictionary<string, string>();
if (skuNumberList == null || !skuNumberList.Any())
{
return resultList;
}
skuNumberList = skuNumberList.Distinct().ToList();
string sql = @"
SELECT tblSku.skuSkuNumber
,tblAccountTaxCode.TaxCode
FROM tblSku
INNER JOIN tblAccountTaxCode ON tblSku.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID ";
var whereBuilder = new Data.Database.SqlWhereBuilder();
whereBuilder.In("tblSku.skuSkuNumber", skuNumberList, "WHERE");
sql += whereBuilder.SqlWhereString;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
if (whereBuilder.ParameterListIsSet)
{
whereBuilder.AddParametersToSqlCommand(cmd);
}
using (var reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
return resultList;
}
while (reader.Read())
{
resultList.Add(reader.GetString(0), reader.GetString(1));
}
}
}
return resultList;
}
public Dictionary<string, string> ReadTaxCodeByInvoiceLineItemCode(List<string> lineItemCode)
{
var resultList = new Dictionary<string, string>();
if (lineItemCode == null || !lineItemCode.Any())
{
return resultList;
}
lineItemCode = lineItemCode.Distinct().ToList();
string sql = @"
SELECT tblAccountInvoiceLineItem.ItemCode
,tblAccountTaxCode.TaxCode
FROM tblAccountInvoiceLineItem
LEFT OUTER JOIN tblAccountTaxCode ON tblAccountInvoiceLineItem.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID
";
var whereBuilder = new Data.Database.SqlWhereBuilder();
whereBuilder.In("tblAccountInvoiceLineItem.ItemCode", lineItemCode, "WHERE");
sql += whereBuilder.SqlWhereString;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
if (whereBuilder.ParameterListIsSet)
{
whereBuilder.AddParametersToSqlCommand(cmd);
}
using (var reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
return resultList;
}
while (reader.Read())
{
if (reader.IsDBNull(1)) { resultList.Add(reader.GetString(0), null); }
else { resultList.Add(reader.GetString(0), reader.GetString(1)); }
}
}
}
return resultList;
}
}
}

View File

@@ -14,11 +14,11 @@ using System.Transactions;
namespace bnhtrade.Core.Data.Database.Repository.Implementation namespace bnhtrade.Core.Data.Database.Repository.Implementation
{ {
internal class ImportAmazonRepository : _Base, IImportAmazonRepository internal class AmazonSettlementRepository : _Base, IAmazonSettlementRepository
{ {
Logic.Log.LogEvent _log = new Logic.Log.LogEvent(); Logic.Log.LogEvent _log = new Logic.Log.LogEvent();
public ImportAmazonRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction) public AmazonSettlementRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{ {
} }
@@ -368,13 +368,39 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
// Update Amazon Settlement Report // Update Amazon Settlement Report
// //
/// <summary>
/// Update the settlement report marketplace name by settlement Id (not table id)
/// </summary>
/// <param name="settlementId">Settlement id (not table/record id) of the settlement to update</param>
/// <param name="marketPlaceName">marketplace name</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public bool UpdateAmazonSettlementMarketPlaceName (string settlementId, Model.Amazon.MarketPlaceEnum marketPlace)
{
if (string.IsNullOrWhiteSpace(settlementId) || marketPlace == null)
{
throw new Exception("Settlement id or market place is invalid.");
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = @"
UPDATE tblImportAmazonSettlementReport
SET [marketplace-name] = @marketPlaceName
WHERE [settlement-id] = @settlementId;";
cmd.Parameters.AddWithValue("@marketPlaceName", marketPlace.GetMarketplaceUrl());
cmd.Parameters.AddWithValue("@settlementId", settlementId);
cmd.Transaction = _transaction as SqlTransaction;
return cmd.ExecuteNonQuery() > 0;
}
}
/// <summary> /// <summary>
/// Set the IsProcessed flag to true or false for the specified settlement Ids. /// Set the IsProcessed flag to true or false for the specified settlement Ids.
/// </summary> /// </summary>
/// <param name="settlementIdList">List of settlement id (not table id)</param> /// <param name="settlementIdList">List of settlement id (not table id)</param>
/// <param name="isProcessed">value to set the isProcessed to</param> /// <param name="isProcessed">value to set the isProcessed to</param>
/// <returns>Number of rows effected</returns> /// <returns>Number of rows effected</returns>
public int SetAmazonSettlementIsProcessed(List<string> settlementIdList, bool isProcessed) public int UpdateAmazonSettlementIsProcessed(List<string> settlementIdList, bool isProcessed)
{ {
if (settlementIdList == null || !settlementIdList.Any()) if (settlementIdList == null || !settlementIdList.Any())
{ {

View File

@@ -1,4 +1,5 @@
using bnhtrade.Core.Data.Database.Repository.Interface; using bnhtrade.Core.Data.Database.Repository.Interface;
using bnhtrade.Core.Logic.Account;
using bnhtrade.Core.Logic.Validate; using bnhtrade.Core.Logic.Validate;
using Microsoft.Data.SqlClient; using Microsoft.Data.SqlClient;
using System; using System;
@@ -164,7 +165,7 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
// //
/// <summary> /// <summary>
/// Returns list of invoice numbers that have not yet been exported (i.e. IsComplete=True) /// Returns list of invoice numbers that have not yet been exported (i.e. IsComplete=True), in InvoiceNumber asending order.
/// </summary> /// </summary>
/// <param name="invoiceType">Sales or Purchase</param> /// <param name="invoiceType">Sales or Purchase</param>
/// <returns>Dictionary where key=ExportAccountInvoiceID, value=InvoiceNumber</returns> /// <returns>Dictionary where key=ExportAccountInvoiceID, value=InvoiceNumber</returns>
@@ -176,7 +177,8 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
SELECT tblExportAccountInvoice.ExportAccountInvoiceID, [InvoiceNumber] SELECT tblExportAccountInvoice.ExportAccountInvoiceID, [InvoiceNumber]
FROM tblExportAccountInvoice FROM tblExportAccountInvoice
WHERE (tblExportAccountInvoice.IsComplete = 0) WHERE (tblExportAccountInvoice.IsComplete = 0)
AND (tblExportAccountInvoice.ExportAccountInvoiceTypeID = @invoiceType);"; AND (tblExportAccountInvoice.ExportAccountInvoiceTypeID = @invoiceType)
ORDER BY [InvoiceNumber];";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{ {
@@ -211,35 +213,35 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
} }
// get the account and tax code objects // get the account and tax code objects
var taxcode = new Data.Database.Account.ReadTaxCode().GetAllActive(); //var taxcode = new Data.Database.Account.ReadTaxCode().GetAllActive();
var account = new Data.Database.Account.ReadAccountCode().All(); //var account = new Data.Database.Account.ReadAccountCode().All();
var taxcodeIds = new Dictionary<int, int>();
var accountIds = new Dictionary<int, int>();
var lineItemIds = new Dictionary<int, int>();
// build sql string // build sql string
string sql = @" string sql = @"
SELECT tblExportAccountInvoice.ExportAccountInvoiceID SELECT tblExportAccountInvoice.ExportAccountInvoiceID,
, tblExportAccountInvoice.ExportAccountInvoiceTypeID tblExportAccountInvoice.ExportAccountInvoiceTypeID,
, tblExportAccountInvoice.Contact tblExportAccountInvoice.Contact,
, tblExportAccountInvoice.InvoiceNumber tblExportAccountInvoice.InvoiceNumber,
, tblExportAccountInvoice.InvoiceDate tblExportAccountInvoice.InvoiceDate,
, tblExportAccountInvoice.InvoiceDueDate tblExportAccountInvoice.InvoiceDueDate,
, tblExportAccountInvoice.Reference tblExportAccountInvoice.Reference,
, tblExportAccountInvoice.CurrencyCode tblExportAccountInvoice.CurrencyCode,
, tblExportAccountInvoice.InvoiceAmount tblExportAccountInvoice.InvoiceAmount,
, tblExportAccountInvoice.IsComplete tblExportAccountInvoice.IsComplete,
, tblExportAccountInvoiceLine.ExportAccountInvoiceLineID tblExportAccountInvoiceLine.ExportAccountInvoiceLineID,
, tblAccountInvoiceLineItem.ItemName tblExportAccountInvoiceLine.AccountInvoiceLineItemID,
, tblExportAccountInvoiceLine.AccountChartOfID tblExportAccountInvoiceLine.AccountChartOfID,
, tblExportAccountInvoiceLine.NetAmount tblExportAccountInvoiceLine.NetAmount,
, tblExportAccountInvoiceLine.AccountTaxCodeID tblExportAccountInvoiceLine.AccountTaxCodeID,
, tblExportAccountInvoiceLine.TaxAmount tblExportAccountInvoiceLine.TaxAmount,
, tblExportAccountInvoice.LineUnitAmountIsTaxExclusive tblExportAccountInvoice.LineUnitAmountIsTaxExclusive
FROM tblExportAccountInvoice FROM tblExportAccountInvoice
INNER JOIN INNER JOIN
tblExportAccountInvoiceLine tblExportAccountInvoiceLine
ON tblExportAccountInvoice.ExportAccountInvoiceID = tblExportAccountInvoiceLine.ExportAccountInvoiceID ON tblExportAccountInvoice.ExportAccountInvoiceID = tblExportAccountInvoiceLine.ExportAccountInvoiceID
INNER JOIN
tblAccountInvoiceLineItem
ON tblExportAccountInvoiceLine.AccountInvoiceLineItemID = tblAccountInvoiceLineItem.AccountInvoiceLineItemID
"; ";
var sqlWhere = new Data.Database.SqlWhereBuilder(); var sqlWhere = new Data.Database.SqlWhereBuilder();
@@ -247,6 +249,7 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
sql = sql + sqlWhere.SqlWhereString + " ORDER BY tblExportAccountInvoice.ExportAccountInvoiceID, tblExportAccountInvoiceLine.ExportAccountInvoiceLineID; "; sql = sql + sqlWhere.SqlWhereString + " ORDER BY tblExportAccountInvoice.ExportAccountInvoiceID, tblExportAccountInvoiceLine.ExportAccountInvoiceLineID; ";
int i = 0;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{ {
cmd.CommandText = sql; cmd.CommandText = sql;
@@ -265,8 +268,10 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
int? previousInvoiceId = null; int? previousInvoiceId = null;
Model.Account.SalesInvoice invoice = null; Model.Account.SalesInvoice invoice = null;
i = -1;
while (reader.Read()) while (reader.Read())
{ {
i++;
invoiceId = reader.GetInt32(0); invoiceId = reader.GetInt32(0);
// test for first/next invoice // test for first/next invoice
@@ -301,11 +306,11 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
// add line info // add line info
var invoiceLine = new Model.Account.SalesInvoice.InvoiceLine(invoice); var invoiceLine = new Model.Account.SalesInvoice.InvoiceLine(invoice);
int lineId = reader.GetInt32(10); int lineId = reader.GetInt32(10);
invoiceLine.ItemCode = reader.GetString(11); lineItemIds.Add(i, reader.GetInt32(11));
invoiceLine.Account = account[Convert.ToUInt32(reader.GetInt32(12))]; accountIds.Add(i, reader.GetInt32(12));
invoiceLine.UnitAmount = reader.GetDecimal(13); invoiceLine.UnitAmount = reader.GetDecimal(13);
invoiceLine.Quantity = 1; invoiceLine.Quantity = 1;
invoiceLine.TaxCode = taxcode[reader.GetByte(14)]; taxcodeIds.Add(i, reader.GetByte(14));
invoiceLine.SetTaxAdjustmentByTaxTotal(reader.GetDecimal(15)); invoiceLine.SetTaxAdjustmentByTaxTotal(reader.GetDecimal(15));
invoice.InvoiceLineList.Add(invoiceLine); invoice.InvoiceLineList.Add(invoiceLine);
@@ -316,6 +321,30 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
returnList.Add(invoiceId.Value, invoice); returnList.Add(invoiceId.Value, invoice);
} }
} }
// get and add account/tax/item objects to invoice
var dbTaxCodes = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, null, taxcodeIds.Values.ToList());
var dbAccountCodes = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIds.Values.ToList());
var dbLineItems = new InvoiceRepository(_connection, _transaction).GetInvoiceLineItem(lineItemIds.Values.ToList());
i = -1;
foreach (var invoice in returnList.Values)
{
foreach (var line in invoice.InvoiceLineList)
{
i++;
line.TaxCode = dbTaxCodes[taxcodeIds[i]];
line.Account = dbAccountCodes[accountIds[i]];
// fill in missing data for line item, if required
var invoiceLineItem = dbLineItems[lineItemIds[i]];
line.ItemCode = invoiceLineItem.ItemCode;
if (string.IsNullOrEmpty(line.Description))
{
line.Description = invoiceLineItem.Name;
}
}
}
return returnList; return returnList;
} }
@@ -323,57 +352,36 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
// invoice update methods // invoice update methods
// //
/// <summary> public int UpdateInvoiceHeaderDetail(int invoiceId, string invoiceNumber = null, bool? isComplete = null)
/// Update the 'IsComplete' field by invoice id
/// </summary>
/// <param name="updateDictionary">key=ExportAccountInvoiceTypeID, value=IsComplete</param>
/// <returns>Number of row effected</returns>
public int SetInvoiceIsCompleteValue(Dictionary<int, bool> updateDictionary)
{ {
int returnCount = 0; if (invoiceNumber == null && isComplete == null)
foreach (var item in updateDictionary)
{ {
string sql = @" throw new ArgumentException("At least one of the parameters must be set to update invoice header details.");
UPDATE }
tblExportAccountInvoice
SET // build the statement with my helper
IsComplete = @isComplete var sqlupdate = new Core.Data.Database.SqlUpdateBuilder();
WHERE sqlupdate.SetTableName("tblExportAccountInvoice");
ExportAccountInvoiceID = @id if (invoiceNumber != null)
"; sqlupdate.AddUpdateArugment("InvoiceNumber", invoiceNumber);
if (isComplete.HasValue)
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) sqlupdate.AddUpdateArugment("IsComplete", isComplete);
{ sqlupdate.AddWhereArugment("ExportAccountInvoiceID", invoiceId);
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction; using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Parameters.AddWithValue("@id", item.Key); cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@isComplete", item.Value); cmd.CommandText = sqlupdate.GetSqlString();
sqlupdate.AddParametersToSqlCommand(cmd);
returnCount = returnCount + cmd.ExecuteNonQuery();
} return cmd.ExecuteNonQuery();
} }
return returnCount;
} }
// //
// Invoice Delete Methods // Invoice Delete Methods
// //
public int DeleteInvoiceLine(int invoiceLineId)
{
// only being able to delete one line at a time is a design/safety decision
// otherwise, delete whole invoice
if (invoiceLineId <= 0)
{
throw new ArgumentException("InvoiceLineId must be greater than zero.");
}
Core.Data.Database.SqlWhereBuilder sqlWhereBuilder = new Core.Data.Database.SqlWhereBuilder();
sqlWhereBuilder.In("ExportAccountInvoiceLineID", new List<int> { invoiceLineId });
return DeleteInvoiceExecuteInvoiceLine(sqlWhereBuilder);
}
public int DeleteInvoice(IEnumerable<int> invoiceIdList) public int DeleteInvoice(IEnumerable<int> invoiceIdList)
{ {
if (invoiceIdList == null || invoiceIdList.Count() == 0) if (invoiceIdList == null || invoiceIdList.Count() == 0)
@@ -406,6 +414,19 @@ namespace bnhtrade.Core.Data.Database.Repository.Implementation
} }
} }
public int DeleteInvoiceLine(int invoiceLineId)
{
// only being able to delete one line at a time is a design/safety decision
// otherwise, delete whole invoice
if (invoiceLineId <= 0)
{
throw new ArgumentException("InvoiceLineId must be greater than zero.");
}
Core.Data.Database.SqlWhereBuilder sqlWhereBuilder = new Core.Data.Database.SqlWhereBuilder();
sqlWhereBuilder.In("ExportAccountInvoiceLineID", new List<int> { invoiceLineId });
return DeleteInvoiceExecuteInvoiceLine(sqlWhereBuilder);
}
/// <summary> /// <summary>
/// Helper method Only intended for use with ExecuteInvoice() or ExecuteInvoiceLine() /// Helper method Only intended for use with ExecuteInvoice() or ExecuteInvoiceLine()
/// </summary> /// </summary>

View File

@@ -0,0 +1,585 @@
using bnhtrade.Core.Data.Database.Repository.Interface;
using FikaAmazonAPI.AmazonSpApiSDK.Models.EasyShip20220323;
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 InvoiceRepository : _Base, IInvoiceRepository
{
public InvoiceRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public int CreateDefaultInvoiceLineItem(string itemCode)
{
string sql = @"
INSERT INTO tblAccountInvoiceLineItem ( ItemName, ItemCode )
OUTPUT INSERTED.AccountInvoiceLineItemID
VALUES ( @itemName, @itemCode )
";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@itemName", itemCode);
cmd.Parameters.AddWithValue("@itemCode", itemCode);
object obj = cmd.ExecuteScalar();
if (obj == null || obj == DBNull.Value)
{
throw new Exception("Error inserting new defalt invoice line item into database");
}
return (int)obj;
}
}
/// <summary>
/// Retrieves a collection of invoice line items, optionally including account and tax information.
/// </summary>
/// <remarks>This method queries the database to retrieve invoice line items. If <paramref
/// name="includeAccountInfo"/> or <paramref name="includeTaxInfo"/> is set to <see langword="true"/>,
/// additional queries are performed to fetch the corresponding account and tax information, which may impact
/// performance.</remarks>
/// <param name="itemCodes">An optional collection of item codes to filter the results. If <see langword="null"/> or empty, all invoice
/// line items are retrieved.</param>
/// <param name="includeAccountInfo">A value indicating whether to include account information for each invoice line item. If <see
/// langword="true"/>, the default account code is populated for each item. Defaults to <see langword="true"/>.</param>
/// <param name="includeTaxInfo">A value indicating whether to include tax information for each invoice line item. If <see
/// langword="true"/>, the default tax code is populated for each item. Defaults to <see langword="true"/>.</param>
/// <returns>A dictionary where the key is the table record id of the invoice line item, and the value is the
/// corresponding <see cref="Model.Account.InvoiceLineItem"/> object. The dictionary will be empty if no
/// matching items are found.</returns>
public Dictionary<int, Model.Account.InvoiceLineItem> GetInvoiceLineItem(
IEnumerable<int> itemIds = null, IEnumerable<string> itemCodes = null, bool includeAccountInfo = true, bool includeTaxInfo = true
)
{
var sqlwhere = new SqlWhereBuilder();
var returnList = new Dictionary<int, Model.Account.InvoiceLineItem>();
var accountCodeIdList = new Dictionary<int, int>(); // key=LineItemID, value=AccountChartOfID
var taxCodeIdList = new Dictionary<int, int>(); // key=LineItemID, value=AccountTaxCodeID
string sql = @"
SELECT [AccountInvoiceLineItemID]
,[ItemName]
,[ItemCode]
,[ItemDescription]
,[IsNewReviewRequired]
,[InvoiceLineEntryEnable]
,[AccountChartOfID_Default]
,[AccountTaxCodeID_Default]
FROM [e2A].[dbo].[tblAccountInvoiceLineItem]
WHERE 1=1 ";
if (itemCodes != null && itemCodes.Any())
{
sqlwhere.In("ItemCode", itemCodes, "AND");
sql += sqlwhere.SqlWhereString;
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
sqlwhere.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var lineItem = new Model.Account.InvoiceLineItem();
int recordId = reader.GetInt32(0);
lineItem.Name = reader.GetString(1);
lineItem.ItemCode = reader.GetString(2);
if (!reader.IsDBNull(3)) { lineItem.Description = reader.GetString(3); }
lineItem.IsNewReviewRequired = reader.GetBoolean(4);
lineItem.InvoiceLineEntryEnabled = reader.GetBoolean(5);
if (!reader.IsDBNull(6))
{
accountCodeIdList.Add(recordId, reader.GetInt32(6));
}
if (!reader.IsDBNull(7))
{
taxCodeIdList.Add(recordId, reader.GetInt32(7));
}
returnList.Add(recordId, lineItem);
}
}
}
// get account codes and add to result list
if (includeAccountInfo)
{
var accountCodeDictionary = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountCodeIdList.Values.ToList());
foreach (var accountCode in accountCodeIdList)
{
returnList[accountCode.Key].DefaultAccountCode = accountCodeDictionary[accountCode.Value];
}
}
// get tax codes
if (includeTaxInfo)
{
var taxCodeDictionary = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, null, taxCodeIdList.Values.ToList());
foreach (var taxCode in taxCodeIdList)
{
returnList[taxCode.Key].DefaultTaxCode = taxCodeDictionary[taxCode.Value];
}
}
return returnList;
}
public Dictionary<int, Model.Account.PurchaseInvoice> ReadPurchaseInvoice(IEnumerable<int> purchaseInvoiceIdList)
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoice>();
SqlWhereBuilder sqlBuilder = new SqlWhereBuilder();
//build sql query
string sql = @"
SELECT tblPurchase.PurchaseID
,tblPurchase.PurchaseNumber
,tblPurchase.RecordID
,tblPurchase.PurchaseDate
,tblPurchase.ContactID
,tblPurchase.SupplierRef
,tblPurchase.PurchaseTotalAmount
,tblPurchase.VatInclusiveAmounts
,tblPurchase.RecordCreated
,tblPurchase.RecordModified
,tblPurchase.IsActive
,tblAccountCurrency.CurrencyCode
,tblPurchaseChannel.PurchaseChannelName
,tblPurchaseStatus.PurchaseStatus
FROM tblPurchase
LEFT OUTER JOIN tblAccountCurrency ON tblPurchase.AccountCurrencyID = tblAccountCurrency.AccountCurrencyID
LEFT OUTER JOIN tblPurchaseStatus ON tblPurchase.PurchaseStatusID = tblPurchaseStatus.PurchaseStatusID
LEFT OUTER JOIN tblPurchaseChannel ON tblPurchase.PurchaseChannelID = tblPurchaseChannel.PurchaseChannelID
WHERE 1 = 1
";
// build the where statments
if (purchaseInvoiceIdList.Any())
{
sqlBuilder.In("[PurchaseID]", purchaseInvoiceIdList, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// dictionary so we can fill in details afterwards
var invoiceContactDict = new Dictionary<int, int>();
var purchaseIdList = new List<int>();
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int purchaseID = reader.GetInt32(0);
int purchaseNumber = reader.GetInt32(1);
int? recordID = null;
if (!reader.IsDBNull(2)) { recordID = reader.GetInt32(2); }
DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc);
int? contactID = null;
if (!reader.IsDBNull(4)) { contactID = reader.GetInt32(4); }
string supplierRef = null;
if (!reader.IsDBNull(5)) { supplierRef = reader.GetString(5); }
decimal? purchaseTotalAmount = null;
if (!reader.IsDBNull(6)) { purchaseTotalAmount = reader.GetDecimal(6); }
bool vatInclusiveAmounts = reader.GetBoolean(7);
DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc);
DateTime recordModified = DateTime.SpecifyKind(reader.GetDateTime(9), DateTimeKind.Utc);
bool isActive = reader.GetBoolean(10);
string currencyCode = reader.GetString(11);
string purchaseChannelName = reader.GetString(12);
string purchaseStatus = null;
if (!reader.IsDBNull(13)) { purchaseStatus = reader.GetString(13); }
var invoice = new Model.Account.PurchaseInvoice();
invoice.PurchaseID = purchaseID;
invoice.PurchaseNumber = purchaseNumber;
invoice.RecordID = recordID;
invoice.PurchaseDate = purchaseDate;
invoice.SupplierRef = supplierRef;
//invoice.PurchaseTotalAmount = purchaseTotalAmount;
invoice.VatInclusiveAmounts = vatInclusiveAmounts;
invoice.RecordCreated = recordCreated;
invoice.RecordModified = recordModified;
invoice.IsActive = isActive;
invoice.CurrencyCode = currencyCode;
invoice.PurchaseChannel = purchaseChannelName;
// is there contact info that needs to be added?
if (contactID != null)
{
invoiceContactDict.Add(purchaseID, (int)contactID);
}
purchaseIdList.Add(purchaseID);
returnList.Add(purchaseID, invoice);
}
}
}
}
// add contact info
if (invoiceContactDict.Any())
{
var readContact = new Data.Database.Account.ReadContact();
readContact.ContactIdList = invoiceContactDict.Values.ToList();
var contactDict = readContact.Read();
if (contactDict.Any())
{
foreach (var invoice in returnList)
{
if (invoiceContactDict.ContainsKey(invoice.Value.PurchaseID))
{
int contactId = invoiceContactDict[invoice.Value.PurchaseID];
invoice.Value.Contact = contactDict[contactId];
}
}
}
}
// add invoice lines
var lines = ReadPurchaseInvoiceLine(purchaseIdList);
foreach (var invoice in returnList.Values)
{
foreach (var line in lines.Values)
{
if (line.PurchaseId == invoice.PurchaseID)
{
if (invoice.InvoiceLines == null)
{
invoice.InvoiceLines = new List<Model.Account.PurchaseInvoice.Line>();
}
invoice.InvoiceLines.Add(line);
}
}
}
return returnList;
}
/// <summary>
/// Retrieves purchase invoice lines based on specified filters.
/// </summary>
/// <remarks>This method queries the database to retrieve purchase invoice line details that match
/// the provided filters. The filters include invoice IDs, invoice line IDs, statuses, and item descriptions.
/// The returned dictionary maps the purchase line ID to its corresponding <see
/// cref="Model.Account.PurchaseInvoice.Line"/> object.</remarks>
/// <param name="invoiceIdList">A list of purchase invoice IDs to filter the results. If empty, no filtering is applied.</param>
/// <param name="invoiceLineIdList">A list of purchase invoice line IDs to filter the results. If empty, no filtering is applied.</param>
/// <param name="statusList">A list of statuses to filter the results. If empty, no filtering is applied.</param>
/// <param name="itemDescription">Searches for the specificed phases within the item description. Uses the LIKE AND sql function. Partial matches are supported. If empty, no filtering is
/// applied.</param>
/// <returns>A dictionary where the key is the purchase line ID and the value is the corresponding
/// Model.Account.PurchaseInvoice.Line object containing detailed information about the purchase invoice line.</returns>
/// <exception cref="Exception">Thrown if a fail-safe condition is triggered, indicating an unexpected issue with tax code assignment.</exception>
public Dictionary<int, Model.Account.PurchaseInvoice.Line> ReadPurchaseInvoiceLine
(List<int> invoiceIdList = null, List<int> invoiceLineIdList = null, List<string> statusList = null, List<string> itemDescriptionList = null)
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoice.Line>();
var sqlBuilder = new SqlWhereBuilder();
//build sql query
string sql = @"
SELECT tblPurchaseLine.PurchaseLineID
,tblPurchaseLine.PurchaseID
,tblPurchaseLineStatus.PurchaseLineStatus
,tblPurchaseLine.SupplierRef
,tblPurchaseLine.CheckedIn
,tblPurchaseLine.ItemDescription
,tblPurchaseLine.ItemQuantity
,tblPurchaseLine.ItemGross
,tblPurchaseLine.ItemTax
,tblPurchaseLine.ShippingGross
,tblPurchaseLine.ShippingTax
,tblPurchaseLine.OtherGross
,tblPurchaseLine.OtherTax
,tblPurchaseLine.AccountTaxCodeID
,tblPurchaseLine.Tax_AccountTransactionID
,tblPurchaseLine.Net_AccountChartOfID
,tblPurchaseLine.Net_AccountTransactionID
,tblPurchaseLine.RecordCreated
,tblPurchaseLine.RecordModified
,tblPurchaseLine.IsActive
,tblAccountTaxCode.TaxCode
FROM tblPurchaseLine
INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID
LEFT OUTER JOIN tblAccountTaxCode ON tblPurchaseLine.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID
WHERE 1 = 1 ";
// build the where statments
if (invoiceIdList != null || invoiceIdList.Any())
{
sqlBuilder.In("PurchaseID", invoiceLineIdList, "AND");
}
if (invoiceLineIdList != null || invoiceLineIdList.Any())
{
sqlBuilder.In("PurchaseLineID", invoiceLineIdList, "AND");
}
if (statusList != null || statusList.Any())
{
sqlBuilder.In("PurchaseLineStatus", invoiceLineIdList, "AND");
}
if (itemDescriptionList != null || itemDescriptionList.Any())
{
sqlBuilder.LikeAnd("ItemDescription", itemDescriptionList, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// catch taxcode to add in after db read
var lineTaxCodeDict = new Dictionary<int, string>();
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int purchaseLineID = reader.GetInt32(0);
int purchaseID = reader.GetInt32(1);
string purchaseLineStatus = reader.GetString(2);
string supplierRef = null;
if (!reader.IsDBNull(3)) { supplierRef = reader.GetString(3); }
DateTime? checkedIn = null;
if (!reader.IsDBNull(4)) { checkedIn = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc); }
string itemDescription = null;
if (!reader.IsDBNull(5)) { itemDescription = reader.GetString(5); }
int itemQuantity = reader.GetInt32(6);
decimal itemGross = 0;
if (!reader.IsDBNull(7)) { itemGross = reader.GetDecimal(7); }
decimal itemTax = 0;
if (!reader.IsDBNull(8)) { itemTax = reader.GetDecimal(8); }
decimal shippingGross = 0;
if (!reader.IsDBNull(9)) { shippingGross = reader.GetDecimal(9); }
decimal shippingTax = 0;
if (!reader.IsDBNull(10)) { shippingTax = reader.GetDecimal(10); }
decimal otherGross = 0;
if (!reader.IsDBNull(11)) { otherGross = reader.GetDecimal(11); }
decimal otherTax = 0;
if (!reader.IsDBNull(12)) { otherTax = reader.GetDecimal(12); }
int accountTaxCodeID = reader.GetInt32(13);
int? tax_AccountTransactionID = null;
if (!reader.IsDBNull(14)) { tax_AccountTransactionID = reader.GetInt32(14); }
int net_AccountChartOfID = reader.GetInt32(15);
int? net_AccountTransactionID = null;
if (!reader.IsDBNull(16)) { net_AccountTransactionID = reader.GetInt32(16); }
DateTime recordModified;
DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(17), DateTimeKind.Utc);
if (reader.IsDBNull(18)) { recordModified = recordCreated; }
else { recordModified = DateTime.SpecifyKind(reader.GetDateTime(18), DateTimeKind.Utc); }
bool isActive = reader.GetBoolean(19);
string accountTaxCode = reader.GetString(20);
var line = new Model.Account.PurchaseInvoice.Line();
line.PurchaseLineId = purchaseLineID;
line.PurchaseId = purchaseID;
line.Status = purchaseLineStatus;
line.SupplierRef = supplierRef;
line.CheckedIn = checkedIn;
line.ItemDescription = itemDescription;
line.ItemQuantity = itemQuantity;
line.ItemGross = itemGross;
line.ItemTax = itemTax;
line.ShippingGross = shippingGross;
line.ShippingTax = shippingTax;
line.OtherGross = otherGross;
line.OtherTax = otherTax;
line.Tax_AccountTransactionId = tax_AccountTransactionID;
line.Net_AccountChartOfId = net_AccountChartOfID;
line.Net_AccountTransactionId = net_AccountTransactionID;
line.RecordModified = recordModified;
line.RecordCreated = recordCreated;
line.IsActive = isActive;
returnList.Add(purchaseLineID, line);
lineTaxCodeDict.Add(purchaseLineID, accountTaxCode);
}
}
}
}
// read tax codes form db and add to return object
var taxcodeList = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, lineTaxCodeDict.Values.ToList()).Values.ToList();
foreach (var line in returnList.Values)
{
foreach (var taxcode in taxcodeList)
{
if (taxcode.TaxCode == lineTaxCodeDict[line.PurchaseLineId])
{
line.AccountTaxCode = taxcode;
break;
}
}
if (line.AccountTaxCode == null)
{
throw new Exception("Fail safe, this really shouodn't happen");
}
}
// all done
return returnList;
}
public Dictionary<int, Model.Account.PurchaseInvoiceLineStatus> ReadPurchaseInvoiceLineStatus()
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoiceLineStatus>();
string sql = @"
SELECT [PurchaseLineStatusID]
,[PurchaseLineStatus]
,[ListSort]
,[TimeStamp]
FROM [e2A].[dbo].[tblPurchaseLineStatus]
ORDER BY [ListSort]";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
// do something
}
else
{
while (reader.Read())
{
int id = reader.GetInt32(0);
string name = reader.GetString(1);
int lineSort = reader.GetInt32(2);
var returnItem = new Model.Account.PurchaseInvoiceLineStatus(id, name, lineSort);
returnList.Add(id, returnItem);
}
}
}
}
return returnList;
}
public List<Model.Account.PurchaseInvoiceLineSummary> ReadPurchaseInvoiceLineSummary(DateTime periodTo, string lineStatus, List<string> descriptionSearch)
{
var returnList = new List<Model.Account.PurchaseInvoiceLineSummary>();
var sqlBuilder = new bnhtrade.Core.Data.Database.SqlWhereBuilder();
//build sql query
string sql = @"
SELECT tblPurchase.PurchaseDate
,tblPurchase.PurchaseID
,tblPurchase.PurchaseNumber
,tblPurchaseLine.PurchaseLineID
,tblPurchaseLine.ItemDescription
,tblPurchaseLineStatus.PurchaseLineStatus
FROM tblPurchase
INNER JOIN tblPurchaseLine ON tblPurchase.PurchaseID = tblPurchaseLine.PurchaseID
INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID
WHERE tblPurchase.PurchaseDate <= @purchaseDate
";
if (lineStatus != null)
{
sql = sql + " AND PurchaseLineStatus = @purchaseLineStatus ";
}
// build the where statments
if (descriptionSearch.Any())
{
sqlBuilder.LikeAnd("ItemDescription", descriptionSearch, "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;
cmd.Parameters.AddWithValue("@purchaseDate", periodTo);
if (lineStatus != null)
{
cmd.Parameters.AddWithValue("@purchaseLineStatus", lineStatus);
}
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc);
int purchaseID = reader.GetInt32(1);
int purchaseNumber = reader.GetInt32(2);
int purchaseLineID = reader.GetInt32(3);
string itemDescription = reader.GetString(4);
string purchaseLineStatus = reader.GetString(5);
var item = new Model.Account.PurchaseInvoiceLineSummary();
item.PurchaseDate = purchaseDate;
item.PurchaseId = purchaseID;
item.PurchaseNumber = purchaseNumber;
item.PurchaseLineId = purchaseLineID;
item.ItemDescription = itemDescription;
item.LineStatus = purchaseLineStatus;
returnList.Add(item);
}
}
}
return returnList;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,117 @@
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 SkuRepository : _Base, ISkuRepository
{
public SkuRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public int? ReadSkuId(int productId, int conditionId, int accountTaxCodeId)
{
int? returnId = null;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = @"
SELECT
tblSku.skuSkuID
FROM
tblSku
WHERE
(((tblSku.skuProductID)=@productId) AND ((tblSku.skuSkuConditionID)=@conditionId) AND ((tblSku.AccountTaxCodeID)=@accountTaxCodeId));
";
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@productId", productId);
cmd.Parameters.AddWithValue("@conditionId", conditionId);
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
object obj = cmd.ExecuteScalar();
if (obj != null || obj == DBNull.Value)
{
returnId = (int)obj;
}
}
return returnId;
}
public int InsertNewSku(int productId, int conditionId, int accountTaxCodeId)
{
// check tax code id is a valid for SKU
var taxCodeList = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, null, new List<int> { accountTaxCodeId });
if (taxCodeList.ContainsKey(accountTaxCodeId) == false)
{
throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " doesn't exist!");
}
else if (taxCodeList[accountTaxCodeId].IsValidOnIncome == false)
{
throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " is not a valid type for an SKU.");
}
// get info to create sku number
int skuCount;
int skuSuffix;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = "SELECT NEXT VALUE FOR SkuCountSequence;";
cmd.Transaction = _transaction as SqlTransaction;
skuCount = (int)cmd.ExecuteScalar();
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = @"
SELECT tblSkuCondition.scnSkuNumberSuffix
FROM tblSkuCondition
WHERE (((tblSkuCondition.scnSkuConditionID)=@conditionId));";
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@conditionId", conditionId);
try
{
skuSuffix = (int)cmd.ExecuteScalar();
}
catch (Exception ex)
{
throw new Exception("Error retriving SKU number suffix for SkuConditionID=" + conditionId + "." +
System.Environment.NewLine + "Error Message: " + ex.Message);
}
}
string skuNumber = skuCount.ToString("D6") + "-" + skuSuffix.ToString("D2");
// insert new sku
int skuId;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = @"
INSERT INTO tblSku
(skuSkuNumber, skuProductID, skuSkuConditionID, AccountTaxCodeID)
OUTPUT INSERTED.skuSkuID
VALUES
(@skuNumber, @productId, @conditionId, @accountTaxCodeId)";
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@skuNumber", skuNumber);
cmd.Parameters.AddWithValue("@productId", productId);
cmd.Parameters.AddWithValue("@conditionId", conditionId);
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
skuId = (int)cmd.ExecuteScalar();
}
return skuId;
}
}
}

View File

@@ -0,0 +1,141 @@
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 StockRepository : _Base, IStockRepository
{
public StockRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public List<Model.Stock.Status> ReadStatus(List<int> statusIds = null, List<int> statusTypeIds = null)
{
var sqlBuilder = new SqlWhereBuilder();
var returnList = new List<Model.Stock.Status>();
//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())
{
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 Dictionary<int, Model.Stock.StatusType> ReadStatusType()
{
var returnDict = new Dictionary<int, Model.Stock.StatusType>();
// get all account info before we start
var accountDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode();
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = @"
SELECT [StockStatusTypeID]
,[StatusTypeName]
,[ForeignKeyType]
,[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;
}
}
}

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Repository.Implementation namespace bnhtrade.Core.Data.Database.Repository.Implementation
{ {
abstract class _Base public abstract class _Base
{ {
protected readonly IDbConnection _connection; protected readonly IDbConnection _connection;
protected readonly IDbTransaction _transaction; protected readonly IDbTransaction _transaction;

View File

@@ -0,0 +1,13 @@
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 IAccountCodeRepository
{
Dictionary<int, Model.Account.Account> ReadAccountCode(List<int> accountIdList = null, List<int> accountCodeList = null);
}
}

View File

@@ -0,0 +1,15 @@
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 IAccountTaxRepository
{
Dictionary<int, Model.Account.TaxCodeInfo> ReadTaxCodeInfo(bool? IsActive = null, List<string> taxcodeList = null, List<int> taxcodeIdList = null);
Dictionary<string, string> GetTaxCodeBySkuNumber(List<string> skuNumberList);
Dictionary<string, string> ReadTaxCodeByInvoiceLineItemCode(List<string> lineItemCode);
}
}

View File

@@ -0,0 +1,27 @@
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 IAmazonSettlementRepository
{
List<Model.Import.AmazonSettlementHeader> ReadAmazonSettlementHeaderInfoBySettlementId(List<string> settlementIdList);
List<Model.Import.AmazonSettlementHeader> ReadAmazonSettlementHeaderInfoBySpapiReportId(List<string> spapiReportIdList);
Dictionary<int, Model.Import.AmazonSettlement> ReadAmazonSettlements(
List<string> settlementIdList = null, List<string> marketPlaceNameList = null, bool? isProcessed = null,
bool descendingOrder = false, int? returnTop = null);
bool UpdateAmazonSettlementMarketPlaceName(string settlementId, Model.Amazon.MarketPlaceEnum marketPlace);
int UpdateAmazonSettlementIsProcessed(List<string> settlementIdList, bool isProcessed);
bool CreateAmazonSettlements(string filePath, string reportId);
int SetSpapiReportId(string settlementId, string spapiReportId);
}
}

View File

@@ -8,11 +8,11 @@ namespace bnhtrade.Core.Data.Database.Repository.Interface
{ {
internal interface IExportInvoiceRepository internal interface IExportInvoiceRepository
{ {
internal Dictionary<int, Model.Account.SalesInvoice> InsertSalesInvoices(IEnumerable<Model.Account.SalesInvoice> invoiceList); Dictionary<int, Model.Account.SalesInvoice> InsertSalesInvoices(IEnumerable<Model.Account.SalesInvoice> invoiceList);
internal Dictionary<int, string> GetNewInvoiceNumbers(Model.Account.InvoiceType invoiceType); Dictionary<int, string> GetNewInvoiceNumbers(Model.Account.InvoiceType invoiceType);
internal Dictionary<int, Model.Account.SalesInvoice> GetSalesInvoiceById(IEnumerable<int> idList); Dictionary<int, Model.Account.SalesInvoice> GetSalesInvoiceById(IEnumerable<int> idList);
internal int SetInvoiceIsCompleteValue(Dictionary<int, bool> updateDictionary); int UpdateInvoiceHeaderDetail(int invoiceId, string invoiceNumber = null, bool? isComplete = null);
internal int DeleteInvoiceLine(int invoiceLineId); int DeleteInvoiceLine(int invoiceLineId);
internal int DeleteInvoice(IEnumerable<int> invoiceIdList); int DeleteInvoice(IEnumerable<int> invoiceIdList);
} }
} }

View File

@@ -1,25 +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 IImportAmazonRepository
{
public List<Model.Import.AmazonSettlementHeader> ReadAmazonSettlementHeaderInfoBySettlementId(List<string> settlementIdList);
public List<Model.Import.AmazonSettlementHeader> ReadAmazonSettlementHeaderInfoBySpapiReportId(List<string> spapiReportIdList);
public Dictionary<int, Model.Import.AmazonSettlement> ReadAmazonSettlements(
List<string> settlementIdList = null, List<string> marketPlaceNameList = null, bool? isProcessed = null,
bool descendingOrder = false, int? returnTop = null);
public int SetAmazonSettlementIsProcessed(List<string> settlementIdList, bool isProcessed);
public bool CreateAmazonSettlements(string filePath, string reportId);
public int SetSpapiReportId(string settlementId, string spapiReportId);
}
}

View File

@@ -0,0 +1,21 @@
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 IInvoiceRepository
{
int CreateDefaultInvoiceLineItem(string itemCode);
Dictionary<int, Model.Account.InvoiceLineItem> GetInvoiceLineItem(
IEnumerable<int> itemIds = null, IEnumerable<string> itemCodes = null, bool includeAccountInfo = true, bool includeTaxInfo = true
);
Dictionary<int, Model.Account.PurchaseInvoice> ReadPurchaseInvoice(IEnumerable<int> purchaseInvoiceIdList);
Dictionary<int, Model.Account.PurchaseInvoice.Line> ReadPurchaseInvoiceLine
(List<int> invoiceIdList, List<int> invoiceLineIdList, List<string> statusList, List<string> itemDescriptionList);
Dictionary<int, Model.Account.PurchaseInvoiceLineStatus> ReadPurchaseInvoiceLineStatus();
List<Model.Account.PurchaseInvoiceLineSummary> ReadPurchaseInvoiceLineSummary(DateTime periodTo, string lineStatus, List<string> descriptionSearch);
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,14 @@
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 ISkuRepository
{
int? ReadSkuId(int productId, int conditionId, int accountTaxCodeId);
int InsertNewSku(int productId, int conditionId, int accountTaxCodeId);
}
}

View File

@@ -0,0 +1,14 @@
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 IStockRepository
{
List<Model.Stock.Status> ReadStatus(List<int> statusIds = null, List<int> statusTypeIds = null);
Dictionary<int, Model.Stock.StatusType> ReadStatusType();
}
}

View File

@@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.SqlClient; using Microsoft.Data.SqlClient;
namespace bnhtrade.Core.Data.Database.Sku namespace bnhtrade.Core.Data.Database.Sku
{ {
@@ -102,33 +102,7 @@ namespace bnhtrade.Core.Data.Database.Sku
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public int? ByParameters(int productId, int conditionId, int accountTaxCodeId) public int? ByParameters(int productId, int conditionId, int accountTaxCodeId)
{ {
using (SqlConnection conn = new SqlConnection(SqlConnectionString)) throw new NotSupportedException("This method is not supported in GetSkuId. Use SkuRepository instead.");
{
int? returnId = null;
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
SELECT
tblSku.skuSkuID
FROM
tblSku
WHERE
(((tblSku.skuProductID)=@productId) AND ((tblSku.skuSkuConditionID)=@conditionId) AND ((tblSku.AccountTaxCodeID)=@accountTaxCodeId));
", conn))
{
cmd.Parameters.AddWithValue("@productId", productId);
cmd.Parameters.AddWithValue("@conditionId", conditionId);
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
object obj = cmd.ExecuteScalar();
if (obj != null || obj == DBNull.Value)
{
returnId = (int)obj;
}
}
return returnId;
}
} }
} }
} }

View File

@@ -1,85 +0,0 @@
using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductPricing;
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.Sku
{
internal class InsertSku : Connection
{
public int InsertNew(int productId, int conditionId, int accountTaxCodeId)
{
using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
// check tax code id is a valid for SKU
var dbTax = new Data.Database.Account.ReadTaxCode();
var taxCodeList = dbTax.GetByTaxCodeId(new List<int> { accountTaxCodeId });
if (taxCodeList.ContainsKey(accountTaxCodeId) == false)
{
throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " doesn't exist!");
}
else if (taxCodeList[accountTaxCodeId].IsValidOnIncome == false)
{
throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " is not a valid type for an SKU.");
}
// get info to create sku number
int skuCount;
int skuSuffix;
using (SqlCommand cmd = new SqlCommand("SELECT NEXT VALUE FOR SkuCountSequence;", conn))
{
skuCount = (int)cmd.ExecuteScalar();
}
using (SqlCommand cmd = new SqlCommand(@"
SELECT tblSkuCondition.scnSkuNumberSuffix
FROM tblSkuCondition
WHERE (((tblSkuCondition.scnSkuConditionID)=@conditionId));
", conn))
{
cmd.Parameters.AddWithValue("@conditionId", conditionId);
try
{
skuSuffix = (int)cmd.ExecuteScalar();
}
catch (Exception ex)
{
throw new Exception("Error retriving SKU number suffix for SkuConditionID=" + conditionId + "." +
System.Environment.NewLine + "Error Message: " + ex.Message);
}
}
string skuNumber = skuCount.ToString("D6") + "-" + skuSuffix.ToString("D2");
// insert new sku
int skuId;
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblSku
(skuSkuNumber, skuProductID, skuSkuConditionID, AccountTaxCodeID)
OUTPUT INSERTED.skuSkuID
VALUES
(@skuNumber, @productId, @conditionId, @accountTaxCodeId)
", conn))
{
cmd.Parameters.AddWithValue("@skuNumber", skuNumber);
cmd.Parameters.AddWithValue("@productId", productId);
cmd.Parameters.AddWithValue("@conditionId", conditionId);
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
skuId = (int)cmd.ExecuteScalar();
}
scope.Complete();
return skuId;
}
}
}
}

View File

@@ -0,0 +1,132 @@
using bnhtrade.Core.Data.Database._BoilerPlate;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database
{
internal class SqlUpdateBuilder
{
private Dictionary<string, int> _usedUpdateFields = new Dictionary<string, int>();
private Dictionary<string, object> _parameterList = new Dictionary<string, object>();
private string _tableName = string.Empty;
private int _parameterCount = 0;
private string _sqlUpdate = string.Empty;
private string _sqlWhere = string.Empty;
private bool _updateIsSet = false;
private bool _whereIsSet = false;
public SqlUpdateBuilder() { }
public void Innit()
{
_usedUpdateFields.Clear();
_parameterList.Clear();
_tableName = string.Empty;
_parameterCount = 0;
_sqlUpdate = string.Empty;
_sqlWhere = string.Empty;
_updateIsSet = false;
_whereIsSet = false;
}
public void SetTableName(string tableName)
{
if (string.IsNullOrEmpty(tableName))
{
throw new ArgumentException("Table name cannot be null or empty.", nameof(tableName));
}
_tableName = tableName;
}
public void AddUpdateArugment(string columnName, object newValue)
{
if (string.IsNullOrEmpty(columnName) || newValue == null)
{
throw new ArgumentException("Column name and new value cannot be null or empty.");
}
if (_usedUpdateFields.ContainsKey(columnName))
{
throw new ArgumentException($"Column '{columnName}' already exists in the update arguments.", nameof(columnName));
}
// add the update arguments to sql string and parameter list
if (_updateIsSet)
{
_sqlUpdate += @",
";
}
else
{
_updateIsSet = true;
}
_parameterCount++;
_sqlUpdate += columnName + " = @parameter" + _parameterCount;
_parameterList.Add("@parameter" + _parameterCount, newValue);
}
public void AddWhereArugment(string columnName, object value)
{
if (string.IsNullOrEmpty(columnName) || value == null)
{
throw new ArgumentException("Column name and new value cannot be null or empty.");
}
// add the where arguments to sql string and parameter list
if (_whereIsSet)
{
_sqlWhere += @",
";
}
else
{
_whereIsSet = true;
}
_parameterCount++;
_sqlWhere += columnName + " = @parameter" + _parameterCount;
_parameterList.Add("@parameter" + _parameterCount, value);
}
public string GetSqlString()
{
if (_updateIsSet == false || _whereIsSet == false || string.IsNullOrEmpty(_tableName))
{
throw new InvalidOperationException("Table name, update arguments, and where arguments must be set before generating SQL string.");
}
string sql = @"
UPDATE "+ _tableName + @"
SET " + _sqlUpdate + @"
WHERE " + _sqlWhere + ";";
return sql;
}
public void AddParametersToSqlCommand(System.Data.SqlClient.SqlCommand cmd)
{
if (_parameterList != null)
{
foreach (var item in _parameterList)
{
cmd.Parameters.AddWithValue(item.Key, item.Value);
}
}
}
public void AddParametersToSqlCommand(Microsoft.Data.SqlClient.SqlCommand cmd)
{
if (_parameterList != null)
{
foreach (var item in _parameterList)
{
cmd.Parameters.AddWithValue(item.Key, item.Value);
}
}
}
}
}

View File

@@ -63,6 +63,21 @@ namespace bnhtrade.Core.Data.Database
} }
} }
public bool ParameterListIsSet
{
get
{
if (ParameterList == null || ParameterList.Any() == false)
{
return false;
}
else
{
return true;
}
}
}
/// <summary> /// <summary>
/// Initialises the class /// Initialises the class
/// </summary> /// </summary>
@@ -154,7 +169,7 @@ namespace bnhtrade.Core.Data.Database
int listCount = distinctList.Count(); int listCount = distinctList.Count();
for (int i = 0; i < listCount; i++, parameterCount++) for (int i = 0; i < listCount; i++)
{ {
if (i > 0) if (i > 0)
{ {
@@ -170,15 +185,58 @@ namespace bnhtrade.Core.Data.Database
sqlWhere += " ( " + columnReference + " LIKE '%' + "; sqlWhere += " ( " + columnReference + " LIKE '%' + ";
string param = "@parameter" + parameterCount;
sqlWhere += param;
ParameterList.Add(param, distinctList[i]);
sqlWhere += " + '%' ) "; sqlWhere = sqlWhere + GetSetParameter(distinctList[i]) + " + '%' ) ";
} }
SqlWhereString = SqlWhereString + sqlWhere; SqlWhereString = SqlWhereString + sqlWhere;
} }
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;
}
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 = @"
";
if (wherePrefix != null)
{
sqlWhereString += wherePrefix;
}
sqlWhereString += " ( " + columnReference + " = " + GetSetParameter(stringValue) + " ) ";
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>
@@ -205,16 +263,14 @@ namespace bnhtrade.Core.Data.Database
sqlWhere += " " + columnReference + " IN ( "; sqlWhere += " " + columnReference + " IN ( ";
int listCount = distinctList.Count(); int listCount = distinctList.Count();
for (int i = 0; i < listCount; i++, parameterCount++) for (int i = 0; i < listCount; i++)
{ {
if (i > 0) if (i > 0)
{ {
sqlWhere += ", "; sqlWhere += ", ";
} }
string param = "@parameter" + parameterCount; sqlWhere = sqlWhere + GetSetParameter(distinctList[i].ToString());
sqlWhere += param;
ParameterList.Add(param, distinctList[i]);
} }
sqlWhere += " ) "; sqlWhere += " ) ";
@@ -298,5 +354,19 @@ namespace bnhtrade.Core.Data.Database
In(columnReference, objectList, wherePrefix); In(columnReference, objectList, wherePrefix);
} }
/// <summary>
/// Adds a string value to the ParameterList and returns '@parameterN' that is then appended to the SQL statement
/// i.e. @parameter1, @parameter2, etc.
/// </summary>
/// <param name="value">parameter string that is then appended to the SQL statement</param>
/// <returns></returns>
private string GetSetParameter(string value)
{
parameterCount++;
string parameterString = "@parameter" + parameterCount;
ParameterList.Add(parameterString, value);
return parameterString;
}
} }
} }

View File

@@ -1,115 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static bnhtrade.Core.Data.Database.Constants;
namespace bnhtrade.Core.Data.Database.Stock
{
internal class Status : Connection
{
private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder;
public List<int> StatusIds { get; set; }
public List<int> StatusTypeIds { get; set; }
public Status ()
{
Init();
}
public void Init()
{
sqlBuilder = new SqlWhereBuilder();
StatusIds = new List<int>();
StatusTypeIds = new List<int>();
}
public List<Model.Stock.Status> Read()
{
var returnList = new List<Model.Stock.Status>();
sqlBuilder.Init();
//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 (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
var typeDict = new Data.Database.Stock.StatusType().Read();
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;
}
}
}

View File

@@ -1,63 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Stock
{
public class StatusType : Connection
{
public StatusType()
{
}
/// <summary>
/// Reads all Status Types from database
/// </summary>
/// <returns></returns>
public Dictionary<int, Model.Stock.StatusType> Read()
{
var returnDict = new Dictionary<int, Model.Stock.StatusType>();
// get all account info before we start
var accountDict = new Data.Database.Account.ReadAccountCode().All();
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
SELECT [StockStatusTypeID]
,[StatusTypeName]
,[ForeignKeyType]
,[ReferenceType]
,[AccountChartOfID]
FROM [e2A].[dbo].[tblStockStatusType]
", conn))
{
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[accountId]);
returnDict.Add(statusTypeId, statusType);
}
}
}
}
return returnDict;
}
}
}

View File

@@ -8,7 +8,7 @@ using System.Configuration;
namespace bnhtrade.Core.Data.Database.UnitOfWork namespace bnhtrade.Core.Data.Database.UnitOfWork
{ {
internal class Connection public class Connection
{ {
//protected readonly string SqlConnectionString; //protected readonly string SqlConnectionString;
private Model.Credentials.bnhtradeDB _dbCredentials; private Model.Credentials.bnhtradeDB _dbCredentials;

View File

@@ -10,10 +10,16 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
internal interface IUnitOfWork : IDisposable internal interface IUnitOfWork : IDisposable
{ {
// Properties for repositories, add here for each repository // Properties for repositories, add here for each repository
public ICurrencyRepository CurrencyRepository { get; } IAccountCodeRepository AccountCodeRepository { get; }
IAccountTaxRepository AccountTaxRepository { get; }
ICurrencyRepository CurrencyRepository { get; }
IExportInvoiceRepository ExportInvoiceRepository { get; } IExportInvoiceRepository ExportInvoiceRepository { get; }
IImportAmazonRepository ImportAmazonRepository { get; } IAmazonSettlementRepository AmazonSettlementRepository { get; }
IInvoiceRepository InvoiceRepository { get; }
IJournalRepository JournalRepository { get; }
ISequenceGenerator SequenceGenerator { get; } ISequenceGenerator SequenceGenerator { get; }
ISkuRepository SkuRepository { get; }
IStockRepository StockRepository { get; }
// Methods to manage the transaction // Methods to manage the transaction
void Commit(); void Commit();

View File

@@ -18,18 +18,60 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
private bool _disposed; private bool _disposed;
// Private field for lazy loading, add here for each repository // Private field for lazy loading, add here for each repository
private IAccountCodeRepository _accountCodeRepository;
private IAccountTaxRepository _accountTaxRepository;
private IAmazonSettlementRepository _amazonSettlementRepository;
private ICurrencyRepository _currencyRepository; private ICurrencyRepository _currencyRepository;
private IExportInvoiceRepository _exportInvoiceRepository; private IExportInvoiceRepository _exportInvoiceRepository;
private IImportAmazonRepository _importAmazonRepository; private IInvoiceRepository _invoiceRepository;
private IJournalRepository _journalRepository;
private ISequenceGenerator _sequenceGenerator; private ISequenceGenerator _sequenceGenerator;
private ISkuRepository _skuRepository;
private IStockRepository _stockRepository;
public UnitOfWork() internal UnitOfWork()
{ {
_connection = new SqlConnection(this.SqlConnectionString); _connection = new SqlConnection(this.SqlConnectionString);
_connection.Open(); _connection.Open();
_transaction = _connection.BeginTransaction(); _transaction = _connection.BeginTransaction();
} }
public IAccountCodeRepository AccountCodeRepository
{
get
{
if (_accountCodeRepository == null)
{
_accountCodeRepository = new AccountCodeRepository(_connection, _transaction);
}
return _accountCodeRepository;
}
}
public IAccountTaxRepository AccountTaxRepository
{
get
{
if (_accountTaxRepository == null)
{
_accountTaxRepository = new AccountTaxRepository(_connection, _transaction);
}
return _accountTaxRepository;
}
}
public IAmazonSettlementRepository AmazonSettlementRepository
{
get
{
if (_amazonSettlementRepository == null)
{
_amazonSettlementRepository = new AmazonSettlementRepository(_connection, _transaction);
}
return _amazonSettlementRepository;
}
}
// Properties for repositories, add here for each repository // Properties for repositories, add here for each repository
public ICurrencyRepository CurrencyRepository public ICurrencyRepository CurrencyRepository
{ {
@@ -55,15 +97,26 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
} }
} }
public IImportAmazonRepository ImportAmazonRepository public IInvoiceRepository InvoiceRepository {
get
{
if (_invoiceRepository == null)
{
_invoiceRepository = new InvoiceRepository(_connection, _transaction);
}
return _invoiceRepository;
}
}
public IJournalRepository JournalRepository
{ {
get get
{ {
if (_importAmazonRepository == null) if (_journalRepository == null)
{ {
_importAmazonRepository = new ImportAmazonRepository(_connection, _transaction); _journalRepository = new JournalRepository(_connection, _transaction);
} }
return _importAmazonRepository; return _journalRepository;
} }
} }
@@ -79,6 +132,30 @@ namespace bnhtrade.Core.Data.Database.UnitOfWork
} }
} }
public ISkuRepository SkuRepository
{
get
{
if (_skuRepository == null)
{
_skuRepository = new SkuRepository(_connection, _transaction);
}
return _skuRepository;
}
}
public IStockRepository StockRepository
{
get
{
if (_stockRepository == null)
{
_stockRepository = new StockRepository(_connection, _transaction);
}
return _stockRepository;
}
}
public void Commit() public void Commit()
{ {
try try

View File

@@ -94,10 +94,8 @@ namespace bnhtrade.Core.Data.Xero
public string BrandingTheme { get; set; } public string BrandingTheme { get; set; }
} }
internal void ExportToCsv(List<Core.Model.Account.SalesInvoice> salesInvoiceList, int startingInvoiceNumber, string savePath, bool unitAmountIsTaxExclusive = true) internal void ExportToCsv(List<Core.Model.Account.SalesInvoice> salesInvoiceList, string savePath, bool unitAmountIsTaxExclusive = true)
{ {
int invoiceNumberCount = startingInvoiceNumber;
// convert invoice to unitAmountIsTaxExclusive = true // convert invoice to unitAmountIsTaxExclusive = true
foreach (var invoice in salesInvoiceList) foreach (var invoice in salesInvoiceList)
{ {
@@ -123,7 +121,7 @@ namespace bnhtrade.Core.Data.Xero
} }
string contactName = invoice.ContactName; string contactName = invoice.ContactName;
string invoiceNumber = "INV-" + invoiceNumberCount.ToString("000000"); string invoiceNumber = invoice.InvoiceNumber;
string reference = invoice.InvoiceReference; string reference = invoice.InvoiceReference;
string invoiceDate = invoice.InvoiceDate.GetValueOrDefault().ToString("dd MMM yyyy", CultureInfo.InvariantCulture); string invoiceDate = invoice.InvoiceDate.GetValueOrDefault().ToString("dd MMM yyyy", CultureInfo.InvariantCulture);
string dueDate = invoice.InvoiceDueDate.GetValueOrDefault().ToString("dd MMM yyyy", CultureInfo.InvariantCulture); string dueDate = invoice.InvoiceDueDate.GetValueOrDefault().ToString("dd MMM yyyy", CultureInfo.InvariantCulture);
@@ -153,8 +151,6 @@ namespace bnhtrade.Core.Data.Xero
csvLineList.Add(csvLine); csvLineList.Add(csvLine);
} }
invoiceNumberCount++;
} }
var config = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.CurrentCulture); var config = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.CurrentCulture);

View File

@@ -6,18 +6,18 @@ using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Account namespace bnhtrade.Core.Logic.Account
{ {
public class GetAccountCodeInfo public class AccountCodeService : UnitOfWorkBase
{ {
private Data.Database.Account.ReadAccountCode readAccountCode; public AccountCodeService()
public GetAccountCodeInfo()
{ {
readAccountCode = new Data.Database.Account.ReadAccountCode();
} }
public Dictionary<uint, Model.Account.Account> GetAll() public Dictionary<int, Model.Account.Account> GetAll()
{ {
return readAccountCode.All(); return WithUnitOfWork(uow =>
{
return uow.AccountCodeRepository.ReadAccountCode();
});
} }
public Model.Account.Account ByAccountCode(int accountCode) public Model.Account.Account ByAccountCode(int accountCode)
@@ -35,7 +35,10 @@ namespace bnhtrade.Core.Logic.Account
public List<Model.Account.Account> ByAccountCode(List<int> accountCodeList) public List<Model.Account.Account> ByAccountCode(List<int> accountCodeList)
{ {
return readAccountCode.ByAccountCode(accountCodeList).Values.ToList(); return WithUnitOfWork(uow =>
{
return uow.AccountCodeRepository.ReadAccountCode(null, accountCodeList).Values.ToList();
});
} }
public Dictionary<int, Model.Account.Account> ConvertToDictionary(List<Model.Account.Account> accountCodeList) public Dictionary<int, Model.Account.Account> ConvertToDictionary(List<Model.Account.Account> accountCodeList)

View File

@@ -3,21 +3,22 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms;
namespace bnhtrade.Core.Logic.Account namespace bnhtrade.Core.Logic.Account
{ {
public class GetTaxCodeInfo public class GetTaxCodeInfo : UnitOfWorkBase
{ {
private Data.Database.Account.ReadTaxCode dbRead;
public GetTaxCodeInfo() public GetTaxCodeInfo()
{ {
dbRead = new Data.Database.Account.ReadTaxCode();
} }
public List<Model.Account.TaxCodeInfo> GetByTaxCode(List<string> taxCodeList) public List<Model.Account.TaxCodeInfo> GetByTaxCode(List<string> taxCodeList)
{ {
return dbRead.GetByTaxCode(taxCodeList); return WithUnitOfWork(uow =>
{
return uow.AccountTaxRepository.ReadTaxCodeInfo(null, taxCodeList).Values.ToList();
});
} }
public Model.Account.TaxCodeInfo GetByTaxCode(string taxCode) public Model.Account.TaxCodeInfo GetByTaxCode(string taxCode)
@@ -48,7 +49,11 @@ namespace bnhtrade.Core.Logic.Account
} }
// get db list // get db list
var dbList = dbRead.GetTaxCodeBySkuNumber(skuNumberList); var dbList = WithUnitOfWork(uow =>
{
return uow.AccountTaxRepository.GetTaxCodeBySkuNumber(skuNumberList);
});
// build dictionary // build dictionary
foreach (var item in dbList) foreach (var item in dbList)

View File

@@ -1,4 +1,5 @@
using System; using bnhtrade.Core.Data.Database.UnitOfWork;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -6,9 +7,17 @@ using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Account namespace bnhtrade.Core.Logic.Account
{ {
public class InvoiceLineItemService public class InvoiceLineItemService : UnitOfWorkBase
{ {
private Logic.Log.LogEvent log = new Logic.Log.LogEvent(); private Logic.Log.LogEvent _log = new Logic.Log.LogEvent();
public InvoiceLineItemService()
{
}
internal InvoiceLineItemService(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
/// <summary> /// <summary>
/// Creates new 'default' item code entry. The item code and title are set, will require updating by user before use. /// Creates new 'default' item code entry. The item code and title are set, will require updating by user before use.
@@ -17,25 +26,32 @@ namespace bnhtrade.Core.Logic.Account
/// <returns></returns> /// <returns></returns>
public Model.Account.InvoiceLineItem CreateNew(string itemCode) public Model.Account.InvoiceLineItem CreateNew(string itemCode)
{ {
new Data.Database.Account.CreateInvoiceLineItem().CreateDefault(itemCode); return WithUnitOfWork(uow =>
var item = new Data.Database.Account.ReadInvoiceLineItem().ByItemCode(new List<string> { itemCode });
if (item == null || item.Count == 0)
{ {
log.LogError("InvoiceLineItemService.CreateNew", "Error creating new invoice line item in database for item code: " + itemCode); uow.InvoiceRepository.CreateDefaultInvoiceLineItem(itemCode);
throw new Exception("Error creating new invoice line item in database"); var item = uow.InvoiceRepository.GetInvoiceLineItem(null, new List<string> { itemCode });
} if (item == null || item.Count == 0)
return item[0]; {
_log.LogError("InvoiceLineItemService.CreateNew", "Error creating new invoice line item in database for item code: " + itemCode);
throw new Exception("Error creating new invoice line item in database");
}
CommitIfOwned(uow);
return item[0];
});
} }
public Dictionary<string, Model.Account.InvoiceLineItem> GetLineItems(List<string> itemCodes) public Dictionary<string, Model.Account.InvoiceLineItem> GetLineItems(List<string> itemCodes)
{ {
var dbResult = new Data.Database.Account.ReadInvoiceLineItem().ByItemCode(itemCodes); return WithUnitOfWork(uow =>
var returnDict = new Dictionary<string, Model.Account.InvoiceLineItem>();
foreach ( var item in dbResult)
{ {
returnDict.Add(item.Value.ItemCode, item.Value); var dbResult = uow.InvoiceRepository.GetInvoiceLineItem(null, itemCodes);
} var returnDict = new Dictionary<string, Model.Account.InvoiceLineItem>();
return returnDict; foreach (var item in dbResult)
{
returnDict.Add(item.Value.ItemCode, item.Value);
}
return returnDict;
});
} }
} }
} }

View File

@@ -8,7 +8,7 @@ using System.Transactions;
namespace bnhtrade.Core.Logic.Account namespace bnhtrade.Core.Logic.Account
{ {
public class Journal public class Journal : UnitOfWorkBase
{ {
public int AccountJournalInsert(int journalTypeId, DateTime entryDate, string currencyCode, public int AccountJournalInsert(int journalTypeId, DateTime entryDate, string currencyCode,
decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false) decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false)
@@ -19,7 +19,12 @@ namespace bnhtrade.Core.Logic.Account
public bool AccountJournalDelete(int accountJournalId) public bool AccountJournalDelete(int accountJournalId)
{ {
return new Data.Database.Account.DeleteJournal().AccountJournalDelete(accountJournalId); return WithUnitOfWork(uow =>
{
bool result = uow.JournalRepository.DeleteJournal(accountJournalId);
CommitIfOwned(uow);
return result;
});
} }
} }
} }

View File

@@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Account
{
public class PurchaseInvoice
{
/// <summary>
/// Get purchase invoices by id
/// </summary>
/// <param name="purchaseIdList">purchase id list</param>
/// <returns>dictionary where key=id, value=purchaseinvoice</returns>
public Dictionary<int, Model.Account.PurchaseInvoice> GetPurchaseInvoice(IEnumerable<int> purchaseIdList)
{
var dbRead = new Data.Database.Account.ReadPurchaseInvoice();
dbRead.PurchaseInvoiceIdList = purchaseIdList;
return dbRead.Read();
}
}
}

View File

@@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Account
{
public class PurchaseInvoiceMisc
{
public List<Model.Account.PurchaseInvoiceLineStatus> ReadLineStatusToList()
{
return new Data.Database.Account.ReadPurchaseInvoiceLineStatus().Read().Values.ToList();
}
public List<Model.Account.PurchaseInvoiceLineSummary> GetLineSummary(DateTime maxDate, string lineStatus, List<string> wordSearchList)
{
return new Data.Database.Account.ReadPurchaseInvoiceLineSummary().Read(maxDate,lineStatus, wordSearchList);
}
}
}

View File

@@ -0,0 +1,55 @@
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.Account
{
public class PurchaseInvoiceService : UnitOfWorkBase
{
public PurchaseInvoiceService() { }
internal PurchaseInvoiceService(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
/// <summary>
/// Get purchase invoices by id
/// </summary>
/// <param name="purchaseIdList">purchase id list</param>
/// <returns>dictionary where key=id, value=purchaseinvoice</returns>
public Dictionary<int, Model.Account.PurchaseInvoice> GetPurchaseInvoice(IEnumerable<int> purchaseIdList)
{
return WithUnitOfWork(uow =>
{
var invoiceRepository = uow.InvoiceRepository;
var returnList = invoiceRepository.ReadPurchaseInvoice(purchaseIdList);
return returnList;
});
}
public List<Model.Account.PurchaseInvoiceLineStatus> ReadLineStatusToList()
{
return WithUnitOfWork(uow =>
{
var invoiceRepository = uow.InvoiceRepository;
var returnList = invoiceRepository.ReadPurchaseInvoiceLineStatus().Values.ToList();
return returnList;
});
}
public List<Model.Account.PurchaseInvoiceLineSummary> GetLineSummary(DateTime maxDate, string lineStatus, List<string> wordSearchList)
{
return WithUnitOfWork(uow =>
{
var invoiceRepository = uow.InvoiceRepository;
var returnList = invoiceRepository.ReadPurchaseInvoiceLineSummary(maxDate, lineStatus, wordSearchList);
return returnList;
});
}
}
}

View File

@@ -1,5 +1,6 @@
using Amazon.SQS.Model.Internal.MarshallTransformations; using Amazon.SQS.Model.Internal.MarshallTransformations;
using bnhtrade.Core.Data.Database.UnitOfWork; using bnhtrade.Core.Data.Database.UnitOfWork;
using bnhtrade.Core.Model.Account;
using bnhtrade.Core.Model.Amazon; using bnhtrade.Core.Model.Amazon;
using bnhtrade.Core.Test.Export; using bnhtrade.Core.Test.Export;
using FikaAmazonAPI.ReportGeneration.ReportDataTable; using FikaAmazonAPI.ReportGeneration.ReportDataTable;
@@ -17,24 +18,18 @@ using static bnhtrade.Core.Model.Import.AmazonSettlement;
namespace bnhtrade.Core.Logic.Export.AccountInvoice namespace bnhtrade.Core.Logic.Export.AccountInvoice
{ {
internal class AmazonSettlement : Data.Database.Connection internal class AmazonSettlement : UnitOfWorkBase
{ {
private readonly IUnitOfWork _providedUnitOfWork = null;
private readonly bool _ownsUnitOfWork = false;
private Logic.Log.LogEvent _log = new Logic.Log.LogEvent(); private Logic.Log.LogEvent _log = new Logic.Log.LogEvent();
private List<string> _lineItemCodeList = new List<string>(); private List<string> _lineItemCodeList = new List<string>();
private bool _settlementAmountIsTaxExclusive = false; // i.e. they're tax inclusive private bool _settlementAmountIsTaxExclusive = false; // i.e. they're tax inclusive
public AmazonSettlement() public AmazonSettlement()
{ {
_ownsUnitOfWork = true;
} }
internal AmazonSettlement(IUnitOfWork unitOfWork) internal AmazonSettlement(IUnitOfWork unitOfWork) : base(unitOfWork)
{ {
_providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
_ownsUnitOfWork = false;
} }
public string ErrorMessage { get; private set; } public string ErrorMessage { get; private set; }
@@ -53,34 +48,34 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
Init(); Init();
_log.LogInformation("Starting processing of Amazon settlement data into export invoice table..."); _log.LogInformation("Starting processing of Amazon settlement data into export invoice table...");
// get list of unprocessed settlement reports to export return WithUnitOfWork(uow =>
var settlementList = GetListOfUnprocessedSettlementReports();
if (settlementList == null)
{ {
return false; // get list of unprocessed settlement reports to export
} var settlementList = GetUnprocessedSettlementReports(uow, true);
if (settlementList == null)
{
return false;
}
// create list of settlement ids for later use // create list of settlement ids for later use
var settlementIdList = new List<string>(); var settlementIdList = new List<string>();
foreach (var settlement in settlementList) foreach (var settlement in settlementList)
{ {
settlementIdList.Add(settlement.SettlementId); settlementIdList.Add(settlement.SettlementId);
} }
// create list of invoices from settlement reports // create list of invoices from settlement reports
var invoiceList = CreateInvoices(settlementList, convertToGbp); var invoiceList = CreateInvoices(settlementList, convertToGbp);
if (invoiceList == null || invoiceList.Any() == false) if (invoiceList == null || invoiceList.Any() == false)
{ {
return false; return false;
} }
// add invoice to export queue and set settlements as processed // add invoice to export queue and set settlements as processed
Console.Write("\rWriting to database... "); Console.Write("\rWriting to database... ");
using (UnitOfWork unitOfWork = new UnitOfWork())
{
try try
{ {
var queueService = new Logic.Export.AccountInvoice.QueueService(unitOfWork); var queueService = new Logic.Export.AccountInvoice.QueueService(uow);
// add temp invoice numbers // add temp invoice numbers
queueService.AddTempInvoiceNumber(invoiceList, true); queueService.AddTempInvoiceNumber(invoiceList, true);
@@ -89,12 +84,15 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
if (queueService.ErrorMessageIsSet == false && queueInsertResult.Count() == invoiceList.Count()) if (queueService.ErrorMessageIsSet == false && queueInsertResult.Count() == invoiceList.Count())
{ {
// set settlements to isprocessed // set settlements to isprocessed
unitOfWork.ImportAmazonRepository.SetAmazonSettlementIsProcessed(settlementIdList, true); uow.AmazonSettlementRepository.UpdateAmazonSettlementIsProcessed(settlementIdList, true);
unitOfWork.Commit(); uow.Commit();
Console.Write("\r");
_log.LogInformation("\rFinished processing of Amazon settlement data. " + invoiceList.Count() + " invoices created from " + settlementIdList.Count() + " Amazon settlement reports.");
return true;
} }
else else
{ {
unitOfWork.Rollback(); uow.Rollback();
string error = queueService.ErrorMessage; string error = queueService.ErrorMessage;
ErrorMessage = "Cancelled processing of Amazon settlement data into export invoice table. " + error; ErrorMessage = "Cancelled processing of Amazon settlement data into export invoice table. " + error;
_log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table..."); _log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table...");
@@ -109,115 +107,115 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
_log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table..."); _log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table...");
return false; return false;
} }
} });
Console.Write("\r");
_log.LogInformation("\rFinished processing of Amazon settlement data. " + invoiceList.Count() + " invoices created from " + settlementIdList.Count() + " Amazon settlement reports.");
return true;
} }
/// <summary> /// <summary>
/// Retrives a list of unprocessed settlement reports from the database, checks for gaps in settlement periods, and validates /// Retrives a list of unprocessed settlement reports from the database, checks for gaps in settlement periods, and validates
/// the settlement data. /// the settlement data.
/// </summary> /// </summary>
/// <param name="newMarketplaceNameList">Import will fail on new marketplace, add here to bypass this check</param> /// <param name="updateNullMarketplaceByCurrency">Insert 'Amazon.co.uk' if the market place name is missing and the currecy is GBP</param>
/// <returns></returns> /// <returns></returns>
private List<Model.Import.AmazonSettlement> GetListOfUnprocessedSettlementReports() private List<Model.Import.AmazonSettlement> GetUnprocessedSettlementReports(IUnitOfWork uow, bool updateNullMarketplaceByCurrency = true)
{ {
List<Model.Import.AmazonSettlement> settlementList = null; List<Model.Import.AmazonSettlement> settlementList = null;
IUnitOfWork currentUow = null; // get list of unprocessed settlement reports to export
if (_ownsUnitOfWork) settlementList = uow.AmazonSettlementRepository.ReadAmazonSettlements(null, null, false).Values.ToList();
if (settlementList.Any() == false)
{ {
currentUow = new UnitOfWork(); ErrorMessage = "No new settlement reports to process";
} return null;
else
{
currentUow = _providedUnitOfWork;
} }
// get list of unprocssed settlement reports to export // test marketplace-name has been sucsessfully entered into settlement table --
using (currentUow != null && _ownsUnitOfWork ? currentUow : null) // as this is not supplied in the original report from Amazon and has to be inferred from settlement line data or added below
// via currency (null marketplace anme is not picked up in validate stage as null value is valid)
foreach (var settlement in settlementList)
{ {
settlementList = currentUow.ImportAmazonRepository.ReadAmazonSettlements(null, null, false).Values.ToList(); if (settlement.MarketPlaceNameIsSet == false && updateNullMarketplaceByCurrency && settlement.CurrencyCode == CurrencyCode.GBP.ToString())
if (settlementList.Any() == false)
{ {
ErrorMessage = "No new settlement reports to process"; // update database with market place name
uow.AmazonSettlementRepository.UpdateAmazonSettlementMarketPlaceName(
settlement.SettlementId
, MarketPlaceEnum.AmazonUK
);
// add to settlement
settlement.MarketPlace = MarketPlaceEnum.AmazonUK;
}
else if (settlement.MarketPlaceNameIsSet == false)
{
string error = "User action required: Enter market place name for amazon settlelment report id:" + settlement.SettlementId + ".";
ErrorMessage = "Cancelled processing of Amazon settlement data into export invoice table: " + error;
_log.LogError(
error
, "Unable to process settlement data from report '" + settlement.SettlementId +
"'. Report header table requires a market place name, which is not supplied in original " +
"report from Amazon. This is useually inferred from settlement lines. " +
"However, in this case, it was not not possible. Manual edit/entry for database table required."
);
_log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table...");
return null; return null;
} }
}
// test marketplace-name has been sucsessfully entered into settlement table -- // check for time gaps between settlement periods
// as this is not supplied in the original report from Amazon and has to be inferred from settlement line data settlementList = settlementList.OrderBy(x => x.MarketPlace).ThenBy(x => x.StartDate).ToList();
// this is not picked up in validate stage as null value is valid for (var i = 0; i < settlementList.Count; i++)
foreach (var settlement in settlementList) {
// first marketplace of type in list? retrive the previously completed settlement for that marketplace to compare datetimes
if (i == 0 || settlementList[i].MarketPlace != settlementList[i - 1].MarketPlace)
{ {
if (settlement.MarketPlaceNameIsSet == false) // get previously completed settlement for this marketplace
var completedSettlement = uow.AmazonSettlementRepository.ReadAmazonSettlements(
null, new List<string> { settlementList[i].MarketPlace.GetMarketplaceUrl() }, true, true, 1);
if (completedSettlement.Any())
{ {
string error = "User action required: Enter market place name for amazon settlelment report id:" + settlement.SettlementId + "."; if (completedSettlement.FirstOrDefault().Value.EndDate != settlementList[i].StartDate)
ErrorMessage = "Cancelled processing of Amazon settlement data into export invoice table: " + error;
_log.LogError(
error
, "Unable to process settlement data from report '" + settlement.SettlementId +
"'. Report header table requires a market place name, which is not supplied in original " +
"report from Amazon. This is useually inferred from settlement lines. " +
"However, in this case, it was not not possible. Manual edit/entry for database table required."
);
_log.LogInformation("Cancelled processing of Amazon settlement data into export invoice table...");
return null;
}
}
// check for time gaps between settlement periods
settlementList = settlementList.OrderBy(x => x.MarketPlace).ThenBy(x => x.StartDate).ToList();
for (var i = 0; i < settlementList.Count; i++)
{
// first marketplace of type in list? retrive the previously completed settlement for that marketplace to compare datetimes
if (i == 0 || settlementList[i].MarketPlace != settlementList[i - 1].MarketPlace)
{
// get previously completed settlement for this marketplace
var completedSettlement = currentUow.ImportAmazonRepository.ReadAmazonSettlements(
null, new List<string> { settlementList[i].MarketPlace.GetMarketplaceUrl() }, true, true, 1);
if (completedSettlement.Any())
{
if (completedSettlement.FirstOrDefault().Value.EndDate != settlementList[i].StartDate)
{
string error = (settlementList[i].StartDate - settlementList[i - 1].EndDate).Days + " day gap in "
+ settlementList[i].MarketPlace.GetMarketplaceUrl() + " settlement data (" + settlementList[i - 1].EndDate.ToString("dd MMM yyyy")
+ " to " + settlementList[i].StartDate.ToString("dd MMM yyyy") + "). Ensure all settlement reports have been imported.";
ErrorMessage = error;
_log.LogError("Cancelled processing of Amazon settlement data into invoice export queue: " + error);
return null;
}
}
else
{
// first settlement for this marketplace, no previous settlement to compare against
// continue on
}
}
else
{
if (settlementList[i - 1].EndDate != settlementList[i].StartDate)
{ {
string error = (settlementList[i].StartDate - settlementList[i - 1].EndDate).Days + " day gap in " string error = (settlementList[i].StartDate - settlementList[i - 1].EndDate).Days + " day gap in "
+ settlementList[i].MarketPlace + " settlement data (" + settlementList[i - 1].EndDate.ToString("dd MMM yyyy") + settlementList[i].MarketPlace.GetMarketplaceUrl() + " settlement data (" + settlementList[i - 1].EndDate.ToString("dd MMM yyyy")
+ " to " + settlementList[i].StartDate.ToString("dd MMM yyyy") + "). Ensure all settlement reports have been imported."; + " to " + settlementList[i].StartDate.ToString("dd MMM yyyy") + "). Ensure all settlement reports have been imported.";
ErrorMessage = error; ErrorMessage = error;
_log.LogError("Cancelled processing of Amazon settlement data into invoice export queue: " + error); _log.LogError("Cancelled processing of Amazon settlement data into invoice export queue: " + error);
return null; return null;
} }
} }
else
{
// first settlement for this marketplace, no previous settlement to compare against
// continue on
}
}
else
{
if (settlementList[i - 1].EndDate != settlementList[i].StartDate)
{
string error = (settlementList[i].StartDate - settlementList[i - 1].EndDate).Days + " day gap in "
+ settlementList[i].MarketPlace + " settlement data (" + settlementList[i - 1].EndDate.ToString("dd MMM yyyy")
+ " to " + settlementList[i].StartDate.ToString("dd MMM yyyy") + "). Ensure all settlement reports have been imported.";
ErrorMessage = error;
_log.LogError("Cancelled processing of Amazon settlement data into invoice export queue: " + error);
return null;
}
} }
} }
// validate settlelments if (settlementList == null || settlementList.Any() == false)
{
_log.LogInformation("No new settlement reports to process.");
return null;
}
// validate settlements
var validate = new Logic.Validate.AmazonSettlement(); var validate = new Logic.Validate.AmazonSettlement();
foreach (var settlement in settlementList) foreach (var settlement in settlementList)
{ {
if (!validate.IsValid(settlement)) if (!validate.IsValid(settlement))
{ {
_log.LogError("Error procesing Amazon Settlement data for export.", validate.ValidationResultListToString()); _log.LogError("Error processing Amazon Settlement data for export.", validate.ValidationResultListToString());
} }
} }
if (validate.IsValidResult == false) if (validate.IsValidResult == false)

View File

@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Export.AccountInvoice
{
internal class InvoiceService
{
}
}

View File

@@ -15,22 +15,17 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
/// <summary> /// <summary>
/// Processes the Export Invoice table and exports to Xero /// Processes the Export Invoice table and exports to Xero
/// </summary> /// </summary>
public class QueueService public class QueueService : UnitOfWorkBase
{ {
private Log.LogEvent _log = new Log.LogEvent(); private Log.LogEvent _log = new Log.LogEvent();
private IEnumerable<int> _exportSaleInvoiceIdList = new List<int>(); private UnitOfWork _exportUow = null;
private readonly IUnitOfWork _providedUnitOfWork = null;
private readonly bool _ownsUnitOfWork = false;
public QueueService() public QueueService()
{ {
_ownsUnitOfWork = true;
} }
internal QueueService(IUnitOfWork unitOfWork) internal QueueService(IUnitOfWork unitOfWork) : base(unitOfWork)
{ {
_providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
_ownsUnitOfWork = false;
} }
public string ErrorMessage { get; private set; } = null; public string ErrorMessage { get; private set; } = null;
@@ -64,26 +59,11 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
{ {
Init(); Init();
IUnitOfWork currentUow = null;
if (_ownsUnitOfWork)
{
currentUow = new UnitOfWork();
}
else
{
currentUow = _providedUnitOfWork;
}
string result = null; string result = null;
using (currentUow != null && _ownsUnitOfWork ? currentUow : null) return WithUnitOfWork(uow =>
{ {
result = "_tmp" + currentUow.SequenceGenerator.GetNext("ExportTempInvoiceNumber").ToString("00000000"); return "_tmp" + uow.SequenceGenerator.GetNext("ExportTempInvoiceNumber").ToString("00000000");
if (_ownsUnitOfWork) });
{
currentUow.Commit();
}
}
return result;
} }
public void AddTempInvoiceNumber(IEnumerable<Model.Account.IInvoice> invoiceList, bool overwriteExisting) public void AddTempInvoiceNumber(IEnumerable<Model.Account.IInvoice> invoiceList, bool overwriteExisting)
@@ -110,30 +90,26 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
{ {
Init(); Init();
IUnitOfWork currentUow = null; return WithUnitOfWork(uow =>
if (_ownsUnitOfWork)
{ {
currentUow = new UnitOfWork(); return ReadInvoiceById(uow, invoiceIdList);
} });
else }
{
currentUow = _providedUnitOfWork;
}
using (_ownsUnitOfWork ? currentUow : null)
{
var returnList = currentUow.ExportInvoiceRepository.GetSalesInvoiceById(invoiceIdList);
var validate = new Logic.Validate.Invoice();
bool isValid = validate.IsValidExportInvoice(returnList.Values.ToList());
if (isValid == false) private Dictionary<int, Model.Account.SalesInvoice> ReadInvoiceById(IUnitOfWork uow, IEnumerable<int> invoiceIdList)
{ {
ErrorMessage = "Reading invoices from database failed validation. See logs for further details."; var returnList = uow.ExportInvoiceRepository.GetSalesInvoiceById(invoiceIdList);
_log.LogError("ErrorMessage", validate.ValidationResultListToString()); var validate = new Logic.Validate.Invoice();
throw new Exception(ErrorMessage); bool isValid = validate.IsValidExportInvoice(returnList.Values.ToList());
}
return returnList; if (isValid == false)
{
ErrorMessage = "Reading invoices from database failed validation. See logs for further details.";
_log.LogError("ErrorMessage", validate.ValidationResultListToString());
throw new Exception(ErrorMessage);
} }
return returnList;
} }
/// <summary> /// <summary>
@@ -158,25 +134,12 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
validateInvoice = null; validateInvoice = null;
// save to database // save to database
IUnitOfWork currentUow = null; return WithUnitOfWork(uow =>
if (_ownsUnitOfWork)
{ {
currentUow = new UnitOfWork(); var result = uow.ExportInvoiceRepository.InsertSalesInvoices(invoiceList);
} CommitIfOwned(uow);
else
{
currentUow = _providedUnitOfWork;
}
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
{
var result = currentUow.ExportInvoiceRepository.InsertSalesInvoices(invoiceList);
if (_ownsUnitOfWork)
{
currentUow.Commit();
}
return result; return result;
} });
} }
/// <summary> /// <summary>
@@ -187,25 +150,10 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
{ {
Init(); Init();
IUnitOfWork currentUow = null; return WithUnitOfWork(uow =>
if (_ownsUnitOfWork)
{ {
currentUow = new UnitOfWork(); return uow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType).Count();
} });
else
{
currentUow = _providedUnitOfWork;
}
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
{
var result = currentUow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType).Count();
if (_ownsUnitOfWork)
{
currentUow.Commit();
}
return result;
}
} }
/// <summary> /// <summary>
@@ -213,80 +161,45 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
/// </summary> /// </summary>
/// <param name="filePath"></param> /// <param name="filePath"></param>
/// <param name="firstInvoiceNumber"></param> /// <param name="firstInvoiceNumber"></param>
public void ExportSalesInvoice(string filePath, int firstInvoiceNumber) public bool ExportSalesInvoice(string filePath, int firstInvoiceNumber, Func<bool> getUserConfirmation)
{ {
Init(); Init();
IUnitOfWork currentUow = null; return WithUnitOfWork(uow =>
if (_ownsUnitOfWork)
{
currentUow = new UnitOfWork();
}
else
{
currentUow = _providedUnitOfWork;
}
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
{ {
var invoiceType = Model.Account.InvoiceType.Sale; var invoiceType = Model.Account.InvoiceType.Sale;
var idList = currentUow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType); // get list of unprocessed invoices
_exportSaleInvoiceIdList = idList.Keys.ToList(); var newInvoiceIdDict = uow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType);
var invoiceList = ReadInvoiceById(idList.Keys.ToList());
// update db entries with invoice numbers and set to iscompleted=true
foreach (var newInvoiceId in newInvoiceIdDict)
{
string invoiceNumber = "INV-" + firstInvoiceNumber.ToString("000000");
uow.ExportInvoiceRepository.UpdateInvoiceHeaderDetail(newInvoiceId.Key, invoiceNumber, true);
firstInvoiceNumber++;
}
// read invoices from database
var invoiceList = ReadInvoiceById(uow, newInvoiceIdDict.Keys.ToList());
var exportToFile = new Data.Xero.SalesInvoice(); var exportToFile = new Data.Xero.SalesInvoice();
exportToFile.ExportToCsv(invoiceList.Values.ToList(), firstInvoiceNumber, filePath); exportToFile.ExportToCsv(invoiceList.Values.ToList(), filePath);
}
}
/// <summary> // get user confitmation before marking as exported
/// Call this after ExportSalesInvoice() to mark exported invoices as complete bool userInput = getUserConfirmation.Invoke();
/// </summary>
/// <returns>number of invoices effected</returns>
public int? ExportSalesInvoiceIsComplete()
{
Init();
if (_exportSaleInvoiceIdList.Any() == false) if (userInput == false)
{
ErrorMessage = "Nothing to set as complete, did you call the ExportSalesInvoice method first?";
return null;
}
var parameters = new Dictionary<int, bool>();
foreach (var id in _exportSaleInvoiceIdList)
{
parameters.Add(id, true);
}
// update database
IUnitOfWork currentUow = null;
if (_ownsUnitOfWork)
{
currentUow = new UnitOfWork();
}
else
{
currentUow = _providedUnitOfWork;
}
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
{
int count = currentUow.ExportInvoiceRepository.SetInvoiceIsCompleteValue(parameters);
if (_exportSaleInvoiceIdList.Count() == count)
{ {
currentUow.Commit(); RollbackIfOwned(uow);
return count; ErrorMessage = "User cancelled export, invoices not marked as exported.";
_log.LogInformation(ErrorMessage);
return false;
} }
else
{ CommitIfOwned(uow);
currentUow.Rollback(); return true;
ErrorMessage = "ExportSalesInvoiceIsComplete() Incorrect number of rows updated, changes rolled back."; });
_log.LogError(ErrorMessage);
throw new Exception(ErrorMessage);
}
}
} }
} }
} }

View File

@@ -5,43 +5,26 @@ using System.Linq;
namespace bnhtrade.Core.Logic.Import namespace bnhtrade.Core.Logic.Import
{ {
public class AmazonSettlement public class AmazonSettlement : UnitOfWorkBase
{ {
private readonly IUnitOfWork _providedUnitOfWork = null;
private readonly bool _ownsUnitOfWork = false;
private Data.Amazon.Report.SettlementReport amazonReport;
private Logic.Log.LogEvent log = new Log.LogEvent(); private Logic.Log.LogEvent log = new Log.LogEvent();
public AmazonSettlement() public AmazonSettlement()
{ {
_ownsUnitOfWork = true;
} }
internal AmazonSettlement(IUnitOfWork unitOfWork) internal AmazonSettlement(IUnitOfWork unitOfWork) : base(unitOfWork)
{ {
_providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
_ownsUnitOfWork = false;
} }
public void SyncDatabase() public void SyncDatabase()
{ {
string operation = "Import Amazon Settlement Reports"; string operation = "Import Amazon Settlement Reports";
log.LogInformation("Started '" + operation + "' operation."); log.LogInformation("Started '" + operation + "' operation.");
var amazonReport = new Data.Amazon.Report.SettlementReport();
// get avaiable reports from amazon api // get avaiable reports from amazon api
IUnitOfWork currentUow = null; WithUnitOfWork(uow =>
if (_ownsUnitOfWork)
{
currentUow = new UnitOfWork();
}
else
{
currentUow = _providedUnitOfWork;
}
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
{ {
// get avaiable reports from amazon api // get avaiable reports from amazon api
var spapiReportIdList = amazonReport.ListAvaliableReports(); var spapiReportIdList = amazonReport.ListAvaliableReports();
@@ -54,7 +37,7 @@ namespace bnhtrade.Core.Logic.Import
} }
// query db and remove reports that have already been imported // query db and remove reports that have already been imported
var dbReportList = currentUow.ImportAmazonRepository.ReadAmazonSettlementHeaderInfoBySpapiReportId(spapiReportIdList); var dbReportList = uow.AmazonSettlementRepository.ReadAmazonSettlementHeaderInfoBySpapiReportId(spapiReportIdList);
foreach (var dbReport in dbReportList) foreach (var dbReport in dbReportList)
{ {
if (dbReport.SpapiReportIdIsSet) if (dbReport.SpapiReportIdIsSet)
@@ -82,16 +65,12 @@ namespace bnhtrade.Core.Logic.Import
{ {
UI.Console.WriteLine("Importing settlement report " + (i + 1) + " of " + spapiReportIdList.Count() + " (ReportID:" + spapiReportIdList[i] + ")."); UI.Console.WriteLine("Importing settlement report " + (i + 1) + " of " + spapiReportIdList.Count() + " (ReportID:" + spapiReportIdList[i] + ").");
var filePath = amazonReport.GetReportFile(spapiReportIdList[i]); var filePath = amazonReport.GetReportFile(spapiReportIdList[i]);
bool ack = currentUow.ImportAmazonRepository.CreateAmazonSettlements(filePath, spapiReportIdList[i]); bool ack = uow.AmazonSettlementRepository.CreateAmazonSettlements(filePath, spapiReportIdList[i]);
log.LogInformation("Settlment Report imported (ReportID:" + spapiReportIdList[i] + ")."); log.LogInformation("Settlment Report imported (ReportID:" + spapiReportIdList[i] + ").");
} }
if (_ownsUnitOfWork) CommitIfOwned(uow);
{ });
currentUow.Commit();
}
return;
}
} }
} }
} }

View File

@@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Transactions; using System.Transactions;
using System.Windows.Forms;
namespace bnhtrade.Core.Logic.Sku namespace bnhtrade.Core.Logic.Sku
{ {
public class GetSkuId public class SkuService : UnitOfWorkBase
{ {
/// <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.
@@ -15,11 +17,11 @@ namespace bnhtrade.Core.Logic.Sku
/// <param name="noMatchCreateNew">When set to true, if no match is made, function will create a new sku and return the id for that</param> /// <param name="noMatchCreateNew">When set to true, if no match is made, function will create a new sku and return the id for that</param>
/// <returns>Return the id for the new or existing sku or, dependant on set parameters, 0 if not found</returns> /// <returns>Return the id for the new or existing sku or, dependant on set parameters, 0 if not found</returns>
/// <exception cref="Exception"></exception> /// <exception cref="Exception"></exception>
public int Request(int productId, int conditionId, int accountTaxCodeId, bool noMatchCreateNew) public int GetSkuId(int productId, int conditionId, int accountTaxCodeId, bool noMatchCreateNew)
{ {
using (TransactionScope scope = new TransactionScope()) return WithUnitOfWork(uow =>
{ {
int? skuId = new Data.Database.Sku.GetSkuId().ByParameters(productId, conditionId, accountTaxCodeId); int? skuId = uow.SkuRepository.ReadSkuId(productId, conditionId, accountTaxCodeId);
if (skuId != null) if (skuId != null)
{ {
return (int)skuId; return (int)skuId;
@@ -30,9 +32,11 @@ namespace bnhtrade.Core.Logic.Sku
} }
else else
{ {
return new Data.Database.Sku.InsertSku().InsertNew(productId, conditionId, accountTaxCodeId); int newSkuId = uow.SkuRepository.InsertNewSku(productId, conditionId, accountTaxCodeId);
CommitIfOwned(uow);
return newSkuId;
} }
} });
} }
} }
} }

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Stock namespace bnhtrade.Core.Logic.Stock
{ {
public class StatusBalance public class StatusBalance : UnitOfWorkBase
{ {
public StatusBalance() public StatusBalance()
{ {
@@ -35,91 +35,93 @@ namespace bnhtrade.Core.Logic.Stock
/// <returns></returns> /// <returns></returns>
public Model.Stock.StatusBalance GetStatusBalance(string skuNumber, int statusId, bool includeDetails = true) public Model.Stock.StatusBalance GetStatusBalance(string skuNumber, int statusId, bool includeDetails = true)
{ {
if (string.IsNullOrWhiteSpace(skuNumber)) // need to enroll moree of the code into the unit of work as I redo the database layer
return WithUnitOfWork(uow =>
{ {
throw new Exception("SKU number is null, empty, or whitespace"); if (string.IsNullOrWhiteSpace(skuNumber))
}
// get list of transactions for availale stock
var readStatusTransaction = new Data.Database.Stock.ReadStatusTransaction();
var statusTransaction = readStatusTransaction.BySku(statusId, skuNumber);
// create quantity list
List<int> qtyList = new List<int>();
for (int i = 0; i < statusTransaction.TransactionList.Count; i++)
{
qtyList.Add(statusTransaction.TransactionList[i].Quantity);
}
// tally list
// loop, in reverse, to find credits to tally with debits
for (int iCr = qtyList.Count - 1; iCr > -1; iCr--)
{
if (qtyList[iCr] < 0)
{ {
int crStockNumber = statusTransaction.TransactionList[iCr].StockNumber; throw new Exception("SKU number is null, empty, or whitespace");
DateTime crDate = statusTransaction.TransactionList[iCr].EntryDate; }
// loop, in reverse, to find debits // get list of transactions for availale stock
for (int iDr = qtyList.Count - 1; iDr > -1; iDr--) var readStatusTransaction = new Data.Database.Stock.ReadStatusTransaction(); // ambient uow open above
var statusTransaction = readStatusTransaction.BySku(statusId, skuNumber); // ambient uow open above
// create quantity list
List<int> qtyList = new List<int>();
for (int i = 0; i < statusTransaction.TransactionList.Count; i++)
{
qtyList.Add(statusTransaction.TransactionList[i].Quantity);
}
// tally list
// loop, in reverse, to find credits to tally with debits
for (int iCr = qtyList.Count - 1; iCr > -1; iCr--)
{
if (qtyList[iCr] < 0)
{ {
// find debits, last in first out (filter by date) int crStockNumber = statusTransaction.TransactionList[iCr].StockNumber;
if (statusTransaction.TransactionList[iDr].StockNumber == crStockNumber DateTime crDate = statusTransaction.TransactionList[iCr].EntryDate;
&& statusTransaction.TransactionList[iDr].EntryDate <= crDate
&& qtyList[iDr] > 0) // loop, in reverse, to find debits
for (int iDr = qtyList.Count - 1; iDr > -1; iDr--)
{ {
// credit fully assigned // find debits, last in first out (filter by date)
if ((qtyList[iCr] + qtyList[iDr]) >= 0) if (statusTransaction.TransactionList[iDr].StockNumber == crStockNumber
&& statusTransaction.TransactionList[iDr].EntryDate <= crDate
&& qtyList[iDr] > 0)
{ {
qtyList[iDr] = qtyList[iDr] + qtyList[iCr]; // credit fully assigned
qtyList[iCr] = 0; if ((qtyList[iCr] + qtyList[iDr]) >= 0)
break; {
} qtyList[iDr] = qtyList[iDr] + qtyList[iCr];
// credit partially assigned qtyList[iCr] = 0;
else break;
{ }
qtyList[iCr] = qtyList[iDr] + qtyList[iCr]; // credit partially assigned
qtyList[iDr] = 0; else
{
qtyList[iCr] = qtyList[iDr] + qtyList[iCr];
qtyList[iDr] = 0;
}
} }
} }
} }
} }
}
// build result list from tally results // build result list from tally results
var entryList = new List<(DateTime EntryDate, int StockNumber, int Quantity)>(); var entryList = new List<(DateTime EntryDate, int StockNumber, int Quantity)>();
for (int i = 0; i < qtyList.Count; i++) for (int i = 0; i < qtyList.Count; i++)
{
if (qtyList[i] != 0)
{ {
(DateTime EntryDate, int StockNumber, int Quantity) entryItem = ( if (qtyList[i] != 0)
statusTransaction.TransactionList[i].EntryDate, {
statusTransaction.TransactionList[i].StockNumber, (DateTime EntryDate, int StockNumber, int Quantity) entryItem = (
qtyList[i]); statusTransaction.TransactionList[i].EntryDate,
entryList.Add(entryItem); statusTransaction.TransactionList[i].StockNumber,
qtyList[i]);
entryList.Add(entryItem);
}
} }
}
if (includeDetails) if (includeDetails)
{ {
// get the sku obj // get the sku obj
var readSku = new Logic.Sku.GetSkuInfo(); var readSku = new Logic.Sku.GetSkuInfo(); // ambient uow open above
readSku.IncludeConditionInfo = true; readSku.IncludeConditionInfo = true;
readSku.IncludeProductInfo = true; readSku.IncludeProductInfo = true;
readSku.IncludeTaxCodeInfo = true; readSku.IncludeTaxCodeInfo = true;
var sku = readSku.BySkuNumber(statusTransaction.SkuNumber); var sku = readSku.BySkuNumber(statusTransaction.SkuNumber);
// get the status obj // get the status obj
var readStatus = new Data.Database.Stock.Status(); var status = uow.StockRepository.ReadStatus(new List<int> { statusTransaction.StockStatusId })[0];
readStatus.StatusIds = new List<int> { statusTransaction.StockStatusId };
var status = readStatus.Read()[0];
return new Model.Stock.StatusBalance(status, sku, entryList); return new Model.Stock.StatusBalance(status, sku, entryList);
} }
else else
{ {
return new Model.Stock.StatusBalance(statusTransaction.StockStatusId, statusTransaction.SkuNumber, entryList); return new Model.Stock.StatusBalance(statusTransaction.StockStatusId, statusTransaction.SkuNumber, entryList);
} }
});
} }
/// <summary> /// <summary>

View File

@@ -0,0 +1,76 @@
using bnhtrade.Core.Data.Database.UnitOfWork;
using System;
namespace bnhtrade.Core.Logic
{
public abstract class UnitOfWorkBase
{
private readonly IUnitOfWork _providedUnitOfWork;
private readonly bool _ownsUnitOfWork;
protected UnitOfWorkBase()
{
_ownsUnitOfWork = true;
}
internal UnitOfWorkBase(IUnitOfWork unitOfWork)
{
_providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
_ownsUnitOfWork = false;
}
/// <summary>
/// Executes an action with a managed UnitOfWork, handling disposal and commit if owned.
/// </summary>
internal void WithUnitOfWork(Action<IUnitOfWork> action)
{
IUnitOfWork currentUow = _ownsUnitOfWork ? new UnitOfWork() : _providedUnitOfWork;
try
{
action(currentUow);
}
finally
{
if (_ownsUnitOfWork && currentUow is IDisposable disposable)
disposable.Dispose();
}
}
/// <summary>
/// Executes a function with a managed UnitOfWork, handling disposal and commit if owned.
/// </summary>
internal T WithUnitOfWork<T>(Func<IUnitOfWork, T> func)
{
IUnitOfWork currentUow = _ownsUnitOfWork ? new UnitOfWork() : _providedUnitOfWork;
try
{
return func(currentUow);
}
finally
{
if (_ownsUnitOfWork && currentUow is IDisposable disposable)
disposable.Dispose();
}
}
/// <summary>
/// Executes an action with a managed UnitOfWork, committing if owned.
/// </summary>
/// <param name="uow"></param>
internal void CommitIfOwned(IUnitOfWork uow)
{
if (_ownsUnitOfWork)
uow.Commit();
}
/// <summary>
/// Executes an action with a managed UnitOfWork, rolling back if owned.
/// </summary>
/// <param name="uow"></param>
internal void RollbackIfOwned(IUnitOfWork uow)
{
if (_ownsUnitOfWork)
uow.Rollback();
}
}
}

View File

@@ -1,53 +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._BoilerPlate
{
internal class UnitOfWorkPattern
{
private readonly IUnitOfWork _providedUnitOfWork = null;
private readonly bool _ownsUnitOfWork = false;
public UnitOfWorkPattern()
{
_ownsUnitOfWork = true;
}
internal UnitOfWorkPattern(IUnitOfWork unitOfWork)
{
_providedUnitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
_ownsUnitOfWork = false;
}
public void LogicThatUsesService()
{
IUnitOfWork currentUow = null;
if (_ownsUnitOfWork)
{
currentUow = new UnitOfWork();
}
else
{
currentUow = _providedUnitOfWork;
}
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
{
//
// Perform operations using currentUow, e.g. repository calls
//
if (_ownsUnitOfWork)
{
currentUow.Commit();
}
}
}
}
}

View File

@@ -0,0 +1,38 @@
using bnhtrade.Core.Data.Database.UnitOfWork;
using System;
using System.Collections.Generic;
namespace bnhtrade.Core.Logic._boilerplate
{
public class UnitOfWorkService : UnitOfWorkBase
{
public UnitOfWorkService() : base() { }
internal UnitOfWorkService(IUnitOfWork unitOfWork) : base(unitOfWork) { }
public Model.Account.InvoiceLineItem ReturnExample(string itemCode)
{
return WithUnitOfWork(uow =>
{
// add all code in here that uses the unit of work, this will ensure that the unit of work is disposed of correctly
var item = uow.InvoiceRepository.GetInvoiceLineItem(null, new List<string> { itemCode });
// use the base method to commit, it will check if the unit of work is owned by this service before committing
CommitIfOwned(uow);
// return
return item[0];
});
}
public void VoidExample()
{
WithUnitOfWork(uow =>
{
var items = uow.InvoiceRepository.GetInvoiceLineItem();
// use the base method to commit, it will check if the unit of work is owned by this service before committing
CommitIfOwned(uow);
});
}
}
}

View File

@@ -9,7 +9,7 @@ namespace bnhtrade.Core.Model.Account
{ {
public class Account public class Account
{ {
public Account(uint id, uint 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)
{ {
Id = id; Id = id;
AccountCode = accountCode; AccountCode = accountCode;
@@ -23,9 +23,9 @@ namespace bnhtrade.Core.Model.Account
/// <summary> /// <summary>
/// Database record id /// Database record id
/// </summary> /// </summary>
public uint Id { get; private set; } public int Id { get; private set; }
public uint AccountCode { get; private set; } public int AccountCode { get; private set; }
public string AccountName { get; private set; } public string AccountName { get; private set; }

View File

@@ -10,7 +10,7 @@ namespace bnhtrade.Core.Model.Account
{ {
public class Journal : IValidatableObject public class Journal : IValidatableObject
{ {
internal Journal(uint journalId, Core.Model.Account.JournalType type, List<Post> posts, DateTime entryDate, DateTime postDate, DateTime lastModifed, bool isLocked) internal Journal(int journalId, Core.Model.Account.JournalType type, List<Post> posts, DateTime entryDate, DateTime postDate, DateTime lastModifed, bool isLocked)
{ {
JournalId = journalId; JournalId = journalId;
Type = type; Type = type;
@@ -21,7 +21,7 @@ namespace bnhtrade.Core.Model.Account
IsLocked = isLocked; IsLocked = isLocked;
} }
public uint JournalId { get; private set; } public int JournalId { get; private set; }
public Core.Model.Account.JournalType Type { get; private set; } public Core.Model.Account.JournalType Type { get; private set; }
public List<Post> Posts { get; private set; } = new List<Post>(); public List<Post> Posts { get; private set; } = new List<Post>();
public DateTime EntryDate { get; private set; } public DateTime EntryDate { get; private set; }
@@ -31,14 +31,14 @@ namespace bnhtrade.Core.Model.Account
public class Post public class Post
{ {
internal Post(uint postId, Core.Model.Account.Account account, decimal amountGbp) internal Post(int postId, Core.Model.Account.Account account, decimal amountGbp)
{ {
PostId = postId; PostId = postId;
Account = account; Account = account;
AmountGbp = amountGbp; AmountGbp = amountGbp;
} }
public uint PostId { get; private set; } public int PostId { get; private set; }
public Core.Model.Account.Account Account { get; private set; } public Core.Model.Account.Account Account { get; private set; }
public decimal AmountGbp { get; private set; } public decimal AmountGbp { get; private set; }
} }

View File

@@ -8,7 +8,7 @@ namespace bnhtrade.Core.Model.Account
{ {
public class JournalType public class JournalType
{ {
internal JournalType(uint journalTypeId, string title, Model.Account.Account defaultCreditAccount = null, Model.Account.Account defaultDebitAccount = null) internal JournalType(int journalTypeId, string title, Model.Account.Account defaultCreditAccount = null, Model.Account.Account defaultDebitAccount = null)
{ {
JournalTypeId = journalTypeId; JournalTypeId = journalTypeId;
Title = title; Title = title;
@@ -22,7 +22,7 @@ namespace bnhtrade.Core.Model.Account
DefaultDebitAccount = defaultDebitAccount; DefaultDebitAccount = defaultDebitAccount;
} }
public uint JournalTypeId { get ; private set; } public int JournalTypeId { get ; private set; }
public string Title { get; private set; } public string Title { get; private set; }

View File

@@ -1,11 +1,14 @@
using System; using bnhtrade.Core.Logic;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.SqlClient; using System.Data;
using System.Data.Common;
using System.Data.SqlTypes;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Transactions;
using System.Data.SqlTypes;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Transactions;
namespace bnhtrade.Core namespace bnhtrade.Core
{ {
@@ -231,7 +234,7 @@ namespace bnhtrade.Core
namespace Stock namespace Stock
{ {
public class StockCreate public class StockCreate : UnitOfWorkBase
{ {
private int WIP_StockInsert(string sqlConnectionString, int accountJournalType, int stockJournalType, string currencyCode, decimal amount, private int WIP_StockInsert(string sqlConnectionString, int accountJournalType, int stockJournalType, string currencyCode, decimal amount,
int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId) int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
@@ -337,7 +340,7 @@ namespace bnhtrade.Core
} }
// get/set an skuId // get/set an skuId
int skuId = new Logic.Sku.GetSkuId().Request(productId, conditionId, accountTaxCodeId, true); int skuId = new Logic.Sku.SkuService().GetSkuId(productId, conditionId, accountTaxCodeId, true);
// add the entry to the stock table (minus stockJournalId) // add the entry to the stock table (minus stockJournalId)
int stockId = 0; int stockId = 0;
@@ -563,10 +566,10 @@ namespace bnhtrade.Core
// to be used by other methods within a transaction scope // to be used by other methods within a transaction scope
private static void WIP_StockDeleteSubAccountJournalEntry(string sqlConnectionString, int stockId) private static void WIP_StockDeleteSubAccountJournalEntry(string sqlConnectionString, int stockId)
{ {
using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = new SqlConnection(sqlConnectionString)) using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{ {
conn.Open(); conn.Open();
var trans = conn.BeginTransaction();
// get the account journal id // get the account journal id
int accountJournalId = 0; int accountJournalId = 0;
@@ -576,6 +579,7 @@ namespace bnhtrade.Core
WHERE StockID=@stockId; WHERE StockID=@stockId;
", conn)) ", conn))
{ {
cmd.Transaction = trans;
cmd.Parameters.AddWithValue("@stockId", stockId); cmd.Parameters.AddWithValue("@stockId", stockId);
object obj = cmd.ExecuteScalar(); object obj = cmd.ExecuteScalar();
@@ -601,6 +605,7 @@ namespace bnhtrade.Core
WHERE StockID=@stockId; WHERE StockID=@stockId;
", conn)) ", conn))
{ {
cmd.Transaction = trans;
cmd.Parameters.AddWithValue("@stockId", stockId); cmd.Parameters.AddWithValue("@stockId", stockId);
int count = cmd.ExecuteNonQuery(); int count = cmd.ExecuteNonQuery();
@@ -612,9 +617,9 @@ namespace bnhtrade.Core
} }
// delete account journal entry // delete account journal entry
new Data.Database.Account.DeleteJournal().AccountJournalDelete(accountJournalId); new Data.Database.Repository.Implementation.JournalRepository(conn, trans).DeleteJournal(accountJournalId);
scope.Complete(); trans.Commit();
} }
} }
@@ -1457,10 +1462,10 @@ namespace bnhtrade.Core
public static void WIP_PurchaseLineTransactionDelete(string sqlConnectionString, int purchaseLineId, int accountJournalId) public static void WIP_PurchaseLineTransactionDelete(string sqlConnectionString, int purchaseLineId, int accountJournalId)
{ {
using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = new SqlConnection(sqlConnectionString)) using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{ {
conn.Open(); conn.Open();
var trans = conn.BeginTransaction();
// check accountJournalId does not exist in stock table // check accountJournalId does not exist in stock table
using (SqlCommand cmd = new SqlCommand(@" using (SqlCommand cmd = new SqlCommand(@"
@@ -1469,6 +1474,7 @@ namespace bnhtrade.Core
WHERE AccountJournalID=@accountJournalId; WHERE AccountJournalID=@accountJournalId;
", conn)) ", conn))
{ {
cmd.Transaction = trans;
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId); cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
using (var reader = cmd.ExecuteReader()) using (var reader = cmd.ExecuteReader())
@@ -1493,6 +1499,7 @@ namespace bnhtrade.Core
WHERE AccountJournalID=@accountJournalId; WHERE AccountJournalID=@accountJournalId;
", conn)) ", conn))
{ {
cmd.Transaction = trans;
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId); cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
int count = cmd.ExecuteNonQuery(); int count = cmd.ExecuteNonQuery();
@@ -1504,9 +1511,9 @@ namespace bnhtrade.Core
} }
// delete account journal entry // delete account journal entry
new Data.Database.Account.DeleteJournal().AccountJournalDelete(accountJournalId); new Data.Database.Repository.Implementation.JournalRepository(conn, trans).DeleteJournal(accountJournalId);
scope.Complete(); trans.Commit();
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using bnhtrade.Core.Data.Database.Account; using bnhtrade.Core.Data.Database.Account;
using bnhtrade.Core.Data.Database.UnitOfWork;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -25,28 +26,28 @@ namespace bnhtrade.Core.Test.Account
public void PurchaseInvoice() public void PurchaseInvoice()
{ {
var result = new bnhtrade.Core.Logic.Account.PurchaseInvoice().GetPurchaseInvoice( new List<int> { 14718, 100, 101, 102, 300, 400, 1200, 2734, 6339, 9999 }); // 10 in total var result = new bnhtrade.Core.Logic.Account.PurchaseInvoiceService().GetPurchaseInvoice( new List<int> { 14718, 100, 101, 102, 300, 400, 1200, 2734, 6339, 9999 }); // 10 in total
} }
public void PurchaseInvoiceLine() public void PurchaseInvoiceLine()
{ {
var read = new Data.Database.Account.ReadPurchaseInvoiceLine(); var uof = new UnitOfWork();
read.ItemDescription = new List<string> { "xbox", "kill" }; var result = uof.InvoiceRepository.ReadPurchaseInvoiceLine(null, null, null, new List<string> { "xbox", "kill" });
var result = read.Read();
} }
public void Journal() public void Journal()
{ {
var read = new Data.Database.Account.ReadJournal(); //var read = new Data.Database.Account.ReadJournal();
read.AccountJournalId = new List<uint> { 123, 300, 324, 5678, 22 }; //read.AccountJournalId = new List<uint> { 123, 300, 324, 5678, 22 };
var result = read.Read(); //var result = read.Read();
} }
public void InoivceCurrencyConversion() public void InoivceCurrencyConversion()
{ {
var invoiceService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService(); var uof = new UnitOfWork();
var invoiceService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService(uof);
var invoiceList = invoiceService.ReadInvoiceById(new List<int> { 349, 371, 375, 379 }); var invoiceList = invoiceService.ReadInvoiceById(new List<int> { 349, 371, 375, 379 });
var currencyService = new bnhtrade.Core.Logic.Account.CurrencyService(); var currencyService = new bnhtrade.Core.Logic.Account.CurrencyService(uof);
foreach (var invoice in invoiceList.Values.ToList()) foreach (var invoice in invoiceList.Values.ToList())
{ {

View File

@@ -11,7 +11,7 @@ namespace bnhtrade.Core.Test.Export
{ {
public Export() public Export()
{ {
DeleteExportInvoice(); UPdateInvoiceHeaderDetail();
} }
private void SubmitAmazonInventoryLoader() private void SubmitAmazonInventoryLoader()
@@ -43,24 +43,22 @@ namespace bnhtrade.Core.Test.Export
var list = unitOfWork.ExportInvoiceRepository.GetSalesInvoiceById(new List<int> { 550, 555 }); var list = unitOfWork.ExportInvoiceRepository.GetSalesInvoiceById(new List<int> { 550, 555 });
} }
private void ExportSalesInvoiceQueue()
{
var invoice = new Model.Account.SalesInvoice(true);
invoice.InvoiceLineList = new List<Model.Account.Invoice.InvoiceLine>();
string path = @"%USERPROFILE%\Downloads\TEST.CSV";
var queueService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService();
queueService.ImportAll();
queueService.ExportSalesInvoice(path, 1234);
var return1 = queueService.ExportSalesInvoiceIsComplete();
}
private void DeleteExportInvoice() private void DeleteExportInvoice()
{ {
//var uow = new bnhtrade.Core.Data.Database.UnitOfWork.UnitOfWork(); throw new Exception("This method is for testing purposes only, it will delete export invoices from the database. Use with caution.");
using (var uow = new bnhtrade.Core.Data.Database.UnitOfWork.UnitOfWork()) using (var uow = new bnhtrade.Core.Data.Database.UnitOfWork.UnitOfWork())
{ {
int dfkjl = uow.ExportInvoiceRepository.DeleteInvoice(new List<int> { 576, 577, 584 }); int dfkjl = uow.ExportInvoiceRepository.DeleteInvoice(new List<int> { 591, 590, 589, 588, 587, 586, 585, 583, 582, 581, 580, 579, 578 });
int lskdjflsd = uow.ImportAmazonRepository.SetAmazonSettlementIsProcessed(new List<string> { "24684639382f", "14720584692f", "14386695522f" }, false); int lskdjflsd = uow.AmazonSettlementRepository.UpdateAmazonSettlementIsProcessed(new List<string> { "24945698052", "24684639382", "24859276062", "24769420562", "24684661532", "14720584692", "24593881302", "24508182552", "14386695522", "24416840332", "24334973902", "24162226452" }, false);
uow.Commit();
}
}
private void UPdateInvoiceHeaderDetail()
{
using (var uow = new bnhtrade.Core.Data.Database.UnitOfWork.UnitOfWork())
{
int dfkjl = uow.ExportInvoiceRepository.UpdateInvoiceHeaderDetail(123333, "douche", true);
uow.Commit(); uow.Commit();
} }
} }

View File

@@ -23,7 +23,7 @@ namespace bnhtrade.Core.Test.Logic
{ {
using (var uow = new Data.Database.UnitOfWork.UnitOfWork()) using (var uow = new Data.Database.UnitOfWork.UnitOfWork())
{ {
var list = uow.ImportAmazonRepository.ReadAmazonSettlements(marketPlaceNameList: new List<string> { "Amazon.fr" }, returnTop: 3); var list = uow.AmazonSettlementRepository.ReadAmazonSettlements(marketPlaceNameList: new List<string> { "Amazon.fr" }, returnTop: 3);
} }
} }
public void UpdateExportInvoiceQueue() public void UpdateExportInvoiceQueue()

View File

@@ -60,11 +60,11 @@ namespace bnhtrade.Core.Test.Stock
public void ReadStockStatus() public void ReadStockStatus()
{ {
var db = new Status(); //var db = new Status();
db.StatusIds = new List<int> { 3, 4, 5, 6, 7, 11, 12, 13, 15 }; //db.StatusIds = new List<int> { 3, 4, 5, 6, 7, 11, 12, 13, 15 };
db.StatusTypeIds = new List<int> { 12, 5 }; //db.StatusTypeIds = new List<int> { 12, 5 };
var result = db.Read(); //var result = db.Read();
int i = 0; //int i = 0;
} }
} }
} }

View File

@@ -53,7 +53,7 @@ namespace bnhtrade.gui
private void InitialiseTabReceiving() private void InitialiseTabReceiving()
{ {
Cursor.Current = Cursors.WaitCursor; Cursor.Current = Cursors.WaitCursor;
purchaseLineStatusBindingSource.DataSource = new Core.Logic.Account.PurchaseInvoiceMisc().ReadLineStatusToList(); purchaseLineStatusBindingSource.DataSource = new Core.Logic.Account.PurchaseInvoiceService().ReadLineStatusToList();
comboBox1.SelectedIndex = 3; comboBox1.SelectedIndex = 3;
ListBoxQuery(); ListBoxQuery();
initTabReceiving = true; initTabReceiving = true;
@@ -96,7 +96,7 @@ namespace bnhtrade.gui
comboBox = comboBox1.Text; comboBox = comboBox1.Text;
} }
bsReceivingLines.DataSource = new Core.Logic.Account.PurchaseInvoiceMisc().GetLineSummary( bsReceivingLines.DataSource = new Core.Logic.Account.PurchaseInvoiceService().GetLineSummary(
dateTimeOrderSearch.Value dateTimeOrderSearch.Value
, comboBox , comboBox
, searchList); , searchList);
@@ -120,7 +120,7 @@ namespace bnhtrade.gui
var row = dataGridView1.CurrentCell.RowIndex; var row = dataGridView1.CurrentCell.RowIndex;
var lineSummary = (bnhtrade.Core.Model.Account.PurchaseInvoiceLineSummary)bsReceivingLines[row]; var lineSummary = (bnhtrade.Core.Model.Account.PurchaseInvoiceLineSummary)bsReceivingLines[row];
int purchaseId = lineSummary.PurchaseId; int purchaseId = lineSummary.PurchaseId;
var purchaseInvoiceList = new Core.Logic.Account.PurchaseInvoice().GetPurchaseInvoice(new List<int> { purchaseId }); var purchaseInvoiceList = new Core.Logic.Account.PurchaseInvoiceService().GetPurchaseInvoice(new List<int> { purchaseId });
var purchaseInvoice = purchaseInvoiceList[purchaseId]; var purchaseInvoice = purchaseInvoiceList[purchaseId];
var form = new PurchaseInvoice(purchaseInvoice); var form = new PurchaseInvoice(purchaseInvoice);
form.Show(); form.Show();
@@ -177,12 +177,6 @@ namespace bnhtrade.gui
} }
} }
// create export invoices and export to CSV
var queueService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService();
queueService.ImportAll();
queueService.ExportSalesInvoice(savePath, nextInvoiceNumber);
// open import page // open import page
Process.Start(new ProcessStartInfo Process.Start(new ProcessStartInfo
{ {
@@ -190,33 +184,42 @@ namespace bnhtrade.gui
UseShellExecute = true UseShellExecute = true
}); });
// did the import go okay // create export invoices and export to CSV
var result = MessageBox.Show( var queueService = new bnhtrade.Core.Logic.Export.AccountInvoice.QueueService();
"Import invoices to Xero ensuring UnitAmount field option is set to 'Tax Exclusive' on the import page." queueService.ImportAll();
+ Environment.NewLine + Environment.NewLine queueService.ExportSalesInvoice(savePath, nextInvoiceNumber, () =>
+ "Once the import has completed suscessfully click 'Okay' to mark the invoice(s) as complete/imported.",
"Import Confirmation",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question
);
if (result == DialogResult.OK)
{ {
var completeCount = queueService.ExportSalesInvoiceIsComplete(); // did the import go okay
if (completeCount != invoices) var result = MessageBox.Show(
"Import invoices to Xero ensuring UnitAmount field option is set to 'Tax Exclusive' on the import page."
+ Environment.NewLine + Environment.NewLine
+ "Once the import has completed suscessfully click 'Okay' to mark the invoice(s) as complete/imported.",
"Import Confirmation",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question
);
if (result == DialogResult.OK)
{ {
MessageBox.Show("Error marking invoices as complete. Please check the logs for more details.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return true;
log.LogError("ExportSalesInvoiceIsComplete returned " + completeCount + " but expected " + invoices + ". Please check the logs for more details.", queueService.ErrorMessage);
} }
else else
{ {
MessageBox.Show(completeCount + " invoices marked as complete.", "Export Complete", MessageBoxButtons.OK, MessageBoxIcon.Information); return false;
} }
});
if (queueService.ErrorMessageIsSet)
{
MessageBox.Show("Error exporting invoices: " + queueService.ErrorMessage, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
log.LogError("Error exporting invoices: " + queueService.ErrorMessage);
return;
} }
else else
{ {
MessageBox.Show("Operation cancelled. No invoices marked as complete."); MessageBox.Show("Exported " + invoices + " invoices to " + savePath, "Export Complete", MessageBoxButtons.OK, MessageBoxIcon.Information);
} }
UpdateInvoiceExportBox(); UpdateInvoiceExportBox();
return; return;
} }