mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-03-25 17:17:15 +00:00
Bug fix in ExportSalesInvoice and converted more code over to repository and service pattern
This commit is contained in:
@@ -6,18 +6,18 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Account
|
||||
{
|
||||
public class GetAccountCodeInfo
|
||||
public class AccountCodeService : UnitOfWorkBase
|
||||
{
|
||||
private Data.Database.Account.ReadAccountCode readAccountCode;
|
||||
|
||||
public GetAccountCodeInfo()
|
||||
public AccountCodeService()
|
||||
{
|
||||
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)
|
||||
@@ -35,7 +35,10 @@ namespace bnhtrade.Core.Logic.Account
|
||||
|
||||
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)
|
||||
@@ -3,21 +3,22 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Account
|
||||
{
|
||||
public class GetTaxCodeInfo
|
||||
public class GetTaxCodeInfo : UnitOfWorkBase
|
||||
{
|
||||
private Data.Database.Account.ReadTaxCode dbRead;
|
||||
|
||||
public GetTaxCodeInfo()
|
||||
{
|
||||
dbRead = new Data.Database.Account.ReadTaxCode();
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -48,7 +49,11 @@ namespace bnhtrade.Core.Logic.Account
|
||||
}
|
||||
|
||||
// get db list
|
||||
var dbList = dbRead.GetTaxCodeBySkuNumber(skuNumberList);
|
||||
var dbList = WithUnitOfWork(uow =>
|
||||
{
|
||||
return uow.AccountTaxRepository.GetTaxCodeBySkuNumber(skuNumberList);
|
||||
});
|
||||
|
||||
|
||||
// build dictionary
|
||||
foreach (var item in dbList)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -6,9 +7,17 @@ using System.Threading.Tasks;
|
||||
|
||||
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>
|
||||
/// 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>
|
||||
public Model.Account.InvoiceLineItem CreateNew(string itemCode)
|
||||
{
|
||||
new Data.Database.Account.CreateInvoiceLineItem().CreateDefault(itemCode);
|
||||
var item = new Data.Database.Account.ReadInvoiceLineItem().ByItemCode(new List<string> { itemCode });
|
||||
if (item == null || item.Count == 0)
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
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");
|
||||
}
|
||||
return item[0];
|
||||
uow.InvoiceRepository.CreateDefaultInvoiceLineItem(itemCode);
|
||||
var item = uow.InvoiceRepository.GetInvoiceLineItem(null, 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);
|
||||
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)
|
||||
{
|
||||
var dbResult = new Data.Database.Account.ReadInvoiceLineItem().ByItemCode(itemCodes);
|
||||
var returnDict = new Dictionary<string, Model.Account.InvoiceLineItem>();
|
||||
foreach ( var item in dbResult)
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
returnDict.Add(item.Value.ItemCode, item.Value);
|
||||
}
|
||||
return returnDict;
|
||||
var dbResult = uow.InvoiceRepository.GetInvoiceLineItem(null, itemCodes);
|
||||
var returnDict = new Dictionary<string, Model.Account.InvoiceLineItem>();
|
||||
foreach (var item in dbResult)
|
||||
{
|
||||
returnDict.Add(item.Value.ItemCode, item.Value);
|
||||
}
|
||||
return returnDict;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Account
|
||||
{
|
||||
public class Journal
|
||||
public class Journal : UnitOfWorkBase
|
||||
{
|
||||
public int AccountJournalInsert(int journalTypeId, DateTime entryDate, string currencyCode,
|
||||
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)
|
||||
{
|
||||
return new Data.Database.Account.DeleteJournal().AccountJournalDelete(accountJournalId);
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
bool result = uow.JournalRepository.DeleteJournal(accountJournalId);
|
||||
CommitIfOwned(uow);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/bnhtrade.Core/Logic/Account/PurchaseInvoiceService.cs
Normal file
55
src/bnhtrade.Core/Logic/Account/PurchaseInvoiceService.cs
Normal 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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using Amazon.SQS.Model.Internal.MarshallTransformations;
|
||||
using bnhtrade.Core.Data.Database.UnitOfWork;
|
||||
using bnhtrade.Core.Model.Account;
|
||||
using bnhtrade.Core.Model.Amazon;
|
||||
using bnhtrade.Core.Test.Export;
|
||||
using FikaAmazonAPI.ReportGeneration.ReportDataTable;
|
||||
@@ -17,24 +18,18 @@ using static bnhtrade.Core.Model.Import.AmazonSettlement;
|
||||
|
||||
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 List<string> _lineItemCodeList = new List<string>();
|
||||
private bool _settlementAmountIsTaxExclusive = false; // i.e. they're tax inclusive
|
||||
|
||||
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; }
|
||||
@@ -53,34 +48,34 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
|
||||
Init();
|
||||
_log.LogInformation("Starting processing of Amazon settlement data into export invoice table...");
|
||||
|
||||
// get list of unprocessed settlement reports to export
|
||||
var settlementList = GetListOfUnprocessedSettlementReports();
|
||||
if (settlementList == null)
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
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
|
||||
var settlementIdList = new List<string>();
|
||||
foreach (var settlement in settlementList)
|
||||
{
|
||||
settlementIdList.Add(settlement.SettlementId);
|
||||
}
|
||||
// create list of settlement ids for later use
|
||||
var settlementIdList = new List<string>();
|
||||
foreach (var settlement in settlementList)
|
||||
{
|
||||
settlementIdList.Add(settlement.SettlementId);
|
||||
}
|
||||
|
||||
// create list of invoices from settlement reports
|
||||
var invoiceList = CreateInvoices(settlementList, convertToGbp);
|
||||
if (invoiceList == null || invoiceList.Any() == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// create list of invoices from settlement reports
|
||||
var invoiceList = CreateInvoices(settlementList, convertToGbp);
|
||||
if (invoiceList == null || invoiceList.Any() == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// add invoice to export queue and set settlements as processed
|
||||
Console.Write("\rWriting to database... ");
|
||||
using (UnitOfWork unitOfWork = new UnitOfWork())
|
||||
{
|
||||
// add invoice to export queue and set settlements as processed
|
||||
Console.Write("\rWriting to database... ");
|
||||
try
|
||||
{
|
||||
var queueService = new Logic.Export.AccountInvoice.QueueService(unitOfWork);
|
||||
var queueService = new Logic.Export.AccountInvoice.QueueService(uow);
|
||||
// add temp invoice numbers
|
||||
queueService.AddTempInvoiceNumber(invoiceList, true);
|
||||
|
||||
@@ -89,12 +84,15 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
|
||||
if (queueService.ErrorMessageIsSet == false && queueInsertResult.Count() == invoiceList.Count())
|
||||
{
|
||||
// set settlements to isprocessed
|
||||
unitOfWork.ImportAmazonRepository.SetAmazonSettlementIsProcessed(settlementIdList, true);
|
||||
unitOfWork.Commit();
|
||||
uow.AmazonSettlementRepository.UpdateAmazonSettlementIsProcessed(settlementIdList, true);
|
||||
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
|
||||
{
|
||||
unitOfWork.Rollback();
|
||||
uow.Rollback();
|
||||
string error = queueService.ErrorMessage;
|
||||
ErrorMessage = "Cancelled processing of Amazon settlement data into export invoice table. " + error;
|
||||
_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...");
|
||||
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>
|
||||
/// Retrives a list of unprocessed settlement reports from the database, checks for gaps in settlement periods, and validates
|
||||
/// the settlement data.
|
||||
/// </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>
|
||||
private List<Model.Import.AmazonSettlement> GetListOfUnprocessedSettlementReports()
|
||||
private List<Model.Import.AmazonSettlement> GetUnprocessedSettlementReports(IUnitOfWork uow, bool updateNullMarketplaceByCurrency = true)
|
||||
{
|
||||
List<Model.Import.AmazonSettlement> settlementList = null;
|
||||
|
||||
IUnitOfWork currentUow = null;
|
||||
if (_ownsUnitOfWork)
|
||||
// get list of unprocessed settlement reports to export
|
||||
settlementList = uow.AmazonSettlementRepository.ReadAmazonSettlements(null, null, false).Values.ToList();
|
||||
|
||||
if (settlementList.Any() == false)
|
||||
{
|
||||
currentUow = new UnitOfWork();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUow = _providedUnitOfWork;
|
||||
ErrorMessage = "No new settlement reports to process";
|
||||
return null;
|
||||
}
|
||||
|
||||
// get list of unprocssed settlement reports to export
|
||||
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
|
||||
// test marketplace-name has been sucsessfully entered into settlement table --
|
||||
// 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 (settlementList.Any() == false)
|
||||
if (settlement.MarketPlaceNameIsSet == false && updateNullMarketplaceByCurrency && settlement.CurrencyCode == CurrencyCode.GBP.ToString())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// test marketplace-name has been sucsessfully entered into settlement table --
|
||||
// as this is not supplied in the original report from Amazon and has to be inferred from settlement line data
|
||||
// this is not picked up in validate stage as null value is valid
|
||||
foreach (var settlement in settlementList)
|
||||
// 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)
|
||||
{
|
||||
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 + ".";
|
||||
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)
|
||||
if (completedSettlement.FirstOrDefault().Value.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")
|
||||
+ 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 "
|
||||
+ 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();
|
||||
foreach (var settlement in settlementList)
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -15,22 +15,17 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
|
||||
/// <summary>
|
||||
/// Processes the Export Invoice table and exports to Xero
|
||||
/// </summary>
|
||||
public class QueueService
|
||||
public class QueueService : UnitOfWorkBase
|
||||
{
|
||||
private Log.LogEvent _log = new Log.LogEvent();
|
||||
private IEnumerable<int> _exportSaleInvoiceIdList = new List<int>();
|
||||
private readonly IUnitOfWork _providedUnitOfWork = null;
|
||||
private readonly bool _ownsUnitOfWork = false;
|
||||
private UnitOfWork _exportUow = null;
|
||||
|
||||
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;
|
||||
@@ -64,26 +59,11 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
|
||||
{
|
||||
Init();
|
||||
|
||||
IUnitOfWork currentUow = null;
|
||||
if (_ownsUnitOfWork)
|
||||
{
|
||||
currentUow = new UnitOfWork();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUow = _providedUnitOfWork;
|
||||
}
|
||||
|
||||
string result = null;
|
||||
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
result = "_tmp" + currentUow.SequenceGenerator.GetNext("ExportTempInvoiceNumber").ToString("00000000");
|
||||
if (_ownsUnitOfWork)
|
||||
{
|
||||
currentUow.Commit();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return "_tmp" + uow.SequenceGenerator.GetNext("ExportTempInvoiceNumber").ToString("00000000");
|
||||
});
|
||||
}
|
||||
|
||||
public void AddTempInvoiceNumber(IEnumerable<Model.Account.IInvoice> invoiceList, bool overwriteExisting)
|
||||
@@ -110,30 +90,26 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
|
||||
{
|
||||
Init();
|
||||
|
||||
IUnitOfWork currentUow = null;
|
||||
if (_ownsUnitOfWork)
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
currentUow = new UnitOfWork();
|
||||
}
|
||||
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());
|
||||
return ReadInvoiceById(uow, invoiceIdList);
|
||||
});
|
||||
}
|
||||
|
||||
if (isValid == false)
|
||||
{
|
||||
ErrorMessage = "Reading invoices from database failed validation. See logs for further details.";
|
||||
_log.LogError("ErrorMessage", validate.ValidationResultListToString());
|
||||
throw new Exception(ErrorMessage);
|
||||
}
|
||||
private Dictionary<int, Model.Account.SalesInvoice> ReadInvoiceById(IUnitOfWork uow, IEnumerable<int> invoiceIdList)
|
||||
{
|
||||
var returnList = uow.ExportInvoiceRepository.GetSalesInvoiceById(invoiceIdList);
|
||||
var validate = new Logic.Validate.Invoice();
|
||||
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>
|
||||
@@ -158,25 +134,12 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
|
||||
validateInvoice = null;
|
||||
|
||||
// save to database
|
||||
IUnitOfWork currentUow = null;
|
||||
if (_ownsUnitOfWork)
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
currentUow = new UnitOfWork();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUow = _providedUnitOfWork;
|
||||
}
|
||||
|
||||
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
|
||||
{
|
||||
var result = currentUow.ExportInvoiceRepository.InsertSalesInvoices(invoiceList);
|
||||
if (_ownsUnitOfWork)
|
||||
{
|
||||
currentUow.Commit();
|
||||
}
|
||||
var result = uow.ExportInvoiceRepository.InsertSalesInvoices(invoiceList);
|
||||
CommitIfOwned(uow);
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -187,25 +150,10 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
|
||||
{
|
||||
Init();
|
||||
|
||||
IUnitOfWork currentUow = null;
|
||||
if (_ownsUnitOfWork)
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
currentUow = new UnitOfWork();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUow = _providedUnitOfWork;
|
||||
}
|
||||
|
||||
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
|
||||
{
|
||||
var result = currentUow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType).Count();
|
||||
if (_ownsUnitOfWork)
|
||||
{
|
||||
currentUow.Commit();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return uow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType).Count();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -213,80 +161,45 @@ namespace bnhtrade.Core.Logic.Export.AccountInvoice
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="firstInvoiceNumber"></param>
|
||||
public void ExportSalesInvoice(string filePath, int firstInvoiceNumber)
|
||||
public bool ExportSalesInvoice(string filePath, int firstInvoiceNumber, Func<bool> getUserConfirmation)
|
||||
{
|
||||
Init();
|
||||
|
||||
IUnitOfWork currentUow = null;
|
||||
if (_ownsUnitOfWork)
|
||||
{
|
||||
currentUow = new UnitOfWork();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUow = _providedUnitOfWork;
|
||||
}
|
||||
|
||||
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
|
||||
return WithUnitOfWork(uow =>
|
||||
{
|
||||
var invoiceType = Model.Account.InvoiceType.Sale;
|
||||
|
||||
var idList = currentUow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType);
|
||||
_exportSaleInvoiceIdList = idList.Keys.ToList();
|
||||
var invoiceList = ReadInvoiceById(idList.Keys.ToList());
|
||||
// get list of unprocessed invoices
|
||||
var newInvoiceIdDict = uow.ExportInvoiceRepository.GetNewInvoiceNumbers(invoiceType);
|
||||
|
||||
// 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();
|
||||
exportToFile.ExportToCsv(invoiceList.Values.ToList(), firstInvoiceNumber, filePath);
|
||||
}
|
||||
}
|
||||
exportToFile.ExportToCsv(invoiceList.Values.ToList(), filePath);
|
||||
|
||||
/// <summary>
|
||||
/// Call this after ExportSalesInvoice() to mark exported invoices as complete
|
||||
/// </summary>
|
||||
/// <returns>number of invoices effected</returns>
|
||||
public int? ExportSalesInvoiceIsComplete()
|
||||
{
|
||||
Init();
|
||||
// get user confitmation before marking as exported
|
||||
bool userInput = getUserConfirmation.Invoke();
|
||||
|
||||
if (_exportSaleInvoiceIdList.Any() == 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)
|
||||
if (userInput == false)
|
||||
{
|
||||
currentUow.Commit();
|
||||
return count;
|
||||
RollbackIfOwned(uow);
|
||||
ErrorMessage = "User cancelled export, invoices not marked as exported.";
|
||||
_log.LogInformation(ErrorMessage);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUow.Rollback();
|
||||
ErrorMessage = "ExportSalesInvoiceIsComplete() Incorrect number of rows updated, changes rolled back.";
|
||||
_log.LogError(ErrorMessage);
|
||||
throw new Exception(ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
CommitIfOwned(uow);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,43 +5,26 @@ using System.Linq;
|
||||
|
||||
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();
|
||||
|
||||
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()
|
||||
{
|
||||
string operation = "Import Amazon Settlement Reports";
|
||||
log.LogInformation("Started '" + operation + "' operation.");
|
||||
var amazonReport = new Data.Amazon.Report.SettlementReport();
|
||||
|
||||
// get avaiable reports from amazon api
|
||||
IUnitOfWork currentUow = null;
|
||||
if (_ownsUnitOfWork)
|
||||
{
|
||||
currentUow = new UnitOfWork();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUow = _providedUnitOfWork;
|
||||
}
|
||||
|
||||
|
||||
|
||||
using (currentUow != null && _ownsUnitOfWork ? currentUow : null)
|
||||
WithUnitOfWork(uow =>
|
||||
{
|
||||
// get avaiable reports from amazon api
|
||||
var spapiReportIdList = amazonReport.ListAvaliableReports();
|
||||
@@ -54,7 +37,7 @@ namespace bnhtrade.Core.Logic.Import
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
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] + ").");
|
||||
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] + ").");
|
||||
}
|
||||
|
||||
if (_ownsUnitOfWork)
|
||||
{
|
||||
currentUow.Commit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
CommitIfOwned(uow);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Transactions;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Sku
|
||||
{
|
||||
public class GetSkuId
|
||||
public class SkuService : UnitOfWorkBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// <returns>Return the id for the new or existing sku or, dependant on set parameters, 0 if not found</returns>
|
||||
/// <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)
|
||||
{
|
||||
return (int)skuId;
|
||||
@@ -30,9 +32,11 @@ namespace bnhtrade.Core.Logic.Sku
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Data.Database.Sku.InsertSku().InsertNew(productId, conditionId, accountTaxCodeId);
|
||||
int newSkuId = uow.SkuRepository.InsertNewSku(productId, conditionId, accountTaxCodeId);
|
||||
CommitIfOwned(uow);
|
||||
return newSkuId;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Logic.Stock
|
||||
{
|
||||
public class StatusBalance
|
||||
public class StatusBalance : UnitOfWorkBase
|
||||
{
|
||||
public StatusBalance()
|
||||
{
|
||||
@@ -35,91 +35,93 @@ namespace bnhtrade.Core.Logic.Stock
|
||||
/// <returns></returns>
|
||||
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");
|
||||
}
|
||||
|
||||
// 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)
|
||||
if (string.IsNullOrWhiteSpace(skuNumber))
|
||||
{
|
||||
int crStockNumber = statusTransaction.TransactionList[iCr].StockNumber;
|
||||
DateTime crDate = statusTransaction.TransactionList[iCr].EntryDate;
|
||||
throw new Exception("SKU number is null, empty, or whitespace");
|
||||
}
|
||||
|
||||
// loop, in reverse, to find debits
|
||||
for (int iDr = qtyList.Count - 1; iDr > -1; iDr--)
|
||||
// get list of transactions for availale stock
|
||||
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)
|
||||
if (statusTransaction.TransactionList[iDr].StockNumber == crStockNumber
|
||||
&& statusTransaction.TransactionList[iDr].EntryDate <= crDate
|
||||
&& qtyList[iDr] > 0)
|
||||
int crStockNumber = statusTransaction.TransactionList[iCr].StockNumber;
|
||||
DateTime crDate = statusTransaction.TransactionList[iCr].EntryDate;
|
||||
|
||||
// loop, in reverse, to find debits
|
||||
for (int iDr = qtyList.Count - 1; iDr > -1; iDr--)
|
||||
{
|
||||
// credit fully assigned
|
||||
if ((qtyList[iCr] + qtyList[iDr]) >= 0)
|
||||
// find debits, last in first out (filter by date)
|
||||
if (statusTransaction.TransactionList[iDr].StockNumber == crStockNumber
|
||||
&& statusTransaction.TransactionList[iDr].EntryDate <= crDate
|
||||
&& qtyList[iDr] > 0)
|
||||
{
|
||||
qtyList[iDr] = qtyList[iDr] + qtyList[iCr];
|
||||
qtyList[iCr] = 0;
|
||||
break;
|
||||
}
|
||||
// credit partially assigned
|
||||
else
|
||||
{
|
||||
qtyList[iCr] = qtyList[iDr] + qtyList[iCr];
|
||||
qtyList[iDr] = 0;
|
||||
// credit fully assigned
|
||||
if ((qtyList[iCr] + qtyList[iDr]) >= 0)
|
||||
{
|
||||
qtyList[iDr] = qtyList[iDr] + qtyList[iCr];
|
||||
qtyList[iCr] = 0;
|
||||
break;
|
||||
}
|
||||
// credit partially assigned
|
||||
else
|
||||
{
|
||||
qtyList[iCr] = qtyList[iDr] + qtyList[iCr];
|
||||
qtyList[iDr] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build result list from tally results
|
||||
var entryList = new List<(DateTime EntryDate, int StockNumber, int Quantity)>();
|
||||
for (int i = 0; i < qtyList.Count; i++)
|
||||
{
|
||||
if (qtyList[i] != 0)
|
||||
// build result list from tally results
|
||||
var entryList = new List<(DateTime EntryDate, int StockNumber, int Quantity)>();
|
||||
for (int i = 0; i < qtyList.Count; i++)
|
||||
{
|
||||
(DateTime EntryDate, int StockNumber, int Quantity) entryItem = (
|
||||
statusTransaction.TransactionList[i].EntryDate,
|
||||
statusTransaction.TransactionList[i].StockNumber,
|
||||
qtyList[i]);
|
||||
entryList.Add(entryItem);
|
||||
if (qtyList[i] != 0)
|
||||
{
|
||||
(DateTime EntryDate, int StockNumber, int Quantity) entryItem = (
|
||||
statusTransaction.TransactionList[i].EntryDate,
|
||||
statusTransaction.TransactionList[i].StockNumber,
|
||||
qtyList[i]);
|
||||
entryList.Add(entryItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (includeDetails)
|
||||
{
|
||||
// get the sku obj
|
||||
var readSku = new Logic.Sku.GetSkuInfo();
|
||||
readSku.IncludeConditionInfo = true;
|
||||
readSku.IncludeProductInfo = true;
|
||||
readSku.IncludeTaxCodeInfo = true;
|
||||
var sku = readSku.BySkuNumber(statusTransaction.SkuNumber);
|
||||
if (includeDetails)
|
||||
{
|
||||
// get the sku obj
|
||||
var readSku = new Logic.Sku.GetSkuInfo(); // ambient uow open above
|
||||
readSku.IncludeConditionInfo = true;
|
||||
readSku.IncludeProductInfo = true;
|
||||
readSku.IncludeTaxCodeInfo = true;
|
||||
var sku = readSku.BySkuNumber(statusTransaction.SkuNumber);
|
||||
|
||||
// get the status obj
|
||||
var readStatus = new Data.Database.Stock.Status();
|
||||
readStatus.StatusIds = new List<int> { statusTransaction.StockStatusId };
|
||||
var status = readStatus.Read()[0];
|
||||
// get the status obj
|
||||
var status = uow.StockRepository.ReadStatus(new List<int> { statusTransaction.StockStatusId })[0];
|
||||
|
||||
return new Model.Stock.StatusBalance(status, sku, entryList);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Model.Stock.StatusBalance(statusTransaction.StockStatusId, statusTransaction.SkuNumber, entryList);
|
||||
}
|
||||
return new Model.Stock.StatusBalance(status, sku, entryList);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Model.Stock.StatusBalance(statusTransaction.StockStatusId, statusTransaction.SkuNumber, entryList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
76
src/bnhtrade.Core/Logic/UnitOfWorkBase.cs
Normal file
76
src/bnhtrade.Core/Logic/UnitOfWorkBase.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
38
src/bnhtrade.Core/Logic/_boilerplate/UnitOfWorkService.cs
Normal file
38
src/bnhtrade.Core/Logic/_boilerplate/UnitOfWorkService.cs
Normal 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user