diff --git a/build/bnhtrade.ComTypeLib.RegAsmInstall.bat b/build/bnhtrade.ComTypeLib.RegAsmInstall.bat
index 1d9262b..7007419 100644
--- a/build/bnhtrade.ComTypeLib.RegAsmInstall.bat
+++ b/build/bnhtrade.ComTypeLib.RegAsmInstall.bat
@@ -2,13 +2,13 @@
@set dllpath=%batchpath%
::bnhtrade Database Client\bin\Release\
-@copy "%dllpath%bnhtrade.Core.dll" "%SYSTEMROOT%\SysWOW64\bnhtrade.Core.dll"
+rem @copy "%dllpath%bnhtrade.Core.dll" "%SYSTEMROOT%\SysWOW64\bnhtrade.Core.dll"
@copy "%dllpath%bnhtradeCOM.dll" "%SYSTEMROOT%\SysWOW64\bnhtradeCOM.dll"
-@copy "%dllpath%ABrain.AmazonMWS.dll" "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.dll"
+rem @copy "%dllpath%ABrain.AmazonMWS.dll" "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.dll"
-@copy "%dllpath%bnhtrade.Core.dll" "%SYSTEMROOT%\System32\bnhtrade.Core.dll"
+rem @copy "%dllpath%bnhtrade.Core.dll" "%SYSTEMROOT%\System32\bnhtrade.Core.dll"
@copy "%dllpath%bnhtradeCOM.dll" "%SYSTEMROOT%\System32\bnhtradeCOM.dll"
-@copy "%dllpath%ABrain.AmazonMWS.dll" "%SYSTEMROOT%\System32\ABrain.AmazonMWS.dll"
+rem @copy "%dllpath%ABrain.AmazonMWS.dll" "%SYSTEMROOT%\System32\ABrain.AmazonMWS.dll"
@c:
@cd\Windows\Microsoft.NET\Framework\v4.*
diff --git a/build/bnhtrade.ComTypeLib.RegAsmUninstall.bat b/build/bnhtrade.ComTypeLib.RegAsmUninstall.bat
index 13dc795..ececa7b 100644
--- a/build/bnhtrade.ComTypeLib.RegAsmUninstall.bat
+++ b/build/bnhtrade.ComTypeLib.RegAsmUninstall.bat
@@ -8,18 +8,18 @@ rem regasm.exe /u "%SYSTEMROOT%\System32\bnhtrade.Core.dll"
regasm.exe /u "%SYSTEMROOT%\SysWOW64\bnhtradeCOM.dll"
rem regasm.exe /u "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.dll"
cd
-@del /q "%SYSTEMROOT%\SysWOW64\bnhtrade.Core.dll"
+rem @del /q "%SYSTEMROOT%\SysWOW64\bnhtrade.Core.dll"
rem @del /q "%SYSTEMROOT%\SysWOW64\bnhtrade.Core.tlb"
@del /q "%SYSTEMROOT%\SysWOW64\bnhtradeCOM.dll"
-@del /q "%SYSTEMROOT%\SysWOW64\bnhtradeCOM.tlb"
-@del /q "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.dll"
+rem @del /q "%SYSTEMROOT%\SysWOW64\bnhtradeCOM.tlb"
+rem @del /q "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.dll"
rem @del /q "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.tlb"
-@del /q "%SYSTEMROOT%\System32\bnhtrade.Core.dll"
+rem @del /q "%SYSTEMROOT%\System32\bnhtrade.Core.dll"
rem @del /q "%SYSTEMROOT%\System32\bnhtrade.Core.tlb"
@del /q "%SYSTEMROOT%\System32\bnhtradeCOM.dll"
-@del /q "%SYSTEMROOT%\System32\bnhtradeCOM.tlb"
-@del /q "%SYSTEMROOT%\System32\ABrain.AmazonMWS.dll"
+rem @del /q "%SYSTEMROOT%\System32\bnhtradeCOM.tlb"
+rem @del /q "%SYSTEMROOT%\System32\ABrain.AmazonMWS.dll"
rem @del /q "%SYSTEMROOT%\System32\ABrain.AmazonMWS.tlb"
@echo.
diff --git a/src/bnhtrade.ComTypeLib/ILMerge.props b/src/bnhtrade.ComTypeLib/ILMerge.props
new file mode 100644
index 0000000..b0fc9d2
--- /dev/null
+++ b/src/bnhtrade.ComTypeLib/ILMerge.props
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bnhtrade.ComTypeLib/ILMergeOrder.txt b/src/bnhtrade.ComTypeLib/ILMergeOrder.txt
new file mode 100644
index 0000000..3fda7f5
--- /dev/null
+++ b/src/bnhtrade.ComTypeLib/ILMergeOrder.txt
@@ -0,0 +1,4 @@
+# this file contains the partial list of the merged assemblies in the merge order
+# you can fill it from the obj\CONFIG\PROJECT.ilmerge generated on every build
+# and finetune merge order to your satisfaction
+
diff --git a/src/bnhtrade.ComTypeLib/Product/Product.cs b/src/bnhtrade.ComTypeLib/Product/Product.cs
index f4460c4..47f52d3 100644
--- a/src/bnhtrade.ComTypeLib/Product/Product.cs
+++ b/src/bnhtrade.ComTypeLib/Product/Product.cs
@@ -64,22 +64,24 @@ namespace bnhtrade.ComTypeLib
public string ProductCompetitivePriceGet(int productId, int conditionId, ConnectionCredential sqlConnCred)
{
- var request = new Core.Product.ProductQuery();
- (decimal? price, DateTime? priceDate) result = request.ProductCompetitivePriceGet(sqlConnCred.ConnectionString, productId, conditionId);
- if (result.price == null || result.priceDate == null)
+ var compPrice = new Core.Logic.Product.GetCompetitivePrice(sqlConnCred.ConnectionString).Execute(productId, conditionId);
+
+ if (compPrice == null)
{
return "";
}
else
{
- DateTime priceDate2 = result.priceDate.Value;
- return result.price.ToString() + ";" + priceDate2.ToOADate();
+ return compPrice.Price + ";" + compPrice.PriceDatetime.ToOADate();
}
}
- public int ProductCompetitivePriceSet(int productId, int conditionId, [MarshalAs(UnmanagedType.Currency)] decimal price, bool isBuyBoxPrice, DateTime priceDate, ConnectionCredential sqlConnCred)
+
+ public int ProductCompetitivePriceSet(int productId, int conditionId, [MarshalAs(UnmanagedType.Currency)] decimal price, bool isBuyBoxPrice, DateTime priceDateLocal, ConnectionCredential sqlConnCred)
{
- var request = new Core.Product.ProductQuery();
- return request.ProductCompetitivePriceSet(sqlConnCred.ConnectionString, productId, conditionId, price, isBuyBoxPrice, priceDate);
+ priceDateLocal = DateTime.SpecifyKind(priceDateLocal, DateTimeKind.Local);
+
+ return new Core.Data.Database.Product.CreateCompetitivePrice(sqlConnCred.ConnectionString)
+ .ProductCompetitivePriceSet(productId, conditionId, price, isBuyBoxPrice, priceDateLocal);
}
public void ProductUpdateAmazonEstimateFee(ConnectionCredential sqlConnCred, object inputList)
diff --git a/src/bnhtrade.ComTypeLib/Stock/Stock.cs b/src/bnhtrade.ComTypeLib/Stock/Stock.cs
index 13e16c1..2bfd914 100644
--- a/src/bnhtrade.ComTypeLib/Stock/Stock.cs
+++ b/src/bnhtrade.ComTypeLib/Stock/Stock.cs
@@ -61,7 +61,7 @@ namespace bnhtrade.ComTypeLib
{
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
- return Core.Stock.StockJournal.StockReallocateByStockId(sqlConnCred.ConnectionString, 4, stockId, quantity, debitStatusId, creditStatusId, entryDate);
+ return new Core.Logic.Stock.Reallocate(sqlConnCred.ConnectionString).StockReallocateByStockId(4, stockId, quantity, debitStatusId, creditStatusId, entryDate);
}
public void StockJournalDelete(ConnectionCredential sqlConnCred, int stockJournalId)
@@ -71,10 +71,11 @@ namespace bnhtrade.ComTypeLib
public object ReconcileStockTransactions(ConnectionCredential sqlConnCred)
{
- var request = new Core.Stock.StockReconciliation();
- var result = new Core.Stock.StockReconciliation.ReconcileStockTransactionsResult();
+ //var request = new Core.Stock.StockReconciliation();
+ //var result = new Core.Stock.StockReconciliation.ReconcileStockTransactionsResult();
- result = request.ReconcileStockTransactions(sqlConnCred.ConnectionString, false);
+ var result = new Core.Logic.Stock.SkuTransactionReconcile(sqlConnCred.ConnectionString);
+ result.ReconcileStockTransactions(false);
//ReconcileStockTransactionsResult returnObject = new ReconcileStockTransactionsResult();
@@ -106,8 +107,8 @@ namespace bnhtrade.ComTypeLib
object[] returnArray = new object[7];
returnArray[0] = result.ReconciliationComplete;
returnArray[1] = result.ProgressMessage;
- returnArray[2] = result.StockTransactionId;
- returnArray[3] = result.StockTransactionTypeId;
+ returnArray[2] = result.CurrentTransactionId;
+ returnArray[3] = result.CurrentTransactionTypeId;
returnArray[4] = result.LastItemDateTime;
returnArray[5] = result.ItemsCompleted;
returnArray[6] = result.ItemsRemaining;
diff --git a/src/bnhtrade.ComTypeLib/app.config b/src/bnhtrade.ComTypeLib/app.config
new file mode 100644
index 0000000..8d5ec5f
--- /dev/null
+++ b/src/bnhtrade.ComTypeLib/app.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/bnhtrade.ComTypeLib/bnhtrade.ComTypeLib.csproj b/src/bnhtrade.ComTypeLib/bnhtrade.ComTypeLib.csproj
index 8e41b4a..c840d73 100644
--- a/src/bnhtrade.ComTypeLib/bnhtrade.ComTypeLib.csproj
+++ b/src/bnhtrade.ComTypeLib/bnhtrade.ComTypeLib.csproj
@@ -1,5 +1,7 @@
+
+
Debug
@@ -13,6 +15,8 @@
512
true
+
+
true
@@ -30,6 +34,7 @@
TRACE
prompt
4
+ true
Always
@@ -54,13 +59,20 @@
-
+
+
+
+
+
{339d7413-3da7-46ea-a55c-255a9a6b95eb}
bnhtrade.Core
+
+
+
@@ -71,4 +83,13 @@
copy "$(SolutionDir)build\bnhtrade.ComTypeLib.RegAsmRefresh.bat" "$(TargetDir)bnhtrade.ComTypeLib.RegAsmRefresh.bat"
copy "$(SolutionDir)build\bnhtrade.ComTypeLib.RegAsmUninstall.bat" "$(TargetDir)bnhtrade.ComTypeLib.RegAsmUninstall.bat"
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/bnhtrade.ComTypeLib/packages.config b/src/bnhtrade.ComTypeLib/packages.config
new file mode 100644
index 0000000..b5c3442
--- /dev/null
+++ b/src/bnhtrade.ComTypeLib/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/bnhtrade.Core/App.config b/src/bnhtrade.Core/App.config
index affa224..b035ea2 100644
--- a/src/bnhtrade.Core/App.config
+++ b/src/bnhtrade.Core/App.config
@@ -1,15 +1,15 @@
-
+
-
+
-
+
-
+
@@ -21,4 +21,12 @@
+
+
+
+
+
+
+
+
diff --git a/src/bnhtrade.Core/Data/AmazonMWS/CredentialMws.cs b/src/bnhtrade.Core/Data/AmazonMWS/CredentialMws.cs
index 5bc8d77..f6cd6a6 100644
--- a/src/bnhtrade.Core/Data/AmazonMWS/CredentialMws.cs
+++ b/src/bnhtrade.Core/Data/AmazonMWS/CredentialMws.cs
@@ -8,12 +8,18 @@ namespace bnhtrade.Core.Data.AmazonMWS
{
public class CredentialMws
{
- public string merchantId { get { return "A3RUYNKLWWM5KW"; } }
- public string marketPlaceId { get { return "A1F83G8C2ARO7P"; } } // Amazon.co.uk
- public string accessKeyId { get { return "AKIAJU45WSYVINEN45UA"; } }
- public string secretAccessKey { get { return "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"; } }
- public string applicationName { get { return "bnhtrade.Core"; } }
- public string applicationVersion { get { return "0.1"; } }
- public string serviceURL { get { return "https://mws.amazonservices.co.uk"; } }
+ public string MerchantId { get { return "A3RUYNKLWWM5KW"; } }
+
+ public string MarketPlaceIdUK { get { return "A1F83G8C2ARO7P"; } } // Amazon.co.uk
+
+ public string AccessKeyId { get { return "AKIAJU45WSYVINEN45UA"; } }
+
+ public string SecretAccessKey { get { return "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"; } }
+
+ public string ApplicationName { get { return "bnhtrade.Core"; } }
+
+ public string ApplicationVersion { get { return "0.1"; } }
+
+ public string ServiceURL { get { return "https://mws.amazonservices.co.uk"; } }
}
}
diff --git a/src/bnhtrade.Core/Data/AmazonMWS/FBAInbound/ListInboundShipmentItems.cs b/src/bnhtrade.Core/Data/AmazonMWS/FBAInbound/ListInboundShipmentItems.cs
index 71a30ef..3863061 100644
--- a/src/bnhtrade.Core/Data/AmazonMWS/FBAInbound/ListInboundShipmentItems.cs
+++ b/src/bnhtrade.Core/Data/AmazonMWS/FBAInbound/ListInboundShipmentItems.cs
@@ -27,7 +27,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
return LastUpdatedBefore != null;
}
- public List GetByAmazonShipmentId(string amazonShipmentId)
+ public List GetByAmazonShipmentId(string amazonShipmentId)
{
// checks
if (amazonShipmentId.Length < 9)
@@ -43,7 +43,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
return ListInboundShipmentItemsGet(request);
}
- public List GetByDates(DateTime lastUpdatedAfter, DateTime lastUpdatedBefore)
+ public List GetByDates(DateTime lastUpdatedAfter, DateTime lastUpdatedBefore)
{
//checks
if (lastUpdatedAfter >= lastUpdatedBefore)
@@ -61,7 +61,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
return ListInboundShipmentItemsGet(request);
}
- private List ListInboundShipmentItemsGet(ListInboundShipmentItemsRequest request)
+ private List ListInboundShipmentItemsGet(ListInboundShipmentItemsRequest request)
{
// variables
int mwsPollFrequency = 500;
@@ -72,7 +72,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
if (!request.IsSetSellerId())
{
var cred = new AmazonMWS.CredentialMws();
- request.SellerId = cred.merchantId;
+ request.SellerId = cred.MerchantId;
}
// checks
@@ -108,7 +108,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
}
// create the return list
- var returnList = new List();
+ var returnList = new List();
// check a result was returned, return empty list on no results
if (!result.IsSetItemData())
@@ -171,7 +171,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
// load data set into returnList
foreach (var item in infoList)
{
- var returnItem = new Model.AmazonFBAInbound.ShipmentItemInfo();
+ var returnItem = new Model.AmazonFba.ShipmentItemInfo();
returnItem.AmazonShipmentId = item.ShipmentId;
returnItem.SKUNumber = item.SellerSKU;
returnItem.AmazonFNSKU = item.FulfillmentNetworkSKU;
diff --git a/src/bnhtrade.Core/Data/AmazonMWS/FBAInbound/ListInboundShipments.cs b/src/bnhtrade.Core/Data/AmazonMWS/FBAInbound/ListInboundShipments.cs
index 8d13c3b..7261236 100644
--- a/src/bnhtrade.Core/Data/AmazonMWS/FBAInbound/ListInboundShipments.cs
+++ b/src/bnhtrade.Core/Data/AmazonMWS/FBAInbound/ListInboundShipments.cs
@@ -14,31 +14,37 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
/// List of Shipment Status' to return. Default is all status' returned.
///
public List ShipmentStatusList { get; set; }
+
///
/// List of Shipment Id to return.
///
public List ShipmentIdList { get; set; }
+
public DateTime LastUpdatedAfter { get; set; }
+
public DateTime LastUpdatedBefore { get; set; }
public bool IsSetShipmentStatusList()
{
return ShipmentStatusList != null;
}
+
public bool IsSetShipmentIdList()
{
return ShipmentIdList != null;
}
+
public bool IsSetLastUpdatedAfter()
{
return LastUpdatedAfter != null;
}
+
public bool IsSetLastUpdatedBefore()
{
return LastUpdatedBefore != null;
}
- public List GetShipmentInfo()
+ public List GetShipmentInfo()
{
// variables
int mwsPollFrequency = 500; // restore rate of two requests every second
@@ -72,7 +78,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
var request = new ListInboundShipmentsRequest();
var cred = new AmazonMWS.CredentialMws();
- request.SellerId = cred.merchantId;
+ request.SellerId = cred.MerchantId;
// add shipment status to request
if (!IsSetShipmentStatusList() && !IsSetShipmentIdList())
@@ -204,12 +210,12 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
}
// build return value
- var returnItem = new List();
+ var returnItem = new List();
//var lastUpdated = infoList.
foreach( InboundShipmentInfo item in infoList)
{
- var listItem = new Core.Model.AmazonFBAInbound.ShipmentInfo();
- listItem.AmazonShipmentId = item.ShipmentId;
+ var listItem = new Core.Model.AmazonFba.ShipmentInfo();
+ listItem.FbaShipmentId = item.ShipmentId;
listItem.DestinationFulfillmentCenterId = item.DestinationFulfillmentCenterId;
listItem.ShipmentName = item.ShipmentName;
listItem.ShipmentStatus = item.ShipmentStatus;
diff --git a/src/bnhtrade.Core/Data/AmazonMWS/Feeds/GetFeedSubmissions.cs b/src/bnhtrade.Core/Data/AmazonMWS/Feeds/GetFeedSubmissions.cs
new file mode 100644
index 0000000..7b606e5
--- /dev/null
+++ b/src/bnhtrade.Core/Data/AmazonMWS/Feeds/GetFeedSubmissions.cs
@@ -0,0 +1,135 @@
+using MarketplaceWebService;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Data.AmazonMWS.Feeds
+{
+ public class GetFeedSubmissions
+ {
+ private Logic.Log.LogEvent logEvent = new Logic.Log.LogEvent();
+
+ public List FeedSubmissionIdList { get; set; } = new List();
+
+ public int MaxCount { get; set; } = 100;
+
+ public List Invoke()
+ {
+ //build the request
+ var cred = new AmazonMWS.CredentialMws();
+ var request = new MarketplaceWebService.Model.GetFeedSubmissionListRequest();
+ request.MaxCount = MaxCount;
+ request.Merchant = cred.MerchantId;
+
+ if (FeedSubmissionIdList.Any())
+ {
+ var idList = new MarketplaceWebService.Model.IdList();
+ idList.Id = FeedSubmissionIdList;
+ request.FeedSubmissionIdList = idList;
+ }
+
+ string error = "GetFeedSubmissionList failed: ";
+ string errorLong = null;
+ int i = 0;
+ int loopMax = 100;
+
+ try
+ {
+ var service = new Data.AmazonMWS.Service().MarketPlaceWeb;
+
+ // set the return list
+ var feedInfoList = new List();
+
+ string nextToken = null;
+ while (i < loopMax)
+ {
+ i++;
+ try
+ {
+ if (nextToken == null)
+ {
+ var responseList = service.GetFeedSubmissionList(request);
+ if (responseList.IsSetGetFeedSubmissionListResult())
+ {
+ var getFeedListResult = responseList.GetFeedSubmissionListResult;
+ feedInfoList = getFeedListResult.FeedSubmissionInfo;
+ if (getFeedListResult.HasNext)
+ {
+ nextToken = getFeedListResult.NextToken;
+ }
+ else
+ {
+ return feedInfoList;
+ }
+ }
+ else
+ {
+ errorLong = responseList.ToXML();
+ throw new Exception("FeedSubmissionListResult was not set");
+ }
+ if (nextToken == null)
+ break;
+ }
+ else
+ {
+ var requestToken = new MarketplaceWebService.Model.GetFeedSubmissionListByNextTokenRequest();
+ requestToken.NextToken = nextToken;
+ requestToken.Merchant = cred.MerchantId;
+
+ var responseList = service.GetFeedSubmissionListByNextToken(requestToken);
+ if (responseList.IsSetGetFeedSubmissionListByNextTokenResult())
+ {
+ var getFeedListResult = responseList.GetFeedSubmissionListByNextTokenResult;
+ feedInfoList.AddRange(getFeedListResult.FeedSubmissionInfo);
+ if (getFeedListResult.HasNext)
+ {
+ nextToken = getFeedListResult.NextToken;
+ }
+ else
+ {
+ return feedInfoList;
+ }
+ }
+ else
+ {
+ errorLong = responseList.ToXML();
+ throw new Exception("FeedSubmissionListResult was not set");
+ }
+ }
+ }
+ catch (MarketplaceWebServiceException ex) when (ex.ErrorCode == "RequestThrottled")
+ {
+ if (nextToken == null) { MiscFunction.MwsThrottleWait(60); } // 10 intial requests, 1 restore every 45 seconds
+ else { MiscFunction.MwsThrottleWait(5); } // 30 intial requests, 1 restore every 2 seconds
+ }
+ catch (MarketplaceWebServiceException ex)
+ {
+ errorLong = "Caught Exception: " + ex.Message +
+ "\r\nResponse Status Code: " + ex.StatusCode +
+ "\r\nError Code: " + ex.ErrorCode +
+ "\r\nError Type: " + ex.ErrorType +
+ "\r\nRequest ID: " + ex.RequestId +
+ "\r\nResponseHeaderMetadata: " + ex.ResponseHeaderMetadata +
+ "\r\nXML:\r\n" + ex.XML;
+
+ throw new Exception("MarketplaceWebServiceException");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ error = error + ex.Message;
+ }
+
+ // should never get here
+ if (i == loopMax)
+ error += "Timeout";
+
+ logEvent.LogError(error, errorLong);
+ throw new Exception(error);
+ }
+
+ }
+}
diff --git a/src/bnhtrade.Core/Data/AmazonMWS/Feeds/SubmitFeed.cs b/src/bnhtrade.Core/Data/AmazonMWS/Feeds/SubmitFeed.cs
new file mode 100644
index 0000000..d160221
--- /dev/null
+++ b/src/bnhtrade.Core/Data/AmazonMWS/Feeds/SubmitFeed.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using MarketplaceWebService;
+using bnhtrade.Core.Logic;
+
+namespace bnhtrade.Core.Data.AmazonMWS.Feeds
+{
+ public class SubmitFeed
+ {
+ private Logic.Log.LogEvent logEvent = new Logic.Log.LogEvent();
+
+ public bool FeedSubmissionRecived { get; set; } = false;
+
+ public SubmitFeed(Model.Export.AmazonFeedSubmission feedSubmission)
+ {
+ FeedSubmissionRecived = false;
+
+ var cred = new CredentialMws();
+ var config = new MarketplaceWebService.MarketplaceWebServiceConfig();
+ config.ServiceURL = cred.ServiceURL;
+
+
+ var marketPlaceList = new MarketplaceWebService.Model.IdList();
+ marketPlaceList.Id = new List { cred.MarketPlaceIdUK };
+
+ var request = new MarketplaceWebService.Model.SubmitFeedRequest();
+ request.MarketplaceIdList = marketPlaceList;
+ request.Merchant = cred.MerchantId;
+ request.FeedContent = feedSubmission.File.FileData;
+ request.FeedType = feedSubmission.FeedType;
+ request.ContentMD5 = feedSubmission.File.FileMD5base64;
+ request.FeedContent.Position = 0;
+
+ var service = new Data.AmazonMWS.Service().MarketPlaceWeb;
+
+ bool repeat = true;
+ var response = new MarketplaceWebService.Model.SubmitFeedResponse();
+
+ // try for a response
+ while (repeat)
+ {
+ try
+ {
+ response = service.SubmitFeed(request);
+ repeat = false;
+ }
+ catch (MarketplaceWebServiceException ex) when (ex.ErrorCode == "RequestThrottled")
+ {
+ MiscFunction.MwsThrottleWait(150); // 15 inital requests, restore 1 every 2 minutes
+ }
+ catch (MarketplaceWebService.MarketplaceWebServiceException ex)
+ {
+ string errorLong = "Caught Exception: " + ex.Message + Environment.NewLine
+ + "Response Status Code: " + ex.StatusCode + Environment.NewLine
+ + "Error Code: " + ex.ErrorCode + Environment.NewLine
+ + "Error Type: " + ex.ErrorType + Environment.NewLine
+ + "Request ID: " + ex.RequestId + Environment.NewLine
+ + "XML: " + Environment.NewLine + ex.XML + Environment.NewLine
+ + "ResponseHeaderMetadata: " + ex.ResponseHeaderMetadata + Environment.NewLine;
+
+ logEvent.LogError("Unhandled MarketplaceWebServiceException while running InvokeSubmitFeed", errorLong);
+ throw new Exception("Unhandled MarketplaceWebServiceException while running InvokeSubmitFeed");
+ }
+ }
+
+ // test the response
+ if (response.IsSetSubmitFeedResult())
+ {
+ MarketplaceWebService.Model.SubmitFeedResult submitFeedResult = response.SubmitFeedResult;
+
+ if (submitFeedResult.IsSetFeedSubmissionInfo())
+ {
+ MarketplaceWebService.Model.FeedSubmissionInfo feedSubmissionInfo = submitFeedResult.FeedSubmissionInfo;
+ if (feedSubmissionInfo.IsSetFeedSubmissionId())
+ {
+ feedSubmission.FeedSubmissionId = feedSubmissionInfo.FeedSubmissionId;
+ FeedSubmissionRecived = true;
+ }
+ else
+ {
+ logEvent.LogError("Response from MWS SubmitFeed did not contain a 'FeedSubmissionId'", submitFeedResult.ToString());
+ return;
+ }
+ if (feedSubmissionInfo.IsSetFeedProcessingStatus())
+ {
+ feedSubmission.FeedProcessingStatus = feedSubmissionInfo.FeedProcessingStatus;
+ }
+ if (feedSubmissionInfo.IsSetCompletedProcessingDate())
+ {
+ feedSubmission.CompletedProcessingDate = DateTime.SpecifyKind(feedSubmissionInfo.CompletedProcessingDate, DateTimeKind.Utc);
+ }
+ if (feedSubmissionInfo.IsSetStartedProcessingDate())
+ {
+ feedSubmission.StartedProcessingDate = DateTime.SpecifyKind(feedSubmissionInfo.StartedProcessingDate, DateTimeKind.Utc);
+ }
+ if (feedSubmissionInfo.IsSetSubmittedDate())
+ {
+ if (feedSubmissionInfo.SubmittedDate != null)
+ {
+ feedSubmission.SubmittedDate = DateTime.SpecifyKind(DateTime.Parse(feedSubmissionInfo.SubmittedDate), DateTimeKind.Utc);
+ }
+ }
+ }
+ else
+ {
+ logEvent.LogError("Response from MWS SubmitFeed did not contain a 'FeedSubmissionInfo'", response.ToXML());
+ throw new Exception("Request FeedSubmissionInfo not set."); // no idea what to do here, what happened, has it been submitted?
+ }
+ }
+ else
+ {
+ logEvent.LogError("Response from MWS SubmitFeed did not contain a 'SubmitFeedResult'", response.ToXML());
+ throw new Exception("Request SubmitFeedResult not set."); // no idea what to do here, what happened, has it been submitted?
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/AmazonMWS/Service.cs b/src/bnhtrade.Core/Data/AmazonMWS/Service.cs
index 7eb0773..9b3442a 100644
--- a/src/bnhtrade.Core/Data/AmazonMWS/Service.cs
+++ b/src/bnhtrade.Core/Data/AmazonMWS/Service.cs
@@ -25,17 +25,16 @@ namespace bnhtrade.Core.Data.AmazonMWS
{
var cred = new AmazonMWS.CredentialMws();
- this.merchantId = cred.merchantId;
- this.marketplaceId = cred.marketPlaceId;
- this.accessKeyId = cred.accessKeyId;
- this.secretAccessKey = cred.secretAccessKey;
- this.applicationName = cred.applicationName;
- this.applicationVersion = cred.applicationVersion;
- this.serviceURL = cred.serviceURL;
+ this.merchantId = cred.MerchantId;
+ this.marketplaceId = cred.MarketPlaceIdUK;
+ this.accessKeyId = cred.AccessKeyId;
+ this.secretAccessKey = cred.SecretAccessKey;
+ this.applicationName = cred.ApplicationName;
+ this.applicationVersion = cred.ApplicationVersion;
+ this.serviceURL = cred.ServiceURL;
}
public MarketplaceWebService.MarketplaceWebService MarketPlaceWeb
-
{
get
{
diff --git a/src/bnhtrade.Core/Data/Database/Account/CreateInvoiceLineItem.cs b/src/bnhtrade.Core/Data/Database/Account/CreateInvoiceLineItem.cs
new file mode 100644
index 0000000..df00bda
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Account/CreateInvoiceLineItem.cs
@@ -0,0 +1,43 @@
+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
+{
+ public class CreateInvoiceLineItem : Connection
+ {
+ public CreateInvoiceLineItem(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ }
+
+ 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;
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs b/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs
index 1e5fb86..0887af7 100644
--- a/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs
+++ b/src/bnhtrade.Core/Data/Database/Account/ReadAccountCode.cs
@@ -9,62 +9,34 @@ namespace bnhtrade.Core.Data.Database.Account
{
public class ReadAccountCode : Connection
{
- private bool allRetrived;
- private Dictionary cache;
- protected ReadAccountCode(string sqlConnectionString) : base(sqlConnectionString)
+ private Data.Database.WhereBuilder sqlWhere = new WhereBuilder();
+ private List resultList;
+
+ public ReadAccountCode(string sqlConnectionString) : base(sqlConnectionString)
{
- allRetrived = false;
- cache = new Dictionary();
}
- protected void ClearCache()
+
+ public List All()
{
- allRetrived = false;
- cache.Clear();
+ Innit();
+ return Execute(null, null);
}
- public List GetAll()
+
+ public List ByAccountCode(List accountCodeList)
{
- if (allRetrived == false)
+ Innit();
+
+ if (accountCodeList == null || !accountCodeList.Any())
{
- UpdateCache(-1);
- allRetrived = true;
+ return resultList;
}
- var returnList = new List();
- foreach (var item in cache)
- {
- returnList.Add(item.Value);
- }
-
- return returnList;
+ sqlWhere.In("tblAccountChartOf.AccountCode", accountCodeList, " WHERE ");
+ return Execute(sqlWhere.SqlWhereString, sqlWhere.ParameterList);
}
- public Model.Account.AccountCode GetByAccountCode(int accountCode)
- {
- if (cache.ContainsKey(accountCode))
- {
- return cache[accountCode];
- }
- else if (allRetrived)
- {
- return null;
- }
- else
- {
- UpdateCache(accountCode);
- if (cache.ContainsKey(accountCode))
- {
- return cache[accountCode];
- }
- else
- {
- return null;
- }
- }
- }
- protected void UpdateCache(int accountCode = -1)
- {
- var dicCache = new Dictionary();
- bool whereClause = false;
+ private List Execute(string sqlWhere, Dictionary parameters)
+ {
//build sql query
string sqlString = @"
SELECT tblAccountChartOf.AccountChartOfID
@@ -74,13 +46,8 @@ namespace bnhtrade.Core.Data.Database.Account
,tblAccountChartOfType.AccountChartOfType
,tblAccountChartOfType.BasicType
FROM tblAccountChartOf
- INNER JOIN tblAccountChartOfType ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID";
- if (accountCode > -1)
- {
- whereClause = true;
- sqlString = sqlString + @"
- WHERE (((tblAccountChartOf.AccountCode) = @accountCode))";
- }
+ INNER JOIN tblAccountChartOfType ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID
+ " + sqlWhere;
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
@@ -88,9 +55,12 @@ namespace bnhtrade.Core.Data.Database.Account
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
{
- if (whereClause)
+ if (parameters != null)
{
- cmd.Parameters.AddWithValue("@accountCode", accountCode);
+ foreach (var parameter in parameters)
+ {
+ cmd.Parameters.AddWithValue(parameter.Key, parameter.Value);
+ }
}
using (SqlDataReader reader = cmd.ExecuteReader())
@@ -108,30 +78,19 @@ namespace bnhtrade.Core.Data.Database.Account
result.Type = reader.GetString(4);
result.BasicType = reader.GetString(5);
- if (whereClause)
- {
- if (cache.ContainsKey(result.AccountCodeId))
- {
- cache.Remove(result.AccountCodeId);
- }
- cache.Add(result.AccountCodeId, result);
- }
- else
- {
- dicCache.Add(result.AccountCodeId, result);
- }
+ resultList.Add(result);
}
}
+
+ return resultList;
}
}
}
- // update cache
- if (!whereClause)
- {
- cache.Clear();
- allRetrived = true;
- cache = dicCache;
- }
+ }
+
+ private void Innit()
+ {
+ resultList = new List();
}
}
}
diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItem.cs b/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItem.cs
new file mode 100644
index 0000000..ae85e11
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItem.cs
@@ -0,0 +1,113 @@
+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
+{
+ public class ReadInvoiceLineItem : Connection
+ {
+ public ReadInvoiceLineItem(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ Innit();
+ }
+
+ public Dictionary AccountCodeList { get; private set; }
+
+ public Dictionary TaxCodeList { get; private set; }
+
+ private void Innit()
+ {
+ AccountCodeList = new Dictionary();
+ TaxCodeList = new Dictionary();
+ }
+
+ public Model.Account.InvoiceLineItem ByItemCode(string itemCode)
+ {
+ if (string.IsNullOrWhiteSpace(itemCode)) { return null; }
+
+ var result = ByItemCode(new List{ itemCode });
+
+ if (!result.Any())
+ {
+ return null;
+ }
+ else
+ {
+ return result[itemCode];
+ }
+ }
+
+ public Dictionary ByItemCode(List itemCodeList)
+ {
+ Innit();
+ var resultList = new Dictionary();
+
+ if (itemCodeList == null || !itemCodeList.Any())
+ { return resultList; }
+
+ string sql = @"
+ SELECT tblAccountInvoiceLineItem.ItemCode
+ ,tblAccountInvoiceLineItem.ItemName
+ ,tblAccountInvoiceLineItem.ItemDescription
+ ,tblAccountInvoiceLineItem.IsNewReviewRequired
+ ,tblAccountInvoiceLineItem.InvoiceLineEntryEnable
+ ,tblAccountChartOf.AccountCode
+ ,tblAccountTaxCode.TaxCode
+ FROM tblAccountInvoiceLineItem
+ LEFT OUTER JOIN tblAccountTaxCode ON tblAccountInvoiceLineItem.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID
+ LEFT OUTER JOIN tblAccountChartOf ON tblAccountInvoiceLineItem.AccountChartOfID_Default = tblAccountChartOf.AccountChartOfID
+ WHERE ";
+
+ var whereBuilder = new WhereBuilder();
+ whereBuilder.In("tblAccountInvoiceLineItem.ItemCode", itemCodeList);
+ sql += whereBuilder.SqlWhereString;
+
+ using (SqlConnection conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ foreach (var param in whereBuilder.ParameterList)
+ {
+ cmd.Parameters.AddWithValue(param.Key, param.Value);
+ }
+
+ using (SqlDataReader reader = cmd.ExecuteReader())
+ {
+ if (reader.HasRows)
+ {
+ while (reader.Read())
+ {
+ var result = new Model.Account.InvoiceLineItem();
+
+ result.ItemCode = reader.GetString(0);
+ result.Name = reader.GetString(1);
+ if (!reader.IsDBNull(2)) { result.Description = reader.GetString(2); }
+ result.IsNewReviewRequired = reader.GetBoolean(3);
+ result.InvoiceLineEntryEnabled = reader.GetBoolean(4);
+
+ if (!reader.IsDBNull(5))
+ {
+ AccountCodeList.Add(result.ItemCode, reader.GetInt32(5));
+ }
+ if (!reader.IsDBNull(6))
+ {
+ TaxCodeList.Add(result.ItemCode, reader.GetString(6));
+ }
+
+ resultList.Add(result.ItemCode, result);
+ }
+ }
+
+ return resultList;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItemCode.cs b/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItemCode.cs
deleted file mode 100644
index 94708ff..0000000
--- a/src/bnhtrade.Core/Data/Database/Account/ReadInvoiceLineItemCode.cs
+++ /dev/null
@@ -1,148 +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
-{
- public class ReadInvoiceLineItemCode : Connection
- {
- public ReadInvoiceLineItemCode(string sqlConnectionString) : base (sqlConnectionString)
- {
- cacheLineItemByTablePk = new Dictionary();
- cacheTablePkByItemCode = new Dictionary();
- }
-
- private Dictionary cacheLineItemByTablePk;
- private Dictionary cacheTablePkByItemCode;
-
- public bool InsertNewOnNoMatch { get; set; } = false;
-
- public string NewTypeTitle { get; } = "NEW TYPE";
-
- public void CacheClear()
- {
- cacheLineItemByTablePk.Clear();
- cacheTablePkByItemCode.Clear();
- }
-
- private void CacheRemove(int tablePk)
- {
- if (cacheLineItemByTablePk.ContainsKey(tablePk))
- {
- string itemCode = cacheLineItemByTablePk[tablePk].ItemCode;
- cacheLineItemByTablePk.Remove(tablePk);
- cacheTablePkByItemCode.Remove(itemCode);
- }
- }
-
- public void CacheRemove(string itemCode)
- {
- if (cacheTablePkByItemCode.ContainsKey(itemCode))
- {
- CacheRemove(cacheTablePkByItemCode[itemCode]);
- }
- }
-
- private void CacheUpdate(int tablePk, Model.Account.InvoiceLineItem lineItem)
- {
- if (cacheLineItemByTablePk.ContainsKey(tablePk))
- {
- CacheRemove(tablePk);
- }
- cacheLineItemByTablePk.Add(tablePk, lineItem);
- cacheTablePkByItemCode.Add(lineItem.ItemCode, tablePk);
- }
-
- public Model.Account.InvoiceLineItem ByItemCode(string itemCode, bool forceCacheUpdate = false)
- {
- // check cache
- if (!forceCacheUpdate && cacheTablePkByItemCode.ContainsKey(itemCode))
- {
- return cacheLineItemByTablePk[cacheTablePkByItemCode[itemCode]];
- }
-
- var returnObject = new Model.Account.InvoiceLineItem();
- returnObject.ItemCode = itemCode;
-
- using (TransactionScope scopeSupress = new TransactionScope(TransactionScopeOption.Suppress))
- using (SqlConnection conn = new SqlConnection(sqlConnectionString))
- {
- conn.Open();
-
- using (SqlCommand cmd = new SqlCommand(@"
- SELECT tblExportAccountInvoiceLineType.ExportAccountInvoiceLineTypeID
- ,tblExportAccountInvoiceLineType.TypeTitle
- ,tblExportAccountInvoiceLineType.TypeDescription
- ,tblExportAccountInvoiceLineType.IsNewReviewRequired
- ,tblExportAccountInvoiceLineType.InvoiceLineEntryEnable
- ,tblAccountChartOf.AccountCode
- ,tblAccountTaxCode.TaxCode
- FROM (
- tblExportAccountInvoiceLineType LEFT JOIN tblAccountChartOf ON tblExportAccountInvoiceLineType.AccountChartOfID_Default = tblAccountChartOf.AccountChartOfID
- )
- LEFT JOIN tblAccountTaxCode ON tblExportAccountInvoiceLineType.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID
- WHERE (((tblExportAccountInvoiceLineType.MatchString) = @matchString))
- ", conn))
- {
- cmd.Parameters.AddWithValue("@matchString", returnObject.ItemCode);
-
- using (SqlDataReader reader = cmd.ExecuteReader())
- {
- if (reader.Read())
- {
- int tablePk = reader.GetInt32(0);
- returnObject.Title = reader.GetString(1);
- if (!reader.IsDBNull(2)) { returnObject.Description = reader.GetString(2); }
- returnObject.IsNewReviewRequired = reader.GetBoolean(3);
- returnObject.InvoiceLineEntryEnabled = reader.GetBoolean(4);
- if (!reader.IsDBNull(5)) { returnObject.DefaultAccountCode = reader.GetInt32(5); }
- if (!reader.IsDBNull(6)) { returnObject.DefaultTaxCode = reader.GetString(6); }
-
- // add to cache
- CacheUpdate(tablePk, returnObject);
-
- // return object
- return returnObject;
- }
- }
- }
-
- // insert new and retrive new value, if required
- if (InsertNewOnNoMatch)
- {
- int tablePk = 0;
- returnObject.Title = NewTypeTitle;
- returnObject.ItemCode = itemCode;
- returnObject.IsNewReviewRequired = true;
-
- using (SqlCommand insertCmd = new SqlCommand(@"
- INSERT INTO tblExportAccountInvoiceLineType ( TypeTitle, MatchString )
- OUTPUT INSERTED.ExportAccountInvoiceLineTypeID
- VALUES ( @typeTitle, @matchString )
- ", conn))
- {
- insertCmd.Parameters.AddWithValue("@typeTitle", returnObject.Title);
- insertCmd.Parameters.AddWithValue("@matchString", returnObject.ItemCode);
-
- tablePk = (int)insertCmd.ExecuteScalar();
-
- scopeSupress.Complete();
- }
- // add to cache
- CacheUpdate(tablePk, returnObject);
-
- // return object
- return returnObject;
- }
- else
- {
- return null;
- }
- }
- }
- }
-}
diff --git a/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs b/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs
index 7332673..61a8275 100644
--- a/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs
+++ b/src/bnhtrade.Core/Data/Database/Account/ReadTaxCode.cs
@@ -9,165 +9,32 @@ namespace bnhtrade.Core.Data.Database.Account
{
public class ReadTaxCode : Connection
{
- private bool allRetrived;
- private Dictionary cache;
+ private Data.Database.WhereBuilder whereBuilder;
+
public ReadTaxCode(string sqlConnectionString) : base(sqlConnectionString)
{
- allRetrived = false;
- cache = new Dictionary();
+ whereBuilder = new WhereBuilder();
}
- private void ClearCache()
+
+ private List Execute(string sqlWhere, Dictionary parameters)
{
- allRetrived = false;
- cache.Clear();
- }
- public List GetAll()
- {
- if (allRetrived == false)
- {
- UpdateCache(null);
- allRetrived = true;
- }
+ var resultList = new List();
- var returnList = new List();
- foreach (var item in cache)
- {
- returnList.Add(item.Value);
- }
-
- return returnList;
- }
- public Dictionary BySkuNumber(List skuNumberList)
- {
- // check input list for items
- if (skuNumberList == null || !skuNumberList.Any())
- {
- return null;
- }
-
- // build SQL string
- string sqlString = @"
- SELECT
- tblSku.skuSkuNumber, tblAccountTaxCode.TaxCode
- FROM
- tblAccountTaxCode INNER JOIN tblSku ON tblAccountTaxCode.AccountTaxCodeID = tblSku.AccountTaxCodeID
- WHERE
- ";
-
- var parameterValueList = new List>();
- foreach (var item in skuNumberList)
- {
- if (!string.IsNullOrWhiteSpace(item))
- {
- int count = parameterValueList.Count;
- var parameterValue = new Tuple("@parameter" + count, item);
- parameterValueList.Add(parameterValue);
- if (count == 0)
- {
- sqlString = sqlString + @"
- skuSkuNumber = " + parameterValue.Item1;
- }
- else
- {
- sqlString = sqlString + @"
- OR skuSkuNumber = " + parameterValue.Item1;
- }
- }
- }
-
- if (parameterValueList.Count == 0)
- {
- return null;
- }
-
- // execute query and build result list
- var skuTaxCodeList = new List>();
- using (SqlConnection conn = new SqlConnection(sqlConnectionString))
- {
- conn.Open();
-
- using (SqlCommand cmd = new SqlCommand(sqlString, conn))
- {
- foreach (var item in parameterValueList)
- {
- cmd.Parameters.AddWithValue(item.Item1, item.Item2);
- }
-
- using (SqlDataReader reader = cmd.ExecuteReader())
- {
- if (!reader.HasRows)
- {
- return null;
- }
-
- while (reader.Read())
- {
- var skuTaxCode = new Tuple(
- reader.GetString(0),
- reader.GetString(1)
- );
- skuTaxCodeList.Add(skuTaxCode);
- }
- }
- }
-
- // build dictionary of skuNumber to TaxCodeInfo
- var returnDictionary = new Dictionary();
- foreach (var item in skuTaxCodeList)
- {
- returnDictionary.Add(item.Item1, GetByTaxCodeId(item.Item2));
- }
-
- return returnDictionary;
- }
- }
- public Model.Account.TaxCode GetByTaxCodeId(string taxCode)
- {
- if (cache.ContainsKey(taxCode))
- {
- return cache[taxCode];
- }
- else if (allRetrived)
- {
- return null;
- }
- else
- {
- UpdateCache(taxCode);
- if (cache.ContainsKey(taxCode))
- {
- return cache[taxCode];
- }
- else
- {
- return null;
- }
- }
- }
- private void UpdateCache(string taxCode)
- {
- var dicCache = new Dictionary();
-
- bool whereClause = false;
//build sql query
string sqlString = @"
SELECT
TaxCode
- ,TaxRateName
- ,TaxRateMultiplierNet
- ,TaxRateMultiplierGross
+ ,TaxCodeName
+ ,TaxCodeDescription
+ ,TaxRatePercent
+ ,IsMarginScheme
,IsValidOnExpense
,IsVailidOnIncome
- ,Description
,IsActive
,TaxType
FROM tblAccountTaxCode";
- if (!string.IsNullOrWhiteSpace(taxCode))
- {
- whereClause = true;
- sqlString = sqlString + @"
- WHERE TaxCode = @taxCode";
- }
+
+ sqlString += sqlWhere;
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
@@ -175,9 +42,9 @@ namespace bnhtrade.Core.Data.Database.Account
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
{
- if (whereClause)
+ foreach (var paramter in parameters)
{
- cmd.Parameters.AddWithValue("@taxCode", taxCode);
+ cmd.Parameters.AddWithValue(paramter.Key, paramter.Value);
}
using (SqlDataReader reader = cmd.ExecuteReader())
@@ -186,42 +53,160 @@ namespace bnhtrade.Core.Data.Database.Account
{
while (reader.Read())
{
- var result = new Model.Account.TaxCode();
+ string taxCodeId = reader.GetString(0);
+ string name = reader.GetString(1);
+ string description = null;
+ if (!reader.IsDBNull(2)) { description = reader.GetString(2); }
+ decimal rate = reader.GetDecimal(3);
+ bool isMargin = reader.GetBoolean(4);
+ bool isValidOnExpense = reader.GetBoolean(5);
+ bool isValidOnIncome = reader.GetBoolean(6);
+ bool isActive = reader.GetBoolean(7);
+ string taxType = reader.GetString(8);
- result.TaxCodeId = reader.GetString(0);
- result.TaxRateTitle = reader.GetString(1);
- result.NetAmountMultiplier = reader.GetDecimal(2);
- result.GrossAmountMultiplier = reader.GetDecimal(3);
- result.IsValidOnExpense = reader.GetBoolean(4);
- result.IsValidOnIncome = reader.GetBoolean(5);
- if (!reader.IsDBNull(6)) { result.TaxRateDescription = reader.GetString(6); }
- result.IsActive = reader.GetBoolean(7);
- result.TaxType = reader.GetString(8);
+ var result = new Model.Account.TaxCodeInfo(
+ taxCodeId,
+ name,
+ description,
+ rate,
+ isMargin,
+ isValidOnExpense,
+ isValidOnIncome,
+ taxType,
+ isActive);
- if (whereClause)
- {
- if (cache.ContainsKey(result.TaxCodeId))
- {
- cache.Remove(result.TaxCodeId);
- }
- cache.Add(result.TaxCodeId, result);
- }
- else
- {
- dicCache.Add(result.TaxCodeId, result);
- }
+ resultList.Add(result);
}
}
}
}
}
- // update cache
- if (!whereClause)
+ return resultList;
+ }
+
+ public List GetByTaxCode(List taxcodeList)
+ {
+ var resultList = new List();
+
+ if (taxcodeList == null || !taxcodeList.Any())
{
- cache.Clear();
- allRetrived = true;
- cache = dicCache;
+ return resultList;
}
+
+ whereBuilder.Innit();
+ whereBuilder.In("TaxCode", taxcodeList, "WHERE");
+
+ return Execute(whereBuilder.SqlWhereString, whereBuilder.ParameterList);
+ }
+
+ public List GetAllActive()
+ {
+ string sqlWhere = @"
+ WHERE IsActive=@isActive;";
+ var parameters = new Dictionary();
+ parameters.Add("@isActive", true);
+
+ return Execute(sqlWhere, parameters);
+ }
+
+ public Dictionary GetTaxCodeBySkuNumber(List skuNumberList)
+ {
+ var resultList = new Dictionary();
+
+ if (skuNumberList == null || !skuNumberList.Any())
+ {
+ return resultList;
+ }
+
+ string sql = @"
+ SELECT tblSku.skuSkuNumber
+ ,tblAccountTaxCode.TaxCode
+ FROM tblSku
+ INNER JOIN tblAccountTaxCode ON tblSku.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID ";
+
+ whereBuilder.Innit();
+ 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 GetTaxCodeByInvoiceLineItemCode(List lineItemCode)
+ {
+ var resultList = new Dictionary();
+
+ if (lineItemCode == null || !lineItemCode.Any())
+ {
+ return resultList;
+ }
+
+ string sql = @"
+ SELECT tblAccountInvoiceLineItem.ItemCode
+ ,tblAccountTaxCode.TaxCode
+ FROM tblAccountInvoiceLineItem
+ LEFT OUTER JOIN tblAccountTaxCode ON tblAccountInvoiceLineItem.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID
+ ";
+
+ whereBuilder.Innit();
+ 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;
}
}
}
diff --git a/src/bnhtrade.Core/Data/Database/AmazonFba/ReadShipmentInfo.cs b/src/bnhtrade.Core/Data/Database/AmazonFba/ReadShipmentInfo.cs
new file mode 100644
index 0000000..403fb24
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/AmazonFba/ReadShipmentInfo.cs
@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.AmazonShipment
+{
+ public class ReadShipmentInfo : Connection
+ {
+ private List shipmentIdList;
+
+ public ReadShipmentInfo(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ }
+
+ ///
+ /// Return active shipments only. Default is false.
+ ///
+ public bool ReturnOnlyActiveShipments { get; set; } = false;
+
+ private bool IsSetFbaShipmentIdList
+ {
+ get
+ {
+ if (FbaShipmentIdList == null || !FbaShipmentIdList.Any()) { return false; }
+ else { return true; }
+ }
+ }
+
+ ///
+ /// Filter results by Amazon's shipment Id.
+ ///
+ private List FbaShipmentIdList
+ {
+ get { return shipmentIdList; }
+ set
+ {
+ if (value != null)
+ {
+ // clean list
+ shipmentIdList = new List();
+ foreach (string item in value)
+ {
+ if (item.Length > 0)
+ {
+ shipmentIdList.Add(item);
+ }
+ }
+ if (!FbaShipmentIdList.Any())
+ {
+ shipmentIdList = null;
+ throw new Exception("Invalid shipment Id set");
+ }
+ }
+ }
+ }
+
+ public Model.AmazonFba.ShipmentInfo HeaderByFbaShipmentId(string fbaShipmentId)
+ {
+ if (string.IsNullOrWhiteSpace(fbaShipmentId))
+ {
+ return null;
+ }
+ var list = new List { fbaShipmentId };
+ var result = HeaderByFbaShipmentId(list);
+ if (result.Any())
+ {
+ return result[0];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public List HeaderByFbaShipmentId(List fbaShipmentIdList)
+ {
+ FbaShipmentIdList = fbaShipmentIdList;
+
+ if (IsSetFbaShipmentIdList)
+ {
+ string sql = @"
+ AND tblAmazonShipment.ShipmentId IN @shipmentId ";
+
+ var parameters = new DynamicParameters();
+ parameters.Add("@shipmentId", FbaShipmentIdList);
+
+ return HeaderInfo(sql, parameters);
+ }
+ else
+ {
+ return new List();
+ }
+ }
+
+ ///
+ /// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
+ ///
+ /// Amazon's inbound FBA shipment Id.
+ /// Primary key or -1 if match isn't found.
+ private List HeaderInfo(string sqlWhere, DynamicParameters parameters)
+ {
+ // build the sql string
+ string sql = @"
+ SELECT tblAmazonShipment.AmazonShipmentID
+ ,tblAmazonShipment.ShipmentName
+ ,tblAmazonShipment.ShipmentId AS FbaShipmentId
+ ,tblAmazonShipment.CenterId
+ ,tblAmazonShipment.ShipmentStatus
+ ,tblAmazonShipment.LastUpdated
+ ,tblAmazonShipment.IsClosed
+ ,tblStockStatus.StockStatusID AS ShipmentStockStatusId
+ ,tblStockStatus.StockStatus AS ShipmentStockStatus
+ FROM tblAmazonShipment
+ LEFT OUTER JOIN tblStockStatus ON tblAmazonShipment.ShipmentStockStatusID = tblStockStatus.StockStatusID
+ WHERE 1=1 ";
+
+ sql += sqlWhere;
+
+ if (ReturnOnlyActiveShipments)
+ {
+ sql = sql + @"
+ AND IsClosed = 0";
+ }
+
+ using (SqlConnection conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ var result = conn.Query(sql, parameters).ToList();
+
+ // set datetime kind
+ for (int i = 0; i < result.Count; i++)
+ {
+ if (result[i].IsSetLastUpdated())
+ {
+ result[i].LastUpdated = DateTime.SpecifyKind(result[i].LastUpdated, DateTimeKind.Utc);
+ }
+ }
+
+ return result;
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentPrimaryKey.cs b/src/bnhtrade.Core/Data/Database/AmazonFba/ReadShipmentPrimaryKey.cs
similarity index 94%
rename from src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentPrimaryKey.cs
rename to src/bnhtrade.Core/Data/Database/AmazonFba/ReadShipmentPrimaryKey.cs
index 044d03b..7a3fbff 100644
--- a/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentPrimaryKey.cs
+++ b/src/bnhtrade.Core/Data/Database/AmazonFba/ReadShipmentPrimaryKey.cs
@@ -5,14 +5,18 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace bnhtrade.Core.Data.Database.FBAInbound
+namespace bnhtrade.Core.Data.Database.AmazonShipment
{
- public class GetShipmentPrimaryKey : Connection
+ public class ReadShipmentPrimaryKey : Connection
{
private bool enableCache = false;
private Dictionary shipmentPKByAmazonShipmentIdDic;
private Dictionary amazonShipmentIdByShipmentPKDic;
- public GetShipmentPrimaryKey(string sqlConnectionString) : base(sqlConnectionString) { }
+
+ public ReadShipmentPrimaryKey(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ }
+
public bool CacheEnabled
{
get { return enableCache; }
@@ -30,6 +34,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
}
}
}
+
private void ClearCache()
{
if (CacheEnabled)
@@ -38,6 +43,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
amazonShipmentIdByShipmentPKDic.Clear();
}
}
+
private void DeleteCachedShipmentPK(int shipmentPrimaryKey)
{
if (CacheEnabled)
@@ -50,6 +56,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
}
}
}
+
///
/// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
///
@@ -99,6 +106,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
UpdateCache(shipmentPK, amazonShipmentId);
return shipmentPK;
}
+
private void UpdateCache(int shipmentPK, string amazonShipmentId)
{
if (CacheEnabled)
diff --git a/src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs b/src/bnhtrade.Core/Data/Database/AmazonFba/SetShipmentInfo.cs
similarity index 88%
rename from src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs
rename to src/bnhtrade.Core/Data/Database/AmazonFba/SetShipmentInfo.cs
index 049e77b..c83f3ce 100644
--- a/src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs
+++ b/src/bnhtrade.Core/Data/Database/AmazonFba/SetShipmentInfo.cs
@@ -6,20 +6,24 @@ using System.Text;
using System.Threading.Tasks;
using System.Transactions;
-namespace bnhtrade.Core.Data.Database.FBAInbound
+namespace bnhtrade.Core.Data.Database.AmazonShipment
{
public class SetShipmentInfo : Connection
{
- private GetShipmentPrimaryKey getPK;
- private Data.Database.SKU.GetSkuId skuIdLoopkup;
- public SetShipmentInfo(string sqlConnectionString) : base(sqlConnectionString) { }
- private GetShipmentPrimaryKey GetPK
+ private ReadShipmentPrimaryKey getPK;
+ private Data.Database.Sku.GetSkuId skuIdLoopkup;
+
+ public SetShipmentInfo(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ }
+
+ private ReadShipmentPrimaryKey GetPK
{
get
{
if (getPK == null)
{
- getPK = new GetShipmentPrimaryKey(sqlConnectionString);
+ getPK = new ReadShipmentPrimaryKey(sqlConnectionString);
}
return getPK;
}
@@ -28,18 +32,20 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
getPK = value;
}
}
- private Data.Database.SKU.GetSkuId SkuIdLoopkup
+
+ private Data.Database.Sku.GetSkuId SkuIdLoopkup
{
get
{
if (skuIdLoopkup == null)
{
- skuIdLoopkup = new SKU.GetSkuId(sqlConnectionString);
+ skuIdLoopkup = new Sku.GetSkuId(sqlConnectionString);
}
return skuIdLoopkup;
}
}
- public void Excecute(Model.AmazonFBAInbound.ShipmentInfo info)
+
+ public void Excecute(Model.AmazonFba.ShipmentInfo info)
{
using (var scope = new TransactionScope())
{
@@ -54,7 +60,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
}
// get tablePK
- int shipmentPK = GetPK.ByAmazonShipmentId(info.AmazonShipmentId);
+ int shipmentPK = GetPK.ByAmazonShipmentId(info.FbaShipmentId);
// add or update shipment header info
if (shipmentPK == -1)
@@ -106,7 +112,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
}
}
- public void ExcecuteByList(List infoList)
+ public void ExcecuteByList(List infoList)
{
using (var scope = new TransactionScope())
{
@@ -138,7 +144,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
}
}
- private int InsertShipmentHeaderInfo(Model.AmazonFBAInbound.ShipmentInfo info)
+ private int InsertShipmentHeaderInfo(Model.AmazonFba.ShipmentInfo info)
{
if (!info.IsSetAll())
{
@@ -149,7 +155,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
{
conn.Open();
- if (GetPK.ByAmazonShipmentId(info.AmazonShipmentId) != -1)
+ if (GetPK.ByAmazonShipmentId(info.FbaShipmentId) != -1)
{
throw new Exception("Shipment insert failed, shipment with same Amazon Id already exists.");
}
@@ -189,10 +195,10 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
{
cmd.Parameters.AddWithValue("@amazonShipmentCount", sequenceNumber);
cmd.Parameters.AddWithValue("@shipmentName", info.ShipmentName);
- cmd.Parameters.AddWithValue("@shipmentId", info.AmazonShipmentId);
+ cmd.Parameters.AddWithValue("@shipmentId", info.FbaShipmentId);
cmd.Parameters.AddWithValue("@centerId", info.DestinationFulfillmentCenterId);
cmd.Parameters.AddWithValue("@shipmentStatus", info.ShipmentStatus);
- cmd.Parameters.AddWithValue("@lastUpdated", info.LastUpdatedUtc);
+ cmd.Parameters.AddWithValue("@lastUpdated", info.LastUpdated.ToUniversalTime());
cmd.Parameters.AddWithValue("@isClosed", info.ShipmentIsClosed);
int tablePk = (int)cmd.ExecuteScalar();
@@ -203,9 +209,9 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
}
}
- private void UpdateShipmentHeaderInfo(Model.AmazonFBAInbound.ShipmentInfo info)
+ private void UpdateShipmentHeaderInfo(Model.AmazonFba.ShipmentInfo info)
{
- int tablePK = GetPK.ByAmazonShipmentId(info.AmazonShipmentId);
+ int tablePK = GetPK.ByAmazonShipmentId(info.FbaShipmentId);
if (tablePK == -1)
{
throw new Exception("Shipment insert failed, shipment with same Amazon Id already exists.");
@@ -229,7 +235,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
{
cmd.Parameters.AddWithValue("@shipmentName", info.ShipmentName);
cmd.Parameters.AddWithValue("@shipmentStatus", info.ShipmentStatus);
- cmd.Parameters.AddWithValue("@lastUpdated", info.LastUpdatedUtc);
+ cmd.Parameters.AddWithValue("@lastUpdated", info.LastUpdated.ToUniversalTime());
cmd.Parameters.AddWithValue("@isClosed", info.ShipmentIsClosed);
cmd.Parameters.AddWithValue("@tablePK", tablePK);
diff --git a/src/bnhtrade.Core/Data/Database/Connection.cs b/src/bnhtrade.Core/Data/Database/Connection.cs
index ec28d19..35ed544 100644
--- a/src/bnhtrade.Core/Data/Database/Connection.cs
+++ b/src/bnhtrade.Core/Data/Database/Connection.cs
@@ -10,11 +10,14 @@ namespace bnhtrade.Core.Data.Database
public class Connection
{
protected readonly string sqlConnectionString;
+
public Connection(string sqlConnectionString)
{
// setup sql parameters
- if (sqlConnectionString.Length == 0)
- { throw new Exception("Zero length sql connectionstring passed"); }
+ if (string.IsNullOrWhiteSpace(sqlConnectionString))
+ {
+ throw new Exception("Zero length sql connection string passed");
+ }
this.sqlConnectionString = sqlConnectionString;
}
}
diff --git a/src/bnhtrade.Core/Data/Database/Constants.cs b/src/bnhtrade.Core/Data/Database/Constants.cs
new file mode 100644
index 0000000..4b989b5
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Constants.cs
@@ -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
+{
+ public static class Constants
+ {
+ public static int GetProductConditionIdNew()
+ {
+ return 10;
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Export/CreateAmazonFeedSubmission.cs b/src/bnhtrade.Core/Data/Database/Export/CreateAmazonFeedSubmission.cs
new file mode 100644
index 0000000..3b8e5d9
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Export/CreateAmazonFeedSubmission.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Data.Database.Export
+{
+ public class CreateAmazonFeedSubmission : Connection
+ {
+ public CreateAmazonFeedSubmission (string sqlConnectionString) : base(sqlConnectionString)
+ {
+
+ }
+
+ public int Execute(string feedType, Model.Data.DatabaseFileStream fileStreamData)
+ {
+ // write to db
+ int id = 0;
+ var result = new Model.Export.AmazonFeedSubmission();
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (var cmd = new SqlCommand(@"
+ INSERT INTO tblExportAmazonFeedSubmission (
+ FileData
+ ,FileExtention
+ ,FileSize
+ ,FileMD5base64
+ ,ExportAmazonFeedSubmissionTypeID
+ ,ExportAmazonFeedSubmissionStatusID )
+ OUTPUT
+ INSERTED.ExportAmazonFeedSubmissionID
+ ,INSERTED.FileGUID
+ VALUES (
+ @fileData
+ ,@fileExtention
+ ,@fileSize
+ ,@fileMD5base64
+ ,(SELECT ExportAmazonFeedSubmissionTypeID
+ FROM tblExportAmazonFeedSubmissionType
+ WHERE FeedType = @feedType )
+ ,(SELECT ExportAmazonFeedSubmissionStatusID
+ FROM tblExportAmazonFeedSubmissionStatus
+ WHERE FeedProcessingStatus = 'New' )
+ )
+ ", conn))
+ {
+ fileStreamData.FileData.Position = 0;
+ cmd.Parameters.AddWithValue("@fileData", fileStreamData.FileData.ToArray());
+ cmd.Parameters.AddWithValue("@fileExtention", fileStreamData.FileExtention);
+ cmd.Parameters.AddWithValue("@fileSize", fileStreamData.FileSize);
+ cmd.Parameters.AddWithValue("@fileMD5base64", fileStreamData.FileMD5base64);
+ cmd.Parameters.AddWithValue("@feedType", feedType);
+
+ using (var reader = cmd.ExecuteReader())
+ {
+ if (!reader.HasRows)
+ throw new Exception("Insert returned no rows");
+
+ reader.Read();
+ id = reader.GetInt32(0);
+ fileStreamData.FileGUID = reader.GetGuid(1);
+ }
+
+ return id;
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Export/CreateSalesInvoice.cs b/src/bnhtrade.Core/Data/Database/Export/CreateSalesInvoice.cs
index 88919ae..9fdf55a 100644
--- a/src/bnhtrade.Core/Data/Database/Export/CreateSalesInvoice.cs
+++ b/src/bnhtrade.Core/Data/Database/Export/CreateSalesInvoice.cs
@@ -10,88 +10,15 @@ namespace bnhtrade.Core.Data.Database.Export
{
public class CreateSalesInvoice : Connection
{
- private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
-
public CreateSalesInvoice(string sqlConnectionString) : base(sqlConnectionString)
{
}
- public void SaveInvoice(List invoiceList)
+ public void Execute(List invoiceList)
{
using (TransactionScope scope = new TransactionScope())
{
- // get table pks for invoice type line and fill in invoice line details
- var readItemCode = new Data.Database.Account.ReadInvoiceLineItemCode(sqlConnectionString);
- readItemCode.InsertNewOnNoMatch = true;
- bool newTypeFound = false;
- bool newTypeTitleFound = false;
- for (int i = 0; i < invoiceList.Count(); i++)
- {
- for (int j = 0; j < invoiceList[i].InvoiceLineList.Count(); j++)
- {
- var itemCodeInfo = readItemCode.ByItemCode(invoiceList[i].InvoiceLineList[j].ItemCode);
- if (itemCodeInfo.InvoiceLineEntryEnabled == false)
- {
- invoiceList[i].InvoiceAmount = invoiceList[i].InvoiceAmount - invoiceList[i].InvoiceLineList[j].GrossTotalAmount;
- invoiceList[i].InvoiceLineList.RemoveAt(j);
- j = j - 1;
- continue;
- }
- else if (itemCodeInfo.IsNewReviewRequired)
- {
- newTypeFound = true;
- }
- else
- {
- if (itemCodeInfo.Title == readItemCode.NewTypeTitle)
- { newTypeTitleFound = true; }
- else
- {
- invoiceList[i].InvoiceLineList[j].AccountCode = itemCodeInfo.DefaultAccountCode;
- invoiceList[i].InvoiceLineList[j].TaxCode = itemCodeInfo.DefaultTaxCode;
- invoiceList[i].InvoiceLineList[j].Description = itemCodeInfo.Title;
- }
- }
- }
- }
- if (newTypeFound || newTypeTitleFound)
- {
- if (newTypeFound)
- {
- log.LogError("New line ItemCode found. Add item code default values and then try again.");
- }
- if (newTypeTitleFound)
- {
- log.LogError("ItemCode found with the incomplete title '" + readItemCode.NewTypeTitle + "'. Update title and then try again.");
- }
- return;
- }
-
- // add temp invoice numbers to invoices
- var sequence = new Programmability.Sequence(sqlConnectionString);
- for (int i = 0; i < invoiceList.Count(); i++)
- {
- if (invoiceList[i].InvoiceNumberIsSet)
- {
- var log = new Logic.Log.LogEvent();
- log.LogError("Unexpected invoice number found.");
- return;
- }
- invoiceList[i].InvoiceNumber = "_tmp" + sequence.GetNext("ExportTempInvoiceNumber").ToString("00000000");
- }
-
- // validate the list of invoices
- var validateInvoice = new Logic.Account.ValidateSalesInvoice();
- validateInvoice.InvoiceLineDescriptionIsRequired = false;
- validateInvoice.IsValidInvoice(invoiceList);
- if (validateInvoice.ErrorListIsSet)
- {
- log.LogError("Invalid Sales invoice(s) found during Amazon Settlement process. See extended info.", validateInvoice.ErrorListToString());
- return;
- }
- validateInvoice = null;
-
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
{
sqlConn.Open();
@@ -134,7 +61,7 @@ namespace bnhtrade.Core.Data.Database.Export
cmd.Parameters.AddWithValue("@currencyCode", invoiceList[i].InvoiceCurrencyCode);
cmd.Parameters.AddWithValue("@markComplete", false);
cmd.Parameters.AddWithValue("@invoiceNumber", invoiceList[i].InvoiceNumber);
- cmd.Parameters.AddWithValue("@invoiceAmount", invoiceList[i].InvoiceAmount);
+ cmd.Parameters.AddWithValue("@invoiceAmount", invoiceList[i].InvoiceTotalAmount);
invoiceId = (int)cmd.ExecuteScalar();
}
@@ -145,7 +72,7 @@ namespace bnhtrade.Core.Data.Database.Export
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblExportAccountInvoiceLine (
ExportAccountInvoiceID
- ,ExportAccountInvoiceLineTypeID
+ ,AccountInvoiceLineItemID
,NetAmount
,AccountChartOfID
,TaxAmount
@@ -155,9 +82,9 @@ namespace bnhtrade.Core.Data.Database.Export
VALUES (
@invoiceId
,(
- SELECT ExportAccountInvoiceLineTypeID
- FROM tblExportAccountInvoiceLineType
- WHERE MatchString = @itemCode
+ SELECT AccountInvoiceLineItemID
+ FROM tblAccountInvoiceLineItem
+ WHERE ItemCode = @itemCode
)
,@netAmount
,(
@@ -176,10 +103,10 @@ namespace bnhtrade.Core.Data.Database.Export
{
cmd.Parameters.AddWithValue("@invoiceID", invoiceId);
cmd.Parameters.AddWithValue("@itemCode", invoiceList[i].InvoiceLineList[j].ItemCode);
- cmd.Parameters.AddWithValue("@netAmount", invoiceList[i].InvoiceLineList[j].TotalNetAmount);
- cmd.Parameters.AddWithValue("@accountCode", invoiceList[i].InvoiceLineList[j].AccountCode);
+ cmd.Parameters.AddWithValue("@netAmount", invoiceList[i].InvoiceLineList[j].UnitAmount);
+ cmd.Parameters.AddWithValue("@accountCode", invoiceList[i].InvoiceLineList[j].AccountCode.AccountCodeId);
cmd.Parameters.AddWithValue("@taxAmount", invoiceList[i].InvoiceLineList[j].TaxAmount);
- cmd.Parameters.AddWithValue("@taxCode", invoiceList[i].InvoiceLineList[j].TaxCode);
+ cmd.Parameters.AddWithValue("@taxCode", invoiceList[i].InvoiceLineList[j].TaxCode.TaxCode);
int lineId = (int)cmd.ExecuteScalar();
}
@@ -190,4 +117,4 @@ namespace bnhtrade.Core.Data.Database.Export
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/bnhtrade.Core/Data/Database/Export/ReadAmazonFeedSubmission.cs b/src/bnhtrade.Core/Data/Database/Export/ReadAmazonFeedSubmission.cs
new file mode 100644
index 0000000..4471699
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Export/ReadAmazonFeedSubmission.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.Export
+{
+ public class ReadAmazonFeedSubmission : Connection
+ {
+ public ReadAmazonFeedSubmission(string sqlConnectionString) : base(sqlConnectionString)
+ {
+
+ }
+
+ public bool RetriveFile { get; set; } = false;
+
+ public List ByAmazonFeedSubmissionId(List submissionId)
+ {
+ throw new NotImplementedException();
+ }
+
+ public List GetOpenFeeds()
+ {
+ string sql = @"
+ WHERE tblExportAmazonFeedSubmissionStatus.FeedComplete = @feedComplete
+ AND FeedSubmissionId IS NOT NULL;";
+
+ var parameters = new Dictionary { { "@feedComplete", false } };
+
+ return Execute(sql, parameters);
+ }
+
+ private List Execute(string sqlWhereClause, Dictionary parameters)
+ {
+ var returnList = new List();
+
+ // build the sql string
+ string sql = @"
+ SELECT tblExportAmazonFeedSubmissionType.FeedType
+ ,tblExportAmazonFeedSubmission.FeedSubmissionId
+ ,tblExportAmazonFeedSubmissionStatus.FeedProcessingStatus
+ ,tblExportAmazonFeedSubmission.SubmittedDate
+ ,tblExportAmazonFeedSubmission.StartedProcessingDate
+ ,tblExportAmazonFeedSubmission.CompletedProcessingDate";
+
+ if (RetriveFile)
+ sql += @"
+ ,tblExportAmazonFeedSubmission.FileGUID
+ ,tblExportAmazonFeedSubmission.FileData
+ ,tblExportAmazonFeedSubmission.FileExtention
+ ,tblExportAmazonFeedSubmission.FileSize
+ ,tblExportAmazonFeedSubmission.FileMD5base64";
+
+ sql += @"
+ FROM tblExportAmazonFeedSubmission
+ INNER JOIN tblExportAmazonFeedSubmissionStatus
+ ON tblExportAmazonFeedSubmission.ExportAmazonFeedSubmissionStatusID
+ = tblExportAmazonFeedSubmissionStatus.ExportAmazonFeedSubmissionStatusID
+ INNER JOIN tblExportAmazonFeedSubmissionType
+ ON tblExportAmazonFeedSubmission.ExportAmazonFeedSubmissionTypeID
+ = tblExportAmazonFeedSubmissionType.ExportAmazonFeedSubmissionTypeID";
+
+ sql += sqlWhereClause;
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (var cmd = new SqlCommand(sql, conn))
+ {
+ if (parameters != null || !parameters.Any())
+ {
+ foreach(var parameter in parameters)
+ {
+ cmd.Parameters.AddWithValue(parameter.Key, parameter.Value);
+ }
+ }
+
+ using (var reader = cmd.ExecuteReader())
+ {
+ if (!reader.HasRows)
+ return returnList;
+
+ while (reader.Read())
+ {
+ var submission = new Model.Export.AmazonFeedSubmission();
+
+ if (!reader.IsDBNull(0))
+ submission.FeedType = reader.GetString(0);
+ if (!reader.IsDBNull(1))
+ submission.FeedSubmissionId = reader.GetString(1);
+ if (!reader.IsDBNull(2))
+ submission.FeedProcessingStatus = reader.GetString(2);
+ if (!reader.IsDBNull(3))
+ submission.SubmittedDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc);
+ if (!reader.IsDBNull(4))
+ submission.StartedProcessingDate = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc);
+ if (!reader.IsDBNull(5))
+ submission.CompletedProcessingDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc);
+
+ if (RetriveFile)
+ {
+ var file = new Model.Data.DatabaseFileStream();
+
+ file.FileGUID = reader.GetGuid(6);
+ byte[] fileData = (byte[])reader[7];
+ file.FileData = new System.IO.MemoryStream(fileData);
+ file.FileExtention = reader.GetString(8);
+ file.FileSize = reader.GetInt32(9);
+ file.FileMD5base64 = reader.GetString(10);
+
+ submission.File = file;
+ }
+ returnList.Add(submission);
+ }
+ }
+ }
+ }
+ return returnList;
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Export/UpdateAmazonFeedSubmission.cs b/src/bnhtrade.Core/Data/Database/Export/UpdateAmazonFeedSubmission.cs
new file mode 100644
index 0000000..e7ed797
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Export/UpdateAmazonFeedSubmission.cs
@@ -0,0 +1,109 @@
+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.Export
+{
+ public class UpdateAmazonFeedSubmission : Connection
+ {
+ public UpdateAmazonFeedSubmission(string sqlConnectionString) : base(sqlConnectionString)
+ {
+
+ }
+
+ public void AddAmazonFeedId(int exportAmazonFeedSubmissionID, string amazonFeedId)
+ {
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (var cmd = new SqlCommand(@"
+ SELECT COUNT (ExportAmazonFeedSubmissionID)
+ FROM tblExportAmazonFeedSubmission
+ WHERE FeedSubmissionId = @amazonFeedId", conn))
+ {
+ cmd.Parameters.AddWithValue("@amazonFeedId", amazonFeedId);
+
+ int i = (int)cmd.ExecuteScalar();
+
+ if (i > 0)
+ throw new Exception("Amazon submission Id already exists in table");
+ }
+
+ using (var cmd = new SqlCommand(@"
+ UPDATE tblExportAmazonFeedSubmission
+ SET FeedSubmissionId = @amazonFeedId
+ WHERE ExportAmazonFeedSubmissionID=@exportAmazonFeedSubmissionID", conn))
+ {
+ cmd.Parameters.AddWithValue("@amazonFeedId", amazonFeedId);
+ cmd.Parameters.AddWithValue("@exportAmazonFeedSubmissionID", exportAmazonFeedSubmissionID);
+
+ int i = cmd.ExecuteNonQuery();
+
+ if (i == 0)
+ throw new Exception("Error updating table.");
+ }
+ }
+ }
+
+ public void UpdateStatusInfo(Model.Export.AmazonFeedSubmission feedSubmission)
+ {
+ UpdateStatusInfo(new List { feedSubmission });
+ }
+
+ public void UpdateStatusInfo(List feedSubmissionList)
+ {
+ if (feedSubmissionList == null || !feedSubmissionList.Any())
+ return;
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ for (int i = 0; i < feedSubmissionList.Count; i++)
+ {
+ if (!feedSubmissionList[i].IsSetFeedSubmissionId)
+ throw new Exception("Amazon Feed Submission Id required");
+
+ if (!feedSubmissionList[i].IsSetFeedProcessingStatus)
+ throw new Exception("Amazon Feed stauts required");
+
+ string sql = @"
+ UPDATE tblExportAmazonFeedSubmission
+ SET ExportAmazonFeedSubmissionStatusID =
+ (SELECT ExportAmazonFeedSubmissionStatusID
+ FROM tblExportAmazonFeedSubmissionStatus
+ WHERE FeedProcessingStatus = @feedProcessingStatus )
+ ,SubmittedDate = @submittedDate
+ ,StartedProcessingDate = @startedProcessingDate
+ ,CompletedProcessingDate = @completedProcessingDate
+ WHERE FeedSubmissionId = @feedSubmissionId;";
+
+ using (var cmd = new SqlCommand(sql, conn))
+ {
+ cmd.Parameters.AddWithValue("@feedSubmissionId", feedSubmissionList[i].FeedSubmissionId);
+ cmd.Parameters.AddWithValue("@feedProcessingStatus", feedSubmissionList[i].FeedProcessingStatus);
+
+ if (!feedSubmissionList[i].IsSetSubmittedDate) { cmd.Parameters.AddWithValue("@submittedDate", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@submittedDate", feedSubmissionList[i].SubmittedDate.ToUniversalTime()); }
+
+ if (!feedSubmissionList[i].IsSetStartedProcessingDate) { cmd.Parameters.AddWithValue("@startedProcessingDate", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@startedProcessingDate", feedSubmissionList[i].StartedProcessingDate.ToUniversalTime()); }
+
+ if (!feedSubmissionList[i].IsSetCompletedProcessingDate) { cmd.Parameters.AddWithValue("@completedProcessingDate", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@completedProcessingDate", feedSubmissionList[i].CompletedProcessingDate.ToUniversalTime()); }
+
+ int j = cmd.ExecuteNonQuery();
+
+ if (j == 0)
+ throw new Exception("Error updating table.");
+ }
+
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentHeaderInfo.cs b/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentHeaderInfo.cs
deleted file mode 100644
index 9dd3ca6..0000000
--- a/src/bnhtrade.Core/Data/Database/FBAInbound/GetShipmentHeaderInfo.cs
+++ /dev/null
@@ -1,157 +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.FBAInbound
-{
- public class GetShipmentHeaderInfo : Connection
- {
- private List shipmentIdList;
- public GetShipmentHeaderInfo(string sqlConnectionString) : base(sqlConnectionString) { }
- ///
- /// Return active shipments only. Default is false.
- ///
- public bool ActiveShipments { get; set; } = false;
- public bool IsSetActiveShipments { get { return true; } }
- public bool IsSetShipmentIdList
- {
- get
- {
- if (ShipmentIdList == null || !ShipmentIdList.Any()) { return false; }
- else { return true; }
- }
- }
- ///
- /// Filter results by Amazon's shipment Id.
- ///
- public List ShipmentIdList
- {
- get { return shipmentIdList; }
- set
- {
- if (value != null)
- {
- // clean list
- shipmentIdList = new List();
- foreach (string item in value)
- {
- if (item.Length > 0)
- {
- shipmentIdList.Add(item);
- }
- }
- if (!ShipmentIdList.Any())
- {
- shipmentIdList = null;
- throw new Exception("Invalid shipment Id set");
- }
- }
- }
- }
- ///
- /// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
- ///
- /// Amazon's inbound FBA shipment Id.
- /// Primary key or -1 if match isn't found.
- public List Execute()
- {
- // build the sql string
- int countShipId = 0;
- string sqlString = @"
- SELECT
- AmazonShipmentID
- ,ShipmentName
- ,ShipmentId
- ,CenterId
- ,ShipmentStatus
- ,LastUpdated
- ,IsClosed
- FROM
- tblAmazonShipment
- WHERE
- 1 = 1";
- if (ActiveShipments)
- {
- sqlString = sqlString + @"
- AND IsClosed = 0";
- }
- var dicShipIdByParameterString = new Dictionary();
- if (IsSetShipmentIdList)
- {
- foreach (string item in ShipmentIdList)
- {
- countShipId = countShipId + 1;
- string parameterString = "@shipmentId" + countShipId;
- dicShipIdByParameterString.Add(parameterString, item);
- if (countShipId == 1)
- {
- sqlString = sqlString + @"
- AND ( ShipmentId = " + parameterString;
- }
- else
- {
- sqlString = sqlString + @"
- OR ShipmentId = " + parameterString;
- }
- }
- if (countShipId > 0)
- {
- sqlString = sqlString + " )";
- }
- }
-
- using (SqlConnection conn = new SqlConnection(sqlConnectionString))
- {
- conn.Open();
-
- using (SqlCommand cmd = new SqlCommand(sqlString, conn))
- {
- // add shipId parameters
- if (ShipmentIdList.Any())
- {
- foreach (var item in dicShipIdByParameterString)
- {
- cmd.Parameters.AddWithValue(item.Key, item.Value);
- }
- }
-
- using (var reader = cmd.ExecuteReader())
- {
- if (!reader.HasRows)
- {
- // no records
- return null;
- }
-
- var infoList = new List();
- while (reader.Read())
- {
- var info = new Model.AmazonFBAInbound.ShipmentInfo();
-
- int tablePK = reader.GetInt32(0);
- info.ShipmentName = reader.GetString(1);
- info.AmazonShipmentId = reader.GetString(2);
- info.DestinationFulfillmentCenterId = reader.GetString(3);
- info.ShipmentStatus = reader.GetString(4);
- info.LastUpdatedUtc = reader.GetDateTime(5);
- bool dbIsClosed = reader.GetBoolean(6);
-
- // db consistancy check
- if (dbIsClosed != info.ShipmentIsClosed)
- {
- throw new Exception("Data inconstitancy in database: check shipment IsClosed where AmazonShipmentID=" + tablePK);
- }
-
- // update cache
- infoList.Add(info);
- }
- return infoList;
- }
- }
- }
- }
- }
-}
diff --git a/src/bnhtrade.Core/Data/Database/Import/ReadFbaInventoryAge.cs b/src/bnhtrade.Core/Data/Database/Import/ReadFbaInventoryAge.cs
new file mode 100644
index 0000000..d48d07f
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Import/ReadFbaInventoryAge.cs
@@ -0,0 +1,92 @@
+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.Import
+{
+ public class ReadFbaInventoryAge : Connection
+ {
+ public ReadFbaInventoryAge(string sqlConnectionString): base(sqlConnectionString)
+ {
+
+ }
+
+ public (int MinAge, int MaxAge)? BySkuNumber(string skuNumber, string orderChannel)
+ {
+ int minAge = 0;
+ int maxAge = 0;
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (var cmd03 = new SqlCommand(@"
+ SELECT [snapshot-date]
+ ,[inv-age-0-to-90-days]
+ ,[inv-age-91-to-180-days]
+ ,[inv-age-181-to-270-days]
+ ,[inv-age-271-to-365-days]
+ ,[inv-age-365-plus-days]
+ FROM tblImportFbaInventoryAgeReport
+ WHERE sku = @skuNumber AND marketplace = @orderChannel
+ ", conn))
+ {
+ cmd03.Parameters.AddWithValue("@skuNumber", skuNumber);
+ cmd03.Parameters.AddWithValue("@orderChannel", orderChannel);
+
+ using (var reader03 = cmd03.ExecuteReader())
+ {
+ if (reader03.Read())
+ {
+ // final min age
+ if (reader03.GetInt32(1) > 0) { minAge = 1; }
+ else
+ {
+ if (reader03.GetInt32(2) > 0) { minAge = 91; }
+ else
+ {
+ if (reader03.GetInt32(3) > 0) { minAge = 181; }
+ else
+ {
+ if (reader03.GetInt32(4) > 0) { minAge = 271; }
+ else
+ {
+ if (reader03.GetInt32(5) > 0) { minAge = 366; }
+ }
+ }
+ }
+ }
+
+ //find max age
+ if (reader03.GetInt32(5) > 0) { maxAge = 2147483647; }
+ else
+ {
+ if (reader03.GetInt32(4) > 0) { maxAge = 365; }
+ else
+ {
+ if (reader03.GetInt32(3) > 0) { maxAge = 270; }
+ else
+ {
+ if (reader03.GetInt32(2) > 0) { maxAge = 180; }
+ else
+ {
+ if (reader03.GetInt32(1) > 0) { maxAge = 90; }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+ }
+ return (minAge, maxAge);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Import/ReadFbaSaleShipment.cs b/src/bnhtrade.Core/Data/Database/Import/ReadFbaSaleShipment.cs
new file mode 100644
index 0000000..4b8d91b
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Import/ReadFbaSaleShipment.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.Import
+{
+ public class ReadFbaSaleShipment : Connection
+ {
+ public ReadFbaSaleShipment(string sqlConnectionString): base(sqlConnectionString)
+ {
+
+ }
+
+ public Dictionary GetMaxSalePrice(List skuNumber, int timePeriodDay)
+ {
+ var returnList = new Dictionary();
+
+ if (skuNumber == null || !skuNumber.Any())
+ {
+ return returnList;
+ }
+
+ string sql = @"
+ SELECT sku
+ ,Max(ISNULL([tblImportFbaSaleShipment].[item-price], 0) + ISNULL([tblImportFbaSaleShipment].[item-tax], 0)) AS Expr1
+ FROM tblImportFbaSaleShipment
+ WHERE (
+ (sku IN (";
+
+ for (int i = 0; i < skuNumber.Count; i++)
+ {
+ if (!(i + 1 == skuNumber.Count))
+ {
+ sql += "@skuNumber" + i + ", ";
+ }
+ else
+ {
+ sql += "@skuNumber" + i + "))";
+ }
+ }
+
+ sql += @"
+ AND ((tblImportFbaSaleShipment.[shipment-date]) >= @shipDateFilter)
+ )
+ GROUP BY sku;";
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ using (var cmd = new SqlCommand(sql, conn))
+ {
+ for (int i = 0; i < skuNumber.Count; i++)
+ {
+ cmd.Parameters.AddWithValue("@skuNumber" + i, skuNumber[i]);
+ }
+ cmd.Parameters.AddWithValue("@shipDateFilter", DateTime.Today.AddDays(timePeriodDay * -1));
+
+ using (var reader = cmd.ExecuteReader())
+ {
+ if (!reader.HasRows)
+ {
+ return returnList;
+ }
+
+ while (reader.Read())
+ {
+ decimal price = reader.GetDecimal(1);
+ if (price > 0)
+ {
+ returnList.Add(reader.GetString(0), price);
+ }
+ }
+ }
+ }
+ }
+ return returnList;
+ }
+
+ public Dictionary GetSaleCount(List skuNumber, DateTime periodStart, DateTime periodEnd)
+ {
+ var returnList = new Dictionary();
+
+ if (skuNumber == null || !skuNumber.Any())
+ {
+ return returnList;
+ }
+
+ string sql = @"
+ SELECT sku
+ ,Count(1) AS CountOfSku
+ FROM tblImportFbaSaleShipment
+ WHERE (
+ (sku IN @skuNumber)
+ AND (
+ (tblImportFbaSaleShipment.[shipment-date] >= @periodStart)
+ AND tblImportFbaSaleShipment.[shipment-date] <= @periodEnd
+ )
+ )
+ GROUP BY sku;";
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ var param = new DynamicParameters();
+ param.Add("@skuNumber", skuNumber);
+ param.Add("@periodStart", periodStart.ToUniversalTime());
+ param.Add("@periodEnd", periodEnd.ToUniversalTime());
+
+ return conn.Query(sql, param).ToDictionary(
+ row => (string)row.sku,
+ row => (int)row.CountOfSku);
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Product/CreateCompetitivePrice.cs b/src/bnhtrade.Core/Data/Database/Product/CreateCompetitivePrice.cs
new file mode 100644
index 0000000..ad1a5fb
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Product/CreateCompetitivePrice.cs
@@ -0,0 +1,78 @@
+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.Product
+{
+ public class CreateCompetitivePrice : Connection
+ {
+ public CreateCompetitivePrice(string sqlConnectionString) : base(sqlConnectionString)
+ {
+
+ }
+
+ public int ProductCompetitivePriceSet(int productId, int conditionId, decimal price, bool isBuyBoxPrice, DateTime? priceDate = null)
+ {
+ DateTime dt = new DateTime();
+ if (priceDate == null || priceDate == default(DateTime))
+ {
+ dt = DateTime.Now;
+ }
+ else
+ {
+ dt = (DateTime)priceDate;
+ }
+
+ if (priceDate.Value.Kind == DateTimeKind.Unspecified)
+ {
+ throw new Exception("Unspecified DateTimeKind");
+ }
+
+ using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
+ {
+ sqlConn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(@"
+ UPDATE Table1
+ SET (
+ CompetitivePrice = @price
+ ,IsBuyBoxPrice = @isBuyBoxPrice
+ )
+ OUTPUT INSERTED.ProductPriceCompetitiveID
+ WHERE ProductID = @productId
+ AND SkuConditionID = @conditionId
+ AND PriceDate = @priceDate
+
+ IF @@ROWCOUNT = 0
+ INSERT INTO tblProductPriceCompetitive (
+ ProductID
+ ,SkuConditionID
+ ,CompetitivePrice
+ ,PriceDate
+ ,IsBuyBoxPrice
+ )
+ OUTPUT INSERTED.ProductPriceCompetitiveID
+ VALUES (
+ @productId
+ ,@conditionId
+ ,@price
+ ,@priceDate
+ ,@isBuyBoxPrice
+ );"
+ , sqlConn))
+ {
+ cmd.Parameters.AddWithValue("@productId", productId);
+ cmd.Parameters.AddWithValue("@conditionId", conditionId);
+ cmd.Parameters.AddWithValue("@price", price);
+ cmd.Parameters.AddWithValue("@priceDate", dt.ToUniversalTime());
+ cmd.Parameters.AddWithValue("@isBuyBoxPrice", isBuyBoxPrice);
+
+ return (int)cmd.ExecuteScalar();
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Product/ReadCompetitivePrice.cs b/src/bnhtrade.Core/Data/Database/Product/ReadCompetitivePrice.cs
new file mode 100644
index 0000000..21c24c8
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Product/ReadCompetitivePrice.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.Product
+{
+ public class ReadCompetitivePrice : Connection
+ {
+ public ReadCompetitivePrice(string sqlConnectionString) : base(sqlConnectionString)
+ {
+
+ }
+
+ public List Execute(List<(int productId, int conditionId)> productIdAndConditionId)
+ {
+ int maxParameterCount = 2100;
+ int parameterPerPrice = 2;
+ int maxQuery = (int)decimal.Round(maxParameterCount / parameterPerPrice) - 1;
+
+ var resultList = new List();
+
+ if (productIdAndConditionId == null)
+ {
+ return resultList;
+ }
+
+ if (productIdAndConditionId.Count == 0)
+ {
+ return resultList;
+ }
+
+ if (productIdAndConditionId.Count <= maxQuery)
+ {
+ return ExecuteSub(productIdAndConditionId);
+ }
+ else
+ {
+ var partialList = new List<(int productId, int conditionId)>();
+ int queryCount = 0;
+
+ for (int i= 0; i < productIdAndConditionId.Count; i++)
+ {
+ queryCount++;
+ partialList.Add(productIdAndConditionId[i]);
+ if (queryCount == maxQuery)
+ {
+ resultList.AddRange(ExecuteSub(partialList));
+ partialList = new List<(int productId, int conditionId)>();
+ queryCount = 0;
+ }
+ }
+ if (queryCount > 0)
+ {
+ resultList.AddRange(ExecuteSub(partialList));
+ }
+ return resultList;
+ }
+ }
+
+ private List ExecuteSub(List<(int productId, int conditionId)> productIdAndConditionId)
+ {
+ var resultList = new List();
+
+ // build the sql string
+ string sql = @"
+ SELECT t.CompetitivePrice, t.PriceDate, t.ProductID, t.SkuConditionID
+ FROM tblProductPriceCompetitive AS t INNER JOIN (SELECT ProductID, SkuConditionID, Max(PriceDate) AS MaxOfPriceDate
+ FROM tblProductPriceCompetitive ";
+
+ for(int i = 0; i < productIdAndConditionId.Count; i++)
+ {
+ if (i == 0)
+ {
+ sql += @"
+ WHERE (ProductID=@productId" + i + " AND SkuConditionID=@conditionId" + i + ")";
+ }
+ else
+ {
+ sql += @"
+ OR (ProductID=@productId" + i + " AND SkuConditionID=@conditionId" + i + ")";
+ }
+ }
+ sql += @"
+ GROUP BY ProductID , SkuConditionID) AS a
+ ON (t.PriceDate = a.MaxOfPriceDate)
+ AND (t.ProductID = a.ProductID)
+ AND (t.SkuConditionID = a.SkuConditionID)";
+
+
+ using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
+ {
+ sqlConn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(sql, sqlConn))
+ {
+ for (int i = 0; i < productIdAndConditionId.Count; i++)
+ {
+ cmd.Parameters.AddWithValue("@productId" + i, productIdAndConditionId[i].productId);
+ cmd.Parameters.AddWithValue("@conditionId" + i, productIdAndConditionId[i].conditionId);
+ }
+
+ using (SqlDataReader reader = cmd.ExecuteReader())
+ {
+ if (!reader.HasRows)
+ {
+ return resultList;
+ }
+
+ while (reader.Read())
+ {
+ var result = new Model.Product.CompetitivePrice();
+
+ result.ConditionId = reader.GetInt32(3);
+ result.Price = reader.GetDecimal(0);
+ result.PriceDatetime = DateTime.SpecifyKind(reader.GetDateTime(1), DateTimeKind.Utc);
+ result.ProductId = reader.GetInt32(2);
+ result.PriceIsEstimated = false;
+
+ resultList.Add(result);
+ }
+ return resultList;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs b/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs
index 4662e03..60e4155 100644
--- a/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs
+++ b/src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Data.SqlClient;
-namespace bnhtrade.Core.Data.Database.SKU
+namespace bnhtrade.Core.Data.Database.Sku
{
public class GetSkuId
{
diff --git a/src/bnhtrade.Core/Data/Database/SKU/GetSku.cs b/src/bnhtrade.Core/Data/Database/SKU/GetSku.cs
index 835b7fe..e610cbd 100644
--- a/src/bnhtrade.Core/Data/Database/SKU/GetSku.cs
+++ b/src/bnhtrade.Core/Data/Database/SKU/GetSku.cs
@@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace bnhtrade.Core.Data.Database.SKU
+namespace bnhtrade.Core.Data.Database.Sku
{
class GetSku : Connection
{
diff --git a/src/bnhtrade.Core/Data/Database/SKU/Price/CreatePricingDetail.cs b/src/bnhtrade.Core/Data/Database/SKU/Price/CreatePricingDetail.cs
new file mode 100644
index 0000000..bed9aa4
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/SKU/Price/CreatePricingDetail.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Data.SqlClient;
+using System.Transactions;
+
+namespace bnhtrade.Core.Data.Database.Sku.Price
+{
+ public class CreatePricingDetail : Connection
+ {
+ public CreatePricingDetail(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ }
+
+ public void Executue(List newInfo)
+ {
+ if (newInfo == null || !newInfo.Any())
+ { return; }
+
+ using (var scope = new TransactionScope())
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ // write new item to table
+ for (int i = 0; i < newInfo.Count(); i++)
+ {
+ string sql = @"
+ INSERT INTO tblSkuPriceType (
+ SkuID
+ ,[OrderChannelID]
+ ,[PriceInfoTimeStamp]
+ ,[OrderChannelQuantity]
+ ,[UnitPurchaseCost]
+ ,[UnitMinPriceProfit]
+ ,[UnitMinPriceCost]
+ ,[UnitMinPriceDestory]
+ ,[InventoryAgeMin]
+ ,[InventoryAgeMax]
+ ,[SkuPriceTypeID]
+ ,[CompetitivePrice]
+ ,[MinPrice]
+ ,[MaxPrice]
+ ,[RepriceIncrement]
+ ,[ReviewRequired]
+ )
+ VALUES (
+ (SELECT skuSkuID FROM tblSku WHERE skuSkuNumber=@skuNumber)
+ ,(SELECT OrderChannelID FROM tblOrderChannel WHERE OrderChannel=@orderChannel)
+ ,@priceInfoTimeStamp
+ ,@orderChannelQuantity
+ ,@unitPurchaseCost
+ ,@unitMinPriceProfit
+ ,@unitMinPriceCost
+ ,@unitMinPriceDestory
+ ,@inventoryAgeMin
+ ,@inventoryAgeMax
+ ,@skuPriceTypeID
+ ,@competitivePrice
+ ,@minPrice
+ ,@maxPrice
+ ,@repriceIncrement
+ ,@reviewRequired
+ );";
+
+ using (var cmd = new SqlCommand(sql, conn))
+ {
+ cmd.Parameters.AddWithValue("@skuNumber", newInfo[i].SkuNumber);
+ cmd.Parameters.AddWithValue("@orderChannel", newInfo[i].OrderChannel);
+ cmd.Parameters.AddWithValue("@priceInfoTimeStamp", newInfo[i].PriceInfoTimeStamp);
+ cmd.Parameters.AddWithValue("@orderChannelQuantity", newInfo[i].OrderChannelQuantity);
+ cmd.Parameters.AddWithValue("@unitPurchaseCost", newInfo[i].UnitPurchaseCost);
+ cmd.Parameters.AddWithValue("@unitMinPriceProfit", newInfo[i].UnitMinPriceProfit);
+ cmd.Parameters.AddWithValue("@unitMinPriceCost", newInfo[i].UnitMinPriceCost);
+ cmd.Parameters.AddWithValue("@unitMinPriceDestory", newInfo[i].UnitMinPriceDestory);
+ cmd.Parameters.AddWithValue("@inventoryAgeMin", newInfo[i].InventoryAgeMin);
+ cmd.Parameters.AddWithValue("@inventoryAgeMax", newInfo[i].InventoryAgeMax);
+ cmd.Parameters.AddWithValue("@skuPriceTypeID", newInfo[i].PriceTypeId);
+ cmd.Parameters.AddWithValue("@competitivePrice", newInfo[i].CompetitivePrice);
+ cmd.Parameters.AddWithValue("@minPrice", newInfo[i].MinPrice);
+ cmd.Parameters.AddWithValue("@maxPrice", newInfo[i].MaxPrice);
+ cmd.Parameters.AddWithValue("@repriceIncrement", newInfo[i].RepriceIncrement);
+ cmd.Parameters.AddWithValue("@reviewRequired", newInfo[i].ReviewRequired);
+
+ int j = cmd.ExecuteNonQuery();
+
+ if (j < 1)
+ {
+ throw new Exception("Failed database insert statement");
+ }
+ }
+ }
+ scope.Complete();
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/SKU/Price/ReadParameter.cs b/src/bnhtrade.Core/Data/Database/SKU/Price/ReadParameter.cs
new file mode 100644
index 0000000..eb97d20
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/SKU/Price/ReadParameter.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.Sku.Price
+{
+ public class ReadParameter : Connection
+ {
+ public ReadParameter(string sqlConnectionString) : base(sqlConnectionString)
+ {
+
+ }
+
+ public List Execute()
+ {
+ string stringSql = @"
+ SELECT
+ b.SkuID AS SkuId
+ ,b.SkuTotalQuantity AS TotalQuantity
+ ,b.SkuTotalCost AS TotalCost
+ ,b.SkuAvgUnitCost AS UnitCostAverage
+ ,tblSku.skuSkuNumber AS SkuNumber
+ ,tblSku.skuProductID AS ProductId
+ ,tblSku.skuSkuConditionID AS ConditionId
+ ,tblSku.AccountTaxCodeID AS TaxCodeId
+ ,tblProductCategory.ProfitMinPercent AS ProfitMargin
+ ,tblProductCategory.ProfitMinAmount AS PriceMinProfit
+ ,(tblAmazonFeeEstimate.ReferralFee / tblAmazonFeeEstimate.PriceToEstimateFeeListingPrice) As AgentFeeMargin
+ ,(tblAmazonFeeEstimate.VariableClosingFee + tblAmazonFeeEstimate.PerItemFee + tblAmazonFeeEstimate.FBAFee + tblAmazonFeeEstimate.OtherFee_Exception) AS AgentFeeFixed
+ ,tblAccountTaxCode.TaxRateMultiplierGross AS VatMargin
+ ,tblAccountTaxCode.TaxRateName AS TaxRateName
+ ,tblSkuCondition.IsFixedPrice AS IsFixedPrice
+ ,tblSkuCondition.CompetitivePriceMultiplierNew
+ FROM
+ (((((
+ SELECT
+ a.SkuID,
+ Sum(a.SumOfQuantity) AS SkuTotalQuantity,
+ Sum(a.QuanityTimesUnitCost) AS SkuTotalCost,
+ Sum(a.QuanityTimesUnitCost)/Sum(a.SumOfQuantity) AS SkuAvgUnitCost
+ FROM
+ (
+ SELECT
+ tblStock.SkuID,
+ Sum(tblStockJournalPost.Quantity) AS SumOfQuantity,
+ tblStockJournal.StockID, tblAccountStockCost.AmountUnit,
+ Sum([tblStockJournalPost].[Quantity])*[tblAccountStockCost].[AmountUnit] AS QuanityTimesUnitCost
+ FROM
+ (((tblStockJournalPost
+ INNER JOIN tblStockStatus
+ ON tblStockJournalPost.StockStatusID = tblStockStatus.StockStatusID)
+ INNER JOIN tblStockJournal ON tblStockJournalPost.StockJournalID = tblStockJournal.StockJournalID)
+ INNER JOIN tblAccountStockCost ON tblStockJournal.StockID = tblAccountStockCost.StockID)
+ INNER JOIN tblStock ON tblAccountStockCost.StockID = tblStock.StockID
+ WHERE
+ tblStockStatus.StockStatusTypeID=3
+ OR tblStockStatus.StockStatusTypeID=4
+ GROUP BY
+ tblStockJournal.StockID,
+ tblAccountStockCost.AmountUnit,
+ tblStock.SkuID
+ HAVING
+ Sum(tblStockJournalPost.Quantity)>0
+ ) a
+ GROUP BY
+ a.SkuID
+ ) b
+ INNER JOIN tblSku ON b.SkuID = tblSku.skuSkuID)
+ INNER JOIN tblProduct ON tblSku.skuProductID = tblProduct.prdProductID)
+ LEFT JOIN tblAmazonFeeEstimate ON tblProduct.prdProductID = tblAmazonFeeEstimate.ProductIdentifier )
+ INNER JOIN tblProductCategory ON tblProduct.ProductCategoryID = tblProductCategory.ProductCategoryID)
+ INNER JOIN tblAccountTaxCode ON tblSku.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID
+ INNER JOIN tblSkuCondition ON tblSku.skuSkuConditionID = tblSkuCondition.scnSkuConditionID
+ ";
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ var invPricing = conn.Query(stringSql).ToList();
+
+ if (invPricing != null || invPricing.Any())
+ {
+ return invPricing;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/bnhtrade.Core/Data/Database/SKU/Price/ReadPricingDetail.cs b/src/bnhtrade.Core/Data/Database/SKU/Price/ReadPricingDetail.cs
new file mode 100644
index 0000000..3419127
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/SKU/Price/ReadPricingDetail.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.Sku.Price
+{
+ public class ReadPricingDetail : Connection
+ {
+ public ReadPricingDetail(string sqlConnectionString) : base(sqlConnectionString)
+ {
+
+ }
+ public Dictionary ReadDictionary(List skuNumberList, string orderChannel)
+ {
+ var dic = new Dictionary();
+ var list = Read(skuNumberList, orderChannel);
+
+ for (int i = 0; i < list.Count; i++)
+ {
+ dic.Add(list[i].SkuNumber, list[i]);
+ }
+ return dic;
+ }
+
+ public List Read(List skuNumberList, string orderChannel)
+ {
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ string sql = @"
+ SELECT tblSku.skuSkuNumber AS SkuNumber
+ ,tblOrderChannel.OrderChannel
+ ,tblSkuPrice.PriceInfoTimeStamp
+ ,tblSkuPrice.OrderChannelQuantity
+ ,tblSkuPrice.UnitPurchaseCost
+ ,tblSkuPrice.UnitMinPriceProfit
+ ,tblSkuPrice.UnitMinPriceCost
+ ,tblSkuPrice.UnitMinPriceDestory
+ ,tblSkuPrice.InventoryAgeMin
+ ,tblSkuPrice.InventoryAgeMax
+ ,tblSkuPrice.CompetitivePrice
+ ,tblSkuPrice.MinPrice
+ ,tblSkuPrice.MaxPrice
+ ,tblSkuPrice.RepriceIncrement
+ ,tblSkuPrice.ReviewRequired
+ ,tblSkuPriceType.SkuPriceTypeID
+ ,tblSkuPriceType.TypeTitle
+ FROM tblSkuPrice
+ INNER JOIN tblSkuPriceType ON tblSkuPrice.SkuPriceTypeID = tblSkuPriceType.SkuPriceTypeID
+ INNER JOIN tblSku ON tblSkuPrice.SkuID = tblSku.skuSkuID
+ INNER JOIN tblOrderChannel ON tblSkuPrice.OrderChannelID = tblOrderChannel.OrderChannelID
+ WHERE tblSku.skuSkuNumber IN @skuNumber
+ AND (tblOrderChannel.OrderChannel = @orderChannel);";
+
+ var parameters = new DynamicParameters();
+ parameters.Add("@skuNumber", skuNumberList);
+ parameters.Add("@orderChannel", orderChannel);
+
+ return conn.Query(sql, parameters).ToList();
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/SKU/ReadSkuConditionInfo.cs b/src/bnhtrade.Core/Data/Database/SKU/ReadSkuConditionInfo.cs
new file mode 100644
index 0000000..e0e2ad3
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/SKU/ReadSkuConditionInfo.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.Sku
+{
+ public class ReadSkuConditionInfo : Connection
+ {
+ public ReadSkuConditionInfo(string sqlConnectionString): base(sqlConnectionString)
+ {
+
+ }
+
+ public List Read(List conditionIdList)
+ {
+ string sql = @"
+ SELECT scnSkuConditionID AS SkuConditionId
+ ,scnTitleShort AS TitleShort
+ ,scnSkuNumberSuffix AS SkuConditionNumber
+ ,BaseType AS AmazonBaseType
+ ,IsFixedPrice
+ ,CompetitivePriceMultiplierNew AS CompetitivePriceMultiplier
+ ,scnRepricerStrategy AS RepricerStrategy
+ ,scnAmazonIdentifier AS AmazonIdentifier
+ ,scnConditionNoteDefault AS ConditionNoteDefault
+ ,scnDescription AS Description
+ FROM tblSkuCondition";
+
+ if (conditionIdList != null || !conditionIdList.Any())
+ {
+ sql += @"
+ WHERE scnSkuConditionID IN @conditionIdList
+ ";
+ }
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ var paramter = new DynamicParameters();
+ paramter.Add("@conditionIdList", conditionIdList);
+
+ return conn.Query(sql, paramter).ToList();
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Stock/CreateSkuTransaction.cs b/src/bnhtrade.Core/Data/Database/Stock/CreateSkuTransaction.cs
new file mode 100644
index 0000000..2a7b9e0
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Stock/CreateSkuTransaction.cs
@@ -0,0 +1,78 @@
+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 CreateSkuTransaction : Connection
+ {
+ public CreateSkuTransaction(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ }
+
+ public void Create(Model.Stock.SkuTransaction skuTransaction)
+ {
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(@"
+ INSERT INTO tblStockSkuTransaction (
+ TransactionDate
+ ,StockSkuTransactionTypeID
+ ,ForeignKey
+ ,Reference
+ ,Detail
+ ,SkuID
+ ,Quantity
+ ,IsProcessed
+ ,StockJournalID
+ )
+ OUTPUT INSERTED.StockSkuTransactionID
+ VALUES (
+ @transactionDate
+ ,@stockSkuTransactionTypeID
+ ,@foreignKey
+ ,@reference
+ ,@Detail
+ ,(
+ SELECT skuSkuID
+ FROM tblSku
+ WHERE skuSkuNumber = @skuNumber
+ )
+ ,@quantity
+ ,@isProcessed
+ ,@stockJournalID
+ )
+ ", conn))
+ {
+ cmd.Parameters.AddWithValue("@transactionDate", skuTransaction.TransactionDate.ToUniversalTime());
+ cmd.Parameters.AddWithValue("@stockSkuTransactionTypeID", skuTransaction.SkuTransactionTypeId);
+ if (!skuTransaction.IsSetForeignKey) { cmd.Parameters.AddWithValue("@foreignKey", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@foreignKey", skuTransaction.ForeignKey); }
+ if (!skuTransaction.IsSetReference) { cmd.Parameters.AddWithValue("@reference", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@reference", skuTransaction.Reference); }
+ if (!skuTransaction.IsSetDetail) { cmd.Parameters.AddWithValue("@detail", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@detail", skuTransaction.Detail); }
+ cmd.Parameters.AddWithValue("@skuNumber", skuTransaction.SkuNumber);
+ cmd.Parameters.AddWithValue("@quantity", skuTransaction.Quantity);
+ cmd.Parameters.AddWithValue("@isProcessed", skuTransaction.IsProcessed);
+ if (!skuTransaction.IsSetStockJournalId) { cmd.Parameters.AddWithValue("@stockJournalID", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@stockJournalID", skuTransaction.StockJournalId); }
+
+ object obj = cmd.ExecuteScalar();
+
+ if (obj == null || obj == DBNull.Value)
+ {
+ throw new Exception("Sku Reconcile Transaction insert failed");
+ }
+
+ skuTransaction.SkuTransactionId = (int)obj;
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Stock/DeleteSkuTransaction.cs b/src/bnhtrade.Core/Data/Database/Stock/DeleteSkuTransaction.cs
new file mode 100644
index 0000000..fb2fa37
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Stock/DeleteSkuTransaction.cs
@@ -0,0 +1,36 @@
+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 DeleteSkuTransaction : Connection
+ {
+ public DeleteSkuTransaction (string sqlConnectionString): base(sqlConnectionString)
+ {
+ }
+
+ public void ByTransactionId(int skuReconcileId)
+ {
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(@"
+ DELETE FROM tblStockSkuTransaction WHERE StockSkuTransactionID = @transactionId
+ ", conn))
+ {
+ cmd.Parameters.AddWithValue("@transactionId", skuReconcileId);
+
+ if (cmd.ExecuteNonQuery() < 1)
+ {
+ throw new Exception("Delete sku transaction effected no records");
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransaction.cs b/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransaction.cs
new file mode 100644
index 0000000..189f776
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransaction.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.Stock
+{
+ public class ReadSkuTransaction : Connection
+ {
+ public ReadSkuTransaction(string sqlConnectionString) : base(sqlConnectionString)
+ {
+
+ }
+
+ public int? GetJournalId(int skuTransactionId)
+ {
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (var cmd = new SqlCommand(@"
+ SELECT StockJournalID FROM tblStockSkuTransaction WHERE StockSkuTransactionID=@transactionId
+ ", conn))
+ {
+ cmd.Parameters.AddWithValue("@transactionId", skuTransactionId);
+
+ object obj = cmd.ExecuteScalar();
+
+ if (obj == null || obj == DBNull.Value)
+ {
+ return null;
+ }
+ else
+ {
+ return (int)obj;
+ }
+ }
+ }
+ }
+
+ public List GetUnreconciled()
+ {
+ // order by stocktransId desc = Amazon reports are listed in datetime ASC order, some reports have date only,
+ // however I have reason to believe these are in time order.
+ // Adding this means they at least get processed in the correct order (maybe)!
+ string sqlWhere = @"
+ WHERE tblStockSkuTransaction.IsProcessed = 0
+ AND (
+ tblStockSkuTransactionType.StockJournalEntryEnabled = 1
+ OR tblStockSkuTransactionType.IsNewReviewRequired = 1
+ ) ";
+
+ return Read(sqlWhere, new DynamicParameters());
+ }
+
+ private List Read(string sqlWhere, DynamicParameters parameters)
+ {
+ var resultList = new List();
+
+ string sql = @"
+ SELECT tblStockSkuTransaction.StockSkuTransactionID AS SkuTransactionId
+ ,tblStockSkuTransaction.TransactionDate
+ ,tblStockSkuTransaction.StockSkuTransactionTypeID AS SkuTransactionTypeId
+ ,tblStockSkuTransaction.ForeignKey
+ ,tblStockSkuTransaction.Reference
+ ,tblStockSkuTransaction.Detail
+ ,tblStockSkuTransaction.Quantity
+ ,tblStockSkuTransaction.IsProcessed
+ ,tblStockSkuTransaction.StockJournalID AS StockJournalId
+ ,tblStockSkuTransactionType.TypeTitle AS SkuTransactionTypeName
+ ,tblSku.skuSkuNumber AS SkuNumber
+ ,tblStockSkuTransaction.SkuID
+ FROM tblStockSkuTransaction
+ INNER JOIN tblStockSkuTransactionType ON tblStockSkuTransaction.StockSkuTransactionTypeID = tblStockSkuTransactionType.StockSkuTransactionTypeID
+ INNER JOIN tblSku ON tblStockSkuTransaction.SkuID = tblSku.skuSkuID ";
+
+ sql += sqlWhere;
+
+ sql += @"
+ ORDER BY tblStockSkuTransaction.TransactionDate ASC, tblStockSkuTransaction.StockSkuTransactionID DESC;";
+
+ using (SqlConnection conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ resultList = conn.Query(sql, parameters).ToList();
+ }
+
+ // set datetime kind
+ for (int i = 0; i < resultList.Count; i++)
+ {
+ if (resultList[i].IsSetTransactionDate)
+ {
+ resultList[i].TransactionDate = DateTime.SpecifyKind(resultList[i].TransactionDate, DateTimeKind.Utc);
+ }
+ }
+
+ return resultList;
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransactionType.cs b/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransactionType.cs
new file mode 100644
index 0000000..58d0f43
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Stock/ReadSkuTransactionType.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Dapper;
+
+namespace bnhtrade.Core.Data.Database.Stock
+{
+ public class ReadSkuTransactionType : Connection
+ {
+ public ReadSkuTransactionType(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ }
+
+ ///
+ /// Depriciated, delete when not required by other code
+ ///
+ ///
+ ///
+ ///
+ public int GetTypeId(string typeCode)
+ {
+ /* GetStockTransactionTypeId return meanings
+ * >0 use the as the TypeId when inserting transaction
+ * 0 Skip transpose, type doesn't exist or is new (not reviewed yet)
+ * -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
+
+ // old optional parameters
+ // , bool onNewReturnId = false, bool onNewDisableInsert = false
+
+ if (typeCode.Length == 0)
+ {
+ throw new Exception("Empty match string passed to method");
+ }
+ using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
+ {
+ sqlConn.Open();
+ using (SqlCommand cmd = new SqlCommand(@"
+ SELECT
+ StockSkuTransactionTypeID,
+ IsNewReviewRequired,
+ TransactionImportEnabled
+ FROM
+ tblStockSkuTransactionType
+ WHERE
+ TypeCode=@typeCode;
+ ", sqlConn))
+ {
+ cmd.Parameters.AddWithValue("@typeCode", typeCode);
+
+ using (SqlDataReader reader = cmd.ExecuteReader())
+ {
+ if (reader.Read())
+ {
+ int index01 = reader.GetOrdinal("StockSkuTransactionTypeID");
+ int index02 = reader.GetOrdinal("IsNewReviewRequired");
+ int index03 = reader.GetOrdinal("TransactionImportEnabled");
+
+ int transactionTypeId = reader.GetInt32(index01);
+ bool isNew = reader.GetBoolean(index02);
+ bool? importEnabled = reader[index03] as bool? ?? null; // column can be null
+
+ if (isNew == true || importEnabled == null)
+ {
+ // return 0 and 'skip' item
+ return 0;
+ }
+ else if (importEnabled == false)
+ {
+ // mark IsProcessed=true and leave transactionId=null
+ return -1;
+ }
+ else if (transactionTypeId > 0)
+ {
+
+ return transactionTypeId;
+ }
+ else
+ {
+ throw new Exception("Sku TransactionTypeId lookup method failed, is one of the 'enabled' boolean on table set to null?");
+ }
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ }
+ }
+
+ private List Execute(string sqlWhere, DynamicParameters param)
+ {
+ string sql = @"
+ SELECT tblStockSkuTransactionType.StockSkuTransactionTypeID AS TypeId
+ ,tblStockSkuTransactionType.TypeName
+ ,tblStockSkuTransactionType.TypeCode
+ ,tblStockSkuTransactionType.TypeDescription
+ ,tblStockSkuTransactionType.StockJournalTypeID
+ ,tblStockSkuTransactionType.TransactionForeignKeyName
+ ,tblStockSkuTransactionType.TransactionReferenceType
+ ,tblStockSkuTransactionType.IsNewReviewRequired
+ ,tblStockSkuTransactionType.TransactionImportEnabled
+ ,tblStockSkuTransactionType.StockJournalEntryEnabled
+ ,tblStockSkuTransactionType.DebitStockStatusID
+ ,tblStockSkuTransactionType.CreditStockStatusID
+ ,tblStockSkuTransactionType.StatusBalanceCheckRequired
+ ,tblStockSkuTransactionType.FilterStockOnDateTime
+ ,tblStockSkuTransactionType.FirstInFirstOut
+ ,tblStockSkuTransactionType.RecordCreated
+ ,CreditStatus.StockStatus AS CreditStockStatus
+ ,DebitStatus.StockStatus AS DebitStockStatus
+ FROM tblStockStatus AS DebitStatus
+ RIGHT OUTER JOIN tblStockSkuTransactionType ON DebitStatus.StockStatusID = tblStockSkuTransactionType.DebitStockStatusID
+ LEFT OUTER JOIN tblStockStatus AS CreditStatus ON tblStockSkuTransactionType.CreditStockStatusID = CreditStatus.StockStatusID
+ ";
+
+ sql += sqlWhere;
+
+ using (SqlConnection conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ return conn.Query(sql, param).ToList();
+ }
+ }
+
+ public List ByTypeCode(List typeCode)
+ {
+ string sqlWhere = @"
+ WHERE TypeCode IN @typeCode ";
+
+ var param = new DynamicParameters();
+ param.Add("@typeCode", typeCode);
+
+ return Execute(sqlWhere, param);
+ }
+
+ public List ByTypeName(List typeName)
+ {
+ string sqlWhere = @"
+ WHERE TypeName IN @typeName ";
+
+ var param = new DynamicParameters();
+ param.Add("@typeName", typeName);
+
+ return Execute(sqlWhere, param);
+ }
+
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/Stock/UpdateSkuTransaction.cs b/src/bnhtrade.Core/Data/Database/Stock/UpdateSkuTransaction.cs
new file mode 100644
index 0000000..ffcade3
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/Stock/UpdateSkuTransaction.cs
@@ -0,0 +1,198 @@
+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 UpdateSkuTransaction : Connection
+ {
+ private string err = "Database UpdateSkuTransaction: ";
+
+ public UpdateSkuTransaction(string sqlConnectionString) : base(sqlConnectionString)
+ {
+ }
+
+ public void Update(int skuTransactionId, bool isProcessed)
+ {
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(@"
+ UPDATE tblStockSkuTransaction
+ SET IsProcessed=@isProcessed
+ WHERE StockSkuTransactionID=@transactionId
+ ", conn))
+ {
+ cmd.Parameters.AddWithValue("@isProcessed", isProcessed);
+ cmd.Parameters.AddWithValue("@transactionId", skuTransactionId);
+
+ int effected = cmd.ExecuteNonQuery();
+
+ if (effected < 1)
+ {
+ throw new Exception(err += "Sku Transaction IsProcessed update failed");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Update the StockJournalID field. Will also set the IsProcessed value base on input.
+ ///
+ /// Sku Transaction Id
+ /// Stock Journal Id or null to unset
+ public void Update(int skuTransactionId, int? stockJournalId)
+ {
+ string sql = @"
+ UPDATE tblStockSkuTransaction
+ SET IsProcessed = @isProcessed
+ ,StockJournalID = @stockJournalID
+ WHERE StockSkuTransactionID = @transactionId;";
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ if (stockJournalId == null) { cmd.Parameters.AddWithValue("@stockJournalID", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@stockJournalID", (int)stockJournalId); }
+ if (stockJournalId == null) { cmd.Parameters.AddWithValue("@isProcessed", false); }
+ else { cmd.Parameters.AddWithValue("@isProcessed", true); }
+ cmd.Parameters.AddWithValue("@transactionId", skuTransactionId);
+
+ int effected = cmd.ExecuteNonQuery();
+
+ if (effected < 1)
+ {
+ throw new Exception(err += "Sku Transaction StockJournalID update failed");
+ }
+ }
+ }
+ }
+
+ public void Update(int skuTransactionId, int quantity, bool isProcessed)
+ {
+ string sql = @"
+ UPDATE tblStockSkuTransaction
+ SET IsProcessed = @isProcessed
+ ,Quantity = @quantity
+ WHERE StockSkuTransactionID = @transactionId;";
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ cmd.Parameters.AddWithValue("@isProcessed", isProcessed);
+ cmd.Parameters.AddWithValue("@quantity", quantity);
+ cmd.Parameters.AddWithValue("@transactionId", skuTransactionId);
+
+ int effected = cmd.ExecuteNonQuery();
+
+ if (effected < 1)
+ {
+ throw new Exception(err += "Sku Transaction quantity and isprocessed update failed");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Update the StockJournalID field. Will also set the IsProcessed value base on input.
+ ///
+ /// Sku Transaction Id
+ /// Sku Transaction quantity. Set to null to leave database value unchanged.
+ /// Stock Journal Id
+ public void Update(int skuTransactionId, int? quantity, int stockJournalId)
+ {
+ string sql = @"
+ UPDATE tblStockSkuTransaction
+ SET IsProcessed = @isProcessed
+ ,StockJournalID = @stockJournalID ";
+
+ if (quantity != null)
+ {
+ sql += @"
+ ,Quantity = @quantity ";
+ }
+
+ sql += @"
+ WHERE StockSkuTransactionID = @transactionId;";
+
+ using (var conn = new SqlConnection(sqlConnectionString))
+ {
+ conn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(sql, conn))
+ {
+ if (quantity != null) { cmd.Parameters.AddWithValue("@quantity", (int)quantity); }
+ cmd.Parameters.AddWithValue("@isProcessed", true);
+ cmd.Parameters.AddWithValue("@stockJournalID", stockJournalId);
+ cmd.Parameters.AddWithValue("@transactionId", skuTransactionId);
+
+ int effected = cmd.ExecuteNonQuery();
+
+ if (effected < 1)
+ {
+ throw new Exception(err += "Sku Transaction IsProcessed update failed");
+ }
+ }
+ }
+ }
+
+ public void Update(Model.Stock.SkuTransaction skuTransaction)
+ {
+ using (var conn = new SqlConnection())
+ {
+ conn.Open();
+
+ using (SqlCommand cmd = new SqlCommand(@"
+ UPDATE tblStockSkuTransaction
+ SET TransactionDate = @transactionDate
+ ,StockSkuTransactionTypeID = @stockSkuTransactionTypeID
+ ,ForeignKey = @foreignKey
+ ,Reference = @reference
+ ,Detail = @Detail
+ ,SkuID = (
+ SELECT skuSkuID
+ FROM tblSku
+ WHERE skuSkuNumber = @skuNumber
+ )
+ ,Quantity = @quantity
+ ,IsProcessed = @isProcessed
+ ,StockJournalID = @stockJournalID
+ WHERE StockSkuTransactionID = @transactionId
+ ", conn))
+ {
+ cmd.Parameters.AddWithValue("@transactionDate", skuTransaction.TransactionDate.ToUniversalTime());
+ cmd.Parameters.AddWithValue("@stockSkuTransactionTypeID", skuTransaction.SkuTransactionTypeId);
+ if (!skuTransaction.IsSetForeignKey) { cmd.Parameters.AddWithValue("@foreignKey", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@foreignKey", skuTransaction.ForeignKey); }
+ if (!skuTransaction.IsSetReference) { cmd.Parameters.AddWithValue("@reference", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@reference", skuTransaction.Reference); }
+ if (!skuTransaction.IsSetDetail) { cmd.Parameters.AddWithValue("@detail", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@detail", skuTransaction.Detail); }
+ cmd.Parameters.AddWithValue("@skuNumber", skuTransaction.SkuNumber);
+ cmd.Parameters.AddWithValue("@quantity", skuTransaction.Quantity);
+ cmd.Parameters.AddWithValue("@isProcessed", skuTransaction.IsProcessed);
+ if (!skuTransaction.IsSetStockJournalId) { cmd.Parameters.AddWithValue("@stockJournalID", DBNull.Value); }
+ else { cmd.Parameters.AddWithValue("@stockJournalID", skuTransaction.StockJournalId); }
+ cmd.Parameters.AddWithValue("@transactionId", skuTransaction.SkuTransactionId);
+
+ int effected = cmd.ExecuteNonQuery();
+
+ if (effected < 1)
+ {
+ throw new Exception(err += "stockSkuTransaction IsProcessed update failed");
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Data/Database/WhereBuilder.cs b/src/bnhtrade.Core/Data/Database/WhereBuilder.cs
new file mode 100644
index 0000000..9a05760
--- /dev/null
+++ b/src/bnhtrade.Core/Data/Database/WhereBuilder.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Data.Database
+{
+ public class WhereBuilder
+ {
+ private int parameterCount;
+
+ public WhereBuilder()
+ {
+ Innit();
+ }
+
+ public string SqlWhereString { get; private set; }
+
+ public Dictionary ParameterList { get; private set; }
+
+ public void Innit()
+ {
+ SqlWhereString = null;
+ ParameterList = new Dictionary();
+ parameterCount = 0;
+ }
+
+ ///
+ /// Used to create a string for an SQL where condition 'In' statement
+ ///
+ /// Name of the column to used to for the condition statement
+ /// List of values to test in condition statement
+ /// Optional string to prefix to the returned result
+ public void In(string columnReference, List orValueList, string wherePrefix = null)
+ {
+ Innit();
+
+ if (orValueList == null || !orValueList.Any())
+ {
+ return;
+ }
+
+ string sqlWhere = @"
+ ";
+
+ if (wherePrefix != null)
+ {
+ sqlWhere += wherePrefix;
+ }
+
+ sqlWhere += " " + columnReference + " IN ( ";
+
+ var paramters = new Dictionary();
+ int listCount = orValueList.Count();
+ for (int i = 0; i < listCount; i++, parameterCount++)
+ {
+ if (i > 0)
+ {
+ sqlWhere += ", ";
+ }
+
+ string param = "@parameter" + parameterCount;
+ sqlWhere += param;
+ paramters.Add(param, orValueList[i]);
+ }
+ sqlWhere += " )";
+
+ SqlWhereString = sqlWhere;
+ ParameterList = paramters;
+ }
+
+ ///
+ /// Used to create a string for an SQL where condition 'In' statement
+ ///
+ /// Name of the column to used to for the condition statement
+ /// List of values to test in condition statement
+ /// Optional string to prefix to the returned result
+ public void In(string columnReference, List orValueList, string wherePrefix = null)
+ {
+ var stringList = new List();
+
+ if (orValueList != null || !orValueList.Any())
+ {
+ foreach (int value in orValueList)
+ {
+ stringList.Add(value.ToString());
+ }
+ }
+
+ In(columnReference, stringList, wherePrefix);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Extensions.cs b/src/bnhtrade.Core/Extensions.cs
new file mode 100644
index 0000000..d7f479e
--- /dev/null
+++ b/src/bnhtrade.Core/Extensions.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core
+{
+ static class Extensions
+ {
+ public static bool In(this T item, params T[] items)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
+
+ return items.Equals(item);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Account/GetAccountCodeInfo.cs b/src/bnhtrade.Core/Logic/Account/GetAccountCodeInfo.cs
new file mode 100644
index 0000000..7c4663a
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Account/GetAccountCodeInfo.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Account
+{
+ public class GetAccountCodeInfo
+ {
+ private string sqlConnectionString;
+ private Data.Database.Account.ReadAccountCode readAccountCode;
+ private Dictionary cache;
+
+ public GetAccountCodeInfo(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ readAccountCode = new Data.Database.Account.ReadAccountCode(sqlConnectionString);
+ cache = new Dictionary();
+ }
+
+ public void CacheClear()
+ {
+ cache.Clear();
+ }
+
+ public void CacheFill()
+ {
+ CacheClear();
+
+ var resultList = readAccountCode.All();
+ foreach (var result in resultList)
+ {
+ cache.Add(result.AccountCodeId, result);
+ }
+ }
+
+ public void CacheFill(List accountCodeList, bool forceDbRead = false)
+ {
+ if (accountCodeList == null || !accountCodeList.Any())
+ {
+ return;
+ }
+
+ var accountCodeQueryList = new List();
+ foreach (var code in accountCodeList.Distinct().ToList())
+ {
+ if (forceDbRead)
+ {
+ cache.Remove(code);
+ accountCodeQueryList.Add(code);
+ }
+ else if (!cache.ContainsKey(code))
+ {
+ accountCodeQueryList.Add(code);
+ }
+ }
+
+ // get db list
+ var dbList = readAccountCode.ByAccountCode(accountCodeQueryList);
+
+ // add to cache
+ foreach (var item in dbList)
+ {
+ cache.Add(item.AccountCodeId, item);
+ }
+ }
+
+ public Model.Account.AccountCode ByAccountCode(int accountCode, bool forceDbRead = false)
+ {
+ CacheFill(new List { accountCode }, forceDbRead);
+
+ if (cache.ContainsKey(accountCode))
+ {
+ return cache[accountCode];
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Account/GetInvoiceLineItem.cs b/src/bnhtrade.Core/Logic/Account/GetInvoiceLineItem.cs
new file mode 100644
index 0000000..fa7aceb
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Account/GetInvoiceLineItem.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Account
+{
+ public class GetInvoiceLineItem
+ {
+ string sqlConnectionString;
+ private Dictionary cache;
+ private Data.Database.Account.ReadInvoiceLineItem dbRead;
+ private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
+ private Logic.Account.GetTaxCodeInfo getTaxCode;
+ private Logic.Account.GetAccountCodeInfo getAccountCode;
+
+ public GetInvoiceLineItem(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ CacheInnit();
+ dbRead = new Data.Database.Account.ReadInvoiceLineItem(sqlConnectionString);
+ getAccountCode = new GetAccountCodeInfo(sqlConnectionString);
+ getTaxCode = new GetTaxCodeInfo(sqlConnectionString);
+ }
+
+ ///
+ /// Create new 'default' line item code when a requested item code is not found.
+ ///
+ public bool InsertNewOnNoMatch { get; set; } = false;
+
+ public void CacheInnit()
+ {
+ cache = new Dictionary();
+ }
+
+ ///
+ /// Prefill cache in one SQL call, saves multiple SQL calls.
+ ///
+ /// List of item codes to lookup from database
+ /// Forces a database read (does not read cache)
+ public void CacheFill(List itemCodeList, bool forceDbRead = false)
+ {
+ if (itemCodeList == null || !itemCodeList.Any())
+ {
+ return;
+ }
+
+ var itemCodeQueryList = new List();
+ foreach (var itemCode in itemCodeList)
+ {
+ if (forceDbRead)
+ {
+ cache.Remove(itemCode);
+ itemCodeQueryList.Add(itemCode);
+ }
+ else if (!cache.ContainsKey(itemCode))
+ {
+ itemCodeQueryList.Add(itemCode);
+ }
+ }
+
+ // query database
+ var resultList = dbRead.ByItemCode(itemCodeQueryList);
+
+ // fill account & tax codes cache
+ getAccountCode.CacheFill(dbRead.AccountCodeList.Values.ToList(), forceDbRead);
+ getTaxCode.CacheFill(dbRead.TaxCodeList.Values.ToList(), forceDbRead);
+
+ // build final itemcode object and add to cache
+ foreach (var result in resultList.Values)
+ {
+ if (dbRead.AccountCodeList.ContainsKey(result.ItemCode))
+ {
+ result.DefaultAccountCode = getAccountCode.ByAccountCode(dbRead.AccountCodeList[result.ItemCode]);
+ }
+
+ if (dbRead.TaxCodeList.ContainsKey(result.ItemCode))
+ {
+ result.DefaultTaxCode = getTaxCode.GetByTaxCode(dbRead.TaxCodeList[result.ItemCode]);
+ }
+
+ cache.Add(result.ItemCode, result);
+ }
+ }
+
+ ///
+ /// Creates new 'default' item code entry. The item code and title are set the same and will require updating.
+ ///
+ /// Item code string
+ ///
+ public Model.Account.InvoiceLineItem CreateDefault(string itemCode)
+ {
+ new Data.Database.Account.CreateInvoiceLineItem(sqlConnectionString).CreateDefault(itemCode);
+ var item = dbRead.ByItemCode(itemCode);
+ cache.Add(item.ItemCode, item);
+ return item;
+ }
+
+ public Model.Account.InvoiceLineItem ByItemCode(string itemCode, bool forceDbRead = false)
+ {
+ if (string.IsNullOrWhiteSpace(itemCode))
+ {
+ return null;
+ }
+
+ CacheFill(new List { itemCode }, forceDbRead);
+
+ Model.Account.InvoiceLineItem item = null;
+ if (cache.ContainsKey(itemCode))
+ {
+ item = cache[itemCode];
+
+ // check title
+ if (!item.IsNewReviewRequired && item.Name == item.ItemCode)
+ {
+ throw new Exception
+ ("ItemCode found with the incomplete title. Update title and then try again.");
+ }
+
+ return item;
+ }
+
+ if (!InsertNewOnNoMatch)
+ {
+ return null;
+ }
+ else
+ {
+ return CreateDefault(itemCode);
+ }
+ }
+
+ ///
+ /// Tests if ItemCode has Invoice line entry enabled
+ ///
+ /// Item code
+ /// Forces a database read (does not read cache)
+ ///
+ public bool InvoiceLineEntryEnabled(string itemCode, bool forceDbRead = false)
+ {
+ var item = ByItemCode(itemCode, forceDbRead);
+ if (item == null)
+ throw new Exception("Invalid item code");
+ return item.InvoiceLineEntryEnabled;
+ }
+
+ ///
+ /// Tests if ItemCode is new (default) and a review id required
+ ///
+ /// Item code
+ /// Forces a database read (does not read cache)
+ ///
+ public bool IsNewReviewRequired(string itemCode, bool forceDbRead = false)
+ {
+ var item = ByItemCode(itemCode, forceDbRead);
+ if (item == null)
+ {
+ throw new Exception("Invalid item code");
+ }
+ return item.IsNewReviewRequired;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/bnhtrade.Core/Logic/Account/GetTaxCodeInfo.cs b/src/bnhtrade.Core/Logic/Account/GetTaxCodeInfo.cs
new file mode 100644
index 0000000..a50342e
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Account/GetTaxCodeInfo.cs
@@ -0,0 +1,141 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Account
+{
+ public class GetTaxCodeInfo
+ {
+ string sqlConnectionString;
+ private bool allRetrived;
+ private Dictionary cache;
+ private Dictionary cacheInvoiceItem;
+ private Data.Database.Account.ReadTaxCode dbRead;
+
+ public GetTaxCodeInfo(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ allRetrived = false;
+ CacheClear();
+ dbRead = new Data.Database.Account.ReadTaxCode(sqlConnectionString);
+ }
+
+ private void CacheClear()
+ {
+ cache = new Dictionary();
+ cacheInvoiceItem = new Dictionary();
+ }
+
+ public void CacheFill()
+ {
+ CacheClear();
+
+ var list = dbRead.GetAllActive();
+ foreach (var item in list)
+ {
+ cache.Add(item.TaxCode, item);
+ }
+ }
+
+ public void CacheFill(List taxCodeList, bool forceDbRead = false)
+ {
+ if (taxCodeList == null || !taxCodeList.Any())
+ {
+ return;
+ }
+
+ var taxCodeQueryList = new List();
+ foreach (var code in taxCodeList.Distinct().ToList())
+ {
+ if (forceDbRead)
+ {
+ cache.Remove(code);
+ taxCodeQueryList.Add(code);
+ }
+ else if (!cache.ContainsKey(code))
+ {
+ taxCodeQueryList.Add(code);
+ }
+ }
+
+ // get db list
+ var dbList = dbRead.GetByTaxCode(taxCodeQueryList);
+
+ // add to cache
+ foreach (var item in dbList)
+ {
+ cache.Add(item.TaxCode, item);
+ }
+ }
+
+ public List GetAllActive()
+ {
+ CacheFill();
+ return cache.Values.ToList();
+ }
+
+ public Model.Account.TaxCodeInfo GetByTaxCode(string taxCode, bool forceDbRead = false)
+ {
+ if (string.IsNullOrWhiteSpace(taxCode))
+ {
+ return null;
+ }
+
+ CacheFill(new List { taxCode }, forceDbRead);
+
+ if (cache.ContainsKey(taxCode))
+ {
+ return cache[taxCode];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Gets list of Tax Code Info for a given list of Sku Numbers
+ ///
+ /// List of SKU numbers
+ /// Dictionary, key is SkuNumber and value is Tax Code Info
+ public Dictionary GetBySkuNumber(List skuNumberList)
+ {
+ var returnList = new Dictionary();
+
+ if (skuNumberList == null || !skuNumberList.Any())
+ {
+ return returnList;
+ }
+
+ // remove any duplicates
+ var cleanSkuList = skuNumberList.Distinct().ToList();
+
+ // get db list
+ var dbList = dbRead.GetTaxCodeBySkuNumber(skuNumberList);
+
+ if (!dbList.Any()) { return returnList; }
+
+ // charge the cache
+ dbRead.GetAllActive();
+
+ // build dictionary
+ foreach (var item in dbList)
+ {
+ var taxInfo = GetByTaxCode(item.Value);
+ if (taxInfo != null)
+ {
+ returnList.Add(item.Key, taxInfo);
+ }
+ }
+
+ return returnList;
+ }
+
+ public Dictionary Get(List invoiceLineList)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Account/TaxCalculation.cs b/src/bnhtrade.Core/Logic/Account/TaxCalculation.cs
new file mode 100644
index 0000000..73c9b5d
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Account/TaxCalculation.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Account
+{
+ public class TaxCalculation
+ {
+ public decimal GetGrossAmount(decimal netAmount, decimal taxPercent)
+ {
+ return netAmount * (1 + (taxPercent / 100));
+ }
+
+ public decimal GetGrossAmount(decimal netAmount, Model.Account.TaxCodeInfo taxCodeInfo)
+ {
+ return GetGrossAmount(netAmount, taxCodeInfo.TaxRate);
+ }
+
+ public decimal GetNetAmount(decimal grossAmount, decimal taxPercent)
+ {
+ return grossAmount / (1 + (taxPercent / 100));
+ }
+
+ public decimal GetNetAmount(decimal grossAmount, Model.Account.TaxCodeInfo taxCodeInfo)
+ {
+ return GetNetAmount(grossAmount, taxCodeInfo.TaxRate);
+ }
+
+ public decimal GetTaxAmount(decimal amount, bool amountIsTaxInclusive, decimal taxPercent)
+ {
+ if (amountIsTaxInclusive)
+ {
+ return amount - GetNetAmount(amount, taxPercent);
+ }
+ else
+ {
+ return amount * (taxPercent / 100);
+ }
+ }
+
+ public decimal GetTaxAmount(decimal amount, bool amountIsTaxInclusive, Model.Account.TaxCodeInfo taxCodeInfo)
+ {
+ return GetTaxAmount(amount, amountIsTaxInclusive, taxCodeInfo.TaxRate);
+ }
+
+ public decimal GetMarginTaxRate(DateTime transactionDate)
+ {
+ decimal vatRate = 0;
+ if (transactionDate >= new DateTime(2011, 01, 04))
+ {
+ vatRate = 20;
+ }
+ else
+ {
+ // more coding required
+ throw new Exception("Transaction is outside the current margin scheme date scope");
+ }
+ return vatRate;
+ }
+
+ public decimal GetMarginTaxAmount(decimal marginAmount, DateTime transactionDate)
+ {
+ decimal vatRate = GetMarginTaxRate(transactionDate);
+
+ return GetTaxAmount(marginAmount, true, vatRate);
+ }
+
+ public decimal GetMarginTaxAmount(decimal purchasePrice, decimal salePrice, DateTime transactionDate)
+ {
+ return GetMarginTaxAmount(salePrice - purchasePrice, transactionDate);
+ }
+
+ ///
+ /// Returns a value to multiply margin (sale - purchase price) by to find margin scheme tax amount
+ ///
+ /// Date of transaction
+ /// Value between 0 and 1
+ public decimal GetMarginMultiplier(DateTime transactionDate)
+ {
+ decimal vatRate = GetMarginTaxRate(transactionDate);
+ return vatRate / (vatRate + 100);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Account/ValidateInvoice.cs b/src/bnhtrade.Core/Logic/Account/ValidateInvoice.cs
deleted file mode 100644
index 69fd9ad..0000000
--- a/src/bnhtrade.Core/Logic/Account/ValidateInvoice.cs
+++ /dev/null
@@ -1,267 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bnhtrade.Core.Logic.Account
-{
- public abstract class ValidateInvoice : Validate
- {
- protected Account.ValidateAccountCode validateAccountCode = new Account.ValidateAccountCode();
- protected Account.ValidateCurrencyCode validateCurrencyCode = new Account.ValidateCurrencyCode();
- protected Account.ValidateTaxCode validateTaxCode = new ValidateTaxCode();
- protected Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck();
-
- public bool InvoiceNumberIsRequired { get; set; } = true;
- public bool InvoiceLineDescriptionIsRequired { get; set; } = true;
-
- public new void Innit()
- {
- base.Innit();
- validateAccountCode.Innit();
- validateCurrencyCode.Innit();
- validateTaxCode.Innit();
- stringCheck.Innit();
- }
-
- protected bool IsValidInvoice(Model.Account.IInvoice invoice)
- {
- return IsValidInvoice(new List { invoice });
- }
-
- protected bool IsValidInvoice(List invoiceList)
- {
- Innit();
-
- if (invoiceList == null || !invoiceList.Any())
- {
- ErrorListAdd("Invoice list is null or empty.");
- return false;
- }
-
- var tempErrorList = new List();
- for (int i = 0; i < invoiceList.Count(); i++)
- {
- Innit();
-
- // check header info
- if (invoiceList[i].ContactNameIsSet) { IsValidInvoiceContact(invoiceList[i].ContactName); }
- else { ErrorListAdd("'Contact Name' is a required value"); }
-
- if (invoiceList[i].InvoiceAmountIsSet)
- {
- if (!invoiceList[i].IsCreditNoteIsSet)
- { ErrorListAdd("'Is Credit Note' is a required value"); }
- else
- {
- if (invoiceList[i].IsCreditNote && invoiceList[i].InvoiceAmount > 0)
- { ErrorListAdd("Credit Note amount cannot be greater than zero"); }
- else if (!invoiceList[i].IsCreditNote && invoiceList[i].InvoiceAmount < 0)
- { ErrorListAdd("Invoice amount cannot be less than zero"); }
- }
- }
- else { ErrorListAdd("'Invoice Amount' is a required value"); }
-
- if (invoiceList[i].InvoiceCurrencyCodeIsSet) { IsValidInvoiceCurrency(invoiceList[i].InvoiceCurrencyCode); }
- else { ErrorListAdd("'Invoice Currency Code' is a required value"); }
-
- if (invoiceList[i].InvoiceDateIsSet) { IsValidInvoiceDate(invoiceList[i].InvoiceDate); }
- else { ErrorListAdd("'Invoice Date' is a required value"); }
-
- if (!invoiceList[i].InvoiceDateKindIsSet) { ErrorListAdd("'Invoice Date Kind' is a required value"); }
-
- if (invoiceList[i].InvoiceDueDateIsSet) { IsValidInvoiceDueDate(invoiceList[i].InvoiceDueDate); }
-
- if (invoiceList[i].InvoiceNumberIsSet)
- { IsValidInvoiceNumber(invoiceList[i].InvoiceNumber); }
- else
- {
- if (InvoiceNumberIsRequired) { ErrorListAdd("'Invoice Number' is a required value"); }
- }
-
- if (invoiceList[i].InvoiceReferenceIsSet) { IsValidInvoiceReference(invoiceList[i].InvoiceReference); }
- else { ErrorListAdd("'Invoice Reference' is a required value"); }
-
- if (!invoiceList[i].IsCreditNoteIsSet) { ErrorListAdd("'Invoice Reference' is a required value"); }
-
-
- // loop though lines and check and sum totals
- if (!invoiceList[i].InvoiceLineListIsSet)
- { ErrorListAdd("Invoice is required to have lines."); }
- else
- {
- decimal lineTotal = 0;
- for (int j = 0; j < invoiceList[i].InvoiceLineList.Count(); j++)
- {
- if (!invoiceList[i].InvoiceLineList[j].AccountCodeIsSet) { ErrorListAdd("Line 'Account Code' is a required value"); }
- else { IsValidInvoiceLineAccount(invoiceList[i].InvoiceLineList[j].AccountCode); }
-
- if (!invoiceList[i].InvoiceLineList[j].DescriptionIsSet)
- {
- if (InvoiceLineDescriptionIsRequired) { ErrorListAdd("Line 'Description' is a required value"); }
- }
- else { IsValidInvoiceLineDescription(invoiceList[i].InvoiceLineList[j].Description); }
-
- if (!invoiceList[i].InvoiceLineList[j].GrossTotalAmountIsSet) { ErrorListAdd("Line 'Gross Total Amount' is a required value"); }
-
- if (!invoiceList[i].InvoiceLineList[j].ItemCodeIsSet) { ErrorListAdd("Line 'Item Code' is a required value"); }
- else { IsValidLineItemCode(invoiceList[i].InvoiceLineList[j].ItemCode); }
-
- if (!invoiceList[i].InvoiceLineList[j].QuantityIsSet) { ErrorListAdd("Line 'Quantity' is a required value"); }
-
- if (!invoiceList[i].InvoiceLineList[j].TaxAmountIsSet) { ErrorListAdd("Line 'Tax Amount' is a required value"); }
-
- if (!invoiceList[i].InvoiceLineList[j].TaxCodeIsSet) { ErrorListAdd("Line 'Tax Code' is a required value"); }
- else { IsValidLineTaxCode(invoiceList[i].InvoiceLineList[j].TaxCode); }
-
- if (!invoiceList[i].InvoiceLineList[j].TotalNetAmountIsSet) { ErrorListAdd("Line 'Total Net Amount' is a required value"); }
-
- if ((invoiceList[i].InvoiceLineList[j].TaxAmount
- + invoiceList[i].InvoiceLineList[j].TaxAmountAdjust
- + invoiceList[i].InvoiceLineList[j].TotalNetAmount) != invoiceList[i].InvoiceLineList[j].GrossTotalAmount)
- { ErrorListAdd("Incorrect invoice line total (gross) amount."); }
-
- lineTotal = lineTotal + invoiceList[i].InvoiceLineList[j].GrossTotalAmount;
- }
-
- // check totals
- if (invoiceList[i].InvoiceAmountIsSet && (invoiceList[i].InvoiceAmount != lineTotal))
- { ErrorListAdd("Invoice line total does not match invoice total amount."); }
- }
- tempErrorList.AddRange(ErrorList.Select(x => "[Inv" + i + "] " + x).ToList());
- }
-
- Innit();
- ErrorListAdd(tempErrorList);
-
- if (ErrorListIsSet) { return false; }
- else { return true; }
- }
-
- protected bool IsValidInvoiceLineAccount(int accountCode)
- {
- validateAccountCode.Innit();
- if (!validateAccountCode.IsValidAccountCodeId(accountCode))
- {
- ErrorListAdd(validateAccountCode.ErrorList.Select(x => "Invalid invoice line account code: " + x).ToList());
- return false;
- }
- else
- { return true; }
- }
-
- protected bool IsValidInvoiceLineDescription(string lineDescription)
- {
- int maxLength = 150;
- stringCheck.Innit();
- if (!stringCheck.MaxLength(lineDescription, maxLength))
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice line description: " + x).ToList());
- return false;
- }
- return true;
- }
-
- protected bool IsValidInvoiceContact(string contactName)
- {
- int maxlength = 150;
- stringCheck.Innit();
- if (!stringCheck.MaxLength(contactName, maxlength))
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice nontact name: " + x).ToList());
- return false;
- }
- return true;
- }
-
- protected bool IsValidInvoiceDate(DateTime invoiceDate)
- {
- if (invoiceDate.Kind != DateTimeKind.Utc)
- {
- ErrorListAdd(@"Invalid date/time, UTC kind required.");
- return false;
- }
- else if (invoiceDate == default(DateTime))
- {
- ErrorListAdd("Date and time is default value.");
- return false;
- }
- return true;
- }
-
- protected bool IsValidInvoiceDueDate(DateTime invoiceDueDate)
- {
- if (invoiceDueDate.Kind != DateTimeKind.Utc)
- {
- ErrorListAdd(@"Invalid date/time, UTC kind required.");
- return false;
- }
- else if (invoiceDueDate == default(DateTime))
- {
- ErrorListAdd("Date and time is default value.");
- return false;
- }
- return true;
- }
-
- protected bool IsValidInvoiceCurrency(string currencyCode)
- {
- validateCurrencyCode.Innit();
- if (!validateCurrencyCode.IsValidCurrencyCode(currencyCode))
- {
- ErrorListAdd(validateCurrencyCode.ErrorList.Select(x => "Invalid invoice currency code: " + x).ToList());
- return false;
- }
- else { return true; }
- }
-
- protected bool IsValidInvoiceNumber(string invoiceNumber)
- {
- int maxlength = 64;
- stringCheck.Innit();
- if (!stringCheck.MaxLength(invoiceNumber, maxlength))
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice number: " + x).ToList());
- return false;
- }
- return true;
- }
-
- protected bool IsValidInvoiceReference(string invoiceReference)
- {
- int maxlength = 50;
- stringCheck.Innit();
- if (!stringCheck.MaxLength(invoiceReference, maxlength))
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice reference: " + x).ToList());
- return false;
- }
- return true;
- }
-
- protected bool IsValidLineItemCode(string itemCode)
- {
- int maxlength = 250;
- stringCheck.Innit();
- if (!stringCheck.MaxLength(itemCode, maxlength))
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid invoice line item code: " + x).ToList());
- return false;
- }
- return true;
- }
-
- protected bool IsValidLineTaxCode(string taxCode)
- {
- validateTaxCode.Innit();
- if (validateTaxCode.IsValidTaxCodeId(taxCode))
- { return true; }
- else
- {
- ErrorListAdd(validateTaxCode.ErrorList.Select(x => "Invalid invoice line " + x).ToList());
- return false;
- }
- }
- }
-}
diff --git a/src/bnhtrade.Core/Logic/Account/ValidateSalesInvoice.cs b/src/bnhtrade.Core/Logic/Account/ValidateSalesInvoice.cs
deleted file mode 100644
index ef6a103..0000000
--- a/src/bnhtrade.Core/Logic/Account/ValidateSalesInvoice.cs
+++ /dev/null
@@ -1,34 +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 ValidateSalesInvoice : ValidateInvoice
- {
- public ValidateSalesInvoice()
- {
- int propertyCount = new Model.Account.SalesInvoice().GetType().GetProperties().Count();
- if (propertyCount != 20)
- { throw new Exception("Model.Account.SalesInvoice property count has altered. Validate class requires an update."); }
-
- propertyCount = new Model.Account.SalesInvoice.InvoiceLine().GetType().GetProperties().Count();
- if (propertyCount != 18)
- { throw new Exception("Model.Account.SalesInvoice property count has altered. Validate class requires an update."); }
- }
-
- public bool IsValidInvoice(Model.Account.SalesInvoice invoice)
- {
- return IsValidInvoice(new List { invoice });
- }
-
- public bool IsValidInvoice(List invoiceList)
- {
- var interfaceList = invoiceList.Cast().ToList();
-
- return IsValidInvoice(interfaceList);
- }
- }
-}
diff --git a/src/bnhtrade.Core/Logic/Account/ValidateTaxCode.cs b/src/bnhtrade.Core/Logic/Account/ValidateTaxCode.cs
deleted file mode 100644
index ccf72e8..0000000
--- a/src/bnhtrade.Core/Logic/Account/ValidateTaxCode.cs
+++ /dev/null
@@ -1,145 +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 ValidateTaxCode : Validate
- {
- private Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck();
-
- public new void Innit()
- {
- base.Innit();
- stringCheck.Innit();
- }
- public bool IsValidGrossAmountMultiplier(decimal multiplier)
- {
- if (multiplier >= 0 && multiplier <= 1)
- {
- return true;
- }
- else
- {
- ErrorListAdd( "Gross multiplier must be equal to, or between, 0 and 1.");
- return false;
- }
- }
- public bool IsValidNetAmountMultiplier(decimal multiplier)
- {
- if (multiplier >= 0 && multiplier <= 1)
- {
- return true;
- }
- else
- {
- ErrorListAdd("Net multiplier must not be less than 0 or greater than 1.");
- return false;
- }
- }
- public bool IsValidOnExpense(Model.Account.TaxCode taxInfo)
- {
- if (taxInfo.IsValidOnExpense || taxInfo.IsSetIsValidOnIncome)
- {
- if (taxInfo.IsSetIsValidOnExpense)
- {
- return true;
- }
- else
- {
- ErrorListAdd("Is Valid On Expense has not been set.");
- return false;
- }
- }
- else
- {
- ErrorListAdd("Either 'IsValidOnExpense' or 'IsSetIsValidOnSale' must be set to true.");
- return false;
- }
- }
- public bool IsValidOnIncome(Model.Account.TaxCode taxInfo)
- {
- if (taxInfo.IsValidOnExpense || taxInfo.IsSetIsValidOnIncome)
- {
- if (taxInfo.IsSetIsValidOnIncome)
- {
- return true;
- }
- else
- {
- ErrorListAdd("Is Valid On Income has not been set.");
- return false;
- }
- }
- else
- {
- ErrorListAdd("Either 'IsValidOnPurchase' or 'IsSetIsValidOnSale' must be set to true.");
- return false;
- }
- }
- public bool IsValidTaxCodeId(string taxCodeId)
- {
- if (!stringCheck.IsAlphaNumeric(taxCodeId, true))
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Code: " + x).ToList());
- return false;
- }
- if (taxCodeId.Length != 4)
- {
- ErrorListAdd("Invalid Tax Code: Length does not equal 4 charaters.");
- return false;
- }
- return true;
- }
- public bool IsValidTaxRateDescription(string description)
- {
- if (stringCheck.MaxLength(description, 250, true))
- {
- return true;
- }
- else
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Rate Description: " + x).ToList());
- return false;
- }
- }
- public bool IsValidTaxRateTitle(string title)
- {
- if (stringCheck.MaxLength(title, 50, false))
- {
- return true;
- }
- else
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Rate Title: " + x).ToList());
- return false;
- }
- }
- public bool IsValidTaxRateTitleShort(string title)
- {
- if (stringCheck.MaxLength(title, 50, false))
- {
- return true;
- }
- else
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Rate Title Short: " + x).ToList());
- return false;
- }
- }
- public bool IsValidTaxType(string taxType)
- {
- if (stringCheck.MaxLength(taxType, 50, false))
- {
- return true;
- }
- else
- {
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid Tax Rate Type: " + x).ToList());
- return false;
- }
- }
- }
-}
diff --git a/src/bnhtrade.Core/Logic/AmazonFBAInbound/UpdateDatabaseShipmentInfo.cs b/src/bnhtrade.Core/Logic/AmazonFBAInbound/UpdateDatabaseShipmentInfo.cs
index c80adad..b353629 100644
--- a/src/bnhtrade.Core/Logic/AmazonFBAInbound/UpdateDatabaseShipmentInfo.cs
+++ b/src/bnhtrade.Core/Logic/AmazonFBAInbound/UpdateDatabaseShipmentInfo.cs
@@ -36,33 +36,32 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
shipmentRequest.LastUpdatedAfter = dateTimeAfter.AddDays(-14);
shipmentRequest.LastUpdatedBefore = dateTimeBefore;
- List shipmentInfoList = shipmentRequest.GetShipmentInfo();
+ List shipmentInfoList = shipmentRequest.GetShipmentInfo();
// build list of shipments returned from mws
var dicShipExistsInDb = new Dictionary();
foreach (var item in shipmentInfoList)
{
- dicShipExistsInDb.Add(item.AmazonShipmentId, false);
+ dicShipExistsInDb.Add(item.FbaShipmentId, false);
}
// build list of shipmentId that do not exist in database
int complete = 0;
using (TransactionScope scope = new TransactionScope())
{
- List newShipmentInfoList = null;
+ List newShipmentInfoList = null;
if (dicShipExistsInDb.Any())
{
var newShipmentId = new List();
// query db for shipment header info
- var requestHeader = new Data.Database.FBAInbound.GetShipmentHeaderInfo(sqlConnectionString);
- requestHeader.ShipmentIdList = dicShipExistsInDb.Keys.ToList();
- var resultHeader = requestHeader.Execute();
+ var resultHeader = new Data.Database.AmazonShipment.ReadShipmentInfo(sqlConnectionString)
+ .HeaderByFbaShipmentId(dicShipExistsInDb.Keys.ToList());
// compare db and mws result
foreach (var item in resultHeader)
{
- dicShipExistsInDb[item.AmazonShipmentId] = true;
+ dicShipExistsInDb[item.FbaShipmentId] = true;
}
foreach (var item in dicShipExistsInDb)
{
@@ -81,7 +80,7 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
foreach (var item in newShipmentInfoList)
{
var shipmentItemInfoRequest = new Data.AmazonMWS.FBAInbound.ListInboundShipmentItems();
- item.ShipmentItemInfoList = shipmentItemInfoRequest.GetByAmazonShipmentId(item.AmazonShipmentId);
+ item.ShipmentItemInfoList = shipmentItemInfoRequest.GetByAmazonShipmentId(item.FbaShipmentId);
}
}
@@ -91,10 +90,10 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
foreach (var item in newShipmentInfoList)
{
// add the update date
- item.LastUpdatedUtc = dateTimeBefore;
+ item.LastUpdated = dateTimeBefore;
// write to db
- var dbWrite = new Data.Database.FBAInbound.SetShipmentInfo(sqlConnectionString);
+ var dbWrite = new Data.Database.AmazonShipment.SetShipmentInfo(sqlConnectionString);
dbWrite.Excecute(item);
complete = complete + 1;
}
diff --git a/src/bnhtrade.Core/Logic/Export/AmazonSettlement.cs b/src/bnhtrade.Core/Logic/Export/AmazonSettlement.cs
index e853c2b..3fbae60 100644
--- a/src/bnhtrade.Core/Logic/Export/AmazonSettlement.cs
+++ b/src/bnhtrade.Core/Logic/Export/AmazonSettlement.cs
@@ -11,7 +11,8 @@ namespace bnhtrade.Core.Logic.Export
public class AmazonSettlement
{
private string sqlConnectionString;
- private Dictionary taxCodeBySkuNumer;
+ private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
+ private List lineItemCodeList = new List();
public AmazonSettlement(string sqlConnectionString)
{
@@ -21,12 +22,11 @@ namespace bnhtrade.Core.Logic.Export
public void ToInvoice()
{
var console = new UI.Console.Update();
- var log = new Logic.Log.LogEvent();
log.LogInformation("Starting processing of Amazon settlement data into export invoice table...");
// check settlement reports consistancy
var consistencyCheck = new Data.Database.Consistency.ImportAmazonSettlement(sqlConnectionString).PeriodDateGaps();
- if (consistencyCheck == false )
+ if (consistencyCheck == false)
{ return; }
// get list of unprocssed settlement reports to export
@@ -65,38 +65,34 @@ namespace bnhtrade.Core.Logic.Export
}
// validate settlelments
- var validate = new Logic.Import.ValidateAmazonSettlement();
+ var validate = new Logic.Validate.AmazonSettlement();
for (int i = 0; i < settlementList.Count(); i++)
{
if (!validate.IsValid(settlementList[i]))
{
- log.LogError("Error procesing Amazon Settlement data for export.", validate.ErrorListToString());
+ log.LogError("Error procesing Amazon Settlement data for export.", validate.ValidationResultListToString());
}
}
- if (validate.ErrorListIsSet) { return; }
+ if (validate.IsValidResult == false) { return; }
// get dictionary of sku-number to taxcodeId
Console.Write("\rBuilding SKU list... ");
- var dicSkuNumberToTaxCodeId = new Dictionary();
- for (int i = 0; i < settlementList.Count(); i++)
+ var skuList = new List();
+ foreach (var settlement in settlementList)
{
- if (settlementList[i].SettlementLineListIsSet)
+ if (settlement.SettlementLineListIsSet)
{
- for (int j = 0; j < settlementList[i].SettlementLineList.Count(); j++)
+ foreach (var line in settlement.SettlementLineList)
{
- if (settlementList[i].SettlementLineList[j].SkuIsSet
- && !string.IsNullOrWhiteSpace(settlementList[i].SettlementLineList[j].Sku))
+ if (line.SkuIsSet
+ && !string.IsNullOrWhiteSpace(line.Sku))
{
- if (!dicSkuNumberToTaxCodeId.ContainsKey(settlementList[i].SettlementLineList[j].Sku))
- {
- dicSkuNumberToTaxCodeId.Add(settlementList[i].SettlementLineList[j].Sku, null);
- }
+ skuList.Add(line.Sku);
}
}
}
}
- var readTaxCode = new Data.Database.Account.ReadTaxCode(sqlConnectionString);
- taxCodeBySkuNumer = readTaxCode.BySkuNumber(dicSkuNumberToTaxCodeId.Keys.ToList());
+ var taxCodeBySkuNumer = new Logic.Account.GetTaxCodeInfo(sqlConnectionString).GetBySkuNumber(skuList);
// loop through each settlement and build list of invoices to export
Console.Write("\rBuilding invoices to export... ");
@@ -117,7 +113,7 @@ namespace bnhtrade.Core.Logic.Export
var itemCodeTotal = new Dictionary();
foreach (var line in month)
{
- string itemCode = BuildLineItemCode(line.Sku, line.TransactionType, line.AmountType, line.AmountDescription);
+ string itemCode = BuildLineItemCode(taxCodeBySkuNumer, line.Sku, line.TransactionType, line.AmountType, line.AmountDescription);
if (itemCodeTotal.ContainsKey(itemCode))
{
itemCodeTotal[itemCode] += line.Amount;
@@ -137,13 +133,12 @@ namespace bnhtrade.Core.Logic.Export
decimal lineTaxTotal = 0m;
foreach (var item in itemCodeTotal)
{
- var line = new Model.Account.SalesInvoice.InvoiceLine();
+ var line = new Model.Account.SalesInvoice.InvoiceLine(invoice.UnitAmountIsTaxExclusive);
line.ItemCode = item.Key;
- line.TotalNetAmount = item.Value;
- lineNetTotal += item.Value;
- line.TaxAmount = 0;
- lineTaxTotal += 0;
line.Quantity = 1;
+ line.UnitAmount = item.Value;
+ lineNetTotal += item.Value;
+ lineTaxTotal += 0;
invoice.InvoiceLineList.Add(line);
}
@@ -153,11 +148,10 @@ namespace bnhtrade.Core.Logic.Export
{ invoice.InvoiceDate = settlementList[i].EndDate; }
else
{ invoice.InvoiceDate = new DateTime(month.Key.Year, month.Key.Month, 1, 0, 0, 0, DateTimeKind.Utc).AddMonths(1).AddDays(-1); }
- invoice.InvoiceDateKind = DateTimeKind.Utc;
invoice.InvoiceDueDate = settlementList[i].DepositDate;
invoice.InvoiceReference = settlementList[i].SettlementId;
- invoice.InvoiceAmount = lineNetTotal + lineTaxTotal;
- if (invoice.InvoiceAmount < 0) { invoice.IsCreditNote = true; }
+ invoice.InvoiceTotalAmount = lineNetTotal + lineTaxTotal;
+ if (invoice.InvoiceTotalAmount < 0) { invoice.IsCreditNote = true; }
else { invoice.IsCreditNote = false; }
// invoice complete, add to list
@@ -174,11 +168,11 @@ namespace bnhtrade.Core.Logic.Export
{
if (invoiceTotal.ContainsKey(invoiceList[i].InvoiceReference))
{
- invoiceTotal[invoiceList[i].InvoiceReference] += invoiceList[i].InvoiceAmount;
+ invoiceTotal[invoiceList[i].InvoiceReference] += invoiceList[i].InvoiceTotalAmount.GetValueOrDefault();
}
else
{
- invoiceTotal.Add(invoiceList[i].InvoiceReference, invoiceList[i].InvoiceAmount);
+ invoiceTotal.Add(invoiceList[i].InvoiceReference, invoiceList[i].InvoiceTotalAmount.GetValueOrDefault());
}
}
for (int i = 0; i < settlementList.Count(); i++)
@@ -194,8 +188,65 @@ namespace bnhtrade.Core.Logic.Export
return;
}
- // postfix invoices spanning multiple months with -n
- if (invoiceList.Count() > 1)
+ // add invoice item code data to lines
+ // also clean invoices of any disabled lines (remove lines and possibly invoices)
+ var getLineItemInfo = new Logic.Account.GetInvoiceLineItem(sqlConnectionString);
+ getLineItemInfo.InsertNewOnNoMatch = true;
+ getLineItemInfo.CacheFill(lineItemCodeList);
+ bool newTypeFound = false;
+
+ for (int i = 0; i < invoiceList.Count(); i++)
+ {
+ for (int j = 0; j < invoiceList[i].InvoiceLineList.Count(); j++)
+ {
+ var itemCode = getLineItemInfo.ByItemCode(invoiceList[i].InvoiceLineList[j].ItemCode);
+ // error! itemCode should never be null
+ if (itemCode == null)
+ {
+ throw new Exception("Item code is null");
+ }
+ // flag new type and throw exception further on
+ else if (itemCode.IsNewReviewRequired)
+ {
+ newTypeFound = true;
+ }
+ // clean invoices of any disabled lines (remove lines and possibly invoices)
+ else if (itemCode.InvoiceLineEntryEnabled == false)
+ {
+ // remove line
+ invoiceList[i].InvoiceTotalAmount = invoiceList[i].InvoiceTotalAmount - invoiceList[i].InvoiceLineList[j].LineTotalAmount;
+ invoiceList[i].InvoiceLineList.RemoveAt(j);
+ j = j - 1;
+
+ // remove invoice?
+ if (invoiceList[i].InvoiceLineList.Count == 0)
+ {
+ invoiceList.RemoveAt(i);
+ i = i - 1;
+ }
+ }
+ // get here add info to lines
+ else
+ {
+ invoiceList[i].InvoiceLineList[j].AccountCode = itemCode.DefaultAccountCode;
+ invoiceList[i].InvoiceLineList[j].Description = itemCode.Name;
+ invoiceList[i].InvoiceLineList[j].ItemCode = itemCode.ItemCode;
+ invoiceList[i].InvoiceLineList[j].TaxCode = itemCode.DefaultTaxCode;
+ }
+ }
+ }
+
+ if (newTypeFound)
+ {
+ if (newTypeFound)
+ {
+ throw new Exception("New line ItemCode found. Add item code default values and then try again.");
+ }
+ return;
+ }
+
+ // postfix invoices references that span multiple months with -n
+ if (invoiceList.Count > 1)
{
string lastRef = invoiceList[0].InvoiceReference;
int countRef = 1;
@@ -215,7 +266,7 @@ namespace bnhtrade.Core.Logic.Export
if (countRef > 2)
{
log.LogError(
- countRef + " total numner of export invoices created from Amazon Settlement Id" + lastRef + "."
+ countRef + " invoices where created from Amazon Settlement Id" + lastRef + "."
, "Settlement period appears to span more 3 months or more. Whilst this is possible, it is unsual. Confirm his is correct.");
}
@@ -230,8 +281,12 @@ namespace bnhtrade.Core.Logic.Export
{
try
{
+ var saveInv = new Logic.Export.SalesInvoice(sqlConnectionString);
+ // add temp invoice numbers
+ saveInv.AddTempInvoiceNumber(invoiceList, true);
+
// write to the database (gets validated there)
- new Data.Database.Export.CreateSalesInvoice(sqlConnectionString).SaveInvoice(invoiceList);
+ saveInv.SaveSalesInvoice(invoiceList);
// set settlements to isprocessed
new Data.Database.Import.UpdateAmazonSettlement(sqlConnectionString).SetIsProcessedTrue(settlementIdList);
@@ -241,15 +296,16 @@ namespace bnhtrade.Core.Logic.Export
catch (Exception ex)
{
scope.Dispose();
- log.LogError(ex.Message);
+ log.LogError("Exeception caught while writing Amazon settlement invoices to DB. Changes were rolled back."
+ , ex.Message);
return;
}
}
Console.Write("\r");
- log.LogInformation("\rFinished processing of Amazon settlement data. " + invoiceList.Count() + " invoices created from "+ settlementIdList.Count() + " Amazon settlement reports.");
+ log.LogInformation("\rFinished processing of Amazon settlement data. " + invoiceList.Count() + " invoices created from " + settlementIdList.Count() + " Amazon settlement reports.");
}
- private string BuildLineItemCode(string skuNumber, string transactionType, string amountType, string amountDescription)
+ private string BuildLineItemCode(Dictionary taxCodeBySkuNumer, string skuNumber, string transactionType, string amountType, string amountDescription)
{
// build the match string
// NB special case for global accounting sale and refunds (also note Goodlwill is included) and sku's where tax is included
@@ -264,13 +320,18 @@ namespace bnhtrade.Core.Logic.Export
{
if (taxCodeBySkuNumer.ContainsKey(skuNumber))
{
- matchString = matchString + "";
+ matchString = matchString + "";
}
else
{
throw new Exception("Sku#" + skuNumber + " tax info not found in dictionary list.");
}
}
+
+ // add to list of generated line item codes
+ lineItemCodeList.Add(matchString);
+
+ // return value
return matchString;
}
}
diff --git a/src/bnhtrade.Core/Logic/Export/AmazonSubmitFile.cs b/src/bnhtrade.Core/Logic/Export/AmazonSubmitFile.cs
new file mode 100644
index 0000000..70ba709
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Export/AmazonSubmitFile.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+using System.Transactions;
+
+namespace bnhtrade.Core.Logic.Export
+{
+ public class AmazonSubmitFile
+ {
+ private string sqlConnectionString;
+ private Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck();
+ private Log.LogEvent log = new Log.LogEvent();
+
+ public AmazonSubmitFile(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ }
+
+ public void SubmitInventoryLoader(MemoryStream stream)
+ {
+ Model.Export.AmazonFeedSubmission result;
+ int queueId = QueueInventoryLoader(stream, out result);
+ SubmitQueuedFeedSubmission(queueId, result);
+ }
+
+ public void SubmitInventoryLoader(MemoryStream stream, out Model.Export.AmazonFeedSubmission result)
+ {
+ int queueId = QueueInventoryLoader(stream, out result);
+ SubmitQueuedFeedSubmission(queueId, result);
+ }
+
+ public int QueueInventoryLoader(MemoryStream stream)
+ {
+ Model.Export.AmazonFeedSubmission result;
+ return QueueFeedSubbmission("_POST_FLAT_FILE_INVLOADER_DATA_", "txt", stream, out result);
+ }
+
+ public int QueueInventoryLoader(MemoryStream stream, out Model.Export.AmazonFeedSubmission result)
+ {
+ // write file database
+ return QueueFeedSubbmission("_POST_FLAT_FILE_INVLOADER_DATA_", "txt", stream, out result);
+ }
+
+ private int QueueFeedSubbmission(string feedType, string fileExtention, MemoryStream stream, out Model.Export.AmazonFeedSubmission result)
+ {
+ // construct file object
+ var fileInfo = new Model.Data.DatabaseFileStream();
+ fileInfo.FileExtention = fileExtention;
+ fileInfo.FileData = stream;
+ fileInfo.FileMD5base64 = new Logic.Utilities.CalculateMD5().Base64(stream);
+
+ long longSize = stream.Length;
+ if (longSize > 2147483647)
+ throw new Exception("File size over 2.15 GB");
+ fileInfo.FileSize = (int)longSize;
+
+ // save to database
+ int queueId = 0;
+ using (var scope = new TransactionScope())
+ {
+ queueId = new Data.Database.Export.CreateAmazonFeedSubmission(sqlConnectionString).Execute(feedType, fileInfo);
+
+ // validate the result
+ var validateResults = new List();
+
+ bool isValid = Validator.TryValidateObject(
+ fileInfo,
+ new ValidationContext(fileInfo, null, null),
+ validateResults);
+
+ if (isValid == false)
+ {
+ string error = "Create Database Amazon Feed Submission cancelled. Object validation failed.";
+ new Log.LogEvent().LogError(error, string.Join(Environment.NewLine, validateResults));
+ scope.Dispose();
+ throw new Exception(error);
+ }
+ scope.Complete();
+ }
+
+ // create feed object
+ result = new Model.Export.AmazonFeedSubmission();
+ result.FeedType = feedType;
+ result.File = fileInfo;
+
+ return queueId;
+ }
+
+ // private, only to be used where you're sure feedSubmission matches DB and you don't want to call info from DB (large file)
+ private void SubmitQueuedFeedSubmission(int queueId, Model.Export.AmazonFeedSubmission feedSubmission)
+ {
+ // upload to mws
+ var feedSubmitt = new Data.AmazonMWS.Feeds.SubmitFeed(feedSubmission);
+
+ if (!feedSubmitt.FeedSubmissionRecived)
+ {
+ // failed do something here
+ throw new NotImplementedException();
+ }
+
+ // set the amazon feed Id
+ var dbUpdate = new Data.Database.Export.UpdateAmazonFeedSubmission(sqlConnectionString);
+ dbUpdate.AddAmazonFeedId(queueId, feedSubmission.FeedSubmissionId);
+
+ // update progress info
+ dbUpdate.UpdateStatusInfo(feedSubmission);
+ }
+
+ private void SubmitQueuedFeedSubmission(int queueId)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void SubmitQueuedFeedSubmission()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Export/AmazonSubmitFileStatus.cs b/src/bnhtrade.Core/Logic/Export/AmazonSubmitFileStatus.cs
new file mode 100644
index 0000000..b2ac14c
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Export/AmazonSubmitFileStatus.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Export
+{
+ public class AmazonSubmitFileStatus
+ {
+ private string sqlConnectionString;
+ private bnhtrade.Core.Logic.Log.LogEvent log = new Log.LogEvent();
+
+ public AmazonSubmitFileStatus(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ }
+
+ public void UpdateStatusInfo()
+ {
+ var openList = new Data.Database.Export.ReadAmazonFeedSubmission(sqlConnectionString).GetOpenFeeds();
+ if (openList.Count == 0)
+ return;
+
+ var getStatus = new Data.AmazonMWS.Feeds.GetFeedSubmissions();
+ getStatus.FeedSubmissionIdList = openList.Select(x => x.FeedSubmissionId).ToList();
+ var currentStatus = getStatus.Invoke();
+
+ for (int i = 0; i < openList.Count; i++)
+ {
+ bool found = false;
+ for (int j = 0; j < currentStatus.Count; j++)
+ {
+ if (openList[i].FeedSubmissionId == currentStatus[j].FeedSubmissionId)
+ {
+ found = true;
+
+ openList[i].FeedProcessingStatus = currentStatus[j].FeedProcessingStatus;
+ if (currentStatus[j].IsSetCompletedProcessingDate())
+ openList[i].CompletedProcessingDate = currentStatus[j].CompletedProcessingDate;
+ if (currentStatus[j].IsSetStartedProcessingDate())
+ openList[i].StartedProcessingDate = currentStatus[j].StartedProcessingDate;
+ if (currentStatus[j].IsSetSubmittedDate())
+ openList[i].SubmittedDate = DateTime.Parse(currentStatus[j].SubmittedDate);
+ }
+ }
+ if (found == false)
+ {
+ log.LogError("FeedSubmissionId '" + openList[i].FeedSubmissionId + "' exists in database but was not returned by Amazon MWS when queried.");
+ openList.RemoveAt(i);
+ i = i - 1;
+ }
+ }
+
+ // update the database
+ new Data.Database.Export.UpdateAmazonFeedSubmission(sqlConnectionString).UpdateStatusInfo(openList);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Export/SalesInvoice.cs b/src/bnhtrade.Core/Logic/Export/SalesInvoice.cs
new file mode 100644
index 0000000..8ade92b
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Export/SalesInvoice.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Export
+{
+ public class SalesInvoice
+ {
+ private string sqlConnectionString;
+ private Logic.Log.LogEvent log = new Log.LogEvent();
+
+ public SalesInvoice(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ }
+
+ public string GetNextTempInvoiceNumber()
+ {
+ var sequence = new Data.Database.Programmability.Sequence(sqlConnectionString);
+ return "_tmp" + sequence.GetNext("ExportTempInvoiceNumber").ToString("00000000");
+ }
+
+ public void AddTempInvoiceNumber(IEnumerable invoiceList, bool overwriteExisting)
+ {
+ for (int i = 0; i < invoiceList.Count(); i++)
+ {
+ if (invoiceList.ElementAt(i).InvoiceNumber != null && overwriteExisting == false)
+ {
+ continue;
+ }
+ invoiceList.ElementAt(i).InvoiceNumber = GetNextTempInvoiceNumber();
+ }
+ }
+
+ public void SaveSalesInvoice(List invoiceList)
+ {
+ // validate the list of invoices
+ var validateInvoice = new Logic.Validate.SalesInvoice();
+ validateInvoice.IsValidExportInvoice(invoiceList);
+ if (validateInvoice.IsValidResult == false)
+ {
+ log.LogError("Invalid Sales invoice(s) found. See extended info.", validateInvoice.ValidationResultListToString());
+ return;
+ }
+ validateInvoice = null;
+
+ // save to database
+ new Data.Database.Export.CreateSalesInvoice(sqlConnectionString).Execute(invoiceList);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/bnhtrade.Core/Logic/Export/ValidateSalesInvoice.cs b/src/bnhtrade.Core/Logic/Export/ValidateSalesInvoice.cs
deleted file mode 100644
index f07e20b..0000000
--- a/src/bnhtrade.Core/Logic/Export/ValidateSalesInvoice.cs
+++ /dev/null
@@ -1,134 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bnhtrade.Core.Logic.Export
-{
- class ValidateSalesInvoice : Logic.Account.ValidateInvoice
- {
- //public bool IsValidInvoice(Model.Export.SetSalesInvoice invoice)
- //{
- // ErrorMessage = null;
-
- // var baseInvoice = CopyInvoiceToBase(invoice);
- // if (!base.IsValidInvoice(baseInvoice))
- // {
- // return false;
- // }
-
- // // check each match string only appears once
- // var dicLookup = new Dictionary();
- // foreach (var line in invoice.InvoiceLineList)
- // {
- // if (dicLookup.ContainsKey(line.LineTypeMatchString))
- // {
- // ErrorMessage = "'Line type match string' duplication.";
- // return false;
- // }
- // else
- // {
- // dicLookup.Add(line.LineTypeMatchString, null);
- // }
- // }
-
- // return true;
- //}
- //public bool IsValidInvoiceHeader(Model.Export.SetSalesInvoice invoice)
- //{
- // ErrorMessage = null;
-
- // var baseInvoice = CopyInvoiceHeaderToBase(invoice);
- // if (base.IsValidInvoiceHeader(baseInvoice))
- // {
- // return true;
- // }
- // else
- // {
- // return false;
- // }
- //}
- //public bool IsValidInvoiceLine(Model.Export.SetSalesInvoiceLine invoiceLine)
- //{
- // ErrorMessage = null;
-
- // var baseLine = CopyInvoiceLineToBase(invoiceLine);
- // if (!IsValidLineTypeMatchString(invoiceLine.LineTypeMatchString)
- // || !base.IsValidInvoiceLine(baseLine))
- // {
- // return false;
- // }
-
- // return true;
- //}
- //public bool IsValidLineTypeMatchString(string matchString)
- //{
- // ErrorMessage = null;
- // var stringCheck = new Logic.Utilities.StringCheck();
- // if (!stringCheck.MaxLength(matchString, 250))
- // {
- // ErrorMessage = "Invalid Line Type Match String: " + stringCheck.ErrorMessage;
- // return false;
- // }
- // return true;
- //}
- //private Model.Account.SalesInvoice CopyInvoiceToBase(Model.Export.SetSalesInvoice invoice)
- //{
- // var baseInvoice = CopyInvoiceHeaderToBase(invoice);
- // if (invoice.IsSetInvoiceLineList)
- // {
- // var baseLineList = new List();
- // foreach (var line in invoice.InvoiceLineList)
- // {
- // baseLineList.Add(CopyInvoiceLineToBase(line));
- // }
- // baseInvoice.InvoiceLineList = baseLineList;
- // }
- // return baseInvoice;
- //}
-
- //private Model.Account.SalesInvoice CopyInvoiceHeaderToBase(Model.Export.SetSalesInvoice invoice)
- //{
- // var baseInvoice = new Model.Account.SalesInvoice();
-
- // if (invoice.IsSetContactName)
- // { baseInvoice.ContactName = invoice.ContactName; }
- // if (invoice.IsSetInvoiceAmount)
- // { baseInvoice.InvoiceAmount = invoice.InvoiceAmount; }
- // if (invoice.IsSetInvoiceCurrencyCode)
- // { baseInvoice.InvoiceCurrencyCode = invoice.InvoiceCurrencyCode; }
- // if (invoice.IsSetInvoiceDate)
- // { baseInvoice.InvoiceDate = invoice.InvoiceDate; }
- // if (invoice.IsSetInvoiceNumber)
- // { baseInvoice.InvoiceNumber = invoice.InvoiceNumber; }
- // if (invoice.IsSetInvoiceReference)
- // { baseInvoice.InvoiceReference = invoice.InvoiceReference; }
- // if (invoice.IsSetIsComplete)
- // { baseInvoice.IsComplete = invoice.IsComplete; }
-
- // return baseInvoice;
- //}
- //private Model.Account.SalesInvoiceLine CopyInvoiceLineToBase(Model.Export.SetSalesInvoiceLine invoiceLine)
- //{
- // var baseLine = new Model.Account.SalesInvoiceLine();
-
- // if (invoiceLine.IsSetAccountCode)
- // { baseLine.AccountCode = invoiceLine.AccountCode; }
-
- // // something missing here ??????
-
- // if (invoiceLine.IsSetDescription)
- // { baseLine.Description = invoiceLine.Description; }
- // if (invoiceLine.IsSetNetAmount)
- // { baseLine.TotalNetAmount = invoiceLine.NetAmount; }
-
- // // tax adjustment to set ??????????
-
- // if (invoiceLine.IsSetTaxCode)
- // { baseLine.TaxCode = invoiceLine.TaxCode; }
-
- // return baseLine;
- //}
- }
-}
diff --git a/src/bnhtrade.Core/Logic/Product/GetCompetitivePrice.cs b/src/bnhtrade.Core/Logic/Product/GetCompetitivePrice.cs
new file mode 100644
index 0000000..4733759
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Product/GetCompetitivePrice.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Product
+{
+ public class GetCompetitivePrice
+ {
+ private Dictionary competitivePrices;
+ private int newConditionId = Data.Database.Constants.GetProductConditionIdNew();
+ private string sqlConnectionString;
+ private Data.Database.Product.ReadCompetitivePrice read;
+ private List productIdList;
+ private List conditionIdList;
+ private Data.Database.Product.ReadCompetitivePrice dbRead;
+ private Dictionary newConditionMultipier;
+
+ public GetCompetitivePrice(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ dbRead = new Data.Database.Product.ReadCompetitivePrice(sqlConnectionString);
+ newConditionMultipier = new Dictionary();
+ }
+
+ ///
+ /// If a competitive price for a used condition is not found, return an estimated figure.
+ ///
+ public bool EstimatePrice { get; set; } = false;
+
+ public int DistinctRequestCount { get; private set; } = 0;
+
+ public int DistinctResponceCount { get; private set; } = 0;
+
+ public void Innit()
+ {
+ DistinctRequestCount = 0;
+ DistinctResponceCount = 0;
+ }
+
+ public Dictionary Execute(List skuParamList)
+ {
+ var requestList = new List<(int ProductId, int ConditionId)>();
+ for (int i = 0; i < skuParamList.Count; i++)
+ {
+ requestList.Add((skuParamList[i].ProductId, skuParamList[i].ConditionId));
+ }
+ var result = Execute(requestList);
+
+ // build return list
+ var returnList = new Dictionary();
+ for (int i = 0; i < skuParamList.Count; i++)
+ {
+ // skip?
+ if (returnList.ContainsKey(skuParamList[i].SkuNumber))
+ {
+ continue;
+ }
+ // make a match
+ for (int j = 0; j < result.Count; j++)
+ {
+ if (skuParamList[i].ProductId == result[j].ProductId && skuParamList[i].ConditionId == result[j].ConditionId)
+ {
+ returnList.Add(skuParamList[i].SkuNumber, result[j].Clone());
+ break;
+ }
+ }
+ }
+ return returnList;
+ }
+
+ public List Execute(List<(int ProductId, int ConditionId)> requestList)
+ {
+ Innit();
+
+ var result = new List();
+
+ if (requestList == null || !requestList.Any())
+ {
+ return result;
+ }
+
+ // build distinct list
+ var distinctRequestList = new List<(int productId, int conditionId)>();
+ for (int i = 0; i < requestList.Count; i++)
+ {
+ // filter values already requested
+ bool distinct = true;
+ for (int j = 0; j < distinctRequestList.Count; j++)
+ {
+ if (requestList[i].ProductId == distinctRequestList[j].productId
+ && requestList[i].ConditionId == distinctRequestList[j].conditionId)
+ {
+ distinct = false;
+ break;
+ }
+ }
+ if (distinct)
+ { distinctRequestList.Add((requestList[i].ProductId, requestList[i].ConditionId)); }
+ }
+
+ DistinctRequestCount = distinctRequestList.Count();
+ var dbResult = dbRead.Execute(distinctRequestList);
+
+ // only contiue if estimated values are retured
+ if (DistinctRequestCount == dbResult.Count || !EstimatePrice)
+ {
+ DistinctResponceCount = dbResult.Count;
+ return result;
+ }
+
+ // build estimated list
+ var estimatedRequestList = new List<(int productId, int conditionId)>();
+ //var conditionMultipier = new Dictionary();
+ for (int i = 0; i < distinctRequestList.Count; i++)
+ {
+ bool request = true;
+ // check if db returned record
+ for (int j = 0; j < dbResult.Count; j++)
+ {
+ if (distinctRequestList[i].productId == dbResult[j].ProductId
+ && distinctRequestList[i].conditionId == dbResult[j].ConditionId)
+ {
+ request = false;
+ break;
+ }
+ }
+ // check if 'new' condition price has already been retrived
+ if (request)
+ {
+ for (int j = 0; j < dbResult.Count; j++)
+ {
+ if (distinctRequestList[i].productId == dbResult[j].ProductId
+ && dbResult[j].ConditionId == newConditionId)
+ {
+ request = false;
+ break;
+ }
+ }
+ }
+ // add to request lists
+ if (request)
+ {
+ estimatedRequestList.Add((distinctRequestList[i].productId, newConditionId));
+ if (!newConditionMultipier.ContainsKey(distinctRequestList[i].conditionId))
+ {
+ newConditionMultipier.Add(distinctRequestList[i].conditionId, -1);
+ }
+ }
+ }
+
+ dbResult.AddRange(dbRead.Execute(estimatedRequestList));
+ UpdateConditionMultipers();
+
+ // build a new return list
+ var newResult = new List();
+ var noMatchList = new List<(int productId, int conditionId)>();
+ for (int i = 0; i < distinctRequestList.Count; i++)
+ {
+ // add exact matches
+ bool noMatch = true;
+ for (int j = 0; j < dbResult.Count; j++)
+ {
+ if (distinctRequestList[i].productId == dbResult[j].ProductId
+ && distinctRequestList[i].conditionId == dbResult[j].ConditionId)
+ {
+ noMatch = false;
+ newResult.Add(dbResult[j]);
+ break;
+ }
+ }
+ // add estimated matches
+ if (noMatch)
+ {
+ for (int j = 0; j < dbResult.Count; j++)
+ {
+ if (distinctRequestList[i].productId == dbResult[j].ProductId
+ && dbResult[j].ConditionId == newConditionId)
+ {
+ if (!newConditionMultipier.ContainsKey(distinctRequestList[i].conditionId))
+ {
+ break;
+ }
+
+ var clone = dbResult[j].Clone();
+ clone.ConditionId = distinctRequestList[i].conditionId;
+ clone.Price = decimal.Round(clone.Price * newConditionMultipier[distinctRequestList[i].conditionId], 2);
+ clone.PriceIsEstimated = true;
+
+ newResult.Add(clone);
+ noMatch = false;
+ break;
+ }
+ }
+ }
+ if (noMatch)
+ {
+ noMatchList.Add(distinctRequestList[i]);
+ }
+ }
+
+ DistinctResponceCount = newResult.Count;
+ return newResult;
+ }
+
+ public Model.Product.CompetitivePrice Execute(int productId, int conditionId)
+ {
+ Innit();
+ DistinctRequestCount = 1;
+ var result = dbRead.Execute(new List<(int, int)> { (productId, conditionId) });
+
+ if (!result.Any())
+ {
+ DistinctResponceCount = 0;
+ return null;
+ }
+ else
+ {
+ DistinctResponceCount = 1;
+ return result.First();
+ }
+ }
+
+ private void UpdateConditionMultipers()
+ {
+ var conditionInfo = new List();
+
+ if (newConditionMultipier.Any())
+ {
+ conditionInfo = new Logic.Sku.GetSkuConditionInfo(sqlConnectionString)
+ .GetByConditionId(newConditionMultipier.Keys.ToList());
+ }
+ else
+ {
+ conditionInfo = new Logic.Sku.GetSkuConditionInfo(sqlConnectionString).GetAll();
+ }
+
+ for(int i = 0; i < conditionInfo.Count; i++)
+ {
+ if (newConditionMultipier.ContainsKey(conditionInfo[i].SkuConditionId))
+ {
+ newConditionMultipier[conditionInfo[i].SkuConditionId] = conditionInfo[i].CompetitivePriceMultiplier;
+ }
+ else
+ {
+ throw new Exception("Condition Id mismatch");
+ }
+ }
+
+ // check all multipilers have been set
+ for (int i = 0; i < newConditionMultipier.Count; i++)
+ {
+ if (newConditionMultipier.ElementAt(i).Value <= 0)
+ {
+ throw new Exception("Invalid price multiplier");
+ }
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Sku/GetSkuConditionInfo.cs b/src/bnhtrade.Core/Logic/Sku/GetSkuConditionInfo.cs
new file mode 100644
index 0000000..c4142ee
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Sku/GetSkuConditionInfo.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Sku
+{
+ public class GetSkuConditionInfo
+ {
+ private string sqlConnectionString;
+ private Data.Database.Sku.ReadSkuConditionInfo dbRead;
+
+ public GetSkuConditionInfo(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ dbRead = new Data.Database.Sku.ReadSkuConditionInfo(sqlConnectionString);
+ }
+
+ public List GetAll()
+ {
+ return dbRead.Read(new List());
+ }
+
+ public List GetByConditionId(List conditionIdList)
+ {
+ return dbRead.Read(conditionIdList);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Sku/Price/FbaPricing.cs b/src/bnhtrade.Core/Logic/Sku/Price/FbaPricing.cs
new file mode 100644
index 0000000..3dc41ce
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Sku/Price/FbaPricing.cs
@@ -0,0 +1,386 @@
+using CsvHelper;
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Transactions;
+
+namespace bnhtrade.Core.Logic.Sku.Price
+{
+ public class FbaPricing
+ {
+ private string sqlConnectionString;
+ private bnhtrade.Core.Logic.Log.LogEvent log = new Log.LogEvent();
+ string err = "FbaPricing Error: ";
+ private string marginSchemeTaxCode = "T190";
+ int repriceHoldOnSalePeriod = 14; // days
+ private int newConditionId = Data.Database.Constants.GetProductConditionIdNew();
+ private List skuInfo;
+ private Dictionary competitivePrices;
+ DateTime crTimeStamp = DateTime.UtcNow;
+ private int repriceIncrementDivisor = 60;
+ private Dictionary saleCountInPeriod = new Dictionary();
+ private Logic.Account.TaxCalculation taxCalc;
+ private decimal marginSchemeMargin;
+
+ public FbaPricing(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ taxCalc = new Account.TaxCalculation();
+ crTimeStamp = DateTime.UtcNow;
+ marginSchemeMargin = taxCalc.GetMarginMultiplier(crTimeStamp);
+ }
+
+ public void Update(bool overrideDayCheck = false)
+ {
+ using (var scope = new TransactionScope())
+ {
+ string orderChannel = "Amazon.co.uk"; // may in future enable other order channels
+
+ // need to add some cheks up here for last stock reconcilliation
+
+
+
+
+
+
+ // get current sku base pricing details (stock quantity, competative price, VAT info, etc.)
+ skuInfo = new Data.Database.Sku.Price.ReadParameter(sqlConnectionString).Execute();
+ if (skuInfo == null || !skuInfo.Any())
+ {
+ throw new Exception("Querying the database returned no records.");
+ }
+
+ // create lists that we'll add to during lopp
+ var loader = new List();
+ var crDictionary = new Dictionary();
+
+ // open needed classes
+ var readAge = new Data.Database.Import.ReadFbaInventoryAge(sqlConnectionString);
+
+ // get current db pricing
+ var dbDictionary = new Data.Database.Sku.Price.ReadPricingDetail(sqlConnectionString).ReadDictionary(skuInfo.Select(o => o.SkuNumber).ToList(), orderChannel);
+
+ // get required competivie prices
+ var readComp = new Logic.Product.GetCompetitivePrice(sqlConnectionString);
+ readComp.EstimatePrice = true;
+ var compPrices = readComp.Execute(skuInfo);
+
+ // loop through skus returnd from stock query
+ for (int i = 0; i < skuInfo.Count(); i++)
+ {
+ string skuNumber = skuInfo[i].SkuNumber;
+
+ var cr = new Model.Sku.Price.PriceInfo();
+
+ if (!overrideDayCheck && dbDictionary.Count > 0 && !OkayToReprice(dbDictionary[skuNumber].PriceInfoTimeStamp))
+ { continue; }
+
+ // load in values from skuInfo
+ cr.PriceTypeId = 1;
+ cr.ReviewRequired = false;
+ cr.OrderChannel = orderChannel;
+ cr.OrderChannelQuantity = skuInfo[i].TotalQuantity;
+ cr.PriceInfoTimeStamp = crTimeStamp;
+ cr.SkuNumber = skuInfo[i].SkuNumber;
+
+ // get inventory age range
+ var invAge = readAge.BySkuNumber(skuInfo[i].SkuNumber, orderChannel);
+ if (invAge == null)
+ {
+ // this means lost stock, or unreconciled inventory... need to pause these skus else the price could decrease without it being on sale
+ err += "No records returned from tblImportFbaInventoryAgeReport for skuID=" + skuInfo[i].SkuId;
+ log.LogError(err);
+ throw new Exception(err);
+ }
+ cr.InventoryAgeMin = invAge.Value.MinAge;
+ cr.InventoryAgeMax = invAge.Value.MaxAge;
+
+ // get minimum prices
+ cr.UnitMinPriceCost = GetMinPriceCost(i);
+ cr.UnitMinPriceProfit = GetMinPriceProfit(i);
+ cr.UnitPurchaseCost = skuInfo[i].UnitCostAverage;
+
+ // set competitive price
+ if (compPrices.ContainsKey(skuInfo[i].SkuNumber))
+ {
+ cr.CompetitivePrice = compPrices[skuInfo[i].SkuNumber].Price;
+ cr.CompetitivePriceIsEstimated = compPrices[skuInfo[i].SkuNumber].PriceIsEstimated;
+ }
+ else
+ {
+ cr.CompetitivePrice = cr.UnitMinPriceProfit + (cr.UnitMinPriceProfit / 2);
+ cr.CompetitivePriceIsEstimated = true;
+ }
+
+ // set min max price
+ cr.RepriceIncrement = cr.CompetitivePrice / repriceIncrementDivisor;
+
+ if (dbDictionary.ContainsKey(skuNumber))
+ {
+ // sales wihtin period, therefore hold price
+ if (GetSaleCountInPeriod(i) > 0)
+ {
+ cr.MaxPrice = dbDictionary[skuNumber].MaxPrice;
+ cr.MinPrice = dbDictionary[skuNumber].MinPrice;
+ cr.RepriceIncrement = dbDictionary[skuNumber].RepriceIncrement;
+ }
+ // else reduce
+ else
+ {
+ if (dbDictionary[skuNumber].MaxPrice < dbDictionary[skuNumber].MinPrice)
+ {
+ err += "Max price lower than min price";
+ log.LogError(err);
+ throw new Exception(err);
+ }
+ // redue both prices together
+ else if (dbDictionary[skuNumber].MaxPrice == dbDictionary[skuNumber].MinPrice)
+ {
+ cr.MaxPrice = dbDictionary[skuNumber].MaxPrice - cr.RepriceIncrement;
+ cr.MinPrice = cr.MaxPrice;
+ }
+ // reduce only max until it hits the min
+ else
+ {
+ cr.MaxPrice = dbDictionary[skuNumber].MaxPrice - cr.RepriceIncrement;
+ if (cr.MaxPrice < dbDictionary[skuNumber].MinPrice)
+ {
+ cr.MinPrice = cr.MaxPrice;
+ }
+ else
+ {
+ cr.MinPrice = dbDictionary[skuNumber].MinPrice;
+ }
+ }
+ }
+ }
+ else
+ {
+ // new value
+ cr.MaxPrice = cr.CompetitivePrice * 1.2m;
+ cr.MinPrice = cr.CompetitivePrice * 1m;
+ }
+
+ // check on min price
+ cr.UnitMinPriceDestory = GetMinPriceDestroy(i);
+ if (cr.MaxPrice < cr.UnitMinPriceDestory) { cr.MaxPrice = cr.UnitMinPriceDestory; }
+ if (cr.MinPrice < cr.UnitMinPriceDestory) { cr.MinPrice = cr.UnitMinPriceDestory; }
+
+ // add values to inventory loader list
+ var item = new Model.Export.AmazonIventoryLoaderFile();
+ item.Sku = skuInfo[i].SkuNumber;
+ item.Price = cr.MaxPrice;
+ item.MinimumAllowedPrice = cr.MinPrice;
+ item.MaximumAllowedPrice = cr.MaxPrice;
+ item.SetFulfillmentCenterId(true);
+ loader.Add(item);
+
+ // save current prices to dictionary
+ if (crDictionary.ContainsKey(skuNumber))
+ {
+ err += "Multiple SkuId found in data";
+ log.LogError(err);
+ throw new Exception(err);
+ }
+ crDictionary.Add(skuNumber, cr);
+ }
+ // finish loop
+
+ // validate and save values to database
+ var validate = new Core.Logic.Validate.SkuPriceInfo();
+ if (!validate.IsValidDatabaseCreate(crDictionary.Values.ToList()))
+ {
+ err += "Database object create validation failed";
+ log.LogError(err, validate.ValidationResultListToString());
+ throw new Exception(err);
+ }
+
+ new Data.Database.Sku.Price.CreatePricingDetail(sqlConnectionString).Executue(crDictionary.Values.ToList());
+
+ // create and upload inventory loader file to amazon
+ var exportList = new List();
+ foreach (var item in crDictionary.Values)
+ {
+ var listItem = new Model.Export.AmazonIventoryLoaderFile();
+ listItem.Sku = item.SkuNumber;
+ listItem.MinimumAllowedPrice = item.MinPrice;
+ listItem.MaximumAllowedPrice = item.MaxPrice;
+ listItem.Price = item.MaxPrice;
+ listItem.SetFulfillmentCenterId(true);
+ exportList.Add(listItem);
+ }
+
+ // validate
+ var vaildateInvLoader = new Validate.AmazonIventoryLoaderFile();
+ if (!vaildateInvLoader.IsValidFbaPricing(exportList))
+ {
+ err += "Inventory loader object validation failed";
+ log.LogError(err, vaildateInvLoader.ValidationResultListToString());
+ throw new Exception(err);
+ }
+
+ // create file stream
+ var config = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.CurrentCulture);
+ config.Delimiter = "\t";
+ config.Encoding = Encoding.UTF8;
+
+ var stream = new MemoryStream();
+ using (var writer = new StreamWriter(stream, Encoding.UTF8))
+ using (var csv = new CsvWriter(writer, config))
+ {
+ csv.WriteRecords(exportList);
+ }
+
+ // submit file to database and amazon mws
+ var submit = new Logic.Export.AmazonSubmitFile(sqlConnectionString);
+
+ return;
+
+ submit.SubmitInventoryLoader(stream);
+
+ scope.Complete();
+ }
+ }
+
+ private bool OkayToReprice(DateTime lastPriceUpdate)
+ {
+ if (lastPriceUpdate == default(DateTime))
+ {
+ err += "Invalid, datetime is default.";
+ log.LogError(err);
+ throw new Exception(err);
+ }
+
+ bool update = false;
+ lastPriceUpdate = new DateTime(lastPriceUpdate.Year, lastPriceUpdate.Month, lastPriceUpdate.Day);
+ DateTime today = new DateTime(crTimeStamp.Year, crTimeStamp.Month, crTimeStamp.Day);
+
+ // will only update once on tue, wed or thurs each week.
+ if (today.DayOfWeek == DayOfWeek.Tuesday || today.DayOfWeek == DayOfWeek.Wednesday || today.DayOfWeek == DayOfWeek.Thursday)
+ {
+ if (today > lastPriceUpdate.AddDays(3))
+ {
+ update = true;
+ }
+ }
+
+ return update;
+ }
+
+ ///
+ /// Get the minimum sale price to break even.
+ ///
+ ///
+ ///
+ private decimal GetMinPriceCost(int i)
+ {
+ decimal costPrice = skuInfo[i].UnitCostAverage;
+ decimal agentFeeFixed = skuInfo[i].AgentFeeFixed;
+ decimal agentFeeMargin = skuInfo[i].AgentFeeMargin;
+ decimal vatMargin = skuInfo[i].VatMargin;
+
+ decimal price = 0;
+
+ if (skuInfo[i].TaxCode == marginSchemeTaxCode)
+ {
+ price = (costPrice + agentFeeFixed - (costPrice * marginSchemeMargin))
+ / (1 - agentFeeMargin - marginSchemeMargin);
+ }
+ else
+ {
+ price = (costPrice + agentFeeFixed)
+ / (1 - agentFeeMargin - vatMargin);
+ }
+ price = decimal.Round(price, 2);
+ return price;
+ }
+
+ ///
+ /// Get the minimum sale price to achieve required profit margin.
+ ///
+ ///
+ /// Minimum price in decimal
+ private decimal GetMinPriceProfit(int i)
+ {
+ decimal costPrice = skuInfo[i].UnitCostAverage;
+ decimal minProfit = skuInfo[i].PriceMinProfit;
+ decimal profitMargin = skuInfo[i].ProfitMargin;
+ decimal agentFeeFixed = skuInfo[i].AgentFeeFixed;
+ decimal agentFeeMargin = skuInfo[i].AgentFeeMargin;
+ decimal vatMargin = skuInfo[i].VatMargin;
+
+ decimal price = 0;
+
+ if (skuInfo[i].TaxCode == marginSchemeTaxCode) // taxcodeinfo now has ismarginscheme boolean
+ {
+ price = (costPrice + agentFeeFixed - (costPrice * marginSchemeMargin))
+ / (1 - profitMargin - agentFeeMargin - marginSchemeMargin);
+ }
+ else
+ {
+ price = (costPrice + agentFeeFixed)
+ / (1 - profitMargin - agentFeeMargin - vatMargin);
+ }
+ price = decimal.Round(price, 2);
+
+ // if profit margin is less than min required, redo using min value (not percent)
+ if (price < minProfit)
+ {
+ if (skuInfo[i].TaxCode == marginSchemeTaxCode)
+ {
+ price = (minProfit + costPrice + agentFeeFixed - (costPrice * marginSchemeMargin))
+ / (1 - agentFeeMargin - marginSchemeMargin);
+ }
+ else
+ {
+ price = (minProfit + costPrice + agentFeeFixed)
+ / (1 - agentFeeMargin - vatMargin);
+ }
+ }
+ price = decimal.Round(price, 2);
+ return price;
+ }
+
+ private decimal GetMinPriceDestroy(int i)
+ {
+ decimal agentFeeFixed = skuInfo[i].AgentFeeFixed;
+ decimal agentFeeMargin = skuInfo[i].AgentFeeMargin;
+ decimal vatMargin = skuInfo[i].VatMargin;
+
+ decimal price = 0;
+
+ if (skuInfo[i].TaxCode == marginSchemeTaxCode)
+ {
+ price = (agentFeeFixed) / (1 - agentFeeMargin);
+ }
+ else
+ {
+ price = (agentFeeFixed) / (1 - agentFeeMargin - vatMargin);
+ }
+ price = decimal.Round(price, 2);
+ return price;
+ }
+
+ private int GetSaleCountInPeriod(int i)
+ {
+ if (!saleCountInPeriod.Any())
+ {
+ saleCountInPeriod = new Data.Database.Import.ReadFbaSaleShipment(sqlConnectionString)
+ .GetSaleCount(skuInfo.Select(x => x.SkuNumber).ToList(), DateTime.Now.AddDays(repriceHoldOnSalePeriod * -1), DateTime.Now);
+ }
+ if (saleCountInPeriod.ContainsKey(skuInfo[i].SkuNumber))
+ {
+ return saleCountInPeriod[skuInfo[i].SkuNumber];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Sku/Price/UpdateRepricingValues.cs b/src/bnhtrade.Core/Logic/Sku/Price/UpdateRepricingValues.cs
new file mode 100644
index 0000000..5ea3010
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Sku/Price/UpdateRepricingValues.cs
@@ -0,0 +1,787 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Data.SqlClient;
+using System.Transactions;
+
+namespace bnhtrade.Core.Logic.Sku.Price
+{
+ public class UpdateRepricingValues
+ {
+ //public void Update(string sqlConnectionString, bool skipReportUpdate = false)
+ //{
+ // // need to add some cheks up here for last amazon reports import dates
+
+
+
+ // /*
+ // * Quite complex this one, order of business
+ // *
+ // * Stage 1 - Stock Ledger Query reporting FBA stock (loop through this table)
+ // * Stage 1 - Read current values from SkuPrice tabel into variables
+ // * Stage 2 - Get/Set current MIN Price type 'crPriceMin_SkuPriceType'
+ // * Stage 3 - Set MIN Price, based off type
+ // * Stage 4 - Get/Set current MAX Price type 'crPriceMin_SkuPriceType'
+ // * Stage 5 - Set MAX Price, based off type
+ // * Stage 6 - Final check before db update
+ // * Stage 7 - Update main/history table
+ // */
+
+ // DateTime crTimeStamp = DateTime.UtcNow;
+ // int orderChannelId = 2; // may in future enable other order channels
+
+ // // refers to max price movements
+ // decimal repriceDecreaseIncrement = 0.03m; // 3% each week
+ // int repriceDecreasePeriod = 7; // days
+ // int repriceHoldOnSalePeriod = 14; // days
+ // decimal repriceIncreaseIncrement = repriceDecreaseIncrement; // increases price if max sale price is within % of max price
+ // decimal repriceIncreaseOnStockSold = 0.3m; // percent of total qty sold over sale hold period
+
+ // // add a check up here to test for any ASINs that do not have an estimated fee
+
+
+
+
+
+ // // maybe add a constistancy check here (double entries in table (sku and order channel combination)
+
+
+ // using (var conn = new SqlConnection(sqlConnectionString))
+ // {
+ // // loop through table
+ // using (var cmd01 = new SqlCommand("needs deleteing", conn))
+ // {
+ // using (var reader01 = cmd01.ExecuteReader())
+ // {
+ // var skuPricing = new Data.Database.Sku.Price.ReadParameter(sqlConnectionString).Execute();
+
+ // if (skuPricing == null)
+ // {
+ // throw new Exception("Querying the database returned no records.");
+ // }
+ // else
+ // {
+ // new Data.Database.Sku.Price.UpdateSkuPriceIsProcessed(sqlConnectionString).Update();
+ // }
+
+ // using (var scope = new TransactionScope())
+ // using (var scopeConn = new SqlConnection(sqlConnectionString))
+ // {
+ // scopeConn.Open();
+
+ // foreach (var sku in skuPricing)
+ // {
+ // // switches
+ // bool insertRequired = false; // skuId does not already exist in table
+ // bool updateRequired = false; // skuId exists and an edit is required
+ // bool resetMaxBaseAndMultiplier = false; // Quantity is moving from 0 to >0, lookup/update some values is required
+
+ // // current (cr) variables
+ // var cr = new Model.Sku.Price.DetailResponce();
+
+ // cr.OrderChannelQuantity = sku.TotalQuantity;
+ // cr.UnitAvgCost = sku.UnitCostAverage;
+
+
+ // // Stage 1
+ // // get db values from inventory table
+ // var db = new Data.Database.Sku.Price.ReadPricingDetail(sqlConnectionString).Read(sku.SkuId, orderChannelId);
+ // if (db == null)
+ // {
+ // insertRequired = true;
+ // db = new Model.Sku.Price.DetailResponce();
+
+ // // if this is null alot of the following code can be skipped, wip
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // }
+
+ // // STAGE 2
+ // // SKU current stock details (i.e. quantity, cost per unit, inventory age, etc.)
+
+ // // get inventory age range
+ // var invAge = new Data.Database.Import.ReadFbaInventoryAge(sqlConnectionString).BySkuId(sku.SkuId, db.OrderChannelId);
+
+ // if (invAge == null)
+ // {
+ // throw new Exception("No records returned from tblImportFbaInventoryAgeReport for skuID=" + sku.SkuId);
+ // }
+ // cr.InventoryAgeMin = invAge.Value.MinAge;
+ // cr.InventoryAgeMax = invAge.Value.MaxAge;
+
+
+ // // STAGE 3
+ // // Get/Set Min Price SkukPriceTypeID
+ // // Do not change the 'crPriceMin_SkuPriceType' value after this stage
+
+ // //
+ // //bool setMinToAuto = true;
+ // cr.PriceMin_SkuPriceType = 0;
+ // switch (db.PriceMin_SkuPriceType)
+ // {
+ // // Out of Stock
+ // case 0:
+ // if (cr.OrderChannelQuantity > 0)
+ // { cr.PriceMin_SkuPriceType = 1; }
+ // break;
+
+ // //Auto
+ // case 1:
+ // cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType;
+ // break;
+
+ // // Fixed SKU price
+ // case 2:
+ // cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType;
+ // break;
+
+ // // Manual Price, Permanent
+ // case 100:
+ // cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType;
+ // break;
+
+ // // Manual Price, Inv Age Range Includes
+ // case 110:
+ // if (db.PriceMinStoredInt >= cr.InventoryAgeMin && db.PriceMinStoredInt <= cr.InventoryAgeMax)
+ // { cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType; }
+ // else { cr.PriceMin_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Age Range Less Than
+ // case 111:
+ // if (cr.InventoryAgeMax < db.PriceMinStoredInt)
+ // { cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType; }
+ // else { cr.PriceMin_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Age Range Greater Than
+ // case 112:
+ // if (cr.InventoryAgeMin > db.PriceMinStoredInt)
+ // { cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType; }
+ // else { cr.PriceMin_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Quanity is Less than
+ // case 120:
+ // if (cr.OrderChannelQuantity < db.PriceMinStoredInt)
+ // { cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType; }
+ // else { cr.PriceMin_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Quanity is Greater than
+ // case 121:
+ // if (cr.OrderChannelQuantity > db.PriceMinStoredInt)
+ // { cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType; }
+ // else { cr.PriceMin_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Quanity is Equal to
+ // case 122:
+ // if (cr.OrderChannelQuantity == db.PriceMinStoredInt)
+ // { cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType; }
+ // else { cr.PriceMin_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Quanity is Equal to
+ // case 123:
+ // if (cr.OrderChannelQuantity != db.PriceMinStoredInt)
+ // { cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType; }
+ // else { cr.PriceMin_SkuPriceType = 1; }
+ // break;
+
+ // default:
+ // // review of some sort required
+ // if (db.PriceMin_SkuPriceType >= 200 && db.PriceMin_SkuPriceType < 225)
+ // {
+ // cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType;
+ // cr.ReviewRequired = true;
+ // }
+ // // error type
+ // else if (db.PriceMin_SkuPriceType >= 225 && db.PriceMin_SkuPriceType < 256)
+ // {
+ // cr.PriceMin_SkuPriceType = db.PriceMin_SkuPriceType;
+ // }
+ // // unhandled id type
+ // else
+ // {
+ // cr.PriceMin_SkuPriceType = 255;
+ // cr.ReviewRequired = true;
+ // }
+ // break;
+ // }
+
+ // // Check manual enteries are present, if they are required
+ // if ((db.RequireAmountManual && db.PriceMinAmountManual == null) || (db.RequireStordedInt && db.PriceMinStoredInt == null))
+ // {
+ // cr.PriceMin_SkuPriceType = 253;
+ // cr.ReviewRequired = true;
+ // }
+
+ // // Stage 4
+ // // Set MIN Price
+
+ // // calculate the min 'auto' sku price & tax
+ // decimal crProfitMinAmount;
+ // decimal crPriceMinCalculatedTax;
+
+ // if (sku.TaxRateName == "MS" || sku.TaxRateName == "GA")
+ // {
+ // cr.PriceMinAmountAuto = (5m * cr.UnitAvgCost + 6m * sku.AgentFeeFixed) / (-6m * sku.ProfitMargin - 6m * sku.AmazonMargin + 5m);
+ // crPriceMinCalculatedTax = (cr.PriceMinAmountAuto - cr.UnitAvgCost) * (1 / 6);
+ // crProfitMinAmount = cr.PriceMinAmountAuto * sku.ProfitMargin;
+ // }
+ // else
+ // {
+ // cr.PriceMinAmountAuto = (cr.UnitAvgCost + sku.AgentFeeFixed) / (1 - (sku.ProfitMargin + sku.AmazonMargin + sku.VatMargin));
+ // crPriceMinCalculatedTax = cr.PriceMinAmountAuto * sku.VatMargin;
+ // crProfitMinAmount = cr.PriceMinAmountAuto * sku.ProfitMargin;
+ // }
+
+ // // if profit margin is less than min required, redo
+ // if (crProfitMinAmount < sku.PriceMinProfit)
+ // {
+ // if (sku.TaxRateName == "MS" || sku.TaxRateName == "GA")
+ // {
+ // cr.PriceMinAmountAuto = (6m * sku.PriceMinProfit + 5m * cr.UnitAvgCost + 6m * sku.AgentFeeFixed) / (-6m * sku.AmazonMargin + 5m);
+ // crPriceMinCalculatedTax = (cr.PriceMinAmountAuto - cr.UnitAvgCost) * (1 / 6);
+ // crProfitMinAmount = cr.PriceMinAmountAuto * sku.ProfitMargin;
+ // }
+ // else
+ // {
+ // cr.PriceMinAmountAuto = (cr.UnitAvgCost + sku.AgentFeeFixed + sku.PriceMinProfit) / (1 - (sku.AgentFeeMargin + sku.VatMargin));
+ // crPriceMinCalculatedTax = cr.PriceMinAmountAuto * sku.VatMargin;
+ // crProfitMinAmount = cr.PriceMinAmountAuto * sku.ProfitMargin;
+ // }
+ // }
+
+ // // Calculate current final MIN price values
+ // if (cr.PriceMin_SkuPriceType == 1)
+ // {
+ // cr.PriceMinAmountFinal = cr.PriceMinAmountAuto;
+ // cr.PriceMinAmountFinalFee = (cr.PriceMinAmountFinal * sku.AgentFeeMargin) + sku.AgentFeeFixed;
+ // cr.PriceMinAmountFinalTax = crPriceMinCalculatedTax;
+ // }
+ // else
+ // {
+ // cr.PriceMinAmountFinal = (decimal)db.PriceMinAmountManual;
+ // cr.PriceMinAmountFinalFee = ((decimal)db.PriceMinAmountManual * sku.AgentFeeMargin) + sku.AgentFeeFixed;
+ // if (sku.TaxRateName == "MS" || sku.TaxRateName == "GA")
+ // {
+ // cr.PriceMinAmountFinalTax = ((decimal)db.PriceMinAmountManual - cr.UnitAvgCost) * (1 / 6);
+ // }
+ // else
+ // {
+ // cr.PriceMinAmountFinalTax = cr.PriceMinAmountAuto * sku.VatMargin;
+ // }
+ // }
+
+ // // STAGE 5
+ // // Get/Set MAX Price SkukPriceTypeID
+ // // Do not change the 'cr.PriceMax_SkuPriceType' value after this stage
+
+ // cr.PriceMax_SkuPriceType = 0;
+ // switch (db.PriceMax_SkuPriceType)
+ // {
+ // // Out of Stock
+ // case 0:
+ // if (cr.OrderChannelQuantity > 0)
+ // { cr.PriceMax_SkuPriceType = 1; }
+ // break;
+
+ // // Auto
+ // case 1:
+ // cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType;
+ // break;
+
+ // // Fixed SKU price
+ // case 2:
+ // cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType;
+ // break;
+
+ // // Manual Price, Permanent
+ // case 100:
+ // cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType;
+ // break;
+
+ // // Manual Price, Inv Age Range Includes
+ // case 110:
+ // if (db.PriceMaxStoredInt >= cr.InventoryAgeMin && db.PriceMaxStoredInt <= cr.InventoryAgeMax)
+ // { cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType; }
+ // else { cr.PriceMax_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Age Range Less Than
+ // case 111:
+ // if (cr.InventoryAgeMax < db.PriceMaxStoredInt)
+ // { cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType; }
+ // else { cr.PriceMax_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Age Range Greater Than
+ // case 112:
+ // if (cr.InventoryAgeMin > db.PriceMaxStoredInt)
+ // { cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType; }
+ // else { cr.PriceMax_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Quanity is Less than
+ // case 120:
+ // if (cr.OrderChannelQuantity < db.PriceMaxStoredInt)
+ // { cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType; }
+ // else { cr.PriceMax_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Quanity is Greater than
+ // case 121:
+ // if (cr.OrderChannelQuantity > db.PriceMaxStoredInt)
+ // { cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType; }
+ // else { cr.PriceMax_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Quanity is Equal to
+ // case 122:
+ // if (cr.OrderChannelQuantity == db.PriceMaxStoredInt)
+ // { cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType; }
+ // else { cr.PriceMax_SkuPriceType = 1; }
+ // break;
+
+ // // Manual Price, Inv Quanity is Not Equal to
+ // case 123:
+ // if (cr.OrderChannelQuantity == db.PriceMaxStoredInt)
+ // { cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType; }
+ // else { cr.PriceMax_SkuPriceType = 1; }
+ // break;
+
+ // default:
+ // // review of some sort required
+ // if (db.PriceMax_SkuPriceType >= 200 && db.PriceMax_SkuPriceType < 225)
+ // {
+ // cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType;
+ // cr.ReviewRequired = true;
+ // }
+ // // error type
+ // else if (db.PriceMax_SkuPriceType >= 225 && db.PriceMax_SkuPriceType < 256)
+ // {
+ // cr.PriceMax_SkuPriceType = db.PriceMax_SkuPriceType;
+ // }
+ // // unhandled id type
+ // else
+ // {
+ // cr.PriceMax_SkuPriceType = 255;
+ // cr.ReviewRequired = true;
+ // }
+ // break;
+ // }
+
+ // // Check manual enteried are present, if they are required
+ // if ((db.RequireAmountManualMax && db.PriceMaxAmountManual == null) || (db.RequireStordedIntMax && db.PriceMaxStoredInt == null))
+ // {
+ // cr.PriceMax_SkuPriceType = 253;
+ // cr.ReviewRequired = true;
+ // }
+
+ // // STAGE 6
+ // // Set MAX Price
+
+ // // CASE: Reset MAX-Price base & multiplier values (new record or switching back to auto)
+ // if (insertRequired || (cr.PriceMax_SkuPriceType == 1 && db.PriceMax_SkuPriceType != 1))
+ // {
+ // // get competative price and apply multiplier
+ // bool usedForceNew = false;
+ // var request = new bnhtrade.Core.Product.ProductQuery();
+ // var compPrice = request.ProductCompetitivePriceGet(sqlConnectionString, sku.ProductId, sku.ConditionId);
+ // if (compPrice.price == null || compPrice.priceDate == null)
+ // {
+ // if (sku.ConditionId != 10)
+ // {
+ // usedForceNew = true;
+ // compPrice = request.ProductCompetitivePriceGet(sqlConnectionString, sku.ProductId, 10);
+ // }
+ // if (compPrice.price == null || compPrice.priceDate == null)
+ // {
+ // cr.PriceMax_SkuPriceType = 254;
+ // cr.ReviewRequired = true;
+ // }
+ // }
+
+ // cr.PriceMaxAmountAutoBase = compPrice.price ?? 0;
+ // if (usedForceNew)
+ // {
+ // cr.PriceMaxAmountAutoMultiplier = sku.CompetitivePriceMultiplierNew;
+ // }
+ // else
+ // {
+ // cr.PriceMaxAmountAutoMultiplier = sku.CompetitivePriceMultiplierMatch;
+ // }
+
+ // // transfer manual values, if required
+ // if (insertRequired == false)
+ // {
+ // cr.PriceMaxAmountManual = db.PriceMaxAmountManual;
+ // cr.PriceMaxStoredInt = db.PriceMaxStoredInt;
+ // }
+
+ // // set final max value
+ // cr.PriceMaxAmountFinal = cr.PriceMaxAmountAutoBase * cr.PriceMaxAmountAutoMultiplier;
+ // }
+
+ // // already on auto, adjust existing value, if required
+ // else if (db.PriceMax_SkuPriceType == 1)
+ // {
+ // // get last sale date
+ // int shipmentsInSaleHoldPeriod = 0;
+ // // works from last unit ship-date, not the preferred order-date
+ // // TODO: this could be better when other parts of application get more info
+ // DateTime shipDateFilter = crTimeStamp.AddDays(repriceHoldOnSalePeriod * -1);
+ // shipDateFilter = new DateTime(shipDateFilter.Year, shipDateFilter.Month, shipDateFilter.Day);
+ // using (var cmd04 = new SqlCommand(@"
+ // SELECT COUNT(tblImportFbaSaleShipment.ImportFbaSaleShipmentID) AS RecordCount
+ // FROM tblImportFbaSaleShipment
+ // INNER JOIN tblSku ON tblImportFbaSaleShipment.sku = tblSku.skuSkuNumber
+ // WHERE (tblSku.skuSkuID = @skuID)
+ // AND (tblImportFbaSaleShipment.[shipment-date] >= @shipDateFilter)
+ // ", conn))
+ // {
+ // cmd04.Parameters.AddWithValue("@skuID", sku.SkuId);
+ // cmd04.Parameters.AddWithValue("@shipDateFilter", shipDateFilter);
+
+ // shipmentsInSaleHoldPeriod = (int)cmd04.ExecuteScalar();
+ // }
+ // // get max item sale price during period
+ // decimal maxSalePrice = 0;
+ // if (shipmentsInSaleHoldPeriod > 0)
+ // {
+ // using (var cmd05 = new SqlCommand(@"
+ // SELECT Max(ISNULL([tblImportFbaSaleShipment].[item-price], 0) + ISNULL([tblImportFbaSaleShipment].[item-tax], 0)) AS Expr1
+ // FROM tblImportFbaSaleShipment
+ // INNER JOIN tblSku ON tblImportFbaSaleShipment.sku = tblSku.skuSkuNumber
+ // WHERE (
+ // ((tblSku.skuSkuID) = @skuID)
+ // AND ((tblImportFbaSaleShipment.[shipment-date]) >= @shipDateFilter)
+ // )
+ // ", conn))
+ // {
+ // cmd05.Parameters.AddWithValue("@skuID", sku.SkuId);
+ // cmd05.Parameters.AddWithValue("@shipDateFilter", shipDateFilter);
+
+ // maxSalePrice = (decimal)cmd05.ExecuteScalar();
+ // }
+ // }
+
+ // DateTime updateDate = new DateTime(db.PriceCreated.Year, db.PriceCreated.Month, db.PriceCreated.Day);
+ // updateDate = updateDate.AddDays(repriceDecreasePeriod);
+
+ // // decrease maxx price
+ // if (crTimeStamp >= updateDate && shipmentsInSaleHoldPeriod == 0)
+ // {
+ // cr.PriceMaxAmountAutoBase = db.PriceMaxAmountAutoBase;
+ // cr.PriceMaxAmountAutoMultiplier = db.PriceMaxAmountAutoMultiplier - repriceDecreaseIncrement;
+ // cr.PriceMaxAmountManual = db.PriceMaxAmountManual;
+ // cr.PriceMaxStoredInt = db.PriceMaxStoredInt;
+ // cr.PriceMaxAmountFinal = cr.PriceMaxAmountAutoBase * cr.PriceMaxAmountAutoMultiplier;
+ // }
+ // else
+ // {
+ // // increase price
+ // if (maxSalePrice >= (db.PriceMaxAmountAutoBase * (db.PriceMaxAmountAutoMultiplier - repriceIncreaseIncrement)))
+ // {
+ // cr.PriceMaxAmountAutoBase = db.PriceMaxAmountAutoBase;
+ // cr.PriceMaxAmountAutoMultiplier = db.PriceMaxAmountAutoMultiplier + repriceIncreaseIncrement;
+ // cr.PriceMaxAmountManual = db.PriceMaxAmountManual;
+ // cr.PriceMaxStoredInt = db.PriceMaxStoredInt;
+ // cr.PriceMaxAmountFinal = cr.PriceMaxAmountAutoBase * cr.PriceMaxAmountAutoMultiplier;
+ // }
+ // // remain same
+ // else
+ // {
+ // cr.PriceMaxAmountAutoBase = db.PriceMaxAmountAutoBase;
+ // cr.PriceMaxAmountAutoMultiplier = db.PriceMaxAmountAutoMultiplier;
+ // cr.PriceMaxAmountManual = db.PriceMaxAmountManual;
+ // cr.PriceMaxStoredInt = db.PriceMaxStoredInt;
+ // cr.PriceMaxAmountFinal = cr.PriceMaxAmountAutoBase * cr.PriceMaxAmountAutoMultiplier;
+ // }
+ // }
+ // }
+
+ // // STAGE 7
+ // // Checks before update
+
+ // // max < min
+ // if (cr.PriceMaxAmountFinal < cr.PriceMinAmountFinal)
+ // {
+ // // on auto, set max to min value and update base multipier to reflect new value
+ // if (cr.PriceMax_SkuPriceType == 1)
+ // {
+ // cr.PriceMaxAmountFinal = cr.PriceMinAmountFinal;
+ // cr.PriceMaxAmountAutoMultiplier = cr.PriceMinAmountFinal / cr.PriceMaxAmountAutoBase;
+ // }
+ // else if (cr.PriceMax_SkuPriceType > 0 && cr.PriceMax_SkuPriceType < 200)
+ // {
+ // cr.PriceMax_SkuPriceType = 252;
+ // cr.ReviewRequired = true;
+ // }
+ // }
+
+ // // this should be last check
+ // // check for zero values (where there should not be any) -- this could be a life saver i.e. selling item for £0.00
+ // if (cr.PriceMinAmountFinal * cr.PriceMaxAmountFinal == 0)
+ // {
+ // cr.PriceMax_SkuPriceType = 251;
+ // cr.ReviewRequired = true;
+ // }
+
+ // // STAGE 8
+ // // Update main/history tables, if required
+ // // round decimals for db comarison
+ // cr.UnitAvgCost = decimal.Round(cr.UnitAvgCost, 2);
+ // cr.PriceMinAmountAuto = decimal.Round(cr.PriceMinAmountAuto, 2);
+ // cr.PriceMinAmountFinalFee = decimal.Round(cr.PriceMinAmountFinalFee, 2);
+ // cr.PriceMinAmountFinalTax = decimal.Round(cr.PriceMinAmountFinalTax, 2);
+ // cr.PriceMinAmountFinal = decimal.Round(cr.PriceMinAmountFinal, 2);
+ // cr.PriceMaxAmountAutoMultiplier = decimal.Round(cr.PriceMaxAmountAutoMultiplier, 8);
+ // cr.PriceMaxAmountFinal = decimal.Round(cr.PriceMaxAmountFinal, 2);
+
+ // if (insertRequired == false &&
+ // (
+ // db.OrderChannelQuantity != cr.OrderChannelQuantity ||
+ // db.UnitAvgCost != cr.UnitAvgCost ||
+ // db.InventoryAgeMin != cr.InventoryAgeMin ||
+ // db.InventoryAgeMax != cr.InventoryAgeMax ||
+ // db.PriceMin_SkuPriceType != cr.PriceMin_SkuPriceType ||
+ // db.PriceMinAmountAuto != cr.PriceMinAmountAuto ||
+ // db.PriceMinAmountFinalFee != cr.PriceMinAmountFinalFee ||
+ // db.PriceMinAmountFinalTax != cr.PriceMinAmountFinalTax ||
+ // db.PriceMinAmountFinal != cr.PriceMinAmountFinal ||
+ // db.PriceMax_SkuPriceType != cr.PriceMax_SkuPriceType ||
+ // db.PriceMaxAmountAutoBase != cr.PriceMaxAmountAutoBase ||
+ // db.PriceMaxAmountAutoMultiplier != cr.PriceMaxAmountAutoMultiplier ||
+ // db.PriceMaxAmountFinal != cr.PriceMaxAmountFinal ||
+ // db.ReviewRequired != cr.ReviewRequired
+ // )
+ // )
+ // {
+ // updateRequired = true;
+ // }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ // // insert old data to history table
+ // if (updateRequired)
+ // {
+ // using (var cmd06 = new SqlCommand(@"
+ // INSERT INTO tblSkuPriceHistory (
+ // SkuID
+ // ,OrderChannelID
+ // ,OrderChannelQuantity
+ // ,UnitAvgCost
+ // ,InventoryAgeMin
+ // ,InventoryAgeMax
+ // ,PriceMin_SkuPriceType
+ // ,PriceMinAmountAuto
+ // ,PriceMinAmountManual
+ // ,PriceMinStoredInt
+ // ,PriceMinAmountFinalFee
+ // ,PriceMinAmountFinalTax
+ // ,PriceMinAmountFinal
+ // ,PriceMax_SkuPriceType
+ // ,PriceMaxAmountAutoBase
+ // ,PriceMaxAmountAutoMultiplier
+ // ,PriceMaxAmountManual
+ // ,PriceMaxStoredInt
+ // ,PriceMaxAmountFinal
+ // ,RecordModified
+ // ,ReviewRequired
+ // )
+ // VALUES (
+ // @skuID
+ // ,@dbOrderChannelID
+ // ,@dbOrderChannelQuantity
+ // ,@dbUnitAvgCost
+ // ,@dbInventoryAgeMin
+ // ,@dbInventoryAgeMax
+ // ,@dbPriceMin_SkuPriceType
+ // ,@dbPriceMinAmountAuto
+ // ,@dbPriceMinAmountManual
+ // ,@dbPriceMinStoredInt
+ // ,@dbPriceMinAmountFinalFee
+ // ,@dbPriceMinAmountFinalTax
+ // ,@dbPriceMinAmountFinal
+ // ,@dbPriceMax_SkuPriceType
+ // ,@dbPriceMaxAmountAutoBase
+ // ,@dbPriceMaxAmountAutoMultiplier
+ // ,@dbPriceMaxAmountManual
+ // ,@dbPriceMaxStoredInt
+ // ,@dbPriceMaxAmountFinal
+ // ,@dbRecordModified
+ // ,@dbReviewRequired
+ // )
+ // ", scopeConn))
+ // {
+ // cmd06.Parameters.AddWithValue("@skuID", sku.SkuId);
+ // cmd06.Parameters.AddWithValue("@dbOrderChannelID", db.OrderChannelId);
+ // cmd06.Parameters.AddWithValue("@dbOrderChannelQuantity", db.OrderChannelQuantity);
+ // cmd06.Parameters.AddWithValue("@dbUnitAvgCost", db.UnitAvgCost);
+ // cmd06.Parameters.AddWithValue("@dbInventoryAgeMin", db.InventoryAgeMin);
+ // cmd06.Parameters.AddWithValue("@dbInventoryAgeMax", db.InventoryAgeMax);
+ // cmd06.Parameters.AddWithValue("@dbPriceMin_SkuPriceType", db.PriceMin_SkuPriceType);
+ // cmd06.Parameters.AddWithValue("@dbPriceMinAmountAuto", db.PriceMinAmountAuto);
+ // cmd06.Parameters.AddWithValue("@dbPriceMinAmountManual", db.PriceMinAmountManual);
+ // cmd06.Parameters.AddWithValue("@dbPriceMinStoredInt", db.PriceMinStoredInt);
+ // cmd06.Parameters.AddWithValue("@dbPriceMinAmountFinalFee", db.PriceMinAmountFinalFee);
+ // cmd06.Parameters.AddWithValue("@dbPriceMinAmountFinalTax", db.PriceMinAmountFinalTax);
+ // cmd06.Parameters.AddWithValue("@dbPriceMinAmountFinal", db.PriceMinAmountFinal);
+ // cmd06.Parameters.AddWithValue("@dbPriceMax_SkuPriceType", db.PriceMax_SkuPriceType);
+ // cmd06.Parameters.AddWithValue("@dbPriceMaxAmountAutoBase", db.PriceMaxAmountAutoBase);
+ // cmd06.Parameters.AddWithValue("@dbPriceMaxAmountAutoMultiplier", db.PriceMaxAmountAutoMultiplier);
+ // cmd06.Parameters.AddWithValue("@dbPriceMaxAmountManual", db.PriceMaxAmountManual);
+ // cmd06.Parameters.AddWithValue("@dbPriceMaxStoredInt", db.PriceMaxStoredInt);
+ // cmd06.Parameters.AddWithValue("@dbPriceMaxAmountFinal", db.PriceMaxAmountFinal);
+ // cmd06.Parameters.AddWithValue("@dbRecordModified", db.PriceCreated);
+ // cmd06.Parameters.AddWithValue("@dbReviewRequired", db.ReviewRequired);
+
+ // int count = cmd06.ExecuteNonQuery();
+ // }
+ // }
+
+ // // delete existing data in current table
+ // if (updateRequired)
+ // {
+ // using (var cmd07 = new SqlCommand(@"
+ // DELETE FROM tblSkuPriceHistory
+ // WHERE SkuID = @skuID AND OrderChannelID = @dbOrderChannelID
+ // ", scopeConn))
+ // {
+ // cmd07.Parameters.AddWithValue("@skuID", sku.SkuId);
+ // cmd07.Parameters.AddWithValue("@dbOrderChannelID", db.OrderChannelId);
+
+ // int count = cmd07.ExecuteNonQuery();
+ // }
+ // }
+
+ // // insert new data into current table
+ // if (updateRequired || insertRequired)
+ // {
+ // using (var cmd06 = new SqlCommand(@"
+ // INSERT INTO tblSkuPrice (
+ // SkuID
+ // ,OrderChannelID
+ // ,OrderChannelQuantity
+ // ,UnitAvgCost
+ // ,InventoryAgeMin
+ // ,InventoryAgeMax
+ // ,PriceMin_SkuPriceType
+ // ,PriceMinAmountAuto
+ // ,PriceMinAmountManual
+ // ,PriceMinStoredInt
+ // ,PriceMinAmountFinalFee
+ // ,PriceMinAmountFinalTax
+ // ,PriceMinAmountFinal
+ // ,PriceMax_SkuPriceType
+ // ,PriceMaxAmountAutoBase
+ // ,PriceMaxAmountAutoMultiplier
+ // ,PriceMaxAmountManual
+ // ,PriceMaxStoredInt
+ // ,PriceMaxAmountFinal
+ // ,RecordModified
+ // ,ReviewRequired
+ // )
+ // VALUES (
+ // @skuID
+ // ,@crOrderChannelID
+ // ,@crOrderChannelQuantity
+ // ,@crUnitAvgCost
+ // ,@crInventoryAgeMin
+ // ,@crInventoryAgeMax
+ // ,@crPriceMin_SkuPriceType
+ // ,@crPriceMinAmountAuto
+ // ,@crPriceMinAmountManual
+ // ,@crPriceMinStoredInt
+ // ,@crPriceMinAmountFinalFee
+ // ,@crPriceMinAmountFinalTax
+ // ,@crPriceMinAmountFinal
+ // ,@crPriceMax_SkuPriceType
+ // ,@crPriceMaxAmountAutoBase
+ // ,@crPriceMaxAmountAutoMultiplier
+ // ,@crPriceMaxAmountManual
+ // ,@crPriceMaxStoredInt
+ // ,@crPriceMaxAmountFinal
+ // ,@crRecordModified
+ // ,@crReviewRequired
+ // )
+ // ", scopeConn))
+ // {
+ // cmd06.Parameters.AddWithValue("@skuID", sku.SkuId);
+ // cmd06.Parameters.AddWithValue("@crOrderChannelID", db.OrderChannelId);
+ // cmd06.Parameters.AddWithValue("@crOrderChannelQuantity", cr.OrderChannelQuantity);
+ // cmd06.Parameters.AddWithValue("@crUnitAvgCost", cr.UnitAvgCost);
+ // cmd06.Parameters.AddWithValue("@crInventoryAgeMin", cr.InventoryAgeMin);
+ // cmd06.Parameters.AddWithValue("@crInventoryAgeMax", cr.InventoryAgeMax);
+ // cmd06.Parameters.AddWithValue("@crPriceMin_SkuPriceType", cr.PriceMin_SkuPriceType);
+ // cmd06.Parameters.AddWithValue("@crPriceMinAmountAuto", cr.PriceMinAmountAuto);
+ // cmd06.Parameters.AddWithValue("@crPriceMinAmountManual", cr.PriceMinAmountManual);
+ // cmd06.Parameters.AddWithValue("@crPriceMinStoredInt", cr.PriceMinStoredInt);
+ // cmd06.Parameters.AddWithValue("@crPriceMinAmountFinalFee", cr.PriceMinAmountFinalFee);
+ // cmd06.Parameters.AddWithValue("@crPriceMinAmountFinalTax", cr.PriceMinAmountFinalTax);
+ // cmd06.Parameters.AddWithValue("@crPriceMinAmountFinal", cr.PriceMinAmountFinal);
+ // cmd06.Parameters.AddWithValue("@crPriceMax_SkuPriceType", cr.PriceMax_SkuPriceType);
+ // cmd06.Parameters.AddWithValue("@crPriceMaxAmountAutoBase", cr.PriceMaxAmountAutoBase);
+ // cmd06.Parameters.AddWithValue("@crPriceMaxAmountAutoMultiplier", cr.PriceMaxAmountAutoMultiplier);
+ // cmd06.Parameters.AddWithValue("@crPriceMaxAmountManual", cr.PriceMaxAmountManual);
+ // cmd06.Parameters.AddWithValue("@crPriceMaxStoredInt", cr.PriceMaxStoredInt);
+ // cmd06.Parameters.AddWithValue("@crPriceMaxAmountFinal", cr.PriceMaxAmountFinal);
+ // cmd06.Parameters.AddWithValue("@crRecordModified", cr.PriceCreated);
+ // cmd06.Parameters.AddWithValue("@crReviewRequired", cr.ReviewRequired);
+
+ // int count = cmd06.ExecuteNonQuery();
+ // }
+ // }
+
+
+
+
+
+
+
+
+
+ // } // drop out of query while loop here
+
+ // // set any records that are not IsProcessed=TRUE to no quantity (i.e. by type) and quantity
+ // // or... do I copy record to history and delete <------- THIS
+
+
+ // // also, should add check, cross reference inventory age table against stock ledger results to highlight sku where I reckon
+ // // qty is zero and amazon is >0
+
+
+ // scope.Complete();
+ // }
+ // }
+ // }
+ // }
+ //}
+ }
+}
\ No newline at end of file
diff --git a/src/bnhtrade.Core/Logic/Stock/Reallocate.cs b/src/bnhtrade.Core/Logic/Stock/Reallocate.cs
new file mode 100644
index 0000000..350735e
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Stock/Reallocate.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Transactions;
+
+namespace bnhtrade.Core.Logic.Stock
+{
+ public class Reallocate
+ {
+ private string sqlConnectionString;
+
+ public Reallocate(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ }
+
+ public int StockReallocateByStockId(int journalTypeId, int stockId, int quantity, int debitStatusId, int creditStatusId,
+ DateTime entryDate = default(DateTime))
+ {
+ if (entryDate == default(DateTime))
+ {
+ entryDate = DateTime.Now;
+ }
+
+ // create the list
+ var posts = new List<(int statusId, int quantity)>();
+ posts.Add((debitStatusId, quantity));
+ posts.Add((creditStatusId, (quantity * -1)));
+
+ // execute
+ return Core.Stock.StockJournal.StockJournalInsert(sqlConnectionString, journalTypeId, stockId, posts, entryDate, false);
+ }
+
+
+ ///
+ /// Feed an skuId and quantity into function and the stock will be reallocated
+ ///
+ public List<(int StockJournalId, int Quantity)> StockReallocateBySkuNumber(int journalTypeId, string skuNumber, int quantity, int debitStatusId, int creditStatusId,
+ bool firstInFirstOut = true, DateTime entryDate = default(DateTime), bool reallocatePartialQuantity = false)
+ {
+ var returnList = new List<(int StockJournalId, int Quantity)>();
+
+ List> list = Core.Stock.StockJournal.GetStockStatusBalanceBySkuNumber(sqlConnectionString, skuNumber, creditStatusId, entryDate, firstInFirstOut);
+
+ if (list == null || !list.Any())
+ {
+ return returnList;
+ }
+
+ // quantity check
+ int avaiableQuantity = 0;
+ foreach (Tuple item in list)
+ {
+ avaiableQuantity = avaiableQuantity + item.Item3;
+ }
+ if (avaiableQuantity < quantity && reallocatePartialQuantity == false)
+ {
+ return null;
+ }
+
+ // make the changes
+ using (TransactionScope scope = new TransactionScope())
+ {
+ foreach (Tuple item in list)
+ {
+ if (quantity > item.Item3)
+ {
+ int tempInt = StockReallocateByStockId(journalTypeId, item.Item1, item.Item3, debitStatusId, creditStatusId, entryDate);
+ quantity = quantity - item.Item3;
+ returnList.Add((tempInt, item.Item3));
+ }
+ else
+ {
+ int tempInt = StockReallocateByStockId(journalTypeId, item.Item1, quantity, debitStatusId, creditStatusId, entryDate);
+ returnList.Add((tempInt, quantity));
+ break;
+ }
+ }
+ scope.Complete();
+ return returnList;
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Stock/SkuTransactionPersistance.cs b/src/bnhtrade.Core/Logic/Stock/SkuTransactionPersistance.cs
new file mode 100644
index 0000000..010f596
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Stock/SkuTransactionPersistance.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Transactions;
+
+namespace bnhtrade.Core.Logic.Stock
+{
+ public class SkuTransactionPersistance
+ {
+ private string err = "Sku Transaction Persistance Error; ";
+ private string sqlConnectionString;
+ private Data.Database.Stock.DeleteSkuTransaction dbSkuTransDelete;
+ private Data.Database.Stock.CreateSkuTransaction dbSkuTransCreate;
+ private Data.Database.Stock.ReadSkuTransaction dbSkuTransRead;
+ private Data.Database.Stock.UpdateSkuTransaction dbSkuTransUpdate;
+ private Logic.Validate.SkuTransaction validateSkuTrans;
+ private Logic.Log.LogEvent log;
+
+ public SkuTransactionPersistance(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ log = new Log.LogEvent();
+ }
+
+ private Data.Database.Stock.DeleteSkuTransaction DatabaseSkuTransDelete(bool forceNew = false)
+ {
+ if (dbSkuTransDelete == null || forceNew)
+ {
+ dbSkuTransDelete = new Data.Database.Stock.DeleteSkuTransaction(sqlConnectionString);
+ }
+ return dbSkuTransDelete;
+ }
+
+ private Data.Database.Stock.CreateSkuTransaction DatabaseSkuTransInsert(bool forceNew = false)
+ {
+ if (dbSkuTransCreate == null || forceNew)
+ {
+ dbSkuTransCreate = new Data.Database.Stock.CreateSkuTransaction(sqlConnectionString);
+ }
+ return dbSkuTransCreate;
+ }
+
+ private Data.Database.Stock.ReadSkuTransaction DatabaseSkuTransRead(bool forceNew = false)
+ {
+ if (dbSkuTransRead == null || forceNew)
+ {
+ dbSkuTransRead = new Data.Database.Stock.ReadSkuTransaction(sqlConnectionString);
+ }
+ return dbSkuTransRead;
+ }
+
+ private Data.Database.Stock.UpdateSkuTransaction DatabaseSkuTransUpdate(bool forceNew = false)
+ {
+ if (dbSkuTransUpdate == null || forceNew)
+ {
+ dbSkuTransUpdate = new Data.Database.Stock.UpdateSkuTransaction(sqlConnectionString);
+ }
+ return dbSkuTransUpdate;
+ }
+
+ private Logic.Validate.SkuTransaction Validate()
+ {
+ if (validateSkuTrans == null)
+ {
+ validateSkuTrans = new Validate.SkuTransaction();
+ }
+ return validateSkuTrans;
+ }
+
+ public void Delete(int skuTransactionId)
+ {
+ using (var scope = new TransactionScope())
+ {
+ try
+ {
+ // is there a journal entry attached?
+ int? journalId = DatabaseSkuTransRead().GetJournalId(skuTransactionId);
+ if (journalId != null)
+ {
+ Core.Stock.StockJournal.StockJournalDelete(sqlConnectionString, (int)journalId);
+ }
+
+ DatabaseSkuTransDelete().ByTransactionId(skuTransactionId);
+ scope.Complete();
+ }
+ catch (Exception ex)
+ {
+ scope.Dispose();
+ throw ex;
+ }
+ }
+ }
+
+ public void DeleteJournalEntry(int skuTransactionId)
+ {
+ using (var scope = new TransactionScope())
+ {
+ try
+ {
+ // is there a journal entry attached?
+ int? journalId = DatabaseSkuTransRead().GetJournalId(skuTransactionId);
+ if (journalId != null)
+ {
+ DatabaseSkuTransUpdate().Update(skuTransactionId, null);
+ Core.Stock.StockJournal.StockJournalDelete(sqlConnectionString, (int)journalId);
+ }
+ scope.Complete();
+ }
+ catch (Exception ex)
+ {
+ scope.Dispose();
+ throw ex;
+ }
+ }
+ }
+
+ public void Create(Model.Stock.SkuTransaction skuTransaction)
+ {
+ if (skuTransaction == null)
+ {
+ throw new Exception(err + "Object was null");
+ }
+
+ Validate().Innit();
+ if (!Validate().DatabaseInsert(skuTransaction))
+ {
+ log.LogWarning(err + "Validation failed", Validate().ValidationResultListToString());
+ throw new Exception(err + "Validation failed");
+ }
+
+ // write to database
+ DatabaseSkuTransInsert().Create(skuTransaction);
+ }
+
+ public void Update(Model.Stock.SkuTransaction skuTransaction)
+ {
+ if (skuTransaction == null)
+ {
+ throw new Exception(err + "Object was null");
+ }
+
+ Validate().Innit();
+ if (!Validate().DatabaseUpdate(skuTransaction))
+ {
+ log.LogWarning(err + "Validation failed", Validate().ValidationResultListToString());
+ throw new Exception(err + "Validation failed");
+ }
+
+ using (var scope = new TransactionScope())
+ {
+ // is there an existing journal id that is changing
+ int? journalId = DatabaseSkuTransRead().GetJournalId(skuTransaction.SkuTransactionId);
+ if (journalId != null && skuTransaction.IsSetStockJournalId)
+ {
+ if (journalId != skuTransaction.StockJournalId)
+ {
+ DeleteJournalEntry(skuTransaction.SkuTransactionId);
+ }
+ }
+ dbSkuTransUpdate.Update(skuTransaction);
+ scope.Complete();
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Stock/SkuTransactionReconcile.cs b/src/bnhtrade.Core/Logic/Stock/SkuTransactionReconcile.cs
new file mode 100644
index 0000000..350dc80
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Stock/SkuTransactionReconcile.cs
@@ -0,0 +1,398 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Transactions;
+
+namespace bnhtrade.Core.Logic.Stock
+{
+ public class SkuTransactionReconcile
+ {
+ private string sqlConnectionString;
+ private Data.Database.AmazonShipment.ReadShipmentInfo readShipmentInfo;
+ private Logic.Stock.SkuTransactionPersistance dbSkuTransaction;
+ private Logic.Stock.SkuTransactionTypePersistance dbSkuTransactionType;
+ private Logic.Validate.SkuTransaction validateSkuTrans;
+ private Logic.Stock.Reallocate stockReallocate;
+ private Logic.Log.LogEvent logEvent;
+ private string err = "Reconcile Sku Transaction Exception: ";
+
+ public SkuTransactionReconcile(string sqlConnectionString)
+ {
+ Innit();
+ this.sqlConnectionString = sqlConnectionString;
+ dbSkuTransaction = new SkuTransactionPersistance(sqlConnectionString);
+ dbSkuTransactionType = new SkuTransactionTypePersistance(sqlConnectionString);
+ readShipmentInfo = new Data.Database.AmazonShipment.ReadShipmentInfo(sqlConnectionString);
+ validateSkuTrans = new Validate.SkuTransaction();
+ stockReallocate = new Logic.Stock.Reallocate(sqlConnectionString);
+ logEvent = new Log.LogEvent();
+ }
+
+ public int ItemsCompleted { get; private set; }
+
+ public int ItemsRemaining { get; private set; }
+
+ public DateTime LastItemDateTime { get; private set; }
+
+ public string ProgressMessage { get; private set; }
+
+ public bool ReconciliationComplete { get; private set; }
+
+ public int CurrentTransactionId { get; private set; }
+
+ public int CurrentTransactionTypeId { get; private set; }
+
+ public Model.Stock.SkuTransaction CurrentSkuTransaction { get; private set; }
+
+ private void Innit()
+ {
+ ItemsCompleted = 0;
+ ItemsRemaining = 0;
+ LastItemDateTime = default(DateTime);
+ ProgressMessage = null;
+ ReconciliationComplete = false;
+ CurrentTransactionId = 0;
+ CurrentTransactionTypeId = 0;
+ }
+
+ ///
+ /// Iterates through the stock transaction table and inserts stock journal entries, where applicable
+ /// N.B. This function does not make allowances for status' that can create stock (i.e. if a status does not have stock available, this function will halt processing rows)
+ ///
+ /// Download and process Amazon reports before starting process
+ ///
+ public void ReconcileStockTransactions(bool updateTransactions)
+ {
+ Innit();
+ string currentMethodName = nameof(ReconcileStockTransactions);
+
+ // ensure import table have been processed into transaction table without exception
+ if (updateTransactions == true)
+ {
+ try
+ {
+ var preCheck = new bnhtrade.Core.Stock.StockReconciliation();
+ preCheck.ProcessFbaStockImportData(sqlConnectionString);
+ }
+ catch (Exception ex)
+ {
+ ProgressMessage = "Precheck failed: " + ex.Message;
+ return;
+ }
+ }
+
+ logEvent.LogInformation("Starting ReconcileStockTransactions()");
+ int recordSkip = 0;
+
+ ProcessLostAndFound();
+
+ // get list of sku transactions to reconcile
+ var transList = new Data.Database.Stock.ReadSkuTransaction(sqlConnectionString).GetUnreconciled();
+ ItemsRemaining = transList.Count;
+ ItemsCompleted = 0;
+
+ try
+ {
+ // loop through transaction list
+ for (int i = 0; i < transList.Count; i++)
+ {
+ using (var scope = new TransactionScope())
+ {
+
+ Console.Write("\rProcessing record: {0} ({1} skipped)", (i + 1 + recordSkip), recordSkip);
+
+ // setup return values
+ CurrentSkuTransaction = transList[i];
+ CurrentTransactionId = transList[i].SkuTransactionId;
+ CurrentTransactionTypeId = transList[i].SkuTransactionTypeId;
+ LastItemDateTime = transList[i].TransactionDate;
+
+ // load type into variable
+ var transType = dbSkuTransactionType.GetByTypeName(transList[i].SkuTransactionTypeName);
+
+ // stop if a new transactiontype is encountered
+ if (transType.IsNewReviewRequired)
+ {
+ ProgressMessage = "New 'Transaction-Type' encountered";
+ //Console.Write("\r");
+ //MiscFunction.EventLogInsert(errMessage, 1);
+ goto Stop;
+ }
+
+ // set debit/credit status' for special cases (i.e. NULL or 0 debit/credit ids in stockTransactionType table)
+ if (transType.StockJournalEntryEnabled == true && (transType.DebitStockStatusId == 0 || transType.CreditStockStatusId == 0))
+ {
+ // FBA Shipment Receipt +ve
+ if (transType.TypeCode == "<_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><+ve>"
+ || transType.TypeCode == "<_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><-ve>")
+ {
+ var shipmentInfo = readShipmentInfo.HeaderByFbaShipmentId(transList[i].Reference);
+
+ if (shipmentInfo.IsSetShipmentStockStatusId())
+ {
+ // +ve shipment receipt
+ if (transType.CreditStockStatusId == 0 && transType.DebitStockStatusId > 0)
+ { transType.CreditStockStatusId = shipmentInfo.ShipmentStockStatusId; }
+
+ // -ve shipment receipt
+ else if (transType.DebitStockStatusId == 0 && transType.CreditStockStatusId > 0)
+ { transType.DebitStockStatusId = shipmentInfo.ShipmentStockStatusId; }
+
+ // something went wrong, raise error
+ else
+ {
+ ProgressMessage = "Unable to retrive FBA shipment location/status from tblAmazonShipment for Amazon shipment '" + shipmentInfo.FbaShipmentId + "'.";
+ recordSkip = recordSkip + 1;
+ goto Stop;
+ }
+ }
+ }
+ // something went wrong, raise error
+ else
+ {
+ ProgressMessage = "Coding required. Unhandled special case Transaction-Type encountered (Transaction-Type debit or credit is set to 0).";
+ recordSkip = recordSkip + 1;
+ goto Stop;
+ }
+ }
+
+ // make the changes
+ if (transType.StockJournalEntryEnabled == false)
+ {
+ transList[i].IsProcessed = true;
+ dbSkuTransaction.Update(transList[i]);
+ }
+ else
+ {
+ var list = new List<(int StockJournalId, int Quantity)>();
+ if (transType.FilterStockOnDateTime)
+ {
+ list = stockReallocate.StockReallocateBySkuNumber(
+ transType.StockJournalTypeId,
+ transList[i].SkuNumber,
+ transList[i].Quantity,
+ transType.DebitStockStatusId,
+ transType.CreditStockStatusId,
+ transType.FirstInFirstOut,
+ transList[i].TransactionDate,
+ false);
+ }
+ else
+ {
+ list = stockReallocate.StockReallocateBySkuNumber(
+ transType.StockJournalTypeId,
+ transList[i].SkuNumber,
+ transList[i].Quantity,
+ transType.DebitStockStatusId,
+ transType.CreditStockStatusId,
+ transType.FirstInFirstOut,
+ DateTime.UtcNow,
+ false);
+ }
+
+ // insufficient balance available
+ if (list == null || !list.Any())
+ {
+ // in special case (found inventory), continue
+ if (transType.TypeCode.Contains("<_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_>"))
+ {
+ continue;// <--------------------------------------------------------------------------------------------------- is this the soruce of the bug?
+ }
+ else
+ {
+ ProgressMessage = "Insurficent status/location balance to relocate stock";
+ recordSkip = recordSkip + 1;
+ goto Stop;
+ }
+ }
+
+ // fail safe
+ int qtyAllocated = list.Sum(c => c.Quantity);
+ if (qtyAllocated > transList[i].Quantity)
+ {
+ throw new Exception(
+ currentMethodName + ": StockReallocateBySkuId() returned greater quantity than passed to function"
+ + transList[i].SkuTransactionId);
+ }
+
+ // update sku transaction table
+ int qtyRemain = qtyAllocated;
+ var newRecordList = new List();
+ for (int j = 0; j <= list.Count; j++)
+ {
+ // update existing record
+ if (j == 0)
+ {
+ transList[i].Quantity = (short)list[j].Quantity;
+ transList[i].StockJournalId = list[j].StockJournalId;
+ transList[i].IsProcessed = true;
+
+ dbSkuTransaction.Update(transList[i]);
+ }
+ // new record
+ else if (j < list.Count)
+ {
+ var newRecord = transList[i].Clone();
+ newRecord.Quantity = (short)list[j].Quantity;
+ newRecord.IsProcessed = true;
+ newRecord.StockJournalId = list[j].StockJournalId;
+ newRecordList.Add(newRecord);
+ }
+ // new record, unallocated quantity
+ else if (qtyRemain > 0)
+ {
+ var newRecord = transList[i].Clone();
+ newRecord.Quantity = (short)qtyRemain;
+ newRecord.IsProcessed = false;
+ newRecordList.Add(newRecord);
+ }
+
+ if (j < list.Count)
+ {
+ qtyRemain = qtyRemain - list[j].Quantity;
+ }
+ }
+ // add new transactions to table
+ for (int j = 0; j < newRecordList.Count; j++)
+ {
+ dbSkuTransaction.Create(newRecordList[j]);
+ }
+ }
+ ItemsCompleted++;
+ ItemsRemaining++;
+ scope.Complete();
+ }
+ // end of scope
+ }
+ // end of loop
+ }
+ catch (Exception ex)
+ {
+ Console.Write("\r");
+ ProgressMessage = ex.Message;
+ return;
+ }
+
+ Stop:
+ Console.Write("\r");
+
+ MiscFunction.EventLogInsert("ProcessStockTransactions() compete. " + ItemsCompleted + " total records processed, " + recordSkip + " rows uncompllete due to insurficent stock.");
+ MiscFunction.EventLogInsert("ProcessStockTransactions(), " + recordSkip + " rows skipped due to insurficent stock.", 2);
+
+ ReconciliationComplete = true;
+ ProgressMessage = "Operation complete.";
+ return;
+ }
+
+
+ ///
+ ///
+ ///
+ public void ProcessLostAndFound()
+ {
+ using (var scope = new TransactionScope())
+ {
+
+ // get list of sku transactions to reconcile
+ var transList = new Data.Database.Stock.ReadSkuTransaction(sqlConnectionString).GetUnreconciled();
+ ItemsRemaining = transList.Count;
+ ItemsCompleted = 0;
+
+ // need to loop though table and cancel out any found before they are lost (in reality they were never
+ // lost, therefore should not be entered into journal as lost)
+ string lost = "<_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><-ve>";
+ string found = "<_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><+ve>";
+
+ for (int i = 0; i < transList.Count; i++)
+ {
+ var transType = dbSkuTransactionType.GetByTypeName(transList[i].SkuTransactionTypeName);
+
+ if (transType.TypeCode == found && !transList[i].IsProcessed)
+ {
+ string sku = transList[i].SkuNumber;
+ int foundQty = transList[i].Quantity;
+ int foundQtyUnAllocated = foundQty;
+
+ //loop though list and find matching missing
+ for (int j = 0; j < transList.Count; j++)
+ {
+ // we have a match
+ if (transList[j].SkuNumber == sku && !transList[j].IsProcessed && transType.TypeCode == lost)
+ {
+ // split transaction and break
+ if (foundQtyUnAllocated - transList[j].Quantity < 0)
+ {
+ // create and validate clone
+ var clone = transList[j].Clone();
+ clone.Quantity = (short)foundQtyUnAllocated;
+ clone.IsProcessed = true;
+
+ // modifiy and validate existing record
+ transList[j].IsProcessed = false;
+ transList[j].Quantity = (short)(transList[j].Quantity - foundQtyUnAllocated);
+ foundQtyUnAllocated = 0;
+
+ // submitt to database
+ dbSkuTransaction.Create(clone);
+ dbSkuTransaction.Update(transList[j]);
+ }
+ // set as isprocessed and continue
+ else
+ {
+ foundQtyUnAllocated = foundQtyUnAllocated - transList[j].Quantity;
+ transList[j].IsProcessed = true;
+
+ dbSkuTransaction.Update(transList[j]);
+ }
+
+ // break?
+ if (foundQtyUnAllocated == 0)
+ {
+ break;
+ }
+ }
+ }
+
+ // update the found record
+ if (foundQty != foundQtyUnAllocated)
+ {
+ // set isprocess = true
+ if (foundQtyUnAllocated == 0)
+ {
+ transList[i].IsProcessed = true;
+ dbSkuTransaction.Update(transList[i]);
+ }
+ // split record
+ else if (foundQtyUnAllocated > 0)
+ {
+ throw new NotImplementedException();
+
+ // create clone
+ var clone = transList[i].Clone();
+ clone.Quantity -= (short)foundQtyUnAllocated;
+ clone.IsProcessed = true;
+
+ // modifiy and validate existing record
+ transList[i].IsProcessed = false;
+ transList[i].Quantity -= (short)foundQtyUnAllocated;
+ foundQtyUnAllocated = 0;
+
+ // submitt to database
+ dbSkuTransaction.Create(clone);
+ dbSkuTransaction.Update(transList[i]);
+ }
+ // this shouldn't happen
+ else
+ {
+ throw new Exception("Quantity unallocated is negative number");
+ }
+ }
+ }
+ }
+ scope.Complete();
+ }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Stock/SkuTransactionTypePersistance.cs b/src/bnhtrade.Core/Logic/Stock/SkuTransactionTypePersistance.cs
new file mode 100644
index 0000000..e93bc41
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Stock/SkuTransactionTypePersistance.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Stock
+{
+ public class SkuTransactionTypePersistance
+ {
+ private string sqlConnectionString;
+ private List cache;
+ private Data.Database.Stock.ReadSkuTransactionType dbRead;
+
+ public SkuTransactionTypePersistance(string sqlConnectionString)
+ {
+ this.sqlConnectionString = sqlConnectionString;
+ dbRead = new Data.Database.Stock.ReadSkuTransactionType(sqlConnectionString);
+ InnitCache();
+ }
+
+ public void InnitCache()
+ {
+ cache = new List();
+ }
+
+ public Model.Stock.SkuTransactionType GetByTypeCode(string typeCode, bool clearCache = false)
+ {
+ if (string.IsNullOrWhiteSpace(typeCode))
+ {
+ return null;
+ }
+
+ if (clearCache)
+ {
+ InnitCache();
+ }
+ else
+ {
+ for (int i = 0; i < cache.Count; i++)
+ {
+ if (cache[i].TypeCode == typeCode)
+ {
+ return cache[i];
+ }
+ }
+ }
+
+ var result = dbRead.ByTypeCode(new List { typeCode });
+
+ if (result.Any())
+ {
+ cache.Add(result[0]);
+ return result[0];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public Model.Stock.SkuTransactionType GetByTypeName(string typeName, bool clearCache = false)
+ {
+ if (string.IsNullOrWhiteSpace(typeName))
+ {
+ return null;
+ }
+
+ if (clearCache)
+ {
+ InnitCache();
+ }
+ else
+ {
+ for (int i = 0; i < cache.Count; i++)
+ {
+ if (cache[i].TypeName == typeName)
+ {
+ return cache[i];
+ }
+ }
+ }
+
+ var result = dbRead.ByTypeName(new List { typeName });
+
+ if (result.Any())
+ {
+ cache.Add(result[0]);
+ return result[0];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Utilities/CalculateMD5.cs b/src/bnhtrade.Core/Logic/Utilities/CalculateMD5.cs
new file mode 100644
index 0000000..ae1af28
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Utilities/CalculateMD5.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Utilities
+{
+ public class CalculateMD5
+ {
+ public string Base64(Stream stream)
+ {
+ stream.Position = 0;
+
+ MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
+ byte[] hash = provider.ComputeHash(stream);
+ string returnvalue = Convert.ToBase64String(hash);
+ return returnvalue;
+ }
+
+ public string Base64(byte[] byteArray)
+ {
+ MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
+ byte[] hash = provider.ComputeHash(byteArray);
+ string returnvalue = Convert.ToBase64String(hash);
+ return returnvalue;
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs b/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs
index e5d63ac..dacc3fe 100644
--- a/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs
+++ b/src/bnhtrade.Core/Logic/Utilities/DateTimeCheck.cs
@@ -6,18 +6,18 @@ using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Utilities
{
- public class DateTimeCheck : Validate
+ public class DateTimeCheck : Validate.Validate
{
public bool IsUtc(DateTime dateTimeToCheck)
{
if (dateTimeToCheck == default(DateTime))
{
- ErrorListAdd( "DateTime value set to default.");
+ ValidationResultAdd( "DateTime value set to default.");
return false;
}
if (dateTimeToCheck.Kind != DateTimeKind.Utc)
{
- ErrorListAdd("DateTime not set to UTC kind.");
+ ValidationResultAdd("DateTime not set to UTC kind.");
return false;
}
return true;
@@ -26,12 +26,12 @@ namespace bnhtrade.Core.Logic.Utilities
{
if (dateTimeToCheck == default(DateTime))
{
- ErrorListAdd("DateTime value set to default.");
+ ValidationResultAdd("DateTime value set to default.");
return false;
}
if (dateTimeToCheck.Kind != DateTimeKind.Local)
{
- ErrorListAdd("DateTime not set to Local kind.");
+ ValidationResultAdd("DateTime not set to Local kind.");
return false;
}
return true;
diff --git a/src/bnhtrade.Core/Logic/Utilities/DateTimeParse.cs b/src/bnhtrade.Core/Logic/Utilities/DateTimeParse.cs
new file mode 100644
index 0000000..970a387
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Utilities/DateTimeParse.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Utilities
+{
+ public class DateTimeParse
+ {
+ public DateTime ParseMwsReportDateTime(string reportDateTime)
+ {
+ string isoDateTime =
+ reportDateTime.Substring(6, 4) + "-" +
+ reportDateTime.Substring(3, 2) + "-" +
+ reportDateTime.Substring(0, 2) + "T" +
+ reportDateTime.Substring(11, 2) + ":" +
+ reportDateTime.Substring(14, 2) + ":" +
+ reportDateTime.Substring(17, 2) + "Z";
+ return DateTime.Parse(isoDateTime);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Utilities/DecimalCheck.cs b/src/bnhtrade.Core/Logic/Utilities/DecimalCheck.cs
index eed1d1a..1448e67 100644
--- a/src/bnhtrade.Core/Logic/Utilities/DecimalCheck.cs
+++ b/src/bnhtrade.Core/Logic/Utilities/DecimalCheck.cs
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Utilities
{
- public class DecimalCheck : Validate
+ public class DecimalCheck : Validate.Validate
{
///
/// Finds total number of digits in a decimal number, does not include decimal point.
@@ -36,13 +36,13 @@ namespace bnhtrade.Core.Logic.Utilities
int precision = GetPrecision(decimalToCheck);
if (precision > 2)
{
- ErrorListAdd("Decimal precision overload");
+ ValidationResultAdd("Decimal precision overload");
return false;
}
int length = GetLength(decimalToCheck);
if (length > 9)
{
- ErrorListAdd("Decimal length overload");
+ ValidationResultAdd("Decimal length overload");
return false;
}
return true;
diff --git a/src/bnhtrade.Core/Logic/Utilities/StringCheck.cs b/src/bnhtrade.Core/Logic/Utilities/StringCheck.cs
index b75429e..79f51a3 100644
--- a/src/bnhtrade.Core/Logic/Utilities/StringCheck.cs
+++ b/src/bnhtrade.Core/Logic/Utilities/StringCheck.cs
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Utilities
{
- public class StringCheck : Validate
+ public class StringCheck : Validate.Validate
{
public bool AllowEmpty { get; set; } = false;
public bool AllowWhiteSpace { get; set; } = false;
@@ -22,7 +22,7 @@ namespace bnhtrade.Core.Logic.Utilities
{
if (!allowNull)
{
- ErrorListAdd("String is null");
+ ValidationResultAdd("String is null");
return false;
}
}
@@ -35,12 +35,12 @@ namespace bnhtrade.Core.Logic.Utilities
{
if ((c >= 'a' && c <= 'z') && upperCaseOnly)
{
- ErrorListAdd("String contains lower case numerical charater(s).");
+ ValidationResultAdd("String contains lower case numerical charater(s).");
return false;
}
else
{
- ErrorListAdd("String contains non-alpha charater(s).");
+ ValidationResultAdd("String contains non-alpha charater(s).");
return false;
}
}
@@ -54,7 +54,7 @@ namespace bnhtrade.Core.Logic.Utilities
{
if (!allowNull)
{
- ErrorListAdd("String is null");
+ ValidationResultAdd("String is null");
return false;
}
}
@@ -68,12 +68,12 @@ namespace bnhtrade.Core.Logic.Utilities
{
if ((c >= 'a' && c <= 'z') && upperCaseOnly)
{
- ErrorListAdd("String contains lower case numerical charater(s).");
+ ValidationResultAdd("String contains lower case numerical charater(s).");
return false;
}
else
{
- ErrorListAdd("String contains non-alphanumeric charater(s).");
+ ValidationResultAdd("String contains non-alphanumeric charater(s).");
return false;
}
}
@@ -87,7 +87,7 @@ namespace bnhtrade.Core.Logic.Utilities
{
if (allowNull == false)
{
- ErrorListAdd("String is null");
+ ValidationResultAdd("String is null");
return false;
}
}
@@ -97,7 +97,7 @@ namespace bnhtrade.Core.Logic.Utilities
{
if (c < '0' || c > '9')
{
- ErrorListAdd("String contains non-numeric charater(s).");
+ ValidationResultAdd("String contains non-numeric charater(s).");
return false;
}
}
@@ -114,7 +114,7 @@ namespace bnhtrade.Core.Logic.Utilities
int length = stringToCheck.Length;
if (length != stringLength)
{
- ErrorListAdd("String length (" + length + ") does not equal " + stringLength + " charaters.");
+ ValidationResultAdd("String length (" + length + ") does not equal " + stringLength + " charaters.");
return false;
}
return true;
@@ -131,7 +131,7 @@ namespace bnhtrade.Core.Logic.Utilities
int length = stringToCheck.Length;
if (length > maxLength)
{
- ErrorListAdd("String length (" + length + ") is greater than " + maxLength + " charaters.");
+ ValidationResultAdd("String length (" + length + ") is greater than " + maxLength + " charaters.");
return false;
}
}
@@ -147,7 +147,7 @@ namespace bnhtrade.Core.Logic.Utilities
int length = stringToCheck.Length;
if (length <= minLength)
{
- ErrorListAdd("String length (" + length + ") is less than " + minLength + " charaters.");
+ ValidationResultAdd("String length (" + length + ") is less than " + minLength + " charaters.");
return false;
}
return true;
@@ -161,7 +161,7 @@ namespace bnhtrade.Core.Logic.Utilities
{
if (!allowNull)
{
- ErrorListAdd("String is null, empty or white space.");
+ ValidationResultAdd("String is null, empty or white space.");
return false;
}
}
@@ -169,7 +169,7 @@ namespace bnhtrade.Core.Logic.Utilities
{
if (!AllowEmpty)
{
- ErrorListAdd("String is empty.");
+ ValidationResultAdd("String is empty.");
return false;
}
}
@@ -177,7 +177,7 @@ namespace bnhtrade.Core.Logic.Utilities
{
if (!AllowWhiteSpace)
{
- ErrorListAdd("String is white space.");
+ ValidationResultAdd("String is white space.");
return false;
}
}
diff --git a/src/bnhtrade.Core/Logic/Validate.cs b/src/bnhtrade.Core/Logic/Validate.cs
deleted file mode 100644
index 6c56590..0000000
--- a/src/bnhtrade.Core/Logic/Validate.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace bnhtrade.Core.Logic
-{
- public abstract class Validate
- {
- private List errorList = new List();
-
- public List ErrorList
- {
- get { return errorList; }
- }
-
- public bool ErrorListIsSet
- {
- get
- {
- if (errorList == null || !errorList.Any()) { return false; }
- else { return true; }
- }
- }
-
- protected void ErrorListAdd(string errorString)
- {
- this.errorList.Add(errorString);
- }
-
- protected void ErrorListAdd(List errorList)
- {
- this.errorList.AddRange(errorList);
- }
-
- public string ErrorListToString()
- {
- if (ErrorListIsSet)
- {
- StringBuilder result = new StringBuilder();
- for (int i = 0; i < ErrorList.Count; i++)
- {
- result.AppendLine(ErrorList[i]);
- }
- return result.ToString();
- }
- else { return null; }
- }
-
- public void Innit()
- {
- this.errorList = new List();
- }
- }
-}
diff --git a/src/bnhtrade.Core/Logic/Account/ValidateAccountCode.cs b/src/bnhtrade.Core/Logic/Validate/AccountCode.cs
similarity index 79%
rename from src/bnhtrade.Core/Logic/Account/ValidateAccountCode.cs
rename to src/bnhtrade.Core/Logic/Validate/AccountCode.cs
index 0d3980f..e252f42 100644
--- a/src/bnhtrade.Core/Logic/Account/ValidateAccountCode.cs
+++ b/src/bnhtrade.Core/Logic/Validate/AccountCode.cs
@@ -4,9 +4,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace bnhtrade.Core.Logic.Account
+namespace bnhtrade.Core.Logic.Validate
{
- public class ValidateAccountCode : Validate
+ public class AccountCode : Validate
{
private Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck();
@@ -21,7 +21,7 @@ namespace bnhtrade.Core.Logic.Account
{ return true; }
else
{
- ErrorListAdd("Invalid account code.");
+ ValidationResultAdd("Invalid account code.");
return false;
}
}
@@ -33,7 +33,7 @@ namespace bnhtrade.Core.Logic.Account
}
else
{
- ErrorListAdd(stringCheck.ErrorList);
+ ValidationResultAdd(stringCheck.ValidationResult);
return false;
}
}
@@ -45,7 +45,7 @@ namespace bnhtrade.Core.Logic.Account
}
else
{
- ErrorListAdd(stringCheck.ErrorList);
+ ValidationResultAdd(stringCheck.ValidationResult);
return false;
}
}
@@ -57,7 +57,7 @@ namespace bnhtrade.Core.Logic.Account
}
else
{
- ErrorListAdd(stringCheck.ErrorList);
+ ValidationResultAdd(stringCheck.ValidationResult);
return false;
}
}
@@ -69,7 +69,7 @@ namespace bnhtrade.Core.Logic.Account
}
else
{
- ErrorListAdd(stringCheck.ErrorList);
+ ValidationResultAdd(stringCheck.ValidationResult);
return false;
}
}
diff --git a/src/bnhtrade.Core/Logic/Validate/AmazonIventoryLoaderFile.cs b/src/bnhtrade.Core/Logic/Validate/AmazonIventoryLoaderFile.cs
new file mode 100644
index 0000000..28d5e8a
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Validate/AmazonIventoryLoaderFile.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Validate
+{
+ public class AmazonIventoryLoaderFile : Validate
+ {
+ public bool IsValidFbaPricing(IEnumerable exportList)
+ {
+ if (!IsValid(exportList))
+ {
+ return false;
+ }
+
+ return IsValidResult;
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Import/ValidateAmazonSettlement.cs b/src/bnhtrade.Core/Logic/Validate/AmazonSettlement.cs
similarity index 71%
rename from src/bnhtrade.Core/Logic/Import/ValidateAmazonSettlement.cs
rename to src/bnhtrade.Core/Logic/Validate/AmazonSettlement.cs
index 63a1c21..eb98720 100644
--- a/src/bnhtrade.Core/Logic/Import/ValidateAmazonSettlement.cs
+++ b/src/bnhtrade.Core/Logic/Validate/AmazonSettlement.cs
@@ -4,16 +4,16 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace bnhtrade.Core.Logic.Import
+namespace bnhtrade.Core.Logic.Validate
{
- public class ValidateAmazonSettlement : Validate
+ public class AmazonSettlement : Validate
{
protected Utilities.StringCheck stringCheck = new Utilities.StringCheck();
protected Utilities.DateTimeCheck timeCheck = new Utilities.DateTimeCheck();
- protected Account.ValidateCurrencyCode currencyCheck = new Account.ValidateCurrencyCode();
+ protected Logic.Validate.CurrencyCode currencyCheck = new Logic.Validate.CurrencyCode();
protected Utilities.DecimalCheck decimalCheck = new Utilities.DecimalCheck();
- public ValidateAmazonSettlement() : base()
+ public AmazonSettlement() : base()
{
}
@@ -40,38 +40,38 @@ namespace bnhtrade.Core.Logic.Import
for (int i = 0; i < settlementList.Count; i++)
{
- if (!settlementList[i].CurrencyCodeIsSet) { ErrorListAdd("CurrencyCode is a required value."); }
+ if (!settlementList[i].CurrencyCodeIsSet) { ValidationResultAdd("CurrencyCode is a required value."); }
else { IsValidCurrencyCode(settlementList[i].CurrencyCode); }
- if (!settlementList[i].DepositDateIsSet) { ErrorListAdd("DepositDate is a required value."); }
+ if (!settlementList[i].DepositDateIsSet) { ValidationResultAdd("DepositDate is a required value."); }
else { IsValidDepositDate(settlementList[i].DepositDate); }
- if (!settlementList[i].EndDateIsSet) { ErrorListAdd("EndDate is a required value."); }
+ if (!settlementList[i].EndDateIsSet) { ValidationResultAdd("EndDate is a required value."); }
else { IsValidEndDate(settlementList[i].EndDate); }
- if (!settlementList[i].IsProcessedIsSet) { ErrorListAdd("IsProcessed is a required value."); }
+ if (!settlementList[i].IsProcessedIsSet) { ValidationResultAdd("IsProcessed is a required value."); }
else { IsValidIsProcessed(settlementList[i].IsProcessed); }
if (!settlementList[i].MarketPlaceNameIsSet)
{
- if (ValidateMarketPlaceName) { ErrorListAdd("MarketPlaceName is a required value."); }
+ if (ValidateMarketPlaceName) { ValidationResultAdd("MarketPlaceName is a required value."); }
}
else { IsValidMarketPlaceName(settlementList[i].MarketPlaceName); }
- if (!settlementList[i].SettlementIdIsSet) { ErrorListAdd("SettlementId is a required value."); }
+ if (!settlementList[i].SettlementIdIsSet) { ValidationResultAdd("SettlementId is a required value."); }
else { IsValidSettlementId(settlementList[i].SettlementId); }
- if (!settlementList[i].StartDateIsSet) { ErrorListAdd("StartDate is a required value."); }
+ if (!settlementList[i].StartDateIsSet) { ValidationResultAdd("StartDate is a required value."); }
else { IsValidStartDate(settlementList[i].StartDate); }
- if (!settlementList[i].TotalAmountIsSet) { ErrorListAdd("TotalAmount is a required value."); }
+ if (!settlementList[i].TotalAmountIsSet) { ValidationResultAdd("TotalAmount is a required value."); }
else { IsValidTotalAmount(settlementList[i].TotalAmount); }
// check line list
if (!settlementList[i].SettlementLineListIsSet)
{
- ErrorListAdd("Settlement line list is null or empty");
+ ValidationResultAdd("Settlement line list is null or empty");
continue;
}
else
@@ -88,14 +88,13 @@ namespace bnhtrade.Core.Logic.Import
// check totals
if (lineSum != settlementList[i].TotalAmount)
{
- ErrorListAdd("Settlement header total (" + settlementList[i].TotalAmount +
+ ValidationResultAdd("Settlement header total (" + settlementList[i].TotalAmount +
") does not match line total (" + lineSum + ")");
}
}
}
- if (ErrorListIsSet) { return false; }
- else { return true; }
+ return IsValidResult;
}
public bool IsValid(Model.Import.AmazonSettlement.SettlementLine settlementLine)
@@ -111,7 +110,7 @@ namespace bnhtrade.Core.Logic.Import
}
else
{
- ErrorListAdd("Amount is a required value.");
+ ValidationResultAdd("Amount is a required value.");
}
@@ -121,7 +120,7 @@ namespace bnhtrade.Core.Logic.Import
}
else
{
- ErrorListAdd("Amount Description is a required value.");
+ ValidationResultAdd("Amount Description is a required value.");
}
@@ -131,7 +130,7 @@ namespace bnhtrade.Core.Logic.Import
}
else
{
- ErrorListAdd("Amount Type is a required value.");
+ ValidationResultAdd("Amount Type is a required value.");
}
@@ -141,7 +140,7 @@ namespace bnhtrade.Core.Logic.Import
}
else
{
- ErrorListAdd("Currency Code is a required value.");
+ ValidationResultAdd("Currency Code is a required value.");
}
@@ -161,7 +160,7 @@ namespace bnhtrade.Core.Logic.Import
}
else
{
- ErrorListAdd("Is Processed is a required value.");
+ ValidationResultAdd("Is Processed is a required value.");
}
@@ -201,7 +200,7 @@ namespace bnhtrade.Core.Logic.Import
}
else
{
- ErrorListAdd("Posted DateTime is a required value.");
+ ValidationResultAdd("Posted DateTime is a required value.");
}
if (settlementLine.PromotionIdIsSet)
@@ -230,23 +229,22 @@ namespace bnhtrade.Core.Logic.Import
}
else
{
- ErrorListAdd("Transaction Type is a required value.");
+ ValidationResultAdd("Transaction Type is a required value.");
}
- if (ErrorListIsSet) { return false; }
- else { return true; }
+ return IsValidResult;
}
public bool IsValidSettlementId(string settlementId)
{
if (!stringCheck.IsNumeric(settlementId))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid settlement Id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid settlement Id: " + x).ToList());
return false;
}
if (!stringCheck.MaxLength(settlementId, 50))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid settlement Id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid settlement Id: " + x).ToList());
return false;
}
return true;
@@ -261,7 +259,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(marketPlaceName, 50, true))
{
- ErrorListAdd("Invalid market place name.");
+ ValidationResultAdd("Invalid market place name.");
return false;
}
return true;
@@ -271,7 +269,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!timeCheck.IsUtc(startDate))
{
- ErrorListAdd(timeCheck.ErrorList.Select(x => "Invalid StartDate: " + x).ToList());
+ ValidationResultAdd(timeCheck.ValidationResult.Select(x => "Invalid StartDate: " + x).ToList());
return false;
}
return true;
@@ -281,7 +279,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!timeCheck.IsUtc(endDate))
{
- ErrorListAdd(timeCheck.ErrorList.Select(x => "Invalid EndDate: " + x).ToList());
+ ValidationResultAdd(timeCheck.ValidationResult.Select(x => "Invalid EndDate: " + x).ToList());
return false;
}
return true;
@@ -291,7 +289,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!timeCheck.IsUtc(depositDate))
{
- ErrorListAdd(timeCheck.ErrorList.Select(x => "Invalid DepositDate: " + x).ToList());
+ ValidationResultAdd(timeCheck.ValidationResult.Select(x => "Invalid DepositDate: " + x).ToList());
return false;
}
return true;
@@ -301,7 +299,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!decimalCheck.SqlLength92(totalAmount))
{
- ErrorListAdd(decimalCheck.ErrorList.Select(x => "Total Amount Invalid: " + x).ToList());
+ ValidationResultAdd(decimalCheck.ValidationResult.Select(x => "Total Amount Invalid: " + x).ToList());
return false;
}
return true;
@@ -311,7 +309,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!currencyCheck.IsValidCurrencyCode(currencyCode))
{
- ErrorListAdd(currencyCheck.ErrorList.Select(x => "Total Amount CurrencyCode: " + x).ToList());
+ ValidationResultAdd(currencyCheck.ValidationResult.Select(x => "Total Amount CurrencyCode: " + x).ToList());
return false;
}
return true;
@@ -338,7 +336,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(transactionType, 50))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid transaction type: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid transaction type: " + x).ToList());
return false;
}
return true;
@@ -347,7 +345,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(orderId, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid order id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid order id: " + x).ToList());
return false;
}
return true;
@@ -356,7 +354,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(merchantOrderId, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid merchant order id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid merchant order id: " + x).ToList());
return false;
}
return true;
@@ -365,7 +363,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(adjustmentId, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid adjustment id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid adjustment id: " + x).ToList());
return false;
}
return true;
@@ -374,7 +372,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(shipmentId, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid shipment id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid shipment id: " + x).ToList());
return false;
}
return true;
@@ -383,7 +381,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(amountType, 50))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid amount type: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid amount type: " + x).ToList());
return false;
}
return true;
@@ -392,7 +390,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(amountDescription, 100))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid amount description: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid amount description: " + x).ToList());
return false;
}
return true;
@@ -401,7 +399,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!decimalCheck.SqlLength92(amount))
{
- ErrorListAdd(decimalCheck.ErrorList.Select(x => "Invalid amount: " + x).ToList());
+ ValidationResultAdd(decimalCheck.ValidationResult.Select(x => "Invalid amount: " + x).ToList());
return false;
}
return true;
@@ -410,7 +408,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!currencyCheck.IsValidCurrencyCode(currenyCode))
{
- ErrorListAdd(currencyCheck.ErrorList.Select(x => "Invalid curreny code: " + x).ToList());
+ ValidationResultAdd(currencyCheck.ValidationResult.Select(x => "Invalid curreny code: " + x).ToList());
return false;
}
return true;
@@ -419,7 +417,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(fulfillmentId, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid fulfillment Id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid fulfillment Id: " + x).ToList());
return false;
}
return true;
@@ -429,7 +427,7 @@ namespace bnhtrade.Core.Logic.Import
var timeCheck = new Logic.Utilities.DateTimeCheck();
if (!timeCheck.IsUtc(postDateTime))
{
- ErrorListAdd(@"Invalid post date/time, not set to UTC kind.");
+ ValidationResultAdd(@"Invalid post date/time, not set to UTC kind.");
return false;
}
return true;
@@ -438,7 +436,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(orderItemCode, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid order item code: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid order item code: " + x).ToList());
return false;
}
return true;
@@ -447,7 +445,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(merchantOrderItemId, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid merchant order item id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid merchant order item id: " + x).ToList());
return false;
}
return true;
@@ -456,7 +454,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(merchantAdjustmentItemId, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid merchant adjustment item id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid merchant adjustment item id: " + x).ToList());
return false;
}
return true;
@@ -465,7 +463,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(skuNumber, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid sku number: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid sku number: " + x).ToList());
return false;
}
return true;
@@ -478,7 +476,7 @@ namespace bnhtrade.Core.Logic.Import
{
if (!stringCheck.MaxLength(promotionId, 50, true))
{
- ErrorListAdd(stringCheck.ErrorList.Select(x => "Invalid promotion id: " + x).ToList());
+ ValidationResultAdd(stringCheck.ValidationResult.Select(x => "Invalid promotion id: " + x).ToList());
return false;
}
return true;
@@ -491,7 +489,7 @@ namespace bnhtrade.Core.Logic.Import
}
else
{
- ErrorListAdd("Export account invoice line id cannot be less than 1");
+ ValidationResultAdd("Export account invoice line id cannot be less than 1");
return false;
}
}
diff --git a/src/bnhtrade.Core/Logic/Account/ValidateCurrencyCode.cs b/src/bnhtrade.Core/Logic/Validate/CurrencyCode.cs
similarity index 82%
rename from src/bnhtrade.Core/Logic/Account/ValidateCurrencyCode.cs
rename to src/bnhtrade.Core/Logic/Validate/CurrencyCode.cs
index 478f842..e2acf9f 100644
--- a/src/bnhtrade.Core/Logic/Account/ValidateCurrencyCode.cs
+++ b/src/bnhtrade.Core/Logic/Validate/CurrencyCode.cs
@@ -5,9 +5,9 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-namespace bnhtrade.Core.Logic.Account
+namespace bnhtrade.Core.Logic.Validate
{
- public class ValidateCurrencyCode : Validate
+ public class CurrencyCode : Validate
{
private Logic.Utilities.StringCheck stringCheck = new Logic.Utilities.StringCheck();
public new void Innit()
@@ -23,7 +23,7 @@ namespace bnhtrade.Core.Logic.Account
}
else
{
- ErrorListAdd(stringCheck.ErrorList);
+ ValidationResultAdd(stringCheck.ValidationResult);
return false;
}
}
diff --git a/src/bnhtrade.Core/Logic/Validate/SalesInvoice.cs b/src/bnhtrade.Core/Logic/Validate/SalesInvoice.cs
new file mode 100644
index 0000000..74570c1
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Validate/SalesInvoice.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Validate
+{
+ public class SalesInvoice : Logic.Validate.Validate
+ {
+ public SalesInvoice()
+ {
+ }
+
+ public bool IsValidExportInvoice(IEnumerable invoiceList)
+ {
+ if (!IsValid(invoiceList))
+ {
+ return false;
+ }
+
+ foreach (var invoice in invoiceList)
+ {
+ if (invoice.UnitAmountIsTaxExclusive == false)
+ {
+ ValidationResultAdd("Tax inclusive line unit amounts are not supported");
+ return false;
+ }
+
+ foreach (var invoiceLine in invoice.InvoiceLineList)
+ {
+ if (invoiceLine.Quantity != 1)
+ {
+ ValidationResultAdd("Quantities greater than 1 are not supported");
+ return false;
+ }
+ }
+ }
+
+ return IsValidResult;
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Validate/SkuPriceInfo.cs b/src/bnhtrade.Core/Logic/Validate/SkuPriceInfo.cs
new file mode 100644
index 0000000..ca739b7
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Validate/SkuPriceInfo.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Validate
+{
+ public class SkuPriceInfo : Validate
+ {
+ public SkuPriceInfo()
+ {
+ Innit();
+ }
+
+ public bool IsValidDatabaseCreate(List priceInfoList)
+ {
+ Innit();
+
+ if (!IsValid(priceInfoList))
+ {
+ return false;
+ }
+
+ return IsValidResult;
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Validate/SkuTransaction.cs b/src/bnhtrade.Core/Logic/Validate/SkuTransaction.cs
new file mode 100644
index 0000000..1a7db22
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Validate/SkuTransaction.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Validate
+{
+ public class SkuTransaction : Validate
+ {
+ public bool DatabaseUpdate(Model.Stock.SkuTransaction skuTransaction)
+ {
+ return IsValid(new List { skuTransaction });
+ }
+
+ public bool DatabaseUpdate(List skuTransactionList)
+ {
+ if (!IsValid(skuTransactionList))
+ {
+ return false;
+ }
+
+ for (int i = 0; i < skuTransactionList.Count; i++)
+ {
+ if (!skuTransactionList[i].IsSetSkuTransactionId)
+ {
+ ValidationResultAdd("StockTransactionId is required");
+ }
+ }
+
+ return IsValidResult;
+ }
+
+ public bool DatabaseInsert(Model.Stock.SkuTransaction skuTransaction)
+ {
+ return IsValid(new List { skuTransaction });
+ }
+
+ public bool DatabaseInsert(List skuTransactionList)
+ {
+ return IsValid(skuTransactionList);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Validate/TaxCodeInfo.cs b/src/bnhtrade.Core/Logic/Validate/TaxCodeInfo.cs
new file mode 100644
index 0000000..d4f1dff
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Validate/TaxCodeInfo.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace bnhtrade.Core.Logic.Validate
+{
+ public class TaxCodeInfo : Validate
+ {
+ public bool IsValidPresistanceGet(Model.Account.TaxCodeInfo taxCodeInfo)
+ {
+ return IsValid(taxCodeInfo);
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Logic/Validate/Validate.cs b/src/bnhtrade.Core/Logic/Validate/Validate.cs
new file mode 100644
index 0000000..589f948
--- /dev/null
+++ b/src/bnhtrade.Core/Logic/Validate/Validate.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.ComponentModel.DataAnnotations;
+
+namespace bnhtrade.Core.Logic.Validate
+{
+ public abstract class Validate
+ {
+ public List ValidationResult { get; set; } = new List();
+
+ public bool IsValidResult
+ {
+ get
+ {
+ if (ValidationResult.Any()) { return false; }
+ else { return true; }
+ }
+ }
+
+ public void Innit()
+ {
+ ValidationResult = new List();
+ }
+
+ protected bool IsValid(IValidatableObject validatableObject)
+ {
+ if (validatableObject == null)
+ {
+ ValidationResult.Add(new ValidationResult("Validatable object is null"));
+ return false;
+ }
+
+ var validationContext = new ValidationContext(validatableObject);
+ ValidationResult.AddRange(validatableObject.Validate(validationContext));
+ return IsValidResult;
+ }
+
+ protected bool IsValid(IEnumerable validatableObjectList)
+ {
+ if (validatableObjectList == null || !validatableObjectList.Any())
+ {
+ ValidationResult.Add(new ValidationResult("Validatable object list is empty or null"));
+ return false;
+ }
+
+ foreach (var validatableObject in validatableObjectList)
+ {
+ if (!IsValid(validatableObject)) { return false; }
+ }
+
+ return IsValidResult;
+ }
+
+ protected void ValidationResultAdd(string result)
+ {
+ ValidationResult.Add(new ValidationResult(result));
+ }
+
+ protected void ValidationResultAdd(List result)
+ {
+ foreach (var item in result)
+ {
+ ValidationResultAdd(item);
+ }
+ }
+
+ protected void ValidationResultAdd(ValidationResult result)
+ {
+ ValidationResult.Add(result);
+ }
+
+ protected void ValidationResultAdd(List result)
+ {
+ ValidationResult.AddRange(result);
+ }
+
+ public string ValidationResultListToString()
+ {
+ if (IsValidResult == false)
+ {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < ValidationResult.Count; i++)
+ {
+ result.AppendLine(ValidationResult[i].ErrorMessage);
+ }
+ return result.ToString();
+ }
+ else { return null; }
+ }
+ }
+}
diff --git a/src/bnhtrade.Core/Model/Account/AccountCode.cs b/src/bnhtrade.Core/Model/Account/AccountCode.cs
index 054a14e..861ea3c 100644
--- a/src/bnhtrade.Core/Model/Account/AccountCode.cs
+++ b/src/bnhtrade.Core/Model/Account/AccountCode.cs
@@ -1,58 +1,86 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Account
{
- public class AccountCode
+ public class AccountCode : IValidatableObject
{
private int? accountCodeId;
+
+ [Required(), Range(1, int.MaxValue)]
public int AccountCodeId
{
get { return (int)accountCodeId; }
set { accountCodeId = value; }
}
+
+ [Required(), MaxLength(150)]
public string Title
{
get;
set;
}
+
+ [MaxLength(500)]
public string Description
{
get;
set;
}
+
+ [Required(), MaxLength(50)]
public string Type
{
get;
set;
}
+
+ [Required(), MaxLength(50)]
public string BasicType
{
get;
set;
}
+
public bool IsSetAccountCodeId
{
get { return accountCodeId != null; }
}
+
public bool IsSetTitle
{
get { return Title != null; }
}
+
public bool IsSetDescription
{
get { return Description != null; }
}
+
public bool IsSetType
{
get { return Type != null; }
}
+
public bool IsSetBasicType
{
get { return BasicType != null; }
}
+
+ public IEnumerable Validate(ValidationContext validationContext)
+ {
+ var resultList = new List();
+
+ if (!IsSetAccountCodeId)
+ {
+ resultList.Add(new ValidationResult("Account Code is not set"));
+ }
+
+ return resultList;
+ }
}
}
diff --git a/src/bnhtrade.Core/Model/Account/Invoice.cs b/src/bnhtrade.Core/Model/Account/Invoice.cs
index e00265f..2667f7a 100644
--- a/src/bnhtrade.Core/Model/Account/Invoice.cs
+++ b/src/bnhtrade.Core/Model/Account/Invoice.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -8,6 +9,10 @@ namespace bnhtrade.Core.Model.Account
{
public interface IInvoice : IInvoiceHeader
{
+ decimal InvoiceNetAmount { get; }
+
+ decimal InvoiceTaxAmount { get; }
+
List InvoiceLineList { get; set; }
bool InvoiceLineListIsSet { get; }
@@ -17,163 +22,231 @@ namespace bnhtrade.Core.Model.Account
{
string ItemCode { get; set; }
- bool ItemCodeIsSet { get; }
-
- bool DescriptionIsSet { get; }
-
string Description { get; set; }
- int Quantity { get; set; }
+ decimal? Quantity { get; set; }
- bool QuantityIsSet { get; }
+ decimal? UnitAmount { get; set; }
- decimal TotalNetAmount { get; set; }
+ Model.Account.AccountCode AccountCode { get; set; }
- bool TotalNetAmountIsSet { get; }
+ Model.Account.TaxCodeInfo TaxCode { get; set; }
- bool AccountCodeIsSet { get; }
+ decimal? TaxAmountAdjust { get; set; }
- int AccountCode { get; set; }
+ decimal? TaxAmount { get; }
- bool TaxCodeIsSet { get; }
-
- string TaxCode { get; set; }
-
- decimal TaxAmountAdjust { get; set; }
-
- bool TaxAmountAdjustIsSet { get; }
-
- decimal TaxAmount { get; }
-
- bool TaxAmountIsSet { get; }
-
- decimal GrossTotalAmount { get; }
-
- bool GrossTotalAmountIsSet { get; }
+ decimal LineTotalAmount { get; }
}
public abstract class Invoice : InvoiceHeader, IInvoice
{
+ private bool unitAmountIsTaxExclusive = true;
+
+ public decimal InvoiceNetAmount { get; }
+
+ public decimal InvoiceTaxAmount { get; }
+
+ public bool UnitAmountIsTaxExclusive
+ {
+ get { return unitAmountIsTaxExclusive; }
+ set
+ {
+ unitAmountIsTaxExclusive = value;
+ if (InvoiceLineList != null)
+ {
+ for (int i = 0; i < InvoiceLineList.Count; i++)
+ {
+ InvoiceLineList[i].UnitAmountIsTaxExclusive = unitAmountIsTaxExclusive;
+ }
+ }
+ }
+ }
+
public List InvoiceLineList { get; set; } = new List