Feature repricing min max (#10)

amazon settlement import/export improvements
This commit is contained in:
2020-05-01 09:08:23 +01:00
committed by GitHub
parent 56647c7648
commit 43d61c2ef8
118 changed files with 7930 additions and 3021 deletions

View File

@@ -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.*

View File

@@ -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.

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- -->
<!-- ILMerge project-specific settings. Almost never need to be set explicitly. -->
<!-- for details, see http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx -->
<!-- -->
<!-- *** set this file to Type=None, CopyToOutput=Never *** -->
<!-- If True, all copy local dependencies will also be merged from referenced projects whether they are referenced in the current project explicitly or not -->
<ILMergeTransitive>true</ILMergeTransitive>
<!-- Extra ILMerge library paths (semicolon-separated). Dont put your package dependencies here, they will be added automagically -->
<ILMergeLibraryPath></ILMergeLibraryPath>
<!-- The solution NuGet package directory if not standard 'SOLUTION\packages' -->
<ILMergePackagesPath></ILMergePackagesPath>
<!-- The merge order file name if differs from standard 'ILMergeOrder.txt' -->
<ILMergeOrderFile></ILMergeOrderFile>
<!-- The strong key file name if not specified in the project -->
<ILMergeKeyFile></ILMergeKeyFile>
<!-- The assembly version if differs for the version of the main assembly -->
<ILMergeAssemblyVersion></ILMergeAssemblyVersion>
<!-- added in Version 1.0.4 -->
<ILMergeFileAlignment></ILMergeFileAlignment>
<!-- added in Version 1.0.4, default=none -->
<ILMergeAllowDuplicateType></ILMergeAllowDuplicateType>
<!-- If the <see cref="CopyAttributes"/> is also set, any assembly-level attributes names that have the same type are copied over into the target assembly -->
<ILMergeAllowMultipleAssemblyLevelAttributes></ILMergeAllowMultipleAssemblyLevelAttributes>
<!-- See ILMerge documentation -->
<ILMergeAllowZeroPeKind></ILMergeAllowZeroPeKind>
<!-- The assembly level attributes of each input assembly are copied over into the target assembly -->
<ILMergeCopyAttributes></ILMergeCopyAttributes>
<!-- Creates a .pdb file for the output assembly and merges into it any .pdb files found for input assemblies, default=true -->
<ILMergeDebugInfo>false</ILMergeDebugInfo>
<!-- Target assembly will be delay signed -->
<ILMergeDelaySign></ILMergeDelaySign>
<!-- Types in assemblies other than the primary assembly have their visibility modified -->
<ILMergeInternalize></ILMergeInternalize>
<!-- The path name of the file that will be used to identify types that are not to have their visibility modified -->
<ILMergeInternalizeExcludeFile></ILMergeInternalizeExcludeFile>
<!-- XML documentation files are merged to produce an XML documentation file for the target assembly -->
<ILMergeXmlDocumentation></ILMergeXmlDocumentation>
<!-- External assembly references in the manifest of the target assembly will use full public keys (false) or public key tokens (true, default value) -->
<ILMergePublicKeyTokens></ILMergePublicKeyTokens>
<!-- Types with the same name are all merged into a single type in the target assembly -->
<ILMergeUnionMerge></ILMergeUnionMerge>
<!-- The version of the target framework, default 40 (works for 45 too) -->
<ILTargetPlatform></ILTargetPlatform>
</PropertyGroup>
</Project>

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\MSBuild.ILMerge.Task.1.1.3\build\MSBuild.ILMerge.Task.props" Condition="Exists('..\..\packages\MSBuild.ILMerge.Task.1.1.3\build\MSBuild.ILMerge.Task.props')" />
<Import Project="..\..\packages\ILMerge.3.0.29\build\ILMerge.props" Condition="Exists('..\..\packages\ILMerge.3.0.29\build\ILMerge.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -13,6 +15,8 @@
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -30,6 +34,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
@@ -54,13 +59,20 @@
<Compile Include="Stock\Stock.cs" />
<Compile Include="Utility\LoadComObjextIntoStringArray.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="app.config" />
<None Include="ILMerge.props" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\bnhtrade.Core\bnhtrade.Core.csproj">
<Project>{339d7413-3da7-46ea-a55c-255a9a6b95eb}</Project>
<Name>bnhtrade.Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="ILMergeOrder.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
@@ -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"</PostBuildEvent>
</PropertyGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>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}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\ILMerge.3.0.29\build\ILMerge.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\ILMerge.3.0.29\build\ILMerge.props'))" />
<Error Condition="!Exists('..\..\packages\MSBuild.ILMerge.Task.1.1.3\build\MSBuild.ILMerge.Task.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\MSBuild.ILMerge.Task.1.1.3\build\MSBuild.ILMerge.Task.props'))" />
<Error Condition="!Exists('..\..\packages\MSBuild.ILMerge.Task.1.1.3\build\MSBuild.ILMerge.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\MSBuild.ILMerge.Task.1.1.3\build\MSBuild.ILMerge.Task.targets'))" />
</Target>
<Import Project="..\..\packages\MSBuild.ILMerge.Task.1.1.3\build\MSBuild.ILMerge.Task.targets" Condition="Exists('..\..\packages\MSBuild.ILMerge.Task.1.1.3\build\MSBuild.ILMerge.Task.targets')" />
</Project>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ILMerge" version="3.0.29" targetFramework="net471" />
<package id="MSBuild.ILMerge.Task" version="1.1.3" targetFramework="net471" />
</packages>

View File

@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="e2A_Client.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
<section name="e2A_Client.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<add name="e2A_Client.Properties.Settings.ConnectionString" connectionString="Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=True;User ID=e2A Client;Password=eSYH4EYoK6Guc5KIclhgFDlGc4;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>
<add name="e2A_Client.Properties.Settings.ConnectionString" connectionString="Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=True;User ID=e2A Client;Password=eSYH4EYoK6Guc5KIclhgFDlGc4;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
<applicationSettings>
<e2A_Client.Properties.Settings>
@@ -21,4 +21,12 @@
</setting>
</e2A_Client.Properties.Settings>
</applicationSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

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

View File

@@ -27,7 +27,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
return LastUpdatedBefore != null;
}
public List<Model.AmazonFBAInbound.ShipmentItemInfo> GetByAmazonShipmentId(string amazonShipmentId)
public List<Model.AmazonFba.ShipmentItemInfo> GetByAmazonShipmentId(string amazonShipmentId)
{
// checks
if (amazonShipmentId.Length < 9)
@@ -43,7 +43,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
return ListInboundShipmentItemsGet(request);
}
public List<Model.AmazonFBAInbound.ShipmentItemInfo> GetByDates(DateTime lastUpdatedAfter, DateTime lastUpdatedBefore)
public List<Model.AmazonFba.ShipmentItemInfo> GetByDates(DateTime lastUpdatedAfter, DateTime lastUpdatedBefore)
{
//checks
if (lastUpdatedAfter >= lastUpdatedBefore)
@@ -61,7 +61,7 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
return ListInboundShipmentItemsGet(request);
}
private List<Model.AmazonFBAInbound.ShipmentItemInfo> ListInboundShipmentItemsGet(ListInboundShipmentItemsRequest request)
private List<Model.AmazonFba.ShipmentItemInfo> 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<Model.AmazonFBAInbound.ShipmentItemInfo>();
var returnList = new List<Model.AmazonFba.ShipmentItemInfo>();
// 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;

View File

@@ -14,31 +14,37 @@ namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
/// List of Shipment Status' to return. Default is all status' returned.
/// </summary>
public List<string> ShipmentStatusList { get; set; }
/// <summary>
/// List of Shipment Id to return.
/// </summary>
public List<string> 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<Core.Model.AmazonFBAInbound.ShipmentInfo> GetShipmentInfo()
public List<Core.Model.AmazonFba.ShipmentInfo> 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<Core.Model.AmazonFBAInbound.ShipmentInfo>();
var returnItem = new List<Core.Model.AmazonFba.ShipmentInfo>();
//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;

View File

@@ -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<string> FeedSubmissionIdList { get; set; } = new List<string>();
public int MaxCount { get; set; } = 100;
public List<MarketplaceWebService.Model.FeedSubmissionInfo> 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<MarketplaceWebService.Model.FeedSubmissionInfo>();
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);
}
}
}

View File

@@ -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<string> { 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?
}
}
}
}

View File

@@ -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
{

View File

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

View File

@@ -9,62 +9,34 @@ namespace bnhtrade.Core.Data.Database.Account
{
public class ReadAccountCode : Connection
{
private bool allRetrived;
private Dictionary<int, Model.Account.AccountCode> cache;
protected ReadAccountCode(string sqlConnectionString) : base(sqlConnectionString)
private Data.Database.WhereBuilder sqlWhere = new WhereBuilder();
private List<Model.Account.AccountCode> resultList;
public ReadAccountCode(string sqlConnectionString) : base(sqlConnectionString)
{
allRetrived = false;
cache = new Dictionary<int, Model.Account.AccountCode>();
}
protected void ClearCache()
{
allRetrived = false;
cache.Clear();
}
public List<Model.Account.AccountCode> GetAll()
{
if (allRetrived == false)
{
UpdateCache(-1);
allRetrived = true;
}
var returnList = new List<Model.Account.AccountCode>();
foreach (var item in cache)
public List<Model.Account.AccountCode> All()
{
returnList.Add(item.Value);
Innit();
return Execute(null, null);
}
return returnList;
}
public Model.Account.AccountCode GetByAccountCode(int accountCode)
public List<Model.Account.AccountCode> ByAccountCode(List<int> accountCodeList)
{
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<int, Model.Account.AccountCode>();
Innit();
bool whereClause = false;
if (accountCodeList == null || !accountCodeList.Any())
{
return resultList;
}
sqlWhere.In("tblAccountChartOf.AccountCode", accountCodeList, " WHERE ");
return Execute(sqlWhere.SqlWhereString, sqlWhere.ParameterList);
}
private List<Model.Account.AccountCode> Execute(string sqlWhere, Dictionary<string, object> 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)
resultList.Add(result);
}
}
return resultList;
}
}
}
}
private void Innit()
{
if (cache.ContainsKey(result.AccountCodeId))
{
cache.Remove(result.AccountCodeId);
}
cache.Add(result.AccountCodeId, result);
}
else
{
dicCache.Add(result.AccountCodeId, result);
}
}
}
}
}
}
// update cache
if (!whereClause)
{
cache.Clear();
allRetrived = true;
cache = dicCache;
}
resultList = new List<Model.Account.AccountCode>();
}
}
}

View File

@@ -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<string, int> AccountCodeList { get; private set; }
public Dictionary<string, string> TaxCodeList { get; private set; }
private void Innit()
{
AccountCodeList = new Dictionary<string, int>();
TaxCodeList = new Dictionary<string, string>();
}
public Model.Account.InvoiceLineItem ByItemCode(string itemCode)
{
if (string.IsNullOrWhiteSpace(itemCode)) { return null; }
var result = ByItemCode(new List<string>{ itemCode });
if (!result.Any())
{
return null;
}
else
{
return result[itemCode];
}
}
public Dictionary<string, Model.Account.InvoiceLineItem> ByItemCode(List<string> itemCodeList)
{
Innit();
var resultList = new Dictionary<string, Model.Account.InvoiceLineItem>();
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;
}
}
}
}
}
}

View File

@@ -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<int, Model.Account.InvoiceLineItem>();
cacheTablePkByItemCode = new Dictionary<string, int>();
}
private Dictionary<int, Model.Account.InvoiceLineItem> cacheLineItemByTablePk;
private Dictionary<string, int> 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;
}
}
}
}
}

View File

@@ -9,165 +9,32 @@ namespace bnhtrade.Core.Data.Database.Account
{
public class ReadTaxCode : Connection
{
private bool allRetrived;
private Dictionary<string, Model.Account.TaxCode> cache;
private Data.Database.WhereBuilder whereBuilder;
public ReadTaxCode(string sqlConnectionString) : base(sqlConnectionString)
{
allRetrived = false;
cache = new Dictionary<string, Model.Account.TaxCode>();
}
private void ClearCache()
{
allRetrived = false;
cache.Clear();
}
public List<Model.Account.TaxCode> GetAll()
{
if (allRetrived == false)
{
UpdateCache(null);
allRetrived = true;
whereBuilder = new WhereBuilder();
}
var returnList = new List<Model.Account.TaxCode>();
foreach (var item in cache)
private List<Model.Account.TaxCodeInfo> Execute(string sqlWhere, Dictionary<string, object> parameters)
{
returnList.Add(item.Value);
}
var resultList = new List<Model.Account.TaxCodeInfo>();
return returnList;
}
public Dictionary<string, Model.Account.TaxCode> BySkuNumber(List<string> 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<Tuple<string, string>>();
foreach (var item in skuNumberList)
{
if (!string.IsNullOrWhiteSpace(item))
{
int count = parameterValueList.Count;
var parameterValue = new Tuple<string, string>("@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<Tuple<string, string>>();
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<string, string>(
reader.GetString(0),
reader.GetString(1)
);
skuTaxCodeList.Add(skuTaxCode);
}
}
}
// build dictionary of skuNumber to TaxCodeInfo
var returnDictionary = new Dictionary<string, Model.Account.TaxCode>();
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<string, Model.Account.TaxCode>();
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)
resultList.Add(result);
}
}
}
}
}
return resultList;
}
public List<Model.Account.TaxCodeInfo> GetByTaxCode(List<string> taxcodeList)
{
if (cache.ContainsKey(result.TaxCodeId))
var resultList = new List<Model.Account.TaxCodeInfo>();
if (taxcodeList == null || !taxcodeList.Any())
{
cache.Remove(result.TaxCodeId);
return resultList;
}
cache.Add(result.TaxCodeId, result);
whereBuilder.Innit();
whereBuilder.In("TaxCode", taxcodeList, "WHERE");
return Execute(whereBuilder.SqlWhereString, whereBuilder.ParameterList);
}
else
public List<Model.Account.TaxCodeInfo> GetAllActive()
{
dicCache.Add(result.TaxCodeId, result);
string sqlWhere = @"
WHERE IsActive=@isActive;";
var parameters = new Dictionary<string, object>();
parameters.Add("@isActive", true);
return Execute(sqlWhere, parameters);
}
}
}
}
}
}
// update cache
if (!whereClause)
public Dictionary<string, string> GetTaxCodeBySkuNumber(List<string> skuNumberList)
{
cache.Clear();
allRetrived = true;
cache = dicCache;
var resultList = new Dictionary<string, string>();
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<string, string> GetTaxCodeByInvoiceLineItemCode(List<string> lineItemCode)
{
var resultList = new Dictionary<string, string>();
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;
}
}
}

View File

@@ -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<string> shipmentIdList;
public ReadShipmentInfo(string sqlConnectionString) : base(sqlConnectionString)
{
}
/// <summary>
/// Return active shipments only. Default is false.
/// </summary>
public bool ReturnOnlyActiveShipments { get; set; } = false;
private bool IsSetFbaShipmentIdList
{
get
{
if (FbaShipmentIdList == null || !FbaShipmentIdList.Any()) { return false; }
else { return true; }
}
}
/// <summary>
/// Filter results by Amazon's shipment Id.
/// </summary>
private List<string> FbaShipmentIdList
{
get { return shipmentIdList; }
set
{
if (value != null)
{
// clean list
shipmentIdList = new List<string>();
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<string> { fbaShipmentId };
var result = HeaderByFbaShipmentId(list);
if (result.Any())
{
return result[0];
}
else
{
return null;
}
}
public List<Model.AmazonFba.ShipmentInfo> HeaderByFbaShipmentId(List<string> 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<Model.AmazonFba.ShipmentInfo>();
}
}
/// <summary>
/// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
/// </summary>
/// <param name="amazonShipmentId">Amazon's inbound FBA shipment Id.</param>
/// <returns>Primary key or -1 if match isn't found.</returns>
private List<Model.AmazonFba.ShipmentInfo> 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<Model.AmazonFba.ShipmentInfo>(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;
}
}
}
}

View File

@@ -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<string, int> shipmentPKByAmazonShipmentIdDic;
private Dictionary<int, string> 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
}
}
}
/// <summary>
/// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
/// </summary>
@@ -99,6 +106,7 @@ namespace bnhtrade.Core.Data.Database.FBAInbound
UpdateCache(shipmentPK, amazonShipmentId);
return shipmentPK;
}
private void UpdateCache(int shipmentPK, string amazonShipmentId)
{
if (CacheEnabled)

View File

@@ -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<Model.AmazonFBAInbound.ShipmentInfo> infoList)
public void ExcecuteByList(List<Model.AmazonFba.ShipmentInfo> 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);

View File

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

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database
{
public static class Constants
{
public static int GetProductConditionIdNew()
{
return 10;
}
}
}

View File

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

View File

@@ -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<Model.Account.SalesInvoice> invoiceList)
public void Execute(List<Model.Account.SalesInvoice> 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();
}

View File

@@ -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<Model.Export.AmazonFeedSubmission> ByAmazonFeedSubmissionId(List<string> submissionId)
{
throw new NotImplementedException();
}
public List<Model.Export.AmazonFeedSubmission> GetOpenFeeds()
{
string sql = @"
WHERE tblExportAmazonFeedSubmissionStatus.FeedComplete = @feedComplete
AND FeedSubmissionId IS NOT NULL;";
var parameters = new Dictionary<string, object> { { "@feedComplete", false } };
return Execute(sql, parameters);
}
private List<Model.Export.AmazonFeedSubmission> Execute(string sqlWhereClause, Dictionary<string, object> parameters)
{
var returnList = new List<Model.Export.AmazonFeedSubmission>();
// 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;
}
}
}

View File

@@ -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<Model.Export.AmazonFeedSubmission> { feedSubmission });
}
public void UpdateStatusInfo(List<Model.Export.AmazonFeedSubmission> 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.");
}
}
}
}
}
}

View File

@@ -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<string> shipmentIdList;
public GetShipmentHeaderInfo(string sqlConnectionString) : base(sqlConnectionString) { }
/// <summary>
/// Return active shipments only. Default is false.
/// </summary>
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; }
}
}
/// <summary>
/// Filter results by Amazon's shipment Id.
/// </summary>
public List<string> ShipmentIdList
{
get { return shipmentIdList; }
set
{
if (value != null)
{
// clean list
shipmentIdList = new List<string>();
foreach (string item in value)
{
if (item.Length > 0)
{
shipmentIdList.Add(item);
}
}
if (!ShipmentIdList.Any())
{
shipmentIdList = null;
throw new Exception("Invalid shipment Id set");
}
}
}
}
/// <summary>
/// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
/// </summary>
/// <param name="amazonShipmentId">Amazon's inbound FBA shipment Id.</param>
/// <returns>Primary key or -1 if match isn't found.</returns>
public List<Model.AmazonFBAInbound.ShipmentInfo> 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<string, string>();
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<Model.AmazonFBAInbound.ShipmentInfo>();
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;
}
}
}
}
}
}

View File

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

View File

@@ -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<string, decimal> GetMaxSalePrice(List<string> skuNumber, int timePeriodDay)
{
var returnList = new Dictionary<string, decimal>();
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<string, int> GetSaleCount(List<string> skuNumber, DateTime periodStart, DateTime periodEnd)
{
var returnList = new Dictionary<string, int>();
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);
}
}
}
}

View File

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

View File

@@ -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<Model.Product.CompetitivePrice> 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<Model.Product.CompetitivePrice>();
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<Model.Product.CompetitivePrice> ExecuteSub(List<(int productId, int conditionId)> productIdAndConditionId)
{
var resultList = new List<Model.Product.CompetitivePrice>();
// 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;
}
}
}
}
}
}

View File

@@ -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
{

View File

@@ -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
{

View File

@@ -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<Model.Sku.Price.PriceInfo> 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();
}
}
}
}

View File

@@ -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<Model.Sku.Price.SkuPriceParameter> 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<Model.Sku.Price.SkuPriceParameter>(stringSql).ToList();
if (invPricing != null || invPricing.Any())
{
return invPricing;
}
else
{
return null;
}
}
}
}
}

View File

@@ -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<string, Model.Sku.Price.PriceInfo> ReadDictionary(List<string> skuNumberList, string orderChannel)
{
var dic = new Dictionary<string, Model.Sku.Price.PriceInfo>();
var list = Read(skuNumberList, orderChannel);
for (int i = 0; i < list.Count; i++)
{
dic.Add(list[i].SkuNumber, list[i]);
}
return dic;
}
public List<Model.Sku.Price.PriceInfo> Read(List<string> 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<Model.Sku.Price.PriceInfo>(sql, parameters).ToList();
}
}
}
}

View File

@@ -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<Model.Sku.SkuConditionInfo> Read(List<int> 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<Model.Sku.SkuConditionInfo>(sql, paramter).ToList();
}
}
}
}

View File

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

View File

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

View File

@@ -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<Model.Stock.SkuTransaction> 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<Model.Stock.SkuTransaction> Read(string sqlWhere, DynamicParameters parameters)
{
var resultList = new List<Model.Stock.SkuTransaction>();
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<Model.Stock.SkuTransaction>(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;
}
}
}

View File

@@ -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)
{
}
/// <summary>
/// Depriciated, delete when not required by other code
/// </summary>
/// <param name="sqlConnectionString"></param>
/// <param name="typeCode"></param>
/// <returns></returns>
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<Model.Stock.SkuTransactionType> 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<Model.Stock.SkuTransactionType>(sql, param).ToList();
}
}
public List<Model.Stock.SkuTransactionType> ByTypeCode(List<string> typeCode)
{
string sqlWhere = @"
WHERE TypeCode IN @typeCode ";
var param = new DynamicParameters();
param.Add("@typeCode", typeCode);
return Execute(sqlWhere, param);
}
public List<Model.Stock.SkuTransactionType> ByTypeName(List<string> typeName)
{
string sqlWhere = @"
WHERE TypeName IN @typeName ";
var param = new DynamicParameters();
param.Add("@typeName", typeName);
return Execute(sqlWhere, param);
}
}
}

View File

@@ -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");
}
}
}
}
/// <summary>
/// Update the StockJournalID field. Will also set the IsProcessed value base on input.
/// </summary>
/// <param name="skuTransactionId">Sku Transaction Id</param>
/// <param name="stockJournalId">Stock Journal Id or null to unset</param>
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");
}
}
}
}
/// <summary>
/// Update the StockJournalID field. Will also set the IsProcessed value base on input.
/// </summary>
/// <param name="skuTransactionId">Sku Transaction Id</param>
/// <param name="quantity">Sku Transaction quantity. Set to null to leave database value unchanged.</param>
/// <param name="stockJournalId">Stock Journal Id</param>
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");
}
}
}
}
}
}

View File

@@ -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<string, object> ParameterList { get; private set; }
public void Innit()
{
SqlWhereString = null;
ParameterList = new Dictionary<string, object>();
parameterCount = 0;
}
/// <summary>
/// Used to create a string for an SQL where condition 'In' statement
/// </summary>
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
/// <param name="orValueList">List of values to test in condition statement</param>
/// <param name="wherePrefix">Optional string to prefix to the returned result</param>
public void In(string columnReference, List<string> 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<string, object>();
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;
}
/// <summary>
/// Used to create a string for an SQL where condition 'In' statement
/// </summary>
/// <param name="columnReference">Name of the column to used to for the condition statement</param>
/// <param name="orValueList">List of values to test in condition statement</param>
/// <param name="wherePrefix">Optional string to prefix to the returned result</param>
public void In(string columnReference, List<int> orValueList, string wherePrefix = null)
{
var stringList = new List<string>();
if (orValueList != null || !orValueList.Any())
{
foreach (int value in orValueList)
{
stringList.Add(value.ToString());
}
}
In(columnReference, stringList, wherePrefix);
}
}
}

View File

@@ -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<T>(this T item, params T[] items)
{
if (items == null)
throw new ArgumentNullException("items");
return items.Equals(item);
}
}
}

View File

@@ -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<int, Model.Account.AccountCode> cache;
public GetAccountCodeInfo(string sqlConnectionString)
{
this.sqlConnectionString = sqlConnectionString;
readAccountCode = new Data.Database.Account.ReadAccountCode(sqlConnectionString);
cache = new Dictionary<int, Model.Account.AccountCode>();
}
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<int> accountCodeList, bool forceDbRead = false)
{
if (accountCodeList == null || !accountCodeList.Any())
{
return;
}
var accountCodeQueryList = new List<int>();
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<int> { accountCode }, forceDbRead);
if (cache.ContainsKey(accountCode))
{
return cache[accountCode];
}
else
{
return null;
}
}
}
}

View File

@@ -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<string, Model.Account.InvoiceLineItem> 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);
}
/// <summary>
/// Create new 'default' line item code when a requested item code is not found.
/// </summary>
public bool InsertNewOnNoMatch { get; set; } = false;
public void CacheInnit()
{
cache = new Dictionary<string, Model.Account.InvoiceLineItem>();
}
/// <summary>
/// Prefill cache in one SQL call, saves multiple SQL calls.
/// </summary>
/// <param name="itemCodeList">List of item codes to lookup from database</param>
/// <param name="forceDbRead">Forces a database read (does not read cache)</param>
public void CacheFill(List<string> itemCodeList, bool forceDbRead = false)
{
if (itemCodeList == null || !itemCodeList.Any())
{
return;
}
var itemCodeQueryList = new List<string>();
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);
}
}
/// <summary>
/// Creates new 'default' item code entry. The item code and title are set the same and will require updating.
/// </summary>
/// <param name="itemCode">Item code string</param>
/// <returns></returns>
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<string> { 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);
}
}
/// <summary>
/// Tests if ItemCode has Invoice line entry enabled
/// </summary>
/// <param name="itemCode">Item code</param>
/// <param name="forceDbRead">Forces a database read (does not read cache)</param>
/// <returns></returns>
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;
}
/// <summary>
/// Tests if ItemCode is new (default) and a review id required
/// </summary>
/// <param name="itemCode">Item code</param>
/// <param name="forceDbRead">Forces a database read (does not read cache)</param>
/// <returns></returns>
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;
}
}
}

View File

@@ -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<string, Model.Account.TaxCodeInfo> cache;
private Dictionary<string, Model.Account.TaxCodeInfo> 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<string, Model.Account.TaxCodeInfo>();
cacheInvoiceItem = new Dictionary<string, Model.Account.TaxCodeInfo>();
}
public void CacheFill()
{
CacheClear();
var list = dbRead.GetAllActive();
foreach (var item in list)
{
cache.Add(item.TaxCode, item);
}
}
public void CacheFill(List<string> taxCodeList, bool forceDbRead = false)
{
if (taxCodeList == null || !taxCodeList.Any())
{
return;
}
var taxCodeQueryList = new List<string>();
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<Model.Account.TaxCodeInfo> 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<string> { taxCode }, forceDbRead);
if (cache.ContainsKey(taxCode))
{
return cache[taxCode];
}
else
{
return null;
}
}
/// <summary>
/// Gets list of Tax Code Info for a given list of Sku Numbers
/// </summary>
/// <param name="skuNumberList">List of SKU numbers</param>
/// <returns>Dictionary, key is SkuNumber and value is Tax Code Info</returns>
public Dictionary<string, Model.Account.TaxCodeInfo> GetBySkuNumber(List<string> skuNumberList)
{
var returnList = new Dictionary<string, Model.Account.TaxCodeInfo>();
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<string, Model.Account.TaxCodeInfo> Get(List<Model.Account.InvoiceLineItem> invoiceLineList)
{
throw new NotImplementedException();
}
}
}

View File

@@ -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);
}
/// <summary>
/// Returns a value to multiply margin (sale - purchase price) by to find margin scheme tax amount
/// </summary>
/// <param name="transactionDate">Date of transaction</param>
/// <returns>Value between 0 and 1</returns>
public decimal GetMarginMultiplier(DateTime transactionDate)
{
decimal vatRate = GetMarginTaxRate(transactionDate);
return vatRate / (vatRate + 100);
}
}
}

View File

@@ -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<Model.Account.IInvoice> { invoice });
}
protected bool IsValidInvoice(List<Model.Account.IInvoice> invoiceList)
{
Innit();
if (invoiceList == null || !invoiceList.Any())
{
ErrorListAdd("Invoice list is null or empty.");
return false;
}
var tempErrorList = new List<string>();
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;
}
}
}
}

View File

@@ -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<Model.Account.SalesInvoice> { invoice });
}
public bool IsValidInvoice(List<Model.Account.SalesInvoice> invoiceList)
{
var interfaceList = invoiceList.Cast<Model.Account.IInvoice>().ToList();
return IsValidInvoice(interfaceList);
}
}
}

View File

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

View File

@@ -36,33 +36,32 @@ namespace bnhtrade.Core.Logic.AmazonFBAInbound
shipmentRequest.LastUpdatedAfter = dateTimeAfter.AddDays(-14);
shipmentRequest.LastUpdatedBefore = dateTimeBefore;
List<Model.AmazonFBAInbound.ShipmentInfo> shipmentInfoList = shipmentRequest.GetShipmentInfo();
List<Model.AmazonFba.ShipmentInfo> shipmentInfoList = shipmentRequest.GetShipmentInfo();
// build list of shipments returned from mws
var dicShipExistsInDb = new Dictionary<string, bool>();
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<Model.AmazonFBAInbound.ShipmentInfo> newShipmentInfoList = null;
List<Model.AmazonFba.ShipmentInfo> newShipmentInfoList = null;
if (dicShipExistsInDb.Any())
{
var newShipmentId = new List<string>();
// 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;
}

View File

@@ -11,7 +11,8 @@ namespace bnhtrade.Core.Logic.Export
public class AmazonSettlement
{
private string sqlConnectionString;
private Dictionary<string, Model.Account.TaxCode> taxCodeBySkuNumer;
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
private List<string> lineItemCodeList = new List<string>();
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<string, string>();
for (int i = 0; i < settlementList.Count(); i++)
var skuList = new List<string>();
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<string, decimal>();
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<string, Model.Account.TaxCodeInfo> 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 + "<TaxCode=" + taxCodeBySkuNumer[skuNumber].TaxCodeId + ">";
matchString = matchString + "<TaxCode=" + taxCodeBySkuNumer[skuNumber].TaxCode + ">";
}
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;
}
}

View File

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

View File

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

View File

@@ -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<Model.Account.IInvoice> 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<Model.Account.SalesInvoice> 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);
}
}
}

View File

@@ -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<string, string>();
// 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<Model.Account.SalesInvoiceLine>();
// 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;
//}
}
}

View File

@@ -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<string, Model.Product.CompetitivePrice> competitivePrices;
private int newConditionId = Data.Database.Constants.GetProductConditionIdNew();
private string sqlConnectionString;
private Data.Database.Product.ReadCompetitivePrice read;
private List<string> productIdList;
private List<string> conditionIdList;
private Data.Database.Product.ReadCompetitivePrice dbRead;
private Dictionary<int, decimal> newConditionMultipier;
public GetCompetitivePrice(string sqlConnectionString)
{
this.sqlConnectionString = sqlConnectionString;
dbRead = new Data.Database.Product.ReadCompetitivePrice(sqlConnectionString);
newConditionMultipier = new Dictionary<int, decimal>();
}
/// <summary>
/// If a competitive price for a used condition is not found, return an estimated figure.
/// </summary>
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<string, Model.Product.CompetitivePrice> Execute(List<Model.Sku.Price.SkuPriceParameter> 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<string, Model.Product.CompetitivePrice>();
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<Model.Product.CompetitivePrice> Execute(List<(int ProductId, int ConditionId)> requestList)
{
Innit();
var result = new List<Model.Product.CompetitivePrice>();
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<int, decimal>();
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<Model.Product.CompetitivePrice>();
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<Model.Sku.SkuConditionInfo>();
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");
}
}
}
}
}

View File

@@ -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<Model.Sku.SkuConditionInfo> GetAll()
{
return dbRead.Read(new List<int>());
}
public List<Model.Sku.SkuConditionInfo> GetByConditionId(List<int> conditionIdList)
{
return dbRead.Read(conditionIdList);
}
}
}

View File

@@ -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<Model.Sku.Price.SkuPriceParameter> skuInfo;
private Dictionary<string, Model.Product.CompetitivePrice> competitivePrices;
DateTime crTimeStamp = DateTime.UtcNow;
private int repriceIncrementDivisor = 60;
private Dictionary<string, int> saleCountInPeriod = new Dictionary<string, int>();
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<Model.Export.AmazonIventoryLoaderFile>();
var crDictionary = new Dictionary<string, Model.Sku.Price.PriceInfo>();
// 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<Model.Export.AmazonIventoryLoaderFile>();
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;
}
/// <summary>
/// Get the minimum sale price to break even.
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Get the minimum sale price to achieve required profit margin.
/// </summary>
/// <param name="i"></param>
/// <returns>Minimum price in decimal</returns>
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;
}
}
}
}

View File

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

View File

@@ -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);
}
/// <summary>
/// Feed an skuId and quantity into function and the stock will be reallocated
/// </summary>
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<Tuple<int, DateTime, int>> list = Core.Stock.StockJournal.GetStockStatusBalanceBySkuNumber(sqlConnectionString, skuNumber, creditStatusId, entryDate, firstInFirstOut);
if (list == null || !list.Any())
{
return returnList;
}
// quantity check
int avaiableQuantity = 0;
foreach (Tuple<int, DateTime, int> item in list)
{
avaiableQuantity = avaiableQuantity + item.Item3;
}
if (avaiableQuantity < quantity && reallocatePartialQuantity == false)
{
return null;
}
// make the changes
using (TransactionScope scope = new TransactionScope())
{
foreach (Tuple<int, DateTime, int> 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;
}
}
}
}

View File

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

View File

@@ -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;
}
/// <summary>
/// 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)
/// </summary>
/// <param name="updateTransactions">Download and process Amazon reports before starting process</param>
/// <returns></returns>
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 == "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><+ve>"
|| transType.TypeCode == "<AmazonReport><_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("<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><F>"))
{
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<Model.Stock.SkuTransaction>();
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;
}
/// <summary>
///
/// </summary>
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 = "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><M><-ve><InventoryMisplaced><SELLABLE>";
string found = "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><F><+ve><InventoryFound><SELLABLE>";
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();
}
}
}
}

View File

@@ -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<Model.Stock.SkuTransactionType> 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<Model.Stock.SkuTransactionType>();
}
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<string> { 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<string> { typeName });
if (result.Any())
{
cache.Add(result[0]);
return result[0];
}
else
{
return null;
}
}
}
}

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Utilities
{
public class DecimalCheck : Validate
public class DecimalCheck : Validate.Validate
{
/// <summary>
/// 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;

View File

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

View File

@@ -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<string> errorList = new List<string>();
public List<string> 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<string> 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<string>();
}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Logic.Validate
{
public class AmazonIventoryLoaderFile : Validate
{
public bool IsValidFbaPricing(IEnumerable<Model.Export.AmazonIventoryLoaderFile> exportList)
{
if (!IsValid(exportList))
{
return false;
}
return IsValidResult;
}
}
}

View File

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

View File

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

View File

@@ -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<Model.Account.Invoice> 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;
}
}
}

View File

@@ -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<Model.Sku.Price.PriceInfo> priceInfoList)
{
Innit();
if (!IsValid(priceInfoList))
{
return false;
}
return IsValidResult;
}
}
}

View File

@@ -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<Model.Stock.SkuTransaction> { skuTransaction });
}
public bool DatabaseUpdate(List<Model.Stock.SkuTransaction> 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<Model.Stock.SkuTransaction> { skuTransaction });
}
public bool DatabaseInsert(List<Model.Stock.SkuTransaction> skuTransactionList)
{
return IsValid(skuTransactionList);
}
}
}

View File

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

View File

@@ -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> ValidationResult { get; set; } = new List<ValidationResult>();
public bool IsValidResult
{
get
{
if (ValidationResult.Any()) { return false; }
else { return true; }
}
}
public void Innit()
{
ValidationResult = new List<ValidationResult>();
}
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<IValidatableObject> 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<string> result)
{
foreach (var item in result)
{
ValidationResultAdd(item);
}
}
protected void ValidationResultAdd(ValidationResult result)
{
ValidationResult.Add(result);
}
protected void ValidationResultAdd(List<ValidationResult> 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; }
}
}
}

View File

@@ -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<ValidationResult> Validate(ValidationContext validationContext)
{
var resultList = new List<ValidationResult>();
if (!IsSetAccountCodeId)
{
resultList.Add(new ValidationResult("Account Code is not set"));
}
return resultList;
}
}
}

View File

@@ -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<Invoice.InvoiceLine> 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<InvoiceLine> InvoiceLineList { get; set; } = new List<InvoiceLine>();
public bool InvoiceLineListIsSet
{
get
{
if (InvoiceLineList == null || !InvoiceLineList.Any())
{ return false; }
else
{ return true; }
if (InvoiceLineList == null || !InvoiceLineList.Any()) { return false; }
else { return true; }
}
}
public class InvoiceLine : IInvoiceLine
public class InvoiceLine : IInvoiceLine, IValidatableObject
{
private int? accountCode;
private decimal? netAmount;
private decimal? taxAmount;
private decimal? unitAmount;
private Model.Account.TaxCodeInfo taxCode;
private decimal? taxAmountAdjust;
private int? quantity;
private decimal? discount;
private decimal? quantity;
public string ItemCode
public InvoiceLine(bool unitAmountIsTaxExclusive)
{
UnitAmountIsTaxExclusive = unitAmountIsTaxExclusive;
}
public string ItemCode { get; set; }
public string Description { get; set; }
[Required(), Range(0, 9999999.99)]
public decimal? Quantity
{
get { return quantity; }
set
{
if (value == null) { quantity = null; }
else { quantity = decimal.Round((decimal)value, 4, MidpointRounding.AwayFromZero); }
}
}
[Required()]
public decimal? UnitAmount
{
get { return unitAmount; }
set
{
if (value == null) { unitAmount = null; }
else { unitAmount = decimal.Round(value.GetValueOrDefault(), 4, MidpointRounding.AwayFromZero); }
}
}
public bool UnitAmountIsTaxExclusive { get; set; }
[Required()]
public Model.Account.AccountCode AccountCode
{
get;
set;
}
public bool ItemCodeIsSet
[Required()]
public Model.Account.TaxCodeInfo TaxCode
{
get { return ItemCode != null; }
get { return taxCode; }
set
{
if (value == null || TaxCode == null || value.TaxCode != taxCode.TaxCode)
{
TaxAmountAdjust = 0;
}
public string Description
{
get;
set;
taxCode = value;
}
}
public bool DescriptionIsSet
[Required()]
public decimal? TaxAmount
{
get { return Description != null; }
get
{
return TaxAmountAdjust + GetCalculatedTax();
}
}
public int Quantity
public decimal? TaxAmountAdjust
{
get { return (int)quantity.GetValueOrDefault(); }
set { quantity = value; }
get { return taxAmountAdjust; }
set
{
if (value == null) { taxAmountAdjust = null; }
else { taxAmountAdjust = decimal.Round((decimal)value, 2, MidpointRounding.AwayFromZero); }
}
}
public bool QuantityIsSet
public decimal LineTotalAmount
{
get { return quantity != null; }
get
{
if (CanCalculateLine())
{
return ((decimal)Quantity * (decimal)UnitAmount) + (decimal)TaxAmount;
}
else { return 0; }
}
}
public decimal TotalNetAmount
private bool CanCalculateLine()
{
get { return (decimal)netAmount.GetValueOrDefault(); }
set { netAmount = value; }
if (Quantity == null || UnitAmount == null || TaxCode == null) { return false; }
else { return true; }
}
public bool TotalNetAmountIsSet
private decimal GetCalculatedTax()
{
get { return netAmount != null; }
decimal calculatedTax = 0;
if (CanCalculateLine())
{
if (UnitAmountIsTaxExclusive)
{
calculatedTax = ((decimal)Quantity * (decimal)UnitAmount) * (TaxCode.TaxRate / 100);
}
else
{
calculatedTax = ((decimal)Quantity * (decimal)UnitAmount) * (TaxCode.TaxRate / (100 + TaxCode.TaxRate));
}
return decimal.Round(calculatedTax, 2, MidpointRounding.AwayFromZero);
}
else
{
return 0;
}
}
public int AccountCode
public void SetTaxAmountAdjust(decimal lineTaxAmount)
{
get { return (int)accountCode.GetValueOrDefault(); }
set { accountCode = value; }
decimal adjustedAmount = lineTaxAmount - GetCalculatedTax();
if (adjustedAmount == 0) { TaxAmountAdjust = null; }
else { TaxAmountAdjust = adjustedAmount; }
}
public bool AccountCodeIsSet
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
get { return accountCode != null; }
throw new NotImplementedException();
var resultList = new List<ValidationResult>();
if (TaxAmount > LineTotalAmount / 2)
{
resultList.Add(new ValidationResult("Line tax amount is greater than net amount"));
}
public string TaxCode
{
get;
set;
}
}
public bool TaxCodeIsSet
public new IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
get { return TaxCode != null; }
var subResult = base.Validate(validationContext);
var resultList = new List<ValidationResult>();
resultList.AddRange(subResult);
// loop though lines and check sum totals
if (!InvoiceLineListIsSet)
{
resultList.Add(new ValidationResult("No lines set on Invoice"));
}
else
{
decimal lineTotal = 0;
foreach (var line in InvoiceLineList)
{
lineTotal += line.LineTotalAmount;
if (UnitAmountIsTaxExclusive != line.UnitAmountIsTaxExclusive)
{
resultList.Add(new ValidationResult("Invalid UnitAmountIsTaxExclusive"));
}
}
public decimal TaxAmount
{
get { return (decimal)taxAmount.GetValueOrDefault(); }
set { taxAmount = decimal.Round(value, 2); }
// check totals
if (InvoiceTotalAmount != lineTotal)
{ resultList.Add(new ValidationResult("Invoice line total does not equal invoice total")); }
}
public bool TaxAmountIsSet
{
get { return taxAmount != null; }
}
public decimal TaxAmountAdjust
{
get { return (decimal)taxAmountAdjust.GetValueOrDefault(); }
set { taxAmountAdjust = decimal.Round(value, 2); }
}
public bool TaxAmountAdjustIsSet
{
get { return taxAmountAdjust != null; }
}
public decimal GrossTotalAmount
{
get { return (decimal)netAmount.GetValueOrDefault() + TaxAmount; }
}
public bool GrossTotalAmountIsSet
{
get { return (TotalNetAmountIsSet && TaxAmountIsSet); }
}
return resultList;
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -9,31 +10,24 @@ namespace bnhtrade.Core.Model.Account
public interface IInvoiceHeader
{
string ContactName { get; set; }
bool ContactNameIsSet { get; }
decimal InvoiceAmount { get; set; }
bool InvoiceAmountIsSet { get; }
decimal? InvoiceTotalAmount { get; set; }
string InvoiceCurrencyCode { get; set; }
bool InvoiceCurrencyCodeIsSet { get; }
DateTime InvoiceDate { get; set; }
bool InvoiceDateIsSet { get; }
DateTime InvoiceDueDate { get; set; }
bool InvoiceDueDateIsSet { get; }
DateTimeKind InvoiceDateKind { get; set; }
bool InvoiceDateKindIsSet { get; }
DateTime? InvoiceDate { get; set; }
DateTime? InvoiceDueDate { get; set; }
string InvoiceNumber { get; set; }
bool InvoiceNumberIsSet { get; }
string InvoiceReference { get; set; }
bool InvoiceReferenceIsSet { get; }
bool IsCreditNote { get; set; }
bool IsCreditNoteIsSet { get; }
}
public abstract class InvoiceHeader : IInvoiceHeader
public abstract class InvoiceHeader :IInvoiceHeader, IValidatableObject
{
private string invoiceCurrencyCode;
private DateTime? invoiceDate;
private DateTime? invoiceDueDate;
private DateTimeKind? invoiceDateKind = DateTimeKind.Utc;
private decimal? invoiceAmount;
public InvoiceHeader()
@@ -41,95 +35,51 @@ namespace bnhtrade.Core.Model.Account
IsCreditNote = false;
}
[Required()]
public string ContactName { get; set; }
public bool ContactNameIsSet
{
get { return ContactName != null; }
}
[Required()]
public DateTime? InvoiceDate { get; set; }
public DateTime InvoiceDate
{
get { return (DateTime)invoiceDate.GetValueOrDefault(); }
set { invoiceDate = value; }
}
[Required()]
public DateTime? InvoiceDueDate { get; set; }
public bool InvoiceDateIsSet
{
get { return invoiceDate != null; }
}
public DateTime InvoiceDueDate
{
get { return (DateTime)invoiceDueDate.GetValueOrDefault(); }
set { invoiceDueDate = value; }
}
public bool InvoiceDueDateIsSet
{
get { return invoiceDueDate != null; }
}
public DateTimeKind InvoiceDateKind
{
get { return (DateTimeKind)invoiceDateKind; }
set { invoiceDateKind = value; }
}
public bool InvoiceDateKindIsSet
{
get { return invoiceDateKind != null; }
}
public string InvoiceCurrencyCode
{
get { return invoiceCurrencyCode; }
set
{
if (!string.IsNullOrWhiteSpace(value))
{
invoiceCurrencyCode = value.ToUpper();
}
}
}
public bool InvoiceCurrencyCodeIsSet
{
get { return InvoiceCurrencyCode != null; }
}
[Required(), MinLength(3), MaxLength(3)]
public string InvoiceCurrencyCode { get; set; }
[Required()]
public string InvoiceNumber { get; set; }
public bool InvoiceNumberIsSet
{
get { return InvoiceNumber != null; }
}
public string InvoiceReference { get; set; }
public bool InvoiceReferenceIsSet
{
get { return InvoiceReference != null; }
}
public decimal InvoiceAmount
[Required()]
public decimal? InvoiceTotalAmount
{
get { return (decimal)invoiceAmount; }
set { invoiceAmount = value; }
set
{
if (value == null) { invoiceAmount = null; }
else { invoiceAmount = decimal.Round((decimal)value, 2, MidpointRounding.AwayFromZero); }
}
}
public bool InvoiceAmountIsSet
[Required()]
public bool IsCreditNote { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
get { return invoiceAmount != null; }
var resultList = new List<ValidationResult>();
if (IsCreditNote && InvoiceTotalAmount > 0)
{
resultList.Add(new ValidationResult("Credit Note amount cannot be greater than zero"));
}
public bool IsCreditNote
else if (!IsCreditNote && InvoiceTotalAmount < 0)
{
get;
set;
resultList.Add(new ValidationResult("Invoice amount cannot be less than zero"));
}
public bool IsCreditNoteIsSet
{
get { return true; }
return resultList;
}
}
}

View File

@@ -1,47 +1,70 @@
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 InvoiceLineItem
public class InvoiceLineItem : IValidatableObject
{
[Required()]
public string ItemCode
{
get;
set;
}
public string Title
[Required()]
public string Name
{
get;
set;
}
public string Description
{
get;
set;
}
[Required()]
public bool IsNewReviewRequired
{
get;
set;
}
[Required()]
public bool InvoiceLineEntryEnabled
{
get;
set;
}
public int DefaultAccountCode
[Required()]
public Model.Account.AccountCode DefaultAccountCode
{
get;
set;
}
public string DefaultTaxCode
[Required()]
public Model.Account.TaxCodeInfo DefaultTaxCode
{
get;
set;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var resultList = new List<ValidationResult>();
resultList.AddRange(DefaultAccountCode.Validate(validationContext));
resultList.AddRange(DefaultTaxCode.Validate(validationContext));
return resultList;
}
}
}

View File

@@ -1,102 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Account
{
public class TaxCode
{
private decimal? netAmountMultiplier = null;
private decimal? grossAmountMultiplier = null;
private bool? isActive = null;
private bool? isValidOnExpense = null;
private bool? isValidOnIncome = null;
public string TaxCodeId { get; set; }
public string TaxRateDescription { get; set; }
public string TaxRateTitle { get; set; }
public string TaxType { get; set; }
public decimal NetAmountMultiplier
{
get { return (decimal)netAmountMultiplier; }
set { netAmountMultiplier = value; }
}
public decimal GrossAmountMultiplier
{
get { return (decimal)grossAmountMultiplier; }
set { grossAmountMultiplier = value; }
}
public bool IsActive
{
get { return (bool)isActive; }
set { isActive = value; }
}
public bool IsSetAll
{
get
{
if (IsSetGrossAmountMultiplier
&& IsSetIsActive
&& IsSetIsValidOnExpense
&& IsSetIsValidOnIncome
&& IsSetNetAmountMultiplier
&& IsSetTaxCodeId
&& IsSetTaxRateTitle
&& IsSetTaxRateDescription
)
{
return true;
}
else { return false; }
}
}
public bool IsSetGrossAmountMultiplier
{
get { return grossAmountMultiplier != null; }
}
public bool IsSetIsActive
{
get { return isActive != null; }
}
public bool IsSetIsValidOnExpense
{
get { return isValidOnExpense != null; }
}
public bool IsSetIsValidOnIncome
{
get { return isValidOnIncome != null; }
}
public bool IsSetNetAmountMultiplier
{
get { return netAmountMultiplier != null; }
}
public bool IsSetTaxCodeId
{
get { return TaxCodeId != null; }
}
public bool IsSetTaxRateTitle
{
get { return TaxRateTitle != null; }
}
public bool IsSetTaxRateDescription
{
get { return TaxRateDescription != null; }
}
public bool IsSetTaxType
{
get { return TaxType != null; }
}
public bool IsValidOnExpense
{
get { return (bool)isValidOnExpense; }
set { isValidOnExpense = value; }
}
public bool IsValidOnIncome
{
get { return (bool)isValidOnIncome; }
set { isValidOnIncome = value; }
}
}
}

View File

@@ -0,0 +1,72 @@
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 TaxCodeInfo : IValidatableObject
{
public TaxCodeInfo(string taxCodeId, string title, string description, decimal taxRatePercent, bool isMarginSchemeRate,
bool isValidOnExpense, bool isValidOnIncome, string taxType, bool isActive)
{
if (TaxRate < 0)
{
throw new Exception("Tax rate is less than zero");
}
if (TaxRate >= 100)
{
// 100% rate has been used where the line total is all tax
// you need to do somemore coding when this facility is required
throw new Exception("Tax rate is >= 100%");
}
TaxCode = taxCodeId;
TaxCodeDescription = description;
TaxRate = taxRatePercent;
IsMarginScheme = isMarginSchemeRate;
TaxCodeName = title;
TaxType = taxType;
IsActive = isActive;
IsValidOnExpense = isValidOnExpense;
IsValidOnIncome = isValidOnIncome;
}
/// <summary>
/// Unique identifier
/// </summary>
[Required()]
public string TaxCode { get; private set; }
[Required()]
public string TaxCodeName { get; private set; }
public string TaxCodeDescription { get; private set; }
/// <summary>
/// Tax rate as a percentage
/// </summary>
[Required(), Range(0, 100)]
public decimal TaxRate { get; private set; }
public bool IsMarginScheme { get; private set; }
[Required()]
public string TaxType { get; private set; }
public bool IsValidOnExpense { get; private set; }
public bool IsValidOnIncome { get; private set; }
public bool IsActive { get; private set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var resultList = new List<ValidationResult>();
return resultList;
}
}
}

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.AmazonFBAInbound
namespace bnhtrade.Core.Model.AmazonFba
{
public class ShipmentInfo
{
@@ -13,9 +13,12 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
private string shipmentStatus;
private DateTime lastUpdatedUtc;
private Dictionary<string, bool> shipmentStatusToIsClosed;
private int? shipmentStockStatusId = null;
public string FbaShipmentId { get; set; }
public string AmazonShipmentId { get; set; }
public string ShipmentName { get; set; }
public string DestinationFulfillmentCenterId
{
get { return destinationFulfillmentCenterId; }
@@ -31,6 +34,7 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
}
}
}
public string ShipmentStatus
{
get
@@ -47,7 +51,16 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
shipmentStatus = status;
}
}
public DateTime LastUpdatedUtc
public string ShipmentStockStatus { get; set; }
public int ShipmentStockStatusId
{
get { return shipmentStockStatusId.GetValueOrDefault(); }
set { shipmentStockStatusId = value; }
}
public DateTime LastUpdated
{
get
{
@@ -58,6 +71,7 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
lastUpdatedUtc = DateTime.SpecifyKind(value, DateTimeKind.Utc);
}
}
public bool ShipmentIsClosed
{
get
@@ -72,6 +86,7 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
}
}
}
public List<ShipmentItemInfo> ShipmentItemInfoList
{
get { return shipmentItemInfoList; }
@@ -84,7 +99,7 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
if (!item.IsSetAll())
{ throw new Exception("Infomation missing from Shipment Item list"); }
if (item.AmazonShipmentId != AmazonShipmentId)
if (item.AmazonShipmentId != FbaShipmentId)
{ throw new Exception("Amazon shipment id in item list does not match header information."); }
if (skuCheck.ContainsKey(item.SKUNumber))
@@ -104,6 +119,7 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
shipmentItemInfoList = value;
}
}
public bool IsSetAll()
{
if (IsSetAllHeaderInfo() && IsSetListShipmentItemInfo())
@@ -115,6 +131,7 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
return false;
}
}
public bool IsSetAllHeaderInfo()
{
if (IsSetAmazonShipmentId()
@@ -131,35 +148,52 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
return false;
}
}
public bool IsSetAmazonShipmentId()
{
return AmazonShipmentId != null;
return FbaShipmentId != null;
}
public bool IsSetShipmentName()
{
return ShipmentName != null;
}
public bool IsSetDestinationFulfillmentCenterId()
{
return DestinationFulfillmentCenterId != null;
}
public bool IsSetLastUpdated()
{
return LastUpdatedUtc != default(DateTime);
return LastUpdated != default(DateTime);
}
public bool IsSetListShipmentItemInfo()
{
return ShipmentItemInfoList != null;
}
public bool IsSetShipmentIsClosed()
{
return ShipmentStatus != null;
}
public bool IsSetShipmentStatus()
{
return ShipmentStatus != null;
}
public bool IsSetShipmentStockStatus()
{
return ShipmentStockStatus != null;
}
public bool IsSetShipmentStockStatusId()
{
return shipmentStockStatusId != null;
}
public ShipmentInfo()
{
shipmentStatusToIsClosed = new Dictionary<string, bool>();

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.AmazonFBAInbound
namespace bnhtrade.Core.Model.AmazonFba
{
public class ShipmentItemInfo
{
@@ -18,14 +18,17 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
/// Gets and sets the AmazonShipmentId property.
/// </summary>
public string AmazonShipmentId { get; set; }
/// <summary>
/// Gets and sets the SKUNumber property.
/// </summary>
public string SKUNumber { get; set; }
/// <summary>
/// Gets and sets the FulfillmentNetworkSKU property.
/// </summary>
public string AmazonFNSKU { get; set; }
/// <summary>
/// Gets and sets the QuantityAllocated property.
/// </summary>
@@ -34,6 +37,7 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
get { return quantityAllocated; }
set { quantityAllocated = value; isSetQuantityAllocated = true; }
}
/// <summary>
/// Gets and sets the QuantityReceived property.
/// </summary>
@@ -59,22 +63,27 @@ namespace bnhtrade.Core.Model.AmazonFBAInbound
return false;
}
}
public bool IsSetAmazonShipmentId()
{
return AmazonShipmentId != null;
}
public bool IsSetSKUNumber()
{
return SKUNumber != null;
}
public bool IsSetFulfillmentNetworkSKU()
{
return AmazonFNSKU != null;
}
public bool IsSetQuantityAllocated()
{
return isSetQuantityAllocated;
}
public bool IsSetQuantityReceived()
{
return isSetQuantityReceived;

View File

@@ -0,0 +1,98 @@
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;
namespace bnhtrade.Core.Model.Data
{
public class DatabaseFileStream : IDisposable, IValidatableObject
{
[Required()]
public Guid FileGUID { get; set; }
[Required()]
public MemoryStream FileData { get; set; }
public bool IsSetFileData
{
get { return FileData != null; }
}
[Required(), StringLength(3, MinimumLength = 3)]
public string FileExtention { get; set; }
[Required(), Range(1, 2147483647)]
public int FileSize { get; set; }
[Required(), StringLength(24, MinimumLength = 24)]
public string FileMD5base64 { get; set; }
public string CalculateContentMD5(MemoryStream stream)
{
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] hash = provider.ComputeHash(stream);
return Convert.ToBase64String(hash);
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var resultList = new List<ValidationResult>();
if (IsSetFileData && FileData.Length == 0)
{
var validate = new ValidationResult("Stream is empty");
resultList.Add(validate);
}
if (IsSetFileData && FileMD5base64 != new Logic.Utilities.CalculateMD5().Base64(FileData))
{
var validate = new ValidationResult("Calculated file MD5 hash does not match.");
resultList.Add(validate);
}
return resultList;
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
if (FileData != null)
FileData.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
//~AmazonFeedSubmission()
//{
// // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
// Dispose(false);
//}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
// GC.SuppressFinalize(this);
}
#endregion
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Export
{
public class AmazonFeedSubmission : IValidatableObject
{
//private int? exportAmazonFeedSubmissionId;
private DateTime? submittedDate;
private DateTime? startedProcessingDate;
private DateTime? completedProcessingDate;
//public int ExportAmazonFeedSubmissionID
//{
// get { return exportAmazonFeedSubmissionId.GetValueOrDefault(); }
// set { exportAmazonFeedSubmissionId = value; }
//}
//public bool IsSetExportAmazonFeedSubmissionID
//{
// get { return exportAmazonFeedSubmissionId != null; }
//}
[Required()]
public string FeedType { get; set; }
public bool IsSetFeedType
{
get { return !string.IsNullOrWhiteSpace(FeedType); }
}
[Required()]
public string FeedSubmissionId { get; set; }
public bool IsSetFeedSubmissionId
{
get { return !string.IsNullOrWhiteSpace(FeedSubmissionId); }
}
public DateTime SubmittedDate
{
get { return submittedDate.GetValueOrDefault(); }
set { submittedDate = value; }
}
public bool IsSetSubmittedDate
{
get { return submittedDate != null; }
}
public string FeedProcessingStatus { get; set; }
public bool IsSetFeedProcessingStatus
{
get { return !string.IsNullOrWhiteSpace(FeedProcessingStatus); }
}
public DateTime StartedProcessingDate
{
get { return startedProcessingDate.GetValueOrDefault(); }
set { startedProcessingDate = value; }
}
public bool IsSetStartedProcessingDate
{
get { return startedProcessingDate != null; }
}
public DateTime CompletedProcessingDate
{
get { return completedProcessingDate.GetValueOrDefault(); }
set { completedProcessingDate = value; }
}
public bool IsSetCompletedProcessingDate
{
get { return completedProcessingDate != null; }
}
public Model.Data.DatabaseFileStream File { get; set; }
public bool FileIsSet
{
get { return File != null; }
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (IsSetSubmittedDate && SubmittedDate == default(DateTime))
results.Add(new ValidationResult("Submitted Date is systen default"));
if (IsSetStartedProcessingDate && StartedProcessingDate == default(DateTime))
results.Add(new ValidationResult("Started Processing Date is systen default"));
if (IsSetCompletedProcessingDate && CompletedProcessingDate == default(DateTime))
results.Add(new ValidationResult("Completed Processing Date is systen default"));
if (IsSetFeedProcessingStatus)
{
if (FeedProcessingStatus != "_DONE_" || FeedProcessingStatus != "_SUBMITTED_" || FeedProcessingStatus != "_IN_PROGRESS_" ||
FeedProcessingStatus != "_UNCONFIRMED_" || FeedProcessingStatus != "_CANCELLED_" || FeedProcessingStatus != "_IN_SAFETY_NET_" ||
FeedProcessingStatus != "_AWAITING_ASYNCHRONOUS_REPLY_")
{
results.Add(new ValidationResult("Invalid Feed Processing Status '" + FeedProcessingStatus + "'"));
}
}
if (FileIsSet)
{
Validator.TryValidateObject(
File,
new ValidationContext(File, null, null),
results);
}
return results;
}
}
}

View File

@@ -0,0 +1,136 @@
using CsvHelper.Configuration.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Export
{
public class AmazonIventoryLoaderFile : IValidatableObject
{
private bool isSetSetFulfillmentCenterId = false;
[Required()]
[Name("sku")]
public string Sku { get; set; }
[Name("product-id")]
public string ProductId { get; set; }
/// <summary>
/// One of the following: 1=ASIN, 2=ISBN, 3=UPC, 4=EAN
/// </summary>
[Name("product-id-type")]
[Range(1,4)]
public int? ProductIdType { get; set; }
[Name("price")]
[Range(0, double.MaxValue)]
public decimal? Price { get; set; }
[Name("minimum-seller-allowed-price")]
[Range(0, double.MaxValue)]
public decimal? MinimumAllowedPrice { get; set; }
[Name("maximum-seller-allowed-price")]
[Range(0, double.MaxValue)]
public decimal? MaximumAllowedPrice { get; set; }
/// <summary>
/// 11=New, 1=Used Like New, 2=Used Very Good, 3=Used Good, 4=Used Acceptable,
/// 5=Collectible Like New, 6=Collectible Very Good, 7=Collectible Good, 8=Collectible Acceptable, 9=Not used
/// </summary>
[Name("item-condition")]
[Range(1,11)]
public int? ItemCondition { get; set; }
[Name("quantity")]
public int? Quantity { get; set; }
/// <summary>
/// a = update/add, d = delete, x = delete completely from system
/// </summary>
[MaxLength(1)]
[Name("add-delete")]
public string AddDelete { get; set; }
[Name("will-ship-internationally")]
[BooleanTrueValues("y")]
[BooleanFalseValues("n")]
public bool? WillShipInternationally { get; set; }
[Name("expedited-shipping")]
public string ExpeditedShipping { get; set; }
[Name("standard-plus")]
public string StandardPlus { get; set; }
[MaxLength(2000)]
[Name("item-note")]
public string ItemNote { get; set; }
[Name("fulfillment-center-id")]
public string FulfillmentCenterId { get; private set; }
[Name("merchant-shipping-group-name")]
public string MerchantShippingGroupName { get; set; }
public void SetFulfillmentCenterId(bool IsFba)
{
isSetSetFulfillmentCenterId = true;
if (IsFba)
{
FulfillmentCenterId = "AMAZON_EU";
}
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (isSetSetFulfillmentCenterId == false)
{
results.Add(new ValidationResult("FulfillmentCenterId is not set."));
}
if (ItemCondition.GetValueOrDefault() == 9 || ItemCondition.GetValueOrDefault() == 10)
{
results.Add(new ValidationResult("Invalid Item Condition id"));
}
if (AddDelete != null && (AddDelete != "a" || AddDelete != "d" || AddDelete != "x"))
{
results.Add(new ValidationResult("Invalid AddDelete"));
}
if (MaximumAllowedPrice != null || MinimumAllowedPrice != null)
{
if (MaximumAllowedPrice == null)
{
results.Add(new ValidationResult("If setting MinimumAllowedPrice, the MaximumAllowedPrice must also be set."));
}
if (MinimumAllowedPrice == null)
{
results.Add(new ValidationResult("If setting MaximumAllowedPrice, the MinimumAllowedPrice must also be set."));
}
if (Price == null)
{
results.Add(new ValidationResult("If setting MaximumAllowedPrice or MinimumAllowedPrice the Price must also be set."));
}
else if (MaximumAllowedPrice != null && MinimumAllowedPrice != null)
{
if (Price < MinimumAllowedPrice || Price > MaximumAllowedPrice)
{
results.Add(new ValidationResult("Price is ouside the bounds set by the MaximumAllowedPrice and MinimumAllowedPrice."));
}
}
}
return results;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Product
{
public class CompetitivePrice
{
private bool? priceIsEstimated;
private decimal? price = null;
public int ProductId { get; set; }
public int ConditionId { get; set; }
public decimal Price
{
get { return price.GetValueOrDefault(); }
set { price = value; }
}
public bool PriceIsSet
{
get { return price != null; }
}
public DateTime PriceDatetime { get; set; }
public bool PriceIsEstimated
{
get { return priceIsEstimated.GetValueOrDefault(); }
set { priceIsEstimated = value; }
}
public bool PriceIsEstimatedIsSet
{
get { return priceIsEstimated != null; }
}
public CompetitivePrice Clone()
{
var clone = new CompetitivePrice();
clone.ConditionId = ConditionId;
if (PriceIsSet) { clone.Price = Price; }
clone.PriceDatetime = PriceDatetime;
if (PriceIsEstimatedIsSet) { clone.priceIsEstimated = PriceIsEstimated; }
clone.ProductId = ProductId;
return clone;
}
}
}

View File

@@ -9,60 +9,95 @@ namespace bnhtrade.Core.Model.Sku
public class Sku
{
private bool? isActive;
public string ConditionModelPlaceholder
private int? conditionId;
private int? productId;
public int ConditionId
{
get { return conditionId.GetValueOrDefault(); }
set { conditionId = value; }
}
public bool ConditionIdIsSet
{
get { return conditionId != null; }
}
public string ConditionTitle
{
get;
set;
}
public string ProductModelPlaceholder
public bool ConditionTitleIsSet
{
get { return ConditionTitle != null; }
}
public int ProductId
{
get { return productId.GetValueOrDefault(); }
set { productId = value; }
}
public bool ProductIdIsSet
{
get { return productId != null; }
}
public string ProductTitle
{
get;
set;
}
public bool ProductTitleIsSet
{
get { return ProductTitle != null; }
}
public string SkuNumber
{
get;
set;
}
public Account.TaxCode TaxCode
public bool SkuNumberIsSet
{
get { return SkuNumber != null; }
}
public string TaxCode
{
get;
set;
}
public bool TaxCodeIsSet
{
get { return TaxCode != null; }
}
public string AmazonFNSKU
{
get;
set;
}
public bool AmazonFNSKUIsSet
{
get { return AmazonFNSKU != null; }
}
public bool IsActive
{
get { return (bool)isActive; }
set { isActive = value; }
}
public bool IsSetConditionModelPlaceholder
{
get { return ConditionModelPlaceholder != null; }
}
public bool IsSetProductModelPlaceholder
{
get { return ProductModelPlaceholder != null; }
}
public bool IsSetSkuNumber
{
get { return SkuNumber != null; }
}
public bool IsSetTaxCode
{
get { return TaxCode != null; }
}
public bool IsSetAmazonFNSKU
{
get { return AmazonFNSKU != null; }
}
public bool IsSetIsActive
public bool IsActiveIsSet
{
get { return isActive != null; }
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Sku
{
public class SkuConditionInfo
{
public int SkuConditionId { get; set; }
public string SkuConditionNumber { get; set; }
public string TitleShort { get; set; }
public string Description { get; set; }
public bool IsFixedPrice { get; set; }
/// <summary>
/// Can be used to estimate a competitve price from 'New' condition competitive price
/// </summary>
public decimal CompetitivePriceMultiplier { get; set; }
public string AmazonBaseType { get; set; }
public int AmazonIdentifier { get; set; }
public string ConditionNoteDefault { get; set; }
public string RepricerStrategy { get; set; }
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Sku.Price
{
public class DetailRequest
{
public int SkuId { get; set; }
public int OrderChannelId { get; set; }
public int OrderChannelQuantity { get; set; }
public decimal OrderChannelFeeFixed { get; set; }
public decimal OrderChannelFeeMargin { get; set; }
public decimal UnitAvgCost { get; set; }
public int InventoryAgeMin { get; set; }
public int InventoryAgeMax { get; set; }
public int PriceMin_SkuPriceType { get; set; }
public decimal? PriceMinAmountManual { get; set; }
public int? PriceMinStoredInt { get; set; }
public int PriceMax_SkuPriceType { get; set; }
public bool PriceMaxBaseMultipilerReset { get; set; } = false;
public decimal? PriceMaxAmountManual { get; set; }
public int? PriceMaxStoredInt { get; set; }
}
}

View File

@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Model.Sku.Price
{
public class DetailResponce
{
public int SkuId { get; set; }
public int OrderChannelId { get; set; }
public int OrderChannelQuantity { get; set; }
public decimal UnitAvgCost { get; set; }
public int InventoryAgeMin { get; set; }
public int InventoryAgeMax { get; set; }
public int PriceMin_SkuPriceType { get; set; }
public decimal PriceMinAmountAuto { get; set; }
public decimal? PriceMinAmountManual { get; set; }
public int? PriceMinStoredInt { get; set; }
public decimal PriceMinAmountFinalFee { get; set; }
public decimal PriceMinAmountFinalTax { get; set; }
public decimal PriceMinAmountFinal { get; set; }
public int PriceMax_SkuPriceType { get; set; }
public decimal PriceMaxAmountAutoBase { get; set; }
public decimal PriceMaxAmountAutoMultiplier { get; set; }
public DateTime PriceMaxAmountAutoModified { get; set; }
public decimal? PriceMaxAmountManual { get; set; }
public int? PriceMaxStoredInt { get; set; }
public decimal PriceMaxAmountFinal { get; set; }
public DateTime PriceCreated { get; set; }
public string TypeTitle { get; set; }
public bool ReviewRequired
{
get
{
if (TypeTitle.Substring(0, 15) == "Review Required")
{ return true; }
else
{ return false; }
}
}
public bool RequireAmountManual { get; set; }
public bool RequireStordedInt { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show More