63 Commits

Author SHA1 Message Date
bobbie 5cd653d700 Bug fix in ExportSalesInvoice and converted more code over to repository and service pattern 2025-07-07 15:22:21 +01:00
bobbie 5900a6e6e4 Bug fixes in converting invoice to gbp method 2025-06-27 09:02:22 +01:00
Bobbie Hodgetts 29f9fae508 Added invoice export function and started implementation of unitofwork pattern (#43)
* complete read invoices from db

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* updated nuget package spapi

* WIP

* wip, now test

* wip, jut need to fix tax inclusive line amounts not supported

* wip

* wip, before I f everything up

* no, it complies now, this is the one before I f everything up

* wip

* wip

* wip, logic ready for testing

* wip it builds!!!!

* wip tested, working, need to complete the gui section

* wip

* wip

* wip - created export invoice data delete, time for testing

* wip testing phase

* wip - delete function fully tested and working

* wip on to sorting out the issue with settlement invoices not tallying

* wip

* wip

* wip

* wip

* wip before I complete change the ReadInvoiceLineItem sections

* that appears to have worked, on with the main quest

* no it's doesn't work, saving before i remove the confusing cache system (just use a dictionary!!)

* wipping picadilli

* wip

* wip

* implemented uow on inovice export, now for testing

* wip

* wip all tested do invoice currency convertion fearure

* wip

* pretty much done so long as xero accepts the exported invoices

* Complete!
2025-06-26 23:29:22 +01:00
Bobbie Hodgetts 8bbf885a48 Merge branch 'Feature-gui-for-amazon-shipments' into master 2025-06-10 07:25:12 +01:00
Bobbie Hodgetts 332a25aec8 Merge branch 'Amazon-inventory-ledger-testing-and-implementation' into master 2025-06-10 07:18:31 +01:00
Bobbie Hodgetts 0fe8bbd91b Trying to correct the timeline part 2 (#37)
* wip

* wip

* migrated all projects over to .net8

* progress has been made. Beer o'clock

* the reciving search box is oworking

* wip

* wip

* reading account journal complete

* wip

* wip

* wip

* pull master into branch

* Migrated projects to dotnet8

migrated all projects over to .net8
incomplete feature for gui shipments

* Amazon inventory ledger testing and implementation

Tested what I can until more data for the Amazon Ledger Detail table comes in

* amazon settlement amounts now set to tax inclusive when exporting to invoice

* Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead

* feature exchange rate update automation

Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-10 07:14:37 +01:00
Bobbie Hodgetts 413ca43cfe Trying to correct the timeline part 1 (#36)
* wip

* wip

* migrated all projects over to .net8

* progress has been made. Beer o'clock

* the reciving search box is oworking

* wip

* wip

* reading account journal complete

* wip

* wip

* wip
2025-06-10 07:13:59 +01:00
Bobbie Hodgetts 14d5b78d44 why wont the master pull into this branch (#35)
* Amazon inventory ledger testing and implementation

Tested what I can until more data for the Amazon Ledger Detail table comes in

* amazon settlement amounts now set to tax inclusive when exporting to invoice

* Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead

* feature exchange rate update automation

Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-10 07:07:03 +01:00
Bobbie Hodgetts 325d6d3bcd pull main into branch (#34)
* Migrated projects to dotnet8

migrated all projects over to .net8
incomplete feature for gui shipments

* Amazon inventory ledger testing and implementation

Tested what I can until more data for the Amazon Ledger Detail table comes in

* amazon settlement amounts now set to tax inclusive when exporting to invoice

* Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead

* feature exchange rate update automation

Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-10 06:58:44 +01:00
Bobbie Hodgetts 25c84525c2 Pull master in branch
* Amazon inventory ledger testing and implementation

Tested what I can until more data for the Amazon Ledger Detail table comes in

* amazon settlement amounts now set to tax inclusive when exporting to invoice

* Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead

* feature exchange rate update automation

Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-10 06:54:32 +01:00
Bobbie Hodgetts d8454bc031 pull master into this branch (#31)
* Migrated projects to dotnet8

migrated all projects over to .net8
incomplete feature for gui shipments

* Amazon inventory ledger testing and implementation

Tested what I can until more data for the Amazon Ledger Detail table comes in

* amazon settlement amounts now set to tax inclusive when exporting to invoice

* Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead

* feature exchange rate update automation

Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-09 21:31:50 +01:00
Bobbie Hodgetts a3af86db46 pull master into branch (#30)
* Migrated projects to dotnet8

migrated all projects over to .net8
incomplete feature for gui shipments

* Amazon inventory ledger testing and implementation

Tested what I can until more data for the Amazon Ledger Detail table comes in

* amazon settlement amounts now set to tax inclusive when exporting to invoice

* Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead

* feature exchange rate update automation

Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-09 21:28:05 +01:00
Bobbie Hodgetts 30174290cf pull master into branch
* Migrated projects to dotnet8

migrated all projects over to .net8
incomplete feature for gui shipments

* Amazon inventory ledger testing and implementation

Tested what I can until more data for the Amazon Ledger Detail table comes in

* amazon settlement amounts now set to tax inclusive when exporting to invoice

* Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead

* feature exchange rate update automation

Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-09 21:23:42 +01:00
Bobbie Hodgetts cb54dc364c Pulled changes on master into branch (#28)
* Amazon inventory ledger testing and implementation

Tested what I can until more data for the Amazon Ledger Detail table comes in

* amazon settlement amounts now set to tax inclusive when exporting to invoice

* Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead

* feature exchange rate update automation

Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-09 21:00:18 +01:00
Bobbie Hodgetts ea0a52b2a0 feature exchange rate update automation
Automated downloading exchange rates from HMRC and updating the database. Added function call to the console and form applications.

Also added a form to show the console output in form application.
2025-06-09 20:56:26 +01:00
bobbie 8e7cd00b74 Some updates to the COM lib to attempt to get it to work on .net 8. Unfinished, porting all Access functions over to vs instead 2025-05-01 18:39:08 +01:00
Bobbie Hodgetts 7465940d48 amazon settlement amounts now set to tax inclusive when exporting to invoice 2025-03-04 14:01:34 +00:00
Bobbie Hodgetts c8689e3bba Amazon inventory ledger testing and implementation
Tested what I can until more data for the Amazon Ledger Detail table comes in
2024-11-21 17:50:18 +00:00
Bobbie Hodgetts 5446c995d2 wip 2024-11-21 17:16:23 +00:00
Bobbie Hodgetts f9b38a98b1 wip 2024-11-21 09:36:16 +00:00
Bobbie Hodgetts 7a12b49b44 Migrated projects to dotnet8
migrated all projects over to .net8
incomplete feature for gui shipments
2024-11-20 16:37:42 +00:00
Bobbie Hodgetts a0c669f1d4 wip 2024-11-06 17:12:34 +00:00
Bobbie Hodgetts a865abb788 wip 2024-08-06 12:07:18 +01:00
Bobbie Hodgetts 1c7ed5da93 wip 2024-05-12 16:22:53 +01:00
Bobbie Hodgetts 0fb45b8090 reading account journal complete 2024-05-12 15:10:24 +01:00
Bobbie Hodgetts fb058fc22f wip 2024-05-12 00:07:24 +01:00
Bobbie Hodgetts a56a97031a wip 2024-05-11 09:46:47 +01:00
Bobbie Hodgetts 960579b0b2 the reciving search box is oworking 2024-05-10 22:42:14 +01:00
Bobbie Hodgetts c2082acf8e progress has been made. Beer o'clock 2024-05-10 18:30:45 +01:00
Bobbie Hodgetts daa4e91e81 migrated all projects over to .net8 2024-05-10 11:16:32 +01:00
Bobbie Hodgetts 97fff18e7e wip 2024-05-09 21:27:51 +01:00
Bobbie Hodgetts b790a7b642 wip 2024-05-09 16:42:32 +01:00
Bobbie Hodgetts 270eebca9a Feature: stock replenishment 2024-05-09 13:23:33 +01:00
Bobbie Hodgetts 91ef9acc78 SP-API stock reconciliation
Amazon had depreciated a number of reports that were used for stock reconciliation. Application now uses the new fba ledger report to reconcile. It is currently untested, as this requires data from Amazon. Methods that require testing will return a 'NotImplementedException'.

Also, removed the depreciated ILMerge and replaced with ILRepack.

Plus much more tidying up, and improvements.
2024-05-07 08:24:00 +01:00
Bobbie Hodgetts 2f919d7b5a removed unused sp-api libary code 2024-04-17 16:04:28 +01:00
Bobbie Hodgetts f8452d274a moving code our of program file 2024-04-17 16:03:15 +01:00
Bobbie Hodgetts c1e6da7a6f tidying up 2024-04-17 13:52:50 +01:00
Bobbie Hodgetts f1d7119306 the abandoned fba repricing feature
* Merge master into branch (#15)

* Bug fix

* Bug fix when retriving shipment stock status id

* Various bug fixs and improvements to stock SKU reconciliation

* Last MWS report import date time saved

* master into branch (#16)

* Bug fix

* Bug fix when retriving shipment stock status id

* Various bug fixs and improvements to stock SKU reconciliation

* Last MWS report import date time saved

* wip

* wip

* wip

* wip

* wip

* some extra tidying up to get it to complie and the main merge is complete

* wip
2024-04-17 13:23:33 +01:00
Bobbie Hodgetts a7bc00e73a Migration from Amazon MWS to Selling Partner API 2024-04-11 12:26:13 +01:00
Bobbie Hodgetts e054278cdd Bug Fix: Exception on deletion of first invoice in list 2021-05-07 11:45:42 +01:00
bobbie d8ebd29c47 Merge branch 'amazon-min-max-repricing' into master 2020-10-06 20:39:22 +01:00
bobbie b266e1cde0 Last MWS report import date time saved 2020-10-06 20:34:22 +01:00
Bobbie Hodgetts ddd2b62743 Various bug fixs and improvements to stock SKU reconciliation 2020-10-05 22:40:55 +01:00
Bobbie Hodgetts cc2534a3e1 Bug fix when retriving shipment stock status id 2020-09-23 20:49:05 +01:00
Bobbie Hodgetts f95c1d7508 Bug fix 2020-09-23 16:49:56 +01:00
bobbie 39ab7922d4 Merge pull request #13 from stokebob/master
update branch
2020-09-23 13:17:17 +01:00
bobbie 8cd27646cd Updating branch with changes from master (#12)
* Copy release version to Dropbox on build

* Bug fix: Error thrown on list containing null item
2020-09-23 13:15:30 +01:00
Bobbie Hodgetts dcd32b76fa Bug fix: Error thrown on list containing null item 2020-09-23 13:09:24 +01:00
bobbie 9ec07b8703 Copy release version to Dropbox on build 2020-08-10 11:54:19 +01:00
bobbie aeef35b57c wip 2020-06-08 15:13:38 +01:00
bobbie 738f87f988 wip 2020-06-05 12:19:46 +01:00
bobbie d6b198777f wip 2020-05-29 16:28:16 +01:00
bobbie 3a53350f85 Stock SKU transaction reconciliation 2020-05-29 14:07:46 +01:00
bobbie 43d61c2ef8 Feature repricing min max (#10)
amazon settlement import/export improvements
2020-05-01 09:08:23 +01:00
bobbie 56647c7648 Fix amazon settlement period and other updates 2020-02-11 17:20:45 +00:00
bobbie 7e50da21e7 Export amazon settlement report fix 2020-02-06 21:20:15 +00:00
Bobbie Hodgetts bed529e1c8 HotFix: Database type change from int to tinyint. Updated code to handle this 2019-07-12 12:03:08 +01:00
Bobbie Hodgetts a342f8adc6 HotFix: DateTimeLog file missing from master branch. 2019-07-12 11:36:30 +01:00
Bobbie Hodgetts 116aedb897 Feature: Sync MWS Shipment with Database
Various restructuring and misc. features added.
Removed reliance on ABrain Amazon MWS NuGet package, added Amazon's own C# lib
2019-06-24 16:01:50 +01:00
bobbie bc44546efd Update/restructure of COM type library 2019-04-02 17:25:30 +01:00
Bobbie Hodgetts 824ebb72ca Solution structure reorganised 2019-03-29 18:49:42 +00:00
Bobbie Hodgetts 94b03eed8a Added option to update Amazon removal order report via console application 2019-03-28 19:13:26 +00:00
bobbie 24eee320e8 Feature to handle different SKU tax types when creating sales invoices
Added feature to handle different tax types when creating Xero sales invoice from Amazon settlement reports. (#1)
2019-03-25 16:32:22 +00:00
306 changed files with 32752 additions and 10978 deletions
+6 -1
View File
@@ -1,6 +1,8 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
*.local.config
# User-specific files
*.suo
*.user
@@ -11,6 +13,8 @@
*.userprefs
# Build results
packages/
artifacts/
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
@@ -258,4 +262,5 @@ paket-files/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
*.pyc
/src/bnhtrade.ScheduledTasks/app.local.config
+6
View File
@@ -0,0 +1,6 @@
[submodule "lib/test"]
path = lib/test
url = https://github.com/abuzuhri/Amazon-SP-API-CSharp
[submodule "src/Amazon-SP-API-CSharp"]
path = src/Amazon-SP-API-CSharp
url = https://github.com/abuzuhri/Amazon-SP-API-CSharp
+1
View File
@@ -0,0 +1 @@
Solution layout taken from github davidfowl/dotnetlayout.md
-38
View File
@@ -1,38 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.2037
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bnhtradeDatabaseClient", "bnhtrade Database Client\bnhtradeDatabaseClient.csproj", "{339D7413-3DA7-46EA-A55C-255A9A6B95EB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bnhtradeScheduledTasks", "bnhtrade Scheduled Tasks\bnhtradeScheduledTasks.csproj", "{5D6E1D66-3901-4340-95C6-EE65051AB623}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CF330C30-8231-4D54-B60C-FF0644713502}"
ProjectSection(SolutionItems) = preProject
bnhtradeRegasmInstall.bat = bnhtradeRegasmInstall.bat
bnhtradeRegasmRefresh.bat = bnhtradeRegasmRefresh.bat
bnhtradeRegasmUninstall.bat = bnhtradeRegasmUninstall.bat
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{339D7413-3DA7-46EA-A55C-255A9A6B95EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{339D7413-3DA7-46EA-A55C-255A9A6B95EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{339D7413-3DA7-46EA-A55C-255A9A6B95EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{339D7413-3DA7-46EA-A55C-255A9A6B95EB}.Release|Any CPU.Build.0 = Release|Any CPU
{5D6E1D66-3901-4340-95C6-EE65051AB623}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D6E1D66-3901-4340-95C6-EE65051AB623}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D6E1D66-3901-4340-95C6-EE65051AB623}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D6E1D66-3901-4340-95C6-EE65051AB623}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9CE53A62-9E0C-460F-9C09-B7DDB3B7F0EA}
EndGlobalSection
EndGlobal
-24
View File
@@ -1,24 +0,0 @@
<?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"/>
</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"/>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
<applicationSettings>
<e2A_Client.Properties.Settings>
<setting name="DocArchivePath" serializeAs="String">
<value>%USERPROFILE%\Desktop\e2A_Client\Archive\</value>
</setting>
<setting name="DocProcessingPath" serializeAs="String">
<value>%USERPROFILE%\Desktop\e2A_Client\Processing\</value>
</setting>
</e2A_Client.Properties.Settings>
</applicationSettings>
</configuration>
File diff suppressed because it is too large Load Diff
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("bnhtrade Database Client")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("bnhtrade Database Client")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("339d7413-3da7-46ea-a55c-255a9a6b95eb")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
-55
View File
@@ -1,55 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace bnhtradeDatabaseClient.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.6.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
[global::System.Configuration.DefaultSettingValueAttribute("Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=True;User ID=e2A" +
" Client;Password=eSYH4EYoK6Guc5KIclhgFDlGc4;MultipleActiveResultSets=true")]
public string ConnectionString {
get {
return ((string)(this["ConnectionString"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("%USERPROFILE%\\Desktop\\e2A_Client\\Archive\\")]
public string DocArchivePath {
get {
return ((string)(this["DocArchivePath"]));
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("%USERPROFILE%\\Desktop\\e2A_Client\\Processing\\")]
public string DocProcessingPath {
get {
return ((string)(this["DocProcessingPath"]));
}
}
}
}
@@ -1,20 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="e2A_Client.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="ConnectionString" Type="(Connection string)" Scope="Application">
<DesignTimeValue Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;SerializableConnectionString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
&lt;ConnectionString&gt;Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=True;User ID=e2A Client;Password=eSYH4EYoK6Guc5KIclhgFDlGc4;MultipleActiveResultSets=true&lt;/ConnectionString&gt;
&lt;ProviderName&gt;System.Data.SqlClient&lt;/ProviderName&gt;
&lt;/SerializableConnectionString&gt;</DesignTimeValue>
<Value Profile="(Default)">Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=True;User ID=e2A Client;Password=eSYH4EYoK6Guc5KIclhgFDlGc4;MultipleActiveResultSets=true</Value>
</Setting>
<Setting Name="DocArchivePath" Type="System.String" Scope="Application">
<Value Profile="(Default)">%USERPROFILE%\Desktop\e2A_Client\Archive\</Value>
</Setting>
<Setting Name="DocProcessingPath" Type="System.String" Scope="Application">
<Value Profile="(Default)">%USERPROFILE%\Desktop\e2A_Client\Processing\</Value>
</Setting>
</Settings>
</SettingsFile>
@@ -1,40 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Runtime.InteropServices;
namespace DatabaseConnection
{
//[ComVisible(true)]
//[Guid("8bebe939-7a73-4ba3-877b-50cd2a7e4586")]
//[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface bnhtradeDbInterface
{
SqlConnection Connection(string DataSource, string InitialCatalog, string UserId, string Password, bool PersistSecurityInfo = true, bool MultipleActiveResultSets = true);
}
//[ComVisible(true)]
//[Guid("b0e29c9e-d353-4d3a-83dd-5278b520af54")]
//[ClassInterface(ClassInterfaceType.None)]
////[ProgId("MyNameSpace.Criteria")]
public class bnhtradeDb : bnhtradeDbInterface
{
public SqlConnection Connection(string DataSource, string InitialCatalog, string UserId, string Password, bool PersistSecurityInfo = true, bool MultipleActiveResultSets = true)
{
if (InitialCatalog == "" || DataSource == "" || UserId == "" || Password == "")
{
throw new Exception("Insuficent info supplied for sql connection string");
}
string connString =
"Data Source=" + DataSource + ";Initial Catalog=" + InitialCatalog + ";Persist Security Info=" + PersistSecurityInfo.ToString() + ";" +
"User ID=" + UserId + ";Password=" + Password + ";MultipleActiveResultSets=" + MultipleActiveResultSets.ToString() + "";
SqlConnection sqlConn = new SqlConnection(connString);
return sqlConn;
}
}
}
-539
View File
@@ -1,539 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using bnhtradeDatabaseClient.Product;
using bnhtradeDatabaseClient.EbayQuery;
using bnhtradeDatabaseClient.Database;
using bnhtradeDatabaseClient;
using bnhtradeDatabaseClient;
using System.Data.SqlClient;
using System.IO;
using System.Reflection;
using static Vba6.StockQuery;
namespace Vba6
{
[ComVisible(true)]
[Guid("033326dd-6edb-4343-8334-4c31acf3565e")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IConnectionCredential
{
string UserId { get; set; }
string Password { get; set; }
string ConnectionString { get; }
}
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("b670a3fc-feeb-487b-ad25-89a1115e9aa5")]
public interface IVbaSqlConnection
{
SqlConnection GetSqlConnection(ConnectionCredential vbaConnCred);
}
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("05860bc9-6a6d-4b8f-a611-3921c4b4755c")]
public interface IEbayQuery
{
int EbayListingItemGet(string itemNumber, DateTime listingEnd, ConnectionCredential sqlConnCred);
object[] EbayListingItemInsert(string itemNumber, DateTime listingEnd, string listingTitle, string listingDescription, string ebayUser,
bool isAuction, [MarshalAs(UnmanagedType.Currency)] decimal price, DateTime priceTime, [MarshalAs(UnmanagedType.Currency)] decimal shipping,
string itemLocation, string category, string imageFilePath, ConnectionCredential sqlConnCred);
}
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("0fd536ce-b913-438d-9343-9a1a7a40af71")]
public interface IAmazonMws
{
}
[ComVisible(true)]
[Guid("90eefc75-11d7-449d-a99f-3e4d1a795ebc")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPurchaseQuery
{
void PurchaseLineTransactionNetInsert(ConnectionCredential sqlConnCred, int purchaseLineId, int debitAccountId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet,
DateTime entryDate);
void PurchaseLineTransactionNetUpdate(ConnectionCredential sqlConnCred, int accountJouranlId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet, int debitAccountId);
void PurchaseLineTransactionDelete(ConnectionCredential sqlConnCred, int purchaseLineId, int accountJournalId);
int PurchaseLineTransactionStockInsert(ConnectionCredential sqlConnCred, int accountJournalId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId,
int accountTaxCodeId, int stockDebitStatusId);
void PurchaseLineTransactionStockDelete(ConnectionCredential sqlConnCred, int stockId);
}
[ComVisible(true)]
[Guid("b6215466-7b84-4d1f-807f-6b305a4c05f0")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAccountQuery
{
int AccountJournalInsert(ConnectionCredential sqlConnCred, int journalTypeId, DateTime entryDate,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false);
bool AccountJournalDelete(ConnectionCredential sqlConnCred, int accountJournalId);
[return: MarshalAs(UnmanagedType.Currency)]
decimal CurrencyConvertToGbp(ConnectionCredential sqlConnCred, string currencyCode,
[MarshalAs(UnmanagedType.Currency)] decimal amount, DateTime conversionDate);
int CurrencyExchangeRateInsert(ConnectionCredential sqlConnCred, int exchangeRateSource, string currencyCode,
[MarshalAs(UnmanagedType.Currency)] decimal currencyUnitsPerGbp, DateTime periodStart, DateTime periodEnd, bool checkOverride = false);
}
[ComVisible(true)]
[Guid("ca9ef5b4-f0e6-4b77-9602-0d5f123a1d8d")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IProductQuery
{
string ReturnStringValue(string stringValue);
double ReturnDateValueAsDouble(string stringValue);
int ProductGetProductIdByCatId(int catId, ConnectionCredential sqlConnCred);
string ProductCompetitivePriceGet(int productId, int conditionId, ConnectionCredential sqlConnCred);
int ProductCompetitivePriceSet(int productId, int conditionId, [MarshalAs(UnmanagedType.Currency)] decimal price, bool isBuyBoxPrice, DateTime priceDate, ConnectionCredential sqlConnCred);
void ProductUpdateAmazonEstimateFee(ConnectionCredential sqlConnCred, object inputList);
}
[ComVisible(true)]
[Guid("d595d682-8b1e-4aa4-86b7-700e44950e1b")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IStockQuery
{
int StockInsertPurchase(ConnectionCredential sqlConnCred, int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId);
int StockInsertOwnerIntroduced(ConnectionCredential sqlConnCred, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId);
void StockDeletePurchase(ConnectionCredential sqlConnCred, int stockId);
void StockDeleteOwnerIntroduced(ConnectionCredential sqlConnCred, int stockId);
int StockReallocate(ConnectionCredential sqlConnCred, int stockId, int quantity, int debitStatusId, int creditStatusId, DateTime entryDate);
void StockJournalDelete(ConnectionCredential sqlConnCred, int stockJournalId);
object ReconcileStockTransactions(ConnectionCredential sqlConnCred);
bool StockJournalConsistencyCheck(ConnectionCredential sqlConnCred, int stockId);
}
//[ComVisible(true)]
//[Guid("0558e6dc-f5d4-41b6-a51c-856426e77e21")]
//[InterfaceType(ComInterfaceType.InterfaceIsDual)]
//public interface IReconcileStockTransactionsResult
//{
// bool ReconciliationComplete { get; set; }
// int StockTransactionId { get; set; }
// int StockTransactionTypeId { get; set; }
// string ProgressMessage { get; set; }
// int ItemsCompleted { get; set; }
// int ItemsRemaining { get; set; }
// DateTime LastItemDateTime { get; set; }
//}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("7aa43409-317a-43ad-85f9-2019b5883ab8")]
[ProgId("bnhtradeDb.ConnectionCredential")]
public class ConnectionCredential : IConnectionCredential
{
public string UserId { get; set; }
public string Password { get; set; }
public string ConnectionString
{
get
{
return "Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=True;User ID=" + UserId +
";Password=" + Password + ";MultipleActiveResultSets=true";
}
}
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("ab7f6468-42db-4f33-8c94-62dc7e1759ea")]
[ProgId("bnhtradeDb.Connection")]
public class VbaSqlConnection : IVbaSqlConnection
{
[ComVisible(false)]
public SqlConnection GetSqlConnection(ConnectionCredential vbaConnCred)
{
Connection.DatabaseConnectionDetail connDetail = new Connection.DatabaseConnectionDetail();
connDetail.UserId = vbaConnCred.UserId;
connDetail.Password = vbaConnCred.Password;
SqlConnection sqlConn = new SqlConnection(connDetail.ConnectionString);
return sqlConn;
}
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("e6743dfa-47d3-4aeb-8f2b-d4e0d5312146")]
[ProgId("bnhtradeDb.EbayQuery")]
public class EbayQuery : IEbayQuery
{
public int EbayListingItemGet(string itemNumber, DateTime listingEnd, ConnectionCredential sqlConnCred)
{
Ebay request = new Ebay();
return request.EbayListingItemGet(sqlConnCred.ConnectionString, itemNumber, listingEnd);
}
public object[] EbayListingItemInsert(string itemNumber, DateTime listingEnd, string listingTitle, string listingDescription, string ebayUser,
bool isAuction, [MarshalAs(UnmanagedType.Currency)] decimal price, DateTime priceTime, [MarshalAs(UnmanagedType.Currency)] decimal shipping,
string itemLocation, string category, string imageFilePath, ConnectionCredential sqlConnCred)
{
// load imagefile
FileStream imageFile = null;
string imageFileExtension = "";
if (imageFilePath.Length > 0)
{
imageFileExtension = Path.GetExtension(imageFilePath);
if (imageFileExtension == string.Empty)
{
throw new Exception("Error parsing file extension from file path.");
}
imageFileExtension = imageFileExtension.Substring(1);
imageFile = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read);
}
// create the return array object
Ebay request = new Ebay();
(int ListingItemId, bool IsNewListingItem, bool IsNewListing) result =
request.EbayListingItemInsert(sqlConnCred.ConnectionString, itemNumber, listingEnd, listingTitle, listingDescription, ebayUser,
isAuction, price, priceTime, shipping, itemLocation, category, imageFile, imageFileExtension);
if (imageFile != null)
{ imageFile.Dispose(); }
// create return array
object[] returnArray = new object[3];
returnArray[0] = result.ListingItemId;
returnArray[1] = result.IsNewListingItem;
returnArray[2] = result.IsNewListing;
return returnArray;
}
}
[ComVisible(true)]
[Guid("23527370-5f3f-47d8-b6a0-35b73890876c")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtradeDb.AmazonMws")]
// [ClassInterface(ClassInterfaceType.AutoDual)]
public class AmazonMws : IAmazonMws
{
static void ProductUpdateAmazonEstimateFee()
{
}
}
[ComVisible(true)]
[Guid("59afd52d-86f4-4863-98e9-7b63a8b3ba51")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtradeDb.ProductQuery")]
public class PurchaseQuery : IPurchaseQuery
{
public void PurchaseLineTransactionNetInsert(ConnectionCredential sqlConnCred, int purchaseLineId, int debitAccountId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet,
DateTime entryDate)
{
bnhtradeDatabaseClient.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionNetInsert(sqlConnCred.ConnectionString,
purchaseLineId, currencyCode, amountNet, entryDate);
}
public void PurchaseLineTransactionNetUpdate(ConnectionCredential sqlConnCred, int accountJouranlId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet, int debitAccountId)
{
bnhtradeDatabaseClient.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionNetUpdate(sqlConnCred.ConnectionString,
accountJouranlId, currencyCode, amountNet, debitAccountId);
}
public void PurchaseLineTransactionDelete(ConnectionCredential sqlConnCred, int purchaseLineId, int accountJournalId)
{
bnhtradeDatabaseClient.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionDelete(sqlConnCred.ConnectionString, purchaseLineId, accountJournalId);
}
public int PurchaseLineTransactionStockInsert(ConnectionCredential sqlConnCred, int accountJournalId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId,
int accountTaxCodeId, int stockDebitStatusId)
{
return bnhtradeDatabaseClient.Stock.StockCreate.WIP_StockInsertPurchase(sqlConnCred.ConnectionString, productId, conditionId, accountTaxCodeId, accountJournalId, quantity, stockDebitStatusId);
}
public void PurchaseLineTransactionStockDelete(ConnectionCredential sqlConnCred, int stockId)
{
bnhtradeDatabaseClient.Stock.StockCreate.WIP_StockDeletePurchase(sqlConnCred.ConnectionString, stockId);
}
}
[ComVisible(true)]
[Guid("debaee08-a3d5-4f9b-b8cf-ad146c3e0ee9")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtradeDb.AccountQuery")]
public class AccountQuery : IAccountQuery
{
public int AccountJournalInsert(ConnectionCredential sqlConnCred, int journalTypeId, DateTime entryDate,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false)
{
return bnhtradeDatabaseClient.Account.AccountQuery.AccountJournalInsert(sqlConnCred.ConnectionString, journalTypeId, entryDate,
currencyCode, amount, debitAccountId, creditAccountId, lockEntry);
}
public bool AccountJournalDelete(ConnectionCredential sqlConnCred, int accountJournalId)
{
return bnhtradeDatabaseClient.Account.AccountQuery.AccountJournalDelete(sqlConnCred.ConnectionString, accountJournalId);
}
[return: MarshalAs(UnmanagedType.Currency)]
public decimal CurrencyConvertToGbp(ConnectionCredential sqlConnCred, string currencyCode,
[MarshalAs(UnmanagedType.Currency)] decimal amount, DateTime conversionDate)
{
return bnhtradeDatabaseClient.Account.AccountQuery.CurrencyConvertToGbp(sqlConnCred.ConnectionString, currencyCode, amount, conversionDate);
}
public int CurrencyExchangeRateInsert(ConnectionCredential sqlConnCred, int exchangeRateSource, string currencyCode,
[MarshalAs(UnmanagedType.Currency)] decimal currencyUnitsPerGbp, DateTime periodStart, DateTime periodEnd, bool checkOverride = false)
{
return bnhtradeDatabaseClient.Account.AccountQuery.CurrencyExchangeRateInsert(sqlConnCred.ConnectionString, exchangeRateSource, currencyCode,
currencyUnitsPerGbp, periodStart, periodEnd, checkOverride);
}
}
[ComVisible(true)]
[Guid("237ac4be-87f0-4500-bd74-0423d1f72c75")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtradeDb.ProductQuery")]
public class ProductQuery : IProductQuery
{
[ComVisible(false)]
[return: MarshalAs(UnmanagedType.BStr)]
public string ReturnStringValue(string stringValue)
{
return "kj;lk1";
}
[ComVisible(false)]
public double ReturnDateValueAsDouble(string stringValue)
{
DateTime theTimeNow = DateTime.UtcNow;
return theTimeNow.ToOADate();
// back in vba use the CDate(return) function to convert the double
// vba Date --> c# DateTime works without marshalling
}
public int ProductGetProductIdByCatId(int catId, ConnectionCredential sqlConnCred)
{
var request = new bnhtradeDatabaseClient.Product.ProductQuery();
int? result = request.ProductGetProductIdByCatId(sqlConnCred.ConnectionString, catId);
if (result == null)
{
return 0;
}
else
{
return result.Value;
}
}
public string ProductCompetitivePriceGet(int productId, int conditionId, ConnectionCredential sqlConnCred)
{
var request = new bnhtradeDatabaseClient.Product.ProductQuery();
(decimal? price, DateTime? priceDate) result = request.ProductCompetitivePriceGet(sqlConnCred.ConnectionString, productId, conditionId);
if (result.price == null || result.priceDate == null)
{
return "";
}
else
{
DateTime priceDate2 = result.priceDate.Value;
return result.price.ToString() + ";" + priceDate2.ToOADate();
}
}
public int ProductCompetitivePriceSet(int productId, int conditionId, [MarshalAs(UnmanagedType.Currency)] decimal price, bool isBuyBoxPrice, DateTime priceDate, ConnectionCredential sqlConnCred)
{
var request = new bnhtradeDatabaseClient.Product.ProductQuery();
return request.ProductCompetitivePriceSet(sqlConnCred.ConnectionString, productId, conditionId, price, isBuyBoxPrice, priceDate);
}
public void ProductUpdateAmazonEstimateFee(ConnectionCredential sqlConnCred, object inputList)
{
// get com object in string array
var inputTuple = new List<(string asin, decimal priceToEstimate)>();
string[] stringArray = Vba6.Functions.LoadComObjectIntoStringArray(inputList);
foreach (var item in stringArray)
{
string[] split = item.Split(';');
if (split.Length != 2)
{
throw new Exception("Split function failed on line: " + item);
}
var tempTuple = (split[0], decimal.Parse(split[1]));
inputTuple.Add(tempTuple);
}
bnhtradeDatabaseClient.Product.ProductQuery.ProductUpdateAmazonEstimateFee(sqlConnCred.ConnectionString, inputTuple);
}
}
[ComVisible(true)]
[Guid("10ff112d-a94f-4818-add4-8dddabf1fa9e")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtradeDb.StockQuery")]
// [ClassInterface(ClassInterfaceType.AutoDual)]
public class StockQuery : IStockQuery
{
public int StockInsertPurchase(ConnectionCredential sqlConnCred, int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId)
{
return bnhtradeDatabaseClient.Stock.StockCreate.WIP_StockInsertPurchase(sqlConnCred.ConnectionString, productId, conditionId, accountTaxCodeId, accountJournalId, quantity, statusDebitId);
}
public int StockInsertOwnerIntroduced(ConnectionCredential sqlConnCred, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
{
return bnhtradeDatabaseClient.Stock.StockCreate.WIP_StockInsertOwnerIntroduced(sqlConnCred.ConnectionString, amount, quantity, productId, conditionId, accountTaxCodeId, entryDate, debitStatusId);
}
public void StockDeletePurchase(ConnectionCredential sqlConnCred, int stockId)
{
bnhtradeDatabaseClient.Stock.StockCreate.WIP_StockDeletePurchase(sqlConnCred.ConnectionString, stockId);
}
public void StockDeleteOwnerIntroduced(ConnectionCredential sqlConnCred, int stockId)
{
bnhtradeDatabaseClient.Stock.StockCreate.WIP_StockDeleteOwnerIntroduced(sqlConnCred.ConnectionString, stockId);
}
public int StockReallocate(ConnectionCredential sqlConnCred, int stockId, int quantity, int debitStatusId, int creditStatusId, DateTime entryDate)
{
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
return bnhtradeDatabaseClient.Stock.StockJournal.StockReallocateByStockId(sqlConnCred.ConnectionString, 4, stockId, quantity, debitStatusId, creditStatusId, entryDate);
}
public void StockJournalDelete(ConnectionCredential sqlConnCred, int stockJournalId)
{
bnhtradeDatabaseClient.Stock.StockJournal.StockJournalDelete(sqlConnCred.ConnectionString, stockJournalId);
}
public object ReconcileStockTransactions(ConnectionCredential sqlConnCred)
{
var request = new bnhtradeDatabaseClient.Stock.StockReconciliation();
var result = new bnhtradeDatabaseClient.Stock.StockReconciliation.ReconcileStockTransactionsResult();
result = request.ReconcileStockTransactions(sqlConnCred.ConnectionString, false);
//ReconcileStockTransactionsResult returnObject = new ReconcileStockTransactionsResult();
// copy values between classes
//PropertyInfo[] infos = typeof(ReconcileStockTransactionsResult).GetProperties();
//foreach (PropertyInfo info in infos)
//{
// info.SetValue(returnObject, info.GetValue(result, null), null);
//}
//foreach (PropertyInfo property in typeof(ReconcileStockTransactionsResult).GetProperties())
//{
// if (property.CanWrite)
// {
// property.SetValue(returnObject, property.GetValue(result, null), null);
// }
//}
//returnObject.ItemsCompleted = result.ItemsCompleted;
//returnObject.ItemsRemaining = result.ItemsRemaining;
//returnObject.LastItemDateTime = result.LastItemDateTime;
//returnObject.ProgressMessage = result.ProgressMessage;
//returnObject.ReconciliationComplete = returnObject.ReconciliationComplete;
//returnObject.StockTransactionId = result.StockTransactionId;
//returnObject.StockTransactionTypeId = result.StockTransactionTypeId;
//create the return array
object[] returnArray = new object[7];
returnArray[0] = result.ReconciliationComplete;
returnArray[1] = result.ProgressMessage;
returnArray[2] = result.StockTransactionId;
returnArray[3] = result.StockTransactionTypeId;
returnArray[4] = result.LastItemDateTime;
returnArray[5] = result.ItemsCompleted;
returnArray[6] = result.ItemsRemaining;
return returnArray;
//return returnObject;
}
public bool StockJournalConsistencyCheck(ConnectionCredential sqlConnCred, int stockId)
{
return bnhtradeDatabaseClient.Stock.StockJournal.WIP_StockJournalConsistencyCheck(sqlConnCred.ConnectionString, stockId, null);
}
}
//[ComVisible(true)]
//[Guid("75a40c36-0b36-4954-8f60-3093f040e54f")]
//[ClassInterface(ClassInterfaceType.None)]
//[ProgId("bnhtradeDb.StockReconciliationResult")]
//// [ClassInterface(ClassInterfaceType.AutoDual)]
//public class ReconcileStockTransactionsResult : IReconcileStockTransactionsResult
//{
// public bool ReconciliationComplete { get; set; } = false;
// public int StockTransactionId { get; set; }
// public int StockTransactionTypeId { get; set; }
// public string ProgressMessage { get; set; }
// public int ItemsCompleted { get; set; }
// public int ItemsRemaining { get; set; }
// public DateTime LastItemDateTime { get; set; }
//}
public class Functions
{
public static string[] LoadComObjectIntoStringArray(object comObject)
{
Type thisType = comObject.GetType();
Type strType = Type.GetType("System.Object[]");
//Type strType = Type.GetType("System.String[*]");
string[] stringArray = new string[1];
// temporary allocation to keep compiler happy.
if (thisType == strType)
{
object[] args = new object[1];
int numEntries = (int)thisType.InvokeMember("Length", BindingFlags.GetProperty, null, comObject, null);
stringArray = new string[numEntries];
for (int i = 0; i < numEntries; i++)
{
args[0] = i; // since VB arrays index from 1, mine doesn't
stringArray[i] = (string)thisType.InvokeMember("GetValue", BindingFlags.InvokeMethod, null, comObject, args);
}
} // End if(thisType == dblType)
else
{
throw new Exception("something went wrong loading object into c# array. Type is '" + thisType.ToString() + "'");
}
return stringArray;
} // End LoadComObjectIntoDoubleArray()
}
}
@@ -1,82 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{339D7413-3DA7-46EA-A55C-255A9A6B95EB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>bnhtradeDatabaseClient</RootNamespace>
<AssemblyName>bnhtradeDatabaseClient</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="ABrain.AmazonMWS, Version=0.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ABrain.AmazonMWS.1.0.1.6\lib\ABrain.AmazonMWS.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Transactions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Include="SQL Connection.cs" />
<Compile Include="VBA Wrapper.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-4
View File
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ABrain.AmazonMWS" version="1.0.1.6" targetFramework="net452" />
</packages>
-12
View File
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="bnhtradeDbConnString"
connectionString="Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=TRUE;User ID=e2A Client;Password=eSYH4EYoK6Guc5KIclhgFDlGc4;MultipleActiveResultSets=TRUE" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
</startup>
</configuration>
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("bnhtrade Scheduled Tasks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("bnhtrade Scheduled Tasks")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("5d6e1d66-3901-4340-95c6-ee65051ab623")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,13 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="bnhtrade_Scheduled_Tasks.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="bnhtradeDbConnString" Type="(Connection string)" Scope="Application">
<DesignTimeValue Profile="(Default)">&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;SerializableConnectionString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
&lt;ConnectionString&gt;Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=TRUE;User ID=e2A Client;Password=eSYH4EYoK6Guc5KIclhgFDlGc4;MultipleActiveResultSets=TRUE&lt;/ConnectionString&gt;
&lt;/SerializableConnectionString&gt;</DesignTimeValue>
<Value Profile="(Default)">Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=TRUE;User ID=e2A Client;Password=eSYH4EYoK6Guc5KIclhgFDlGc4;MultipleActiveResultSets=TRUE</Value>
</Setting>
</Settings>
</SettingsFile>
@@ -1,99 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{5D6E1D66-3901-4340-95C6-EE65051AB623}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>bnhtrade_Scheduled_Tasks</RootNamespace>
<AssemblyName>bnhtradeScheduledTasks</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>bnhtradeScheduledTasks.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Transactions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\bnhtrade Database Client\bnhtradeDatabaseClient.csproj">
<Project>{339d7413-3da7-46ea-a55c-255a9a6b95eb}</Project>
<Name>bnhtradeDatabaseClient</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.1 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+46
View File
@@ -0,0 +1,46 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{CF330C30-8231-4D54-B60C-FF0644713502}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "bnhtrade.ScheduledTasks", "src\bnhtrade.ScheduledTasks\bnhtrade.ScheduledTasks.csproj", "{5D6E1D66-3901-4340-95C6-EE65051AB623}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "bnhtrade.Core", "src\bnhtrade.Core\bnhtrade.Core.csproj", "{339D7413-3DA7-46EA-A55C-255A9A6B95EB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "bnhtrade.ComTypeLib", "src\bnhtrade.ComTypeLib\bnhtrade.ComTypeLib.csproj", "{C3405E9D-B47A-4569-B6A3-BC9E7AA71EE5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{3D90C0F5-02E7-44E5-A89D-F5E217C6602F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "bnhtrade.gui", "src\bnhtrade.gui\bnhtrade.gui.csproj", "{92788EE6-6B75-45BE-A0F3-9E4F51CDEB3F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5D6E1D66-3901-4340-95C6-EE65051AB623}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D6E1D66-3901-4340-95C6-EE65051AB623}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D6E1D66-3901-4340-95C6-EE65051AB623}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D6E1D66-3901-4340-95C6-EE65051AB623}.Release|Any CPU.Build.0 = Release|Any CPU
{339D7413-3DA7-46EA-A55C-255A9A6B95EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{339D7413-3DA7-46EA-A55C-255A9A6B95EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{339D7413-3DA7-46EA-A55C-255A9A6B95EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{339D7413-3DA7-46EA-A55C-255A9A6B95EB}.Release|Any CPU.Build.0 = Release|Any CPU
{C3405E9D-B47A-4569-B6A3-BC9E7AA71EE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3405E9D-B47A-4569-B6A3-BC9E7AA71EE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3405E9D-B47A-4569-B6A3-BC9E7AA71EE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3405E9D-B47A-4569-B6A3-BC9E7AA71EE5}.Release|Any CPU.Build.0 = Release|Any CPU
{92788EE6-6B75-45BE-A0F3-9E4F51CDEB3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{92788EE6-6B75-45BE-A0F3-9E4F51CDEB3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{92788EE6-6B75-45BE-A0F3-9E4F51CDEB3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{92788EE6-6B75-45BE-A0F3-9E4F51CDEB3F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9CE53A62-9E0C-460F-9C09-B7DDB3B7F0EA}
EndGlobalSection
EndGlobal
-23
View File
@@ -1,23 +0,0 @@
@set batchpath=%~dp0
@set dllpath=%batchpath%bnhtrade Database Client\bin\Release\
@copy "%dllpath%bnhtradeDatabaseClient.dll" "%SYSTEMROOT%\SysWOW64\bnhtradeDatabaseClient.dll"
@copy "%dllpath%ABrain.AmazonMWS.dll" "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.dll"
@copy "%dllpath%bnhtradeDatabaseClient.dll" "%SYSTEMROOT%\System32\bnhtradeDatabaseClient.dll"
@copy "%dllpath%ABrain.AmazonMWS.dll" "%SYSTEMROOT%\System32\ABrain.AmazonMWS.dll"
@c:
@cd\Windows\Microsoft.NET\Framework\v4.*
regasm.exe /codebase /tlb "bnhtradeDatabaseClient.dll"
regasm.exe /codebase /tlb "ABrain.AmazonMWS.dll"
@cd\Windows\Microsoft.NET\Framework64\v4.*
regasm.exe /codebase /tlb "bnhtradeDatabaseClient.dll"
regasm.exe /codebase /tlb "ABrain.AmazonMWS.dll"
@echo.
@echo Finished running regasm install script.
@echo.
@rem if no arguments passed, pause
@IF "%~1"=="" @pause
-7
View File
@@ -1,7 +0,0 @@
@set mypath=%~dp0
call "%mypath%bnhtradeRegasmUninstall.bat" nopause
call "%mypath%bnhtradeRegasmInstall.bat" nopause
@echo Completed regasm refresh
@echo.
@pause
-21
View File
@@ -1,21 +0,0 @@
@c:
@cd\Windows\Microsoft.NET\Framework\v4.*
regasm.exe /u "bnhtradeDatabaseClient.dll"
@cd\Windows\Microsoft.NET\Framework64\v4.*
regasm.exe /u "bnhtradeDatabaseClient.dll"
@del /q "%SYSTEMROOT%\SysWOW64\bnhtradeDatabaseClient.dll"
@del /q "%SYSTEMROOT%\SysWOW64\bnhtradeDatabaseClient.tlb"
@del /q "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.dll"
@del /q "%SYSTEMROOT%\SysWOW64\ABrain.AmazonMWS.tlb"
@del /q "%SYSTEMROOT%\System32\bnhtradeDatabaseClient.dll"
@del /q "%SYSTEMROOT%\System32\bnhtradeDatabaseClient.tlb"
@del /q "%SYSTEMROOT%\System32\ABrain.AmazonMWS.dll"
@del /q "%SYSTEMROOT%\System32\ABrain.AmazonMWS.tlb"
@echo.
@echo Finished running regasm uninstall script.
@rem if no arguments passed, pause
@echo.
@IF "%~1"=="" @pause
@@ -0,0 +1,61 @@
using bnhtrade.ComTypeLib.Credential;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.ComTypeLib
{
[ComVisible(true)]
[Guid("17ecbcc2-331b-4a08-86cc-864290a252e9")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAccount
{
int AccountJournalInsert(ConnectionCredential sqlConnCred, int journalTypeId, DateTime entryDate,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false);
bool AccountJournalDelete(ConnectionCredential sqlConnCred, int accountJournalId);
[return: MarshalAs(UnmanagedType.Currency)]
decimal CurrencyConvertToGbp(ConnectionCredential sqlConnCred, string currencyCode,
[MarshalAs(UnmanagedType.Currency)] decimal amount, DateTime conversionDate);
int CurrencyExchangeRateInsert(ConnectionCredential sqlConnCred, int exchangeRateSource, string currencyCode,
[MarshalAs(UnmanagedType.Currency)] decimal currencyUnitsPerGbp, DateTime periodStart, DateTime periodEnd, bool checkOverride = false);
}
[ComVisible(true)]
[Guid("1624ad76-092c-4f0e-949e-71f084dcba52")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtrade.Account")]
public class Account : IAccount
{
public int AccountJournalInsert(ConnectionCredential sqlConnCred, int journalTypeId, DateTime entryDate,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false)
{
return new Core.Logic.Account.Journal().AccountJournalInsert(journalTypeId, entryDate,
currencyCode, amount, debitAccountId, creditAccountId, lockEntry);
}
public bool AccountJournalDelete(ConnectionCredential sqlConnCred, int accountJournalId)
{
return new Core.Logic.Account.Journal().AccountJournalDelete(accountJournalId);
}
[return: MarshalAs(UnmanagedType.Currency)]
public decimal CurrencyConvertToGbp(ConnectionCredential sqlConnCred, string currencyCode,
[MarshalAs(UnmanagedType.Currency)] decimal amount, DateTime conversionDate)
{
return new Core.Logic.Account.CurrencyService().CurrencyConvertToGbp(currencyCode, amount, conversionDate);
}
public int CurrencyExchangeRateInsert(ConnectionCredential sqlConnCred, int exchangeRateSource, string currencyCode,
[MarshalAs(UnmanagedType.Currency)] decimal currencyUnitsPerGbp, DateTime periodStart, DateTime periodEnd, bool checkOverride = false)
{
throw new Exception("This function has been retired, now handled by nightly routines");
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Runtime.InteropServices;
namespace bnhtrade.ComTypeLib.Credential
{
[ComVisible(true)]
[Guid("dd956394-0622-49fa-8c26-1ec82e70d03d")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IConnectionCredential
{
string UserId { get; set; }
string Password { get; set; }
string ConnectionString { get; }
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("de81b703-8d55-4dbc-a561-2317a9068a6f")]
[ProgId("bnhtrade.ConnectionCredential")]
public class ConnectionCredential : IConnectionCredential
{
public string UserId { get; set; }
public string Password { get; set; }
public string ConnectionString
{
get
{
return "Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=True;User ID=" + UserId +
";Password=" + Password + ";MultipleActiveResultSets=true";
}
}
}
}
@@ -0,0 +1,69 @@
using bnhtrade.ComTypeLib.Credential;
using System;
using System.Runtime.InteropServices;
using System.IO;
using bnhtrade.Core.EbayQuery;
namespace bnhtrade.ComTypeLib.Ebay
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("399ef39c-a63b-4dd4-aa18-f8f0f97f9abe")]
public interface IEbayListing
{
int EbayListingItemGet(string itemNumber, DateTime listingEnd, ConnectionCredential sqlConnCred);
object[] EbayListingItemInsert(string itemNumber, DateTime listingEnd, string listingTitle, string listingDescription, string ebayUser,
bool isAuction, [MarshalAs(UnmanagedType.Currency)] decimal price, DateTime priceTime, [MarshalAs(UnmanagedType.Currency)] decimal shipping,
string itemLocation, string category, string imageFilePath, ConnectionCredential sqlConnCred);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("7e075895-fb50-42b4-a676-bf69cbedab39")]
[ProgId("bnhtrade.EbayListing")]
public class EbayListing : IEbayListing
{
public int EbayListingItemGet(string itemNumber, DateTime listingEnd, ConnectionCredential sqlConnCred)
{
EbayListingGetIdByItemNumber request = new EbayListingGetIdByItemNumber();
return request.EbayListingItemGet(sqlConnCred.ConnectionString, itemNumber, listingEnd);
}
public object[] EbayListingItemInsert(string itemNumber, DateTime listingEnd, string listingTitle, string listingDescription, string ebayUser,
bool isAuction, [MarshalAs(UnmanagedType.Currency)] decimal price, DateTime priceTime, [MarshalAs(UnmanagedType.Currency)] decimal shipping,
string itemLocation, string category, string imageFilePath, ConnectionCredential sqlConnCred)
{
// load imagefile
FileStream imageFile = null;
string imageFileExtension = "";
if (imageFilePath.Length > 0)
{
imageFileExtension = Path.GetExtension(imageFilePath);
if (imageFileExtension == string.Empty)
{
throw new Exception("Error parsing file extension from file path.");
}
imageFileExtension = imageFileExtension.Substring(1);
imageFile = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read);
}
// create the return array object
EbayListingGetIdByItemNumber request = new EbayListingGetIdByItemNumber();
(int ListingItemId, bool IsNewListingItem, bool IsNewListing) result =
request.EbayListingItemInsert(sqlConnCred.ConnectionString, itemNumber, listingEnd, listingTitle, listingDescription, ebayUser,
isAuction, price, priceTime, shipping, itemLocation, category, imageFile, imageFileExtension);
if (imageFile != null)
{ imageFile.Dispose(); }
// create return array
object[] returnArray = new object[3];
returnArray[0] = result.ListingItemId;
returnArray[1] = result.IsNewListingItem;
returnArray[2] = result.IsNewListing;
return returnArray;
}
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ClearOutputDirectory>True</ClearOutputDirectory>
</PropertyGroup>
</Project>
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- ILRepack -->
<Target Name="ILRepacker" AfterTargets="Build">
<ItemGroup>
<InputAssemblies Include="$(OutputPath)*.dll" />
<!--ILRepack started complaining it can't resolve CSVHelper when building the project, hence the line below-->
<!--It's a hack, and will need updating when CSVHelper is updated, but I can't figure it out-->
<!--InputAssemblies Include="C:\Users\Bobbie\.nuget\packages\csvhelper\33.0.1\lib\net8.0\CsvHelper.dll"/-->
</ItemGroup>
<ILRepack
AllowDuplicateResources="false"
DebugInfo="true"
Internalize="true"
InternalizeExclude="$(AssemblyName).dll"
InputAssemblies="@(InputAssemblies)"
OutputFile="$(TargetPath)"
Parallel="true"
TargetKind="Dll"
LibraryPath="$(OutputPath)"
/>
</Target>
<!-- /ILRepack -->
</Project>
@@ -0,0 +1,86 @@
using bnhtrade.ComTypeLib.Credential;
using bnhtrade.Core.Test.Account;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.ComTypeLib
{
[ComVisible(true)]
[Guid("030ce07f-3eec-4743-a378-354ece99dd1b")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IProduct
{
double ReturnDateValueAsDouble(string stringValue);
string ProductCompetitivePriceGet(int productId, int conditionId, ConnectionCredential sqlConnCred);
int ProductCompetitivePriceSet(int productId, int conditionId, [MarshalAs(UnmanagedType.Currency)] decimal price, bool isBuyBoxPrice, DateTime priceDate, ConnectionCredential sqlConnCred);
void ProductUpdateAmazonEstimateFee(ConnectionCredential sqlConnCred, object inputList);
}
[ComVisible(true)]
[Guid("3455321c-7f19-4b38-9540-6f8aa7776e71")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtrade.Product")]
public class Product : IProduct
{
public double ReturnDateValueAsDouble(string stringValue)
{
DateTime theTimeNow = DateTime.UtcNow;
return theTimeNow.ToOADate();
// back in vba use the CDate(return) function to convert the double
// vba Date --> c# DateTime works without marshalling.
}
public string ProductCompetitivePriceGet(int productId, int conditionId, ConnectionCredential sqlConnCred)
{
var compPrice = new Core.Logic.Product.GetCompetitivePrice().Execute(productId, conditionId);
if (compPrice == null)
{
return "";
}
else
{
return compPrice.Price + ";" + compPrice.PriceDatetime.ToOADate();
}
}
public int ProductCompetitivePriceSet(int productId, int conditionId, [MarshalAs(UnmanagedType.Currency)] decimal price, bool isBuyBoxPrice, DateTime priceDateLocal, ConnectionCredential sqlConnCred)
{
priceDateLocal = DateTime.SpecifyKind(priceDateLocal, DateTimeKind.Local);
return new Core.Data.Database.Product.CreateCompetitivePrice()
.ProductCompetitivePriceSet(productId, conditionId, price, isBuyBoxPrice, priceDateLocal);
}
public void ProductUpdateAmazonEstimateFee(ConnectionCredential sqlConnCred, object inputList)
{
// get com object in string array
//var inputTuple = new Dictionary<string, decimal>();
var inputTuple = new List<(string asin, decimal listingPrice)>();
var getArray = new Utility.LoadComObjextIntoStringArray();
string[] stringArray = getArray.LoadComObjectIntoStringArray(inputList);
foreach (var item in stringArray)
{
string[] split = item.Split(';');
if (split.Length != 2)
{
throw new Exception("Split function failed on line: " + item);
}
var asin = split[0];
var listingPrice = decimal.Parse(split[1]);
var t = (asin, listingPrice);
inputTuple.Add(t);
}
new Core.Logic.Product.AmazonEstimateFee().UpdateDatabase(inputTuple);
}
}
}
@@ -0,0 +1,13 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c3405e9d-b47a-4569-b6a3-bc9e7aa71ee5")]
@@ -0,0 +1,66 @@
using bnhtrade.ComTypeLib.Credential;
using System;
using System.Runtime.InteropServices;
namespace bnhtrade.ComTypeLib.Purchase
{
[ComVisible(true)]
[Guid("d0a5e2f0-04df-4acc-8ab6-2ac192d3e444")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPurchaseLine
{
void PurchaseLineTransactionNetInsert(ConnectionCredential sqlConnCred, int purchaseLineId, int debitAccountId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet,
DateTime entryDate);
void PurchaseLineTransactionNetUpdate(ConnectionCredential sqlConnCred, int accountJouranlId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet, int debitAccountId);
void PurchaseLineTransactionDelete(ConnectionCredential sqlConnCred, int purchaseLineId, int accountJournalId);
int PurchaseLineTransactionStockInsert(ConnectionCredential sqlConnCred, int accountJournalId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId,
int accountTaxCodeId, int stockDebitStatusId);
void PurchaseLineTransactionStockDelete(ConnectionCredential sqlConnCred, int stockId);
}
[ComVisible(true)]
[Guid("48939768-5deb-49bf-80eb-a64777c97cff")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtrade.ProductLine")]
public class PurchaseLine : IPurchaseLine
{
public void PurchaseLineTransactionNetInsert(ConnectionCredential sqlConnCred, int purchaseLineId, int debitAccountId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet,
DateTime entryDate)
{
Core.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionNetInsert(sqlConnCred.ConnectionString,
purchaseLineId, currencyCode, amountNet, entryDate);
}
public void PurchaseLineTransactionNetUpdate(ConnectionCredential sqlConnCred, int accountJouranlId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amountNet, int debitAccountId)
{
Core.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionNetUpdate(sqlConnCred.ConnectionString,
accountJouranlId, currencyCode, amountNet, debitAccountId);
}
public void PurchaseLineTransactionDelete(ConnectionCredential sqlConnCred, int purchaseLineId, int accountJournalId)
{
Core.Purchase.PurchaseQuery.WIP_PurchaseLineTransactionDelete(sqlConnCred.ConnectionString, purchaseLineId, accountJournalId);
}
public int PurchaseLineTransactionStockInsert(ConnectionCredential sqlConnCred, int accountJournalId,
string currencyCode, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId,
int accountTaxCodeId, int stockDebitStatusId)
{
return Core.Stock.StockCreate.WIP_StockInsertPurchase(sqlConnCred.ConnectionString, productId, conditionId, accountTaxCodeId, accountJournalId, quantity, stockDebitStatusId);
}
public void PurchaseLineTransactionStockDelete(ConnectionCredential sqlConnCred, int stockId)
{
Core.Stock.StockCreate.WIP_StockDeletePurchase(sqlConnCred.ConnectionString, stockId);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
To setup on new computer:
1. Add the app.local.config to the users ..\AppData\Local\bnhtrade\ folder (create the bnhtrade folder)
2. CLone bnhtrade solution from the repo
3. Build bnhtradeCOM project
4. Register the COM host for COM. With an elevated prompt, navigate to the build directory and run "regsvr32 bnhtradeCOM.comhost.dll"
5.
+149
View File
@@ -0,0 +1,149 @@
using bnhtrade.ComTypeLib.Credential;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.ComTypeLib
{
[ComVisible(true)]
[Guid("e0a8c0c3-8d99-402e-b5cb-51fe262ae2ff")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IStock
{
int StockInsertPurchase(ConnectionCredential sqlConnCred, int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId);
int StockInsertOwnerIntroduced(ConnectionCredential sqlConnCred, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId);
void StockDeletePurchase(ConnectionCredential sqlConnCred, int stockId);
void StockDeleteOwnerIntroduced(ConnectionCredential sqlConnCred, int stockId);
int StockReallocate(ConnectionCredential sqlConnCred, int stockId, int quantity, int debitStatusId, int creditStatusId, DateTime entryDate);
void StockJournalDelete(ConnectionCredential sqlConnCred, int stockJournalId);
object ReconcileStockTransactions(ConnectionCredential sqlConnCred);
void UnReconcileSkuTransaction(ConnectionCredential sqlConnCred, int skuTransactionId);
bool StockJournalConsistencyCheck(ConnectionCredential sqlConnCred, int stockId);
void SkuTransactionAdd(ConnectionCredential sqlConnCred, int quantity, string skuNumber, string transactionTypeCode, DateTime transactionDate);
}
[ComVisible(true)]
[Guid("184ee881-5361-43c3-8c46-d8e22863e099")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("bnhtrade.Stock")]
// [ClassInterface(ClassInterfaceType.AutoDual)]
public class Stock : IStock
{
public int StockInsertPurchase(ConnectionCredential sqlConnCred, int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId)
{
return Core.Stock.StockCreate.WIP_StockInsertPurchase(sqlConnCred.ConnectionString, productId, conditionId, accountTaxCodeId, accountJournalId, quantity, statusDebitId);
}
public int StockInsertOwnerIntroduced(ConnectionCredential sqlConnCred, [MarshalAs(UnmanagedType.Currency)] decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
{
return Core.Stock.StockCreate.WIP_StockInsertOwnerIntroduced(sqlConnCred.ConnectionString, amount, quantity, productId, conditionId, accountTaxCodeId, entryDate, debitStatusId);
}
public void StockDeletePurchase(ConnectionCredential sqlConnCred, int stockId)
{
Core.Stock.StockCreate.WIP_StockDeletePurchase(sqlConnCred.ConnectionString, stockId);
}
public void StockDeleteOwnerIntroduced(ConnectionCredential sqlConnCred, int stockId)
{
Core.Stock.StockCreate.WIP_StockDeleteOwnerIntroduced(sqlConnCred.ConnectionString, stockId);
}
public int StockReallocate(ConnectionCredential sqlConnCred, int stockId, int quantity, int debitStatusId, int creditStatusId, DateTime entryDate)
{
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
return new Core.Logic.Stock.StatusReallocate().ByStockId(entryDate, 4, stockId, quantity, debitStatusId, creditStatusId);
}
public void StockJournalDelete(ConnectionCredential sqlConnCred, int stockJournalId)
{
Core.Stock.StockJournal.StockJournalDelete(sqlConnCred.ConnectionString, stockJournalId);
}
public object ReconcileStockTransactions(ConnectionCredential sqlConnCred)
{
//var request = new Core.Stock.StockReconciliation();
//var result = new Core.Stock.StockReconciliation.ReconcileStockTransactionsResult();
var result = new Core.Logic.Stock.SkuTransactionReconcile();
result.ReconcileStockTransactions(false);
//ReconcileStockTransactionsResult returnObject = new ReconcileStockTransactionsResult();
// copy values between classes
//PropertyInfo[] infos = typeof(ReconcileStockTransactionsResult).GetProperties();
//foreach (PropertyInfo info in infos)
//{
// info.SetValue(returnObject, info.GetValue(result, null), null);
//}
//foreach (PropertyInfo property in typeof(ReconcileStockTransactionsResult).GetProperties())
//{
// if (property.CanWrite)
// {
// property.SetValue(returnObject, property.GetValue(result, null), null);
// }
//}
//returnObject.ItemsCompleted = result.ItemsCompleted;
//returnObject.ItemsRemaining = result.ItemsRemaining;
//returnObject.LastItemDateTime = result.LastItemDateTime;
//returnObject.ProgressMessage = result.ProgressMessage;
//returnObject.ReconciliationComplete = returnObject.ReconciliationComplete;
//returnObject.StockTransactionId = result.StockTransactionId;
//returnObject.StockTransactionTypeId = result.StockTransactionTypeId;
//create the return array
object[] returnArray = new object[7];
returnArray[0] = result.ReconciliationComplete;
returnArray[1] = result.ProgressMessage;
returnArray[2] = result.CurrentTransactionId;
returnArray[3] = result.CurrentTransactionTypeCode;
returnArray[4] = result.LastItemDateTime;
returnArray[5] = result.ItemsCompleted;
returnArray[6] = result.ItemsRemaining;
return returnArray;
//return returnObject;
}
public void UnReconcileSkuTransaction(ConnectionCredential sqlConnCred, int skuTransactionId)
{
new Core.Logic.Stock.SkuTransactionReconcile().UnReconcileTransaction(skuTransactionId);
}
public bool StockJournalConsistencyCheck(ConnectionCredential sqlConnCred, int stockId)
{
return Core.Stock.StockJournal.WIP_StockJournalConsistencyCheck(sqlConnCred.ConnectionString, stockId, null);
}
public void SkuTransactionAdd(ConnectionCredential sqlConnCred, int quantity, string skuNumber, string transactionTypeCode, DateTime transactionDate)
{
var trans = new bnhtrade.Core.Model.Stock.SkuTransactionCreate(
transactionDate
, transactionTypeCode
, null
, null
, null
, skuNumber
, quantity
);
new bnhtrade.Core.Logic.Stock.SkuTransactionCrud().Create(trans);
}
}
}
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.ComTypeLib.Utility
{
class LoadComObjextIntoStringArray
{
public string[] LoadComObjectIntoStringArray(object comObject)
{
Type thisType = comObject.GetType();
Type strType = Type.GetType("System.Object[]");
//Type strType = Type.GetType("System.String[*]");
string[] stringArray = new string[1];
// temporary allocation to keep compiler happy.
if (thisType == strType)
{
object[] args = new object[1];
int numEntries = (int)thisType.InvokeMember("Length", BindingFlags.GetProperty, null, comObject, null);
stringArray = new string[numEntries];
for (int i = 0; i < numEntries; i++)
{
args[0] = i; // since VB arrays index from 1, mine doesn't
stringArray[i] = (string)thisType.InvokeMember("GetValue", BindingFlags.InvokeMethod, null, comObject, args);
}
} // End if(thisType == dblType)
else
{
throw new Exception("something went wrong loading object into c# array. Type is '" + thisType.ToString() + "'");
}
return stringArray;
} // End LoadComObjectIntoDoubleArray()
}
}
@@ -0,0 +1,18 @@
@set batchpath=%~dp0
@set filename=bnhtradeCOM.dll
@set sourcepath="%batchpath%%filename%"
@set destpath="%LOCALAPPDATA%\bnhtrade\%filename%"
@copy /y %sourcepath% %destpath%
@cd\Windows\Microsoft.NET\Framework64\v4.*
regasm.exe /codebase /tlb %destpath%
@cd\Windows\Microsoft.NET\Framework\v4.*
regasm.exe /codebase /tlb %destpath%
@echo.
@echo Finished running regasm install script.
@echo.
@rem if no arguments passed, pause
@IF "%~1"=="" @pause
@@ -0,0 +1,7 @@
@set mypath=%~dp0
call "%mypath%RegAsmUninstall.bat" nopause
call "%mypath%RegAsmInstall.bat" nopause
@echo Completed regasm refresh
@echo.
@pause
@@ -0,0 +1,16 @@
@set filename=bnhtradeCOM.dll
@set dllpath="%LOCALAPPDATA%\bnhtrade\%filename%"
@c:
@cd\Windows\Microsoft.NET\Framework64\v4.*
regasm.exe /u %dllpath%
@cd\Windows\Microsoft.NET\Framework\v4.*
regasm.exe /u %dllpath%
@echo.
@echo Finished running regasm uninstall script.
@rem if no arguments passed, pause
@echo.
@IF "%~1"=="" @pause
+103
View File
@@ -0,0 +1,103 @@
<?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>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="RestSharp" publicKeyToken="598062e77f915f75" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-106.13.0.0" newVersion="106.13.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.3" newVersion="8.0.0.3" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Abstractions" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.ProtectedData" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0a613f4dd989e8ae" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.60.3.0" newVersion="4.60.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Azure.Core" publicKeyToken="92742159e12e44c8" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.39.0.0" newVersion="1.39.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Azure.Identity" publicKeyToken="92742159e12e44c8" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.11.3.0" newVersion="1.11.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocols.OpenIdConnect" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocols" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Tokens" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.JsonWebTokens" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Logging" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory.Data" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /></startup></configuration>
@@ -0,0 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>bnhtradeCOM</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<!--Added the line below to copy all dll from .nuget folder to build output folder-->
<!--CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies-->
</PropertyGroup>
<PropertyGroup>
<!--https://learn.microsoft.com/en-us/dotnet/core/native-interop/expose-components-to-com#register-the-com-host-for-com-->
<EnableComHosting>true</EnableComHosting>
</PropertyGroup>
<ItemGroup>
<ComHostTypeLibrary Include="bnhtradeCOM.tlb" />
</ItemGroup>
<PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>..\..\bin\$(AssemblyName)\Debug\</OutputPath>
<CodeAnalysisRuleSet>SecurityRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>..\..\bin\$(AssemblyName)\Release\</OutputPath>
<DebugSymbols>true</DebugSymbols>
<RegisterForComInterop>false</RegisterForComInterop>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\bnhtrade.Core\bnhtrade.Core.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>
<PropertyGroup />
<PropertyGroup>
<AssemblyTitle>bnhtrade COM Type Library</AssemblyTitle>
<Company>bnhtrade</Company>
<Product>bnhtradeCOMAsm</Product>
<Copyright>Copyright © 2019</Copyright>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy &quot;$(ProjectDir)_RegAsmInstall.bat&quot; &quot;$(TargetDir)&quot;&#xD;&#xA;copy &quot;$(ProjectDir)_RegAsmRefresh.bat&quot; &quot;$(TargetDir)&quot;&#xD;&#xA;copy &quot;$(ProjectDir)_RegAsmUninstall.bat&quot; &quot;$(TargetDir)&quot;" />
</Target>
</Project>
+111
View File
@@ -0,0 +1,111 @@
<?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" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<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>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="RestSharp" publicKeyToken="598062e77f915f75" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-106.13.0.0" newVersion="106.13.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ComponentModel.Annotations" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.3" newVersion="8.0.0.3" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Abstractions" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.ProtectedData" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.AccessControl" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.1" newVersion="6.0.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0a613f4dd989e8ae" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.60.3.0" newVersion="4.60.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Azure.Core" publicKeyToken="92742159e12e44c8" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.39.0.0" newVersion="1.39.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Azure.Identity" publicKeyToken="92742159e12e44c8" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.11.3.0" newVersion="1.11.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocols.OpenIdConnect" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocols" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Tokens" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.JsonWebTokens" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Logging" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-7.5.1.0" newVersion="7.5.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory.Data" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
+47
View File
@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core
{
public class Config
{
public string GetAppDataPath()
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\bnhtrade\";
return path;
}
/// <summary>
/// return the directory path for temp files, just add file name onto end
/// </summary>
/// <returns></returns>
public static string GetTempFileDirectoryPath()
{
string directoryPath = Path.GetTempPath()
+ "_" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
System.IO.Directory.CreateDirectory(directoryPath);
return directoryPath;
}
/// <summary>
/// Returns configuration file from local users directory
/// </summary>
/// <returns></returns>
internal Configuration GetConfiguration()
{
string path = new bnhtrade.Core.Config().GetAppDataPath();
string configFileName = "app.local.config";
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = path + configFileName;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
return config;
}
}
}
@@ -0,0 +1,78 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.Parameter.FbaInventory;
using FikaAmazonAPI.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Amazon.FbaInventory
{
public class GetFbaInventoryInfo
{
private AmazonConnection amznConn = new SpApiConnection().Connection;
public List<string> MarketPlaceIds { get; set; }
/// <summary>
/// True to return inventory summaries with additional summarized inventory details and quantities.
/// Otherwise, returns inventory summaries only (the default value).
/// </summary>
public bool WithDetails { get; set; }
public GetFbaInventoryInfo()
{
}
public Dictionary<string, string> GetFnsku(List<string> skuList)
{
var returnList = new Dictionary<string, string>();
var result = GetInventorySummaries(skuList);
foreach (var list in result)
{
foreach(var item in list)
{
returnList.Add(item.SellerSku, item.FnSku);
}
}
return returnList;
}
private List<FikaAmazonAPI.AmazonSpApiSDK.Models.FbaInventory.InventorySummaries> GetInventorySummaries(List<string> skuList, DateTime? startDateTime = null)
{
var returnList = new List<FikaAmazonAPI.AmazonSpApiSDK.Models.FbaInventory.InventorySummaries>();
// max of 50 sku in one call
int i = 0;
int total = skuList.Count;
var skuRequestList = new List<string>();
foreach (string sku in skuList)
{
i++;
skuRequestList.Add(sku);
if (i == total || i % 50 == 0)
{
var parameters = new ParameterGetInventorySummaries();
//parameters.details = WithDetails;
parameters.granularityType = FikaAmazonAPI.AmazonSpApiSDK.Models.FbaInventory.Granularity.GranularityTypeEnum.Marketplace;
parameters.granularityId = new Data.Amazon.SellingPartnerAPI.Defaults().MarketPlaceIdAsString();
parameters.marketplaceIds = MarketPlaceIds;
//parameters.startDateTime = startDateTime;
parameters.sellerSkus = skuRequestList;
var lkdsjflds = amznConn.FbaInventory.GetInventorySummaries(parameters);
returnList.AddRange(lkdsjflds);
skuRequestList = new List<string>();
}
}
return returnList;
}
}
}
@@ -0,0 +1,27 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Feeds
{
public class GetFeed
{
private AmazonConnection amznConn = new SpApiConnection().Connection;
public void GetFeeds(string feedId)
{
var param = new FikaAmazonAPI.Parameter.Feed.ParameterGetFeed();
param.pageSize = 100;
param.processingStatuses = ProcessingStatuses.DONE;
param.feedTypes = new List<FeedType> { FeedType.POST_PRODUCT_PRICING_DATA };
var result = amznConn.Feed.GetFeeds(param);
}
}
}
@@ -0,0 +1,450 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FikaAmazonAPI;
using FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds;
using FikaAmazonAPI.ConstructFeed;
using FikaAmazonAPI.ConstructFeed.Messages;
using FikaAmazonAPI.Utils;
using static FikaAmazonAPI.ConstructFeed.BaseXML;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Feeds
{
public class SampleFeeds
{
AmazonConnection amazonConnection;
public SampleFeeds(AmazonConnection amazonConnection)
{
this.amazonConnection = amazonConnection;
}
public void CallFlatfile()
{
string text = System.IO.File.ReadAllText(@"C:\Users\tareq\Downloads\Beispiel_Upload.txt");
var feedresultTXT = amazonConnection.Feed.SubmitFeed(text
, FeedType.POST_FLAT_FILE_INVLOADER_DATA
, new List<string>() { MarketPlace.UnitedArabEmirates.ID }
, null
, ContentType.TXT);
string pathURL = string.Empty;
while (pathURL == string.Empty)
{
Thread.Sleep(1000 * 30);
var feedOutput = amazonConnection.Feed.GetFeed(feedresultTXT);
if (feedOutput.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds.Feed.ProcessingStatusEnum.DONE)
{
var outPut = amazonConnection.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
pathURL = outPut.Url;
}
}
}
public void GetFeeds()
{
var data = amazonConnection.Feed.GetFeeds(new FikaAmazonAPI.Parameter.Feed.ParameterGetFeed()
{
processingStatuses = ProcessingStatuses.DONE,
pageSize = 100,
feedTypes = new List<FeedType> { FeedType.POST_PRODUCT_PRICING_DATA },
createdSince = DateTime.UtcNow.AddDays(-6),
createdUntil = DateTime.UtcNow.AddDays(-1),
marketplaceIds = new List<string> { MarketPlace.UnitedArabEmirates.ID }
});
}
public void CreateFeedDocument()
{
var data = amazonConnection.Feed.CreateFeedDocument(ContentType.XML);
}
public void GetFeedDocument()
{
var data2 = amazonConnection.Feed.GetFeedDocument("amzn1.tortuga.3.92d8fd38-6ccf-49be-979f-6dc27375ea3e.T2DF7HINJ0NRA2");
}
public void GetFeed()
{
var data2 = amazonConnection.Feed.GetFeed("194146018872");
}
public void CancelFeed()
{
var data2 = amazonConnection.Feed.CancelFeed("194146018872");
}
public void SubmitFeedInventory()
{
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
var list = new List<InventoryMessage>();
list.Add(new InventoryMessage()
{
SKU = "API.853038006021.20789.1001",
Quantity = 1
});
createDocument.AddInventoryMessage(list);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_INVENTORY_AVAILABILITY_DATA);
GetFeedDetails(feedID);
}
/// <summary>
/// UnderTest
/// </summary>
public void SubmitFeedAddProductMessage(string ASIN, string SKU)
{
ConstructFeedService createDocument = new ConstructFeedService(amazonConnection.GetCurrentSellerID, "1.02");
var list = new List<ProductMessage>();
list.Add(new ProductMessage()
{
SKU = SKU,
StandardProductID = new FikaAmazonAPI.ConstructFeed.Messages.StandardProductID()
{
Type = "ASIN",
Value = ASIN
}
});
createDocument.AddProductMessage(list, OperationType.Update);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_DATA);
GetFeedDetails(feedID);
}
public void SubmitFeedDeleteAddProductMessage()
{
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
var list = new List<ProductMessage>();
list.Add(new ProductMessage()
{
SKU = "8432225129778...."
});
createDocument.AddProductMessage(list, OperationType.Delete);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeedContent(xml, FeedType.POST_PRODUCT_DATA);
GetFeedDetails(feedID);
}
public void AddOfferMessageMessage()
{
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
var list = new List<OfferMessage>();
list.Add(new OfferMessage()
{
SKU = "4049639414402_b"
});
createDocument.AddOfferMessage(list, OperationType.Delete);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_DATA);
GetFeedDetails(feedID);
}
public void SubmitFeedPRICING(decimal price, string SKU)
{
ConstructFeedService createDocument = new ConstructFeedService(amazonConnection.GetCurrentSellerID, "1.02");
var list = new List<PriceMessage>();
list.Add(new PriceMessage()
{
SKU = SKU,
StandardPrice = new StandardPrice()
{
currency = amazonConnection.GetCurrentMarketplace.CurrencyCode.ToString(),
Value = price
}
});
createDocument.AddPriceMessage(list);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_PRICING_DATA);
GetFeedDetails(feedID);
}
public async void SubmitFeedPricingWithSalePrice(string sku, decimal price, decimal salePrice, DateTime startDate, DateTime endDate)
{
var currencyCode = amazonConnection.GetCurrentMarketplace.CurrencyCode.ToString();
var createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
var list = new List<PriceMessage>();
list.Add(new PriceMessage
{
SKU = sku,
StandardPrice = new StandardPrice
{
currency = currencyCode,
Value = price
},
Sale = new Sale
{
SalePrice = new StandardPrice
{
currency = currencyCode,
Value = salePrice
},
StartDate = startDate.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"),
EndDate = endDate.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fffK")
}
});
createDocument.AddPriceMessage(list);
var xml = createDocument.GetXML();
var feedId = await amazonConnection.Feed.SubmitFeedAsync(xml, FeedType.POST_PRODUCT_PRICING_DATA);
GetFeedDetails(feedId);
}
public void SubmitFeedSale(decimal price, string SKU)
{
ConstructFeedService createDocument = new ConstructFeedService("A3J37AJU4O9RHK", "1.02");
var list = new List<PriceMessage>();
list.Add(new PriceMessage()
{
SKU = SKU,
StandardPrice = new StandardPrice()
{
currency = amazonConnection.GetCurrentMarketplace.CurrencyCode.ToString(),
Value = price
},
Sale = new Sale()
{
StartDate = DateTime.UtcNow.AddDays(+1).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"),
EndDate = DateTime.UtcNow.AddDays(+2).ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"),
SalePrice = new StandardPrice()
{
currency = amazonConnection.GetCurrentMarketplace.CurrencyCode.ToString(),
Value = price
}
}
});
createDocument.AddPriceMessage(list);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PRODUCT_PRICING_DATA);
GetFeedDetails(feedID);
}
public void FeebPostOrderFullfillment()
{
ConstructFeedService createDocument = new ConstructFeedService("{sellerId}", "1.02");
var list = new List<OrderFulfillmentMessage>();
list.Add(new OrderFulfillmentMessage()
{
AmazonOrderID = "{orderId}",
FulfillmentDate = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK"),
FulfillmentData = new FulfillmentData()
{
CarrierName = "Correos Express",
ShippingMethod = "ePaq",
ShipperTrackingNumber = "{trackingNumber}"
}
});
createDocument.AddOrderFulfillmentMessage(list);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_ORDER_FULFILLMENT_DATA);
GetFeedDetails(feedID);
}
public void SubmitFeedOrderAcknowledgement()
{
ConstructFeedService createDocument = new ConstructFeedService("{sellerId}", "1.02");
var list = new List<OrderAcknowledgementMessage>();
list.Add(new OrderAcknowledgementMessage()
{
AmazonOrderID = "AMZ1234567890123",
MerchantOrderID = "12345678",
StatusCode = OrderAcknowledgementStatusCode.Success,
Item = new List<OrderAcknowledgementItem>() {
new OrderAcknowledgementItem() {
AmazonOrderItemCode = "52986411826454",
MerchantOrderItemID = "1"
}
}
});
createDocument.AddOrderAcknowledgementMessage(list);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_ORDER_ACKNOWLEDGEMENT_DATA);
GetFeedDetails(feedID);
}
public void SubmitFeedOrderAdjustment()
{
ConstructFeedService createDocument = new ConstructFeedService("{sellerId}", "1.02");
var list = new List<OrderAdjustmentMessage>();
list.Add(new OrderAdjustmentMessage()
{
AmazonOrderID = "AMZ1234567890123",
ActionType = AdjustmentActionType.Refund,
AdjustedItem = new List<AdjustedItem>() {
new AdjustedItem() {
AmazonOrderItemCode = "52986411826454",
AdjustmentReason = AdjustmentReason.CustomerCancel,
DirectPaymentAdjustments = new List<DirectPaymentAdjustments>()
{
new DirectPaymentAdjustments()
{
Component = new List<DirectPaymentAdjustmentsComponent>()
{
new DirectPaymentAdjustmentsComponent() {
DirectPaymentType = "Credit Card Refund",
Amount = new CurrencyAmount() {
Value = 10.50M,
currency = amazonConnection.GetCurrentMarketplace.CurrencyCode
}
}
}
}
}
}
}
});
createDocument.AddOrderAdjustmentMessage(list);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_PAYMENT_ADJUSTMENT_DATA);
GetFeedDetails(feedID);
}
public void CartonContentsRequestFeed()
{
ConstructFeedService createDocument2 = new ConstructFeedService("{SellerID}", "1.02");
var list22 = new List<CartonContentsRequest>();
list22.Add(new CartonContentsRequest()
{
ShipmentId = "FBA123456",
Carton = new List<Carton> {
new Carton() {
CartonId="1",
Item=new List<CartonItem>(){
new CartonItem() {
QuantityInCase=1,
QuantityShipped=1,
SKU="7004"
}
}
},
new Carton() {
CartonId="2",
Item=new List<CartonItem>(){
new CartonItem() {
QuantityInCase=12,
QuantityShipped=12,
SKU="4051",
ExpirationDate=DateTime.Now,
}
}
}
}
});
createDocument2.AddCartonContentsRequest(list22);
var xml222 = createDocument2.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml222, FeedType.POST_FBA_INBOUND_CARTON_CONTENTS);
GetFeedDetails(feedID);
}
public void SubmitFeedEasyShipDocument()
{
ConstructFeedService createDocument = new ConstructFeedService("{sellerId}", "1.02");
var list = new List<EasyShipDocumentMessage>();
list.Add(new EasyShipDocumentMessage()
{
AmazonOrderID = "AMZ1234567890123",
DocumentTypes = new List<EasyShipDocumentType>() {
EasyShipDocumentType.ShippingLabel
}
});
createDocument.AddEasyShipDocumentMessage(list);
var xml = createDocument.GetXML();
var feedID = amazonConnection.Feed.SubmitFeed(xml, FeedType.POST_EASYSHIP_DOCUMENTS);
GetFeedDetails(feedID);
}
public void GetFeedDetails(string feedID)
{
string ResultFeedDocumentId = string.Empty;
while (string.IsNullOrEmpty(ResultFeedDocumentId))
{
var feedOutput = amazonConnection.Feed.GetFeed(feedID);
if (feedOutput.ProcessingStatus == Feed.ProcessingStatusEnum.DONE)
{
var outPut = amazonConnection.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
var reportOutput = outPut.Url;
var processingReport = amazonConnection.Feed.GetFeedDocumentProcessingReport(outPut);
DisplayProcessingReportMessage(processingReport);
break;
}
if (!(feedOutput.ProcessingStatus == Feed.ProcessingStatusEnum.INPROGRESS ||
feedOutput.ProcessingStatus == Feed.ProcessingStatusEnum.INQUEUE))
break;
else Thread.Sleep(10000);
}
}
private void DisplayProcessingReportMessage(ProcessingReportMessage processingReport)
{
Console.WriteLine("MessagesProcessed=" + processingReport.ProcessingSummary.MessagesProcessed);
Console.WriteLine("MessagesSuccessful= " + processingReport.ProcessingSummary.MessagesSuccessful);
Console.WriteLine("MessagesWithError=" + processingReport.ProcessingSummary.MessagesWithError);
Console.WriteLine("MessagesWithWarning=" + processingReport.ProcessingSummary.MessagesWithWarning);
if (processingReport.Result != null && processingReport.Result.Count > 0)
{
foreach (var itm in processingReport.Result)
{
Console.WriteLine("ResultDescription=" + (itm.AdditionalInfo?.SKU ?? string.Empty) + " > " + itm.ResultDescription);
}
}
}
}
}
@@ -0,0 +1,113 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Feeds
{
class SubmittFeed
{
private AmazonConnection amznConn = new SpApiConnection().Connection;
private Logic.Log.LogEvent logEvent = new Logic.Log.LogEvent();
public bool FeedSubmissionRecived { get; set; } = false;
// make these functions only accept a database object
public SubmittFeed()
{
}
public Model.Export.AmazonFeedSubmission FlatFileInvLoaderData(System.IO.MemoryStream filestream)
{
return Post("POST_FLAT_FILE_INVLOADER_DATA", filestream, "TXT");
}
private Model.Export.AmazonFeedSubmission Post(string feedType, System.IO.MemoryStream filestream, string fileExtension)
{
throw new NotImplementedException();
if (filestream.Length == 0) { throw new Exception("Filestreeam is empty"); }
if (string.IsNullOrEmpty(fileExtension)) { throw new Exception("Filestreeam is empty"); }
var feedresultTXT = amznConn.Feed.SubmitFeed(filestream.ToString()
, GetFeedType(feedType)
, new List<string>() { amznConn.GetCurrentMarketplace.ID }
, null
, ContentType.TXT);
string pathURL = string.Empty;
while (pathURL == string.Empty)
{
Thread.Sleep(1000 * 30);
var feedOutput = amznConn.Feed.GetFeed(feedresultTXT);
if (feedOutput.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds.Feed.ProcessingStatusEnum.DONE)
{
var outPut = amznConn.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
pathURL = outPut.Url;
}
}
}
private FeedType GetFeedType(string feedTypeText)
{
// add more here as needed
if (feedTypeText == "POST_FLAT_FILE_INVLOADER_DATA")
{ return FeedType.POST_FLAT_FILE_INVLOADER_DATA; }
else
{ throw new NotImplementedException("Need to implement feed type for " + feedTypeText); }
}
public void SubmitFeed(Model.Export.AmazonFeedSubmission feedSubmission)
{
FeedSubmissionRecived = false;
if (feedSubmission.FileIsSet == false) { throw new Exception("Filestreeam is empty"); }
// get feed type
var feedType = GetFeedType(feedSubmission.FeedType);
string text = feedSubmission.File.FileData.ToString();
var feedresultTXT = amznConn.Feed.SubmitFeed(text
, feedType
, new List<string>() { amznConn.GetCurrentMarketplace.ID }
, null
, ContentType.TXT);
var result = new FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds.FeedDocument();
int sleepTime = (1000 * 25);
int retryCount = 0;
int retryTimeout = 20;
UI.Console.Wait("Feed:" + feedType + " submitted to Amazon, awaiting status check.", 5000);
while (retryCount <= retryTimeout)
{
var feedOutput = amznConn.Feed.GetFeed(feedresultTXT);
if (feedOutput.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Feeds.Feed.ProcessingStatusEnum.DONE)
{
result = amznConn.Feed.GetFeedDocument(feedOutput.ResultFeedDocumentId);
break;
}
retryCount++;
UI.Console.Wait("Feed: " + feedType + ", Processing status: " + feedOutput.ProcessingStatus + ", Retry: " + retryCount + " of "+ retryTimeout, sleepTime);
}
// retry timeout
if (retryCount > retryTimeout)
{
logEvent.LogError("Feed submission timeout. Feedtype:" + feedType + " FeedSubmissionId:" + feedSubmission.FeedSubmissionId);
return;
}
// get and do somehting with this
string pathURL = string.Empty;
pathURL = result.Url;
}
}
}
@@ -0,0 +1,66 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Amazon.FulFillmentInbound
{
public class CreateInboundShipmentPlan
{
private AmazonConnection amznConn = new SpApiConnection().Connection;
public CreateInboundShipmentPlan()
{
}
public void CreatePlan(List<bnhtrade.Core.Model.AmazonFba.ShippingPlanItem> itemList)
{
throw new NotImplementedException();
// complete, but not tested (need to do something with the result)
var request = new FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.CreateInboundShipmentPlanRequest();
request.LabelPrepPreference = FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.LabelPrepPreference.SELLERLABEL;
request.ShipFromAddress.Name = ConfigurationManager.AppSettings["AmazonFbaShipFrom.Name"];
request.ShipFromAddress.AddressLine1 = ConfigurationManager.AppSettings["AmazonFbaShipFrom.AddressLine1"];
request.ShipFromAddress.AddressLine2 = ConfigurationManager.AppSettings["AmazonFbaShipFrom.AddressLine2"];
//request.ShipFromAddress.DistrictOrCounty = null; // not required
request.ShipFromAddress.City = ConfigurationManager.AppSettings["AmazonFbaShipFrom.City"];
request.ShipFromAddress.StateOrProvinceCode = ConfigurationManager.AppSettings["AmazonFbaShipFrom.StateOrProvinceCode"]; //required
request.ShipFromAddress.PostalCode = ConfigurationManager.AppSettings["AmazonFbaShipFrom.PostalCode"];
request.ShipFromAddress.CountryCode = ConfigurationManager.AppSettings["AmazonFbaShipFrom.CountryCode"];
request.ShipToCountryCode = ConfigurationManager.AppSettings["AmazonFbaShipFrom.CountryCode"];
// add item list
request.InboundShipmentPlanRequestItems = TransposeItemList(itemList);
var result = amznConn.FulFillmentInbound.CreateInboundShipmentPlan(request);
}
private InboundShipmentPlanRequestItemList TransposeItemList(List<bnhtrade.Core.Model.AmazonFba.ShippingPlanItem> itemList)
{
var returnList = new InboundShipmentPlanRequestItemList();
foreach(var item in itemList)
{
var requestItem = new InboundShipmentPlanRequestItem();
requestItem.SellerSKU = item.SkuNumber;
requestItem.ASIN = item.ASIN;
if (Enum.TryParse(item.Condition, out Condition myStatus)) { requestItem.Condition = myStatus; }
else { throw new Exception("Unable to parse string '" + item.Condition + "' to ENUM"); }
requestItem.Quantity = item.Quantity;
//requestItem.QuantityInCase;
//requestItem.PrepDetailsList;
returnList.Add(requestItem);
}
return returnList;
}
}
}
@@ -0,0 +1,128 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Amazon.FulFillmentInbound
{
public class GetShipmentItems
{
private AmazonConnection amznConn = new SpApiConnection().Connection;
public GetShipmentItems()
{
}
public List<Model.AmazonFba.ShipmentItemInfo> GetByDateRange(DateTime utcDateTimeAfter, DateTime utcDateTimeBefore)
{
var result = new List<Model.AmazonFba.ShipmentItemInfo>();
// build the request
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipmentItems();
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.DATE_RANGE;
parameter.LastUpdatedAfter = utcDateTimeAfter;
parameter.LastUpdatedBefore = utcDateTimeBefore;
var apiResult = amznConn.FulFillmentInbound.GetShipmentItems(parameter);
AppendNextToken(ref apiResult);
return TransposeModel(apiResult);
}
public List<Model.AmazonFba.ShipmentItemInfo> GetByShipmentId(string shipmentId)
{
var result = new List<Model.AmazonFba.ShipmentItemInfo>();
if (string.IsNullOrEmpty(shipmentId)) { return result; }
// build the request
//var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipmentItems();
//parameter.MarketplaceId = marketPlaceId;
//parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.SHIPMENT;
//parameter.ShipmentId = shipmentId;
var apiResult = amznConn.FulFillmentInbound.GetShipmentItemsByShipmentId(shipmentId);
AppendNextToken(ref apiResult);
return TransposeModel(apiResult);
}
// checks for next-token, if true appends additional data to the ShipmentData
private void AppendNextToken(ref FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.InboundShipmentItemList shipmentList)
{
while (!string.IsNullOrEmpty(shipmentList.NextToken))
{
// build the request
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipmentItems();
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.NEXT_TOKEN;
parameter.NextToken = shipmentList.NextToken;
var result = amznConn.FulFillmentInbound.GetShipmentItems(parameter);
shipmentList.AddRange(result);
shipmentList.NextToken = result.NextToken;
}
}
private void AppendNextToken(ref FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.GetShipmentItemsResult shipmentList)
{
while (!string.IsNullOrEmpty(shipmentList.NextToken))
{
// build the request
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipmentItems();
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.NEXT_TOKEN;
parameter.NextToken = shipmentList.NextToken;
var result = amznConn.FulFillmentInbound.GetShipmentItems(parameter);
shipmentList.ItemData.AddRange(result);
shipmentList.NextToken = result.NextToken;
}
}
private List<Model.AmazonFba.ShipmentItemInfo> TransposeModel(FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.InboundShipmentItemList shipmentResult)
{
var returnList = new List<Model.AmazonFba.ShipmentItemInfo>();
for (var i = 0; i < shipmentResult.Count; i++)
{
var item = new Model.AmazonFba.ShipmentItemInfo();
// under new SP-API there are more details to be used, if needed
item.AmazonFNSKU = shipmentResult[i].FulfillmentNetworkSKU;
item.AmazonShipmentId = shipmentResult[i].ShipmentId;
item.QuantityAllocated = shipmentResult[i].QuantityShipped.GetValueOrDefault();
item.QuantityReceived = shipmentResult[i].QuantityReceived.GetValueOrDefault();
item.SKUNumber = shipmentResult[i].SellerSKU;
returnList.Add(item);
}
return returnList;
}
private List<Model.AmazonFba.ShipmentItemInfo> TransposeModel(FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.GetShipmentItemsResult shipmentResult)
{
var returnList = new List<Model.AmazonFba.ShipmentItemInfo>();
for (var i = 0; i < shipmentResult.ItemData.Count; i++)
{
var item = new Model.AmazonFba.ShipmentItemInfo();
// under new SP-API there are more details to be used, if needed
item.AmazonFNSKU = shipmentResult.ItemData[i].FulfillmentNetworkSKU;
item.AmazonShipmentId = shipmentResult.ItemData[i].ShipmentId;
item.QuantityAllocated = shipmentResult.ItemData[i].QuantityShipped.GetValueOrDefault();
item.QuantityReceived = shipmentResult.ItemData[i].QuantityReceived.GetValueOrDefault();
item.SKUNumber = shipmentResult.ItemData[i].SellerSKU;
returnList.Add(item);
}
return returnList;
}
}
}
@@ -0,0 +1,110 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Amazon.FulFillmentInbound
{
public class GetShipments
{
private AmazonConnection amznConn = new SpApiConnection().Connection;
public GetShipments()
{
}
public List<Model.AmazonFba.ShipmentInfo> GetByDateRange(DateTime utcDateTimeAfter, DateTime utcDateTimeBefore)
{
// At least one of the ShipmentStatusList and ShipmentIdList must be provided
var result = new List<Model.AmazonFba.ShipmentInfo>();
// build the request
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipments();
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.DATE_RANGE;
parameter.LastUpdatedAfter = utcDateTimeAfter;
parameter.LastUpdatedBefore = utcDateTimeBefore;
AddShipmentStatusList(ref parameter);
var apiResult = amznConn.FulFillmentInbound.GetShipments(parameter);
AppendNextToken(ref apiResult);
return TransposeModel(apiResult);
}
public List<Model.AmazonFba.ShipmentInfo> GetByShipmentIdList(List<string> shipmentIdList)
{
var result = new List<Model.AmazonFba.ShipmentInfo>();
// build the request
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipments();
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.SHIPMENT;
parameter.ShipmentIdList = shipmentIdList;
var apiResult = amznConn.FulFillmentInbound.GetShipments(parameter);
AppendNextToken(ref apiResult);
return TransposeModel(apiResult);
}
private void AddShipmentStatusList(ref FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipments parameters)
{
var list = new List<ShipmentStatus>();
list.Add(ShipmentStatus.CANCELLED);
list.Add(ShipmentStatus.CHECKED_IN);
list.Add(ShipmentStatus.CLOSED);
list.Add(ShipmentStatus.DELETED);
list.Add(ShipmentStatus.DELIVERED);
list.Add(ShipmentStatus.ERROR);
list.Add(ShipmentStatus.IN_TRANSIT);
list.Add(ShipmentStatus.READY_TO_SHIP);
list.Add(ShipmentStatus.RECEIVING);
list.Add(ShipmentStatus.SHIPPED);
list.Add(ShipmentStatus.WORKING);
parameters.ShipmentStatusList = list;
}
// checks for next-token, if true appends additional data to the ShipmentData
private void AppendNextToken(ref FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.GetShipmentsResult shipmentList)
{
while (!string.IsNullOrEmpty(shipmentList.NextToken))
{
// build the request
var parameter = new FikaAmazonAPI.Parameter.FulFillmentInbound.ParameterGetShipments();
parameter.MarketplaceId = amznConn.GetCurrentMarketplace.ID;
parameter.QueryType = FikaAmazonAPI.Utils.Constants.QueryType.NEXT_TOKEN;
parameter.NextToken = shipmentList.NextToken;
var result = amznConn.FulFillmentInbound.GetShipments(parameter);
shipmentList.ShipmentData.AddRange(result.ShipmentData);
shipmentList.NextToken = result.NextToken;
}
}
// transposes return api object data to my model
private List<Model.AmazonFba.ShipmentInfo> TransposeModel(FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentInbound.GetShipmentsResult shipmentResult)
{
var returnList = new List<Model.AmazonFba.ShipmentInfo>();
for (var i = 0; i < shipmentResult.ShipmentData.Count; i++)
{
var item = new Model.AmazonFba.ShipmentInfo();
item.FbaShipmentId = shipmentResult.ShipmentData[i].ShipmentId;
item.DestinationFulfillmentCenterId = shipmentResult.ShipmentData[i].DestinationFulfillmentCenterId;
item.ShipmentName = shipmentResult.ShipmentData[i].ShipmentName;
item.ShipmentStatus = shipmentResult.ShipmentData[i].ShipmentStatus.ToString();
returnList.Add(item);
}
return returnList;
}
}
}
@@ -0,0 +1,101 @@
//using MarketplaceWebServiceProducts.Model;
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductFees;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Amazon.ProductFee
{
public class GetFeeEstimate
{
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
private AmazonConnection amznConn = new SpApiConnection().Connection;
public string CurrencyCode { get; set; } = "GBP";
public string MarketPlaceId { get; set; }
public GetFeeEstimate()
{
}
public Model.Amazon.ProductFeeEstimate GetFba(string asin, int productId, decimal listingPrice)
{
var returnObj = new Model.Amazon.ProductFeeEstimate();
if (string.IsNullOrWhiteSpace(asin))
{
throw new Exception("ASIN given to GetFeeEstimate is null or whitespace.");
}
var listingPriceObj = new MoneyType(CurrencyCode, listingPrice);
var priceToEstimateFees = new PriceToEstimateFees(listingPriceObj);
// create the request and get a response
var request = new FeesEstimateRequest(MarketPlaceId, true, priceToEstimateFees, productId.ToString());
var result = amznConn.ProductFee.GetMyFeesEstimateForASIN(asin, request);
if (result.FeesEstimateIdentifier.IdValue != asin)
throw new Exception("returned ud value does not match ASIN");
returnObj.Asin = asin;
returnObj.ProductId = int.Parse(result.FeesEstimateIdentifier.SellerInputIdentifier);
// test for error
if (result.Error != null)
{
var sb = new StringBuilder();
sb.AppendLine("ASIN: " + asin);
sb.AppendLine("Error Code: " + result.Error.Code);
if (result.Error.Detail != null)
{ sb.AppendLine("Detail: " + result.Error.Detail); }
if (result.Error.Message != null)
{ sb.AppendLine("Message: " + result.Error.Message); }
if (result.Error.Type != null)
{ sb.AppendLine("Type: " + result.Error.Type); }
log.LogError("Error running GetProductEstimateFee for ASIN:" + asin + ", further details attached.", sb.ToString());
throw new Exception("ProductFeeEstimate error, check logs for further details");
}
returnObj.IsAmazonFulfilled = result.FeesEstimateIdentifier.IsAmazonFulfilled.Value;
returnObj.TimeOfFeeEstimation = result.FeesEstimate.TimeOfFeesEstimation.Value;
returnObj.TotalFeeEstimate = result.FeesEstimate.TotalFeesEstimate.Amount.Value;
returnObj.CurrencyCode = result.FeesEstimate.TotalFeesEstimate.CurrencyCode;
returnObj.PriceToEstimateFeeListingPrice = result.FeesEstimateIdentifier.PriceToEstimateFees.ListingPrice.Amount.Value;
returnObj.PriceToEstimateFeeShipping = 0;
if (result.FeesEstimateIdentifier.PriceToEstimateFees.Shipping != null)
returnObj.PriceToEstimateFeeShipping = result.FeesEstimateIdentifier.PriceToEstimateFees.Shipping.Amount.Value;
returnObj.PriceToEstimateFeePoints = 0;
if (result.FeesEstimateIdentifier.PriceToEstimateFees.Points != null)
returnObj.PriceToEstimateFeePoints = result.FeesEstimateIdentifier.PriceToEstimateFees.Points.PointsMonetaryValue.Amount.Value;
returnObj.ReferralFee = 0m;
returnObj.VariableClosingFee = 0m;
returnObj.FulfillmentFees = 0m;
returnObj.PerItemFee = 0m;
returnObj.OtherFee_Exception = 0m;
FeeDetailList feeDetailList = result.FeesEstimate.FeeDetailList;
List<FeeDetail> feeDetail = feeDetailList;
foreach (FeeDetail feeDetailItem in feeDetail)
{
if (feeDetailItem.FeeType == "AmazonReferralFee" || feeDetailItem.FeeType == "ReferralFee")
{ returnObj.ReferralFee = (decimal)feeDetailItem.FinalFee.Amount; }
else if (feeDetailItem.FeeType == "VariableClosingFee")
{ returnObj.VariableClosingFee = (decimal)feeDetailItem.FinalFee.Amount; }
else if (feeDetailItem.FeeType == "PerItemFee")
{ returnObj.PerItemFee = (decimal)feeDetailItem.FinalFee.Amount; }
else if (feeDetailItem.FeeType == "FBAFees" || feeDetailItem.FeeType == "FulfillmentFees")
{ returnObj.FulfillmentFees = (decimal)feeDetailItem.FinalFee.Amount; }
else
{ returnObj.OtherFee_Exception = returnObj.OtherFee_Exception + (decimal)feeDetailItem.FinalFee.Amount; }
}
return returnObj;
}
}
}
@@ -0,0 +1,155 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.AmazonSpApiSDK.Models.ProductPricing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Amazon.ProductPricing
{
public class GetCompetitivePricing
{
private AmazonConnection amznConn = new SpApiConnection().Connection;
public string MarketPlaceId { get; set; }
/// <summary>
/// Gets Amazon Buy Box price for a given product. Will return no price if page does not have buy box
/// </summary>
public GetCompetitivePricing()
{
}
/// <summary>
/// Retrives current Buy Box price (+ additional info) for a given ASIN
/// </summary>
/// <param name="asin">Amazon ASIN product reference</param>
/// <returns></returns>
public Model.Amazon.ProductCompetitivePrice ByAsin(string asin)
{
var result = Execute(new List<string> { asin }, false);
if (result.Any()) { return result[0]; }
else { return null; }
}
/// <summary>
/// Retrives current Buy Box price (+ additional info) for a given ASIN
/// </summary>
/// <param name="asin">Amazon ASIN product reference</param>
/// <returns></returns>
public List<Model.Amazon.ProductCompetitivePrice> ByAsin(List<string> asinList)
{
return Execute(asinList, false);
}
/// <summary>
/// Ideally use ASIN
/// </summary>
/// <param name="skuList"></param>
/// <returns></returns>
private Model.Amazon.ProductCompetitivePrice BySku(string sku)
{
var result = Execute(new List<string> { sku }, true);
if (result.Any()) { return result[0]; }
else { return null; }
}
/// <summary>
/// Ideally use ASIN
/// </summary>
/// <param name="skuList"></param>
/// <returns></returns>
private List<Model.Amazon.ProductCompetitivePrice> BySku(List<string> skuList)
{
return Execute(skuList, true);
}
private List<Model.Amazon.ProductCompetitivePrice> Execute(List<string> itemList, bool isSkuList)
{
var apiList = new List<Price>();
// max of 20 items in one call
int i = 0;
int total = itemList.Count;
var itemRequestList = new List<string>();
foreach (string sku in itemList)
{
i++;
itemRequestList.Add(sku);
if (i == total || i % 20 == 0)
{
var parameter = new FikaAmazonAPI.Parameter.ProductPricing.ParameterGetCompetitivePricing();
if (isSkuList) { parameter.Skus = itemRequestList; }
else { parameter.Asins = itemRequestList; }
parameter.MarketplaceId = MarketPlaceId;
apiList.AddRange(amznConn.ProductPricing.GetCompetitivePricing(parameter));
itemRequestList = new List<string>();
}
}
return TransposeData(apiList);
}
private List<Model.Amazon.ProductCompetitivePrice> TransposeData(IList<Price> spapiList)
{
var returnList = new List<Model.Amazon.ProductCompetitivePrice>();
foreach (var item in spapiList)
{
string asin = item.ASIN;
decimal competitivePrice;
bool competitivePriceIsSet;
bool isBuyBox;
bool buyBoxBelongsToRequester;
int offersCountNew = 0;
int offersCountUsed = 0;
if (item.Product.CompetitivePricing.CompetitivePrices.Count == 0)
{
competitivePrice = 0;
competitivePriceIsSet = false;
isBuyBox = false;
buyBoxBelongsToRequester = false;
}
else if (item.Product.CompetitivePricing.CompetitivePrices.Count == 1)
{
if (item.Product.CompetitivePricing.CompetitivePrices[0].Condition != "New")
throw new Exception("Condition returned is not new");
competitivePrice = item.Product.CompetitivePricing.CompetitivePrices[0].Price.LandedPrice.Amount.Value;
competitivePriceIsSet = true;
isBuyBox = true;
buyBoxBelongsToRequester = item.Product.CompetitivePricing.CompetitivePrices[0].BelongsToRequester.Value;
}
else
{
throw new Exception("More than one competitive price returned");
}
// get quanities
foreach (var offer in item.Product.CompetitivePricing.NumberOfOfferListings)
{
if (offer.Condition == "New") { offersCountNew = offer.Count.Value; }
if (offer.Condition == "Used") { offersCountUsed = offer.Count.Value; }
}
// add to list
var returnItem = new Model.Amazon.ProductCompetitivePrice(
asin
, competitivePrice
, competitivePriceIsSet
, isBuyBox
, buyBoxBelongsToRequester
, offersCountNew
, offersCountUsed);
returnList.Add(returnItem);
}
return returnList;
}
}
}
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaCustomerReturn : ReportLogic
{
public FbaCustomerReturn() : base(ReportTypes.GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA)
{
}
public void GetReport(DateTime startTime, DateTime endTime)
{
int maxRange = 0; // there doesn't appear to be any limit on time span
DownloadTimePeriodReport(startTime, endTime, maxRange);
}
}
}
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaInventory : ReportLogic
{
public FbaInventory() : base (ReportTypes.GET_FBA_MYI_ALL_INVENTORY_DATA)
{
}
public void GetReport(int reportMaxAge = 30)
{
// Amazon will throttle (return 'FATAL' error) when requesting this report twice within 15 minutes
DownloadReport(reportMaxAge);
}
}
}
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaInventoryAdustment : ReportLogic
{
public FbaInventoryAdustment() : base(ReportTypes.GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA)
{
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
}
public void GetReport(DateTime startTime, DateTime endTime)
{
DownloadTimePeriodReport(startTime, endTime, 0);
}
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaInventoryAge : ReportLogic
{
public FbaInventoryAge() : base(ReportTypes.GET_FBA_INVENTORY_AGED_DATA)
{
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
}
public new void GetReport(int reportMaxAge = 30)
{
throw new Exception("GET_FBA_INVENTORY_AGED_DATA report has been retired since 22/06/2022 and replaced by GET_FBA_INVENTORY_PLANNING_DATA");
//DownloadSnapshotReport(reportMaxAge);
}
}
}
@@ -0,0 +1,90 @@
using CsvHelper;
using FikaAmazonAPI.AmazonSpApiSDK.Models.FulfillmentOutbound;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using static FikaAmazonAPI.Utils.Constants;
using System.Linq;
using CsvHelper.Configuration;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaInventoryLedgerDetailed : ReportLogic
{
List<Model.Import.AmazonFbaInventoryLedgerDetail> resultList = null;
/// <summary>
/// Get report will download the file to local storage. Use this to transpose the data to a model class.
/// </summary>
public List<Model.Import.AmazonFbaInventoryLedgerDetail> ResultList
{
get
{
if (resultList == null)
{
TransposeFileToClass();
}
return resultList;
}
}
public bool IsSetResultList
{
get { return IsSetReportFilePath; }
}
public FbaInventoryLedgerDetailed() : base(ReportTypes.GET_LEDGER_DETAIL_VIEW_DATA)
{
}
public new void Init()
{
base.Init();
resultList = null;
}
public void GetReport(DateTime utcDataStartTime, DateTime utcDataEndTime)
{
// 18 months max historical transactions for report
DownloadTimePeriodReport(utcDataStartTime, utcDataEndTime, 0, 547);
}
private void TransposeFileToClass()
{
var transposeResult = new List<Model.Import.AmazonFbaInventoryLedgerDetail>();
if (IsSetReportFilePath == false)
{
resultList = transposeResult;
}
else
{
using (var reader = new StreamReader(ReportFilePath))
{
// setup csvhelper
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = "\t",
};
using (var csvreader = new CsvReader(reader, config))
{
// check header count
csvreader.Read();
csvreader.ReadHeader();
int columns = csvreader.HeaderRecord.Count();
if (columns < 15)
throw new Exception("Malformed report 'GET_LEDGER_DETAIL_VIEW_DATA' does not have enough headers");
if (columns > 15)
log.LogError("New column in 'GET_LEDGER_DETAIL_VIEW_DATA'");
// transpose the data
transposeResult = csvreader.GetRecords<Model.Import.AmazonFbaInventoryLedgerDetail>().ToList();
resultList = transposeResult;
}
}
}
}
}
}
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaInventoryReceipt : ReportLogic
{
/*
* Not able to uniquley define each row in flat file and check for duplicate in DB
* therefore, do not download report date range that has already been imported, as records will be duplicated
*
* Due to a MWS bug, MWS can/will include some records that are before the specified date range. As mws report is updated once daily,
* it is safe to omitt lines < startDate when parsing/inserting lines into db (as these will have been previously imported)
*/
public FbaInventoryReceipt() : base(ReportTypes.GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA)
{
throw new Exception("report has been depreciated https://developer-docs.amazon.com/sp-api/docs/sp-api-deprecations");
}
public void GetReport(DateTime startTime, DateTime endTime)
{
DownloadTimePeriodReport(startTime, endTime, 0);
}
}
}
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaReimbursement : ReportLogic
{
public FbaReimbursement() : base(ReportTypes.GET_FBA_REIMBURSEMENTS_DATA)
{
}
public void GetReport(DateTime startTime, DateTime endTime)
{
DownloadTimePeriodReport(startTime, endTime, 0);
}
}
}
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaRemovalOrder : ReportLogic
{
public FbaRemovalOrder() : base(ReportTypes.GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA)
{
}
public void GetReport(DateTime startTime, DateTime endTime)
{
DownloadTimePeriodReport(startTime, endTime, 0);
}
}
}
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class FbaSaleShipment : ReportLogic
{
//public FbaSaleShipment() : base(ReportTypes.GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_SALES_DATA)
public FbaSaleShipment() : base(ReportTypes.GET_AMAZON_FULFILLED_SHIPMENTS_DATA_GENERAL)
{
}
public void GetReport(DateTime startTime, DateTime endTime)
{
DownloadTimePeriodReport(startTime, endTime, 30);
}
}
}
@@ -0,0 +1,423 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.AmazonSpApiSDK.Models.Reports;
using FikaAmazonAPI.Parameter.Report;
using FikaAmazonAPI.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class ReportLogic
{
public enum ProcessingStatus
{
NULL,
INQUEUE,
INPROGRESS,
CANCELLED,
DONE,
FATAL
}
private bool _isSetReportProcessingStatus = false;
private AmazonConnection amznConn = new SpApiConnection().Connection;
private FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report report = new FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report();
private ReportTypes reportType;
protected Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public ProcessingStatus ReportProcessingStatus { get; private set; }
public bool IsSetReportProcessingStatus
{
get
{
if (ReportProcessingStatus == ProcessingStatus.NULL)
return false;
else
return true;
}
}
public DateTime? ReportCreatedTime
{
get
{
if (report == null) { return null; }
else { return report.CreatedTime; }
}
}
/// <summary>
/// The report has completed, but there is no data (and hence no file) to download.
/// </summary>
public bool ReportDoneNoData { get; private set; }
/// <summary>
/// File path the the local location of the file
/// </summary>
public string ReportFilePath { get; private set; }
private FikaAmazonAPI.Utils.MarketplaceIds MarketPlaceIds { get; set; }
public bool IsSetReportFilePath
{
get { return !string.IsNullOrWhiteSpace(ReportFilePath); }
}
public ReportLogic(ReportTypes reportType)
{
this.reportType = reportType;
this.MarketPlaceIds = new MarketplaceIds();
this.MarketPlaceIds.Add(amznConn.GetCurrentMarketplace.ID);
Init();
}
protected void Init()
{
ReportDoneNoData = false;
ReportFilePath = null;
report = null;
ReportProcessingStatus = ProcessingStatus.NULL;
}
/// <summary>
/// Return a list of report that are currently available filtered parameters set in class
/// </summary>
/// <returns>report list</returns>
protected IList<FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report> ListAvailableReports()
{
var parameters = new ParameterReportList();
parameters.reportTypes = new List<ReportTypes>() { reportType };
parameters.marketplaceIds.Add(amznConn.GetCurrentMarketplace.ID);
// request from amazon
return amznConn.Reports.GetReports(parameters);
}
/// <summary>
/// For reports that require a start and end period to report over.
/// </summary>
/// <param name="utcDataStartTime"></param>
/// <param name="utcDataEndTime"></param>
/// <param name="maxDateRangeDays">The max time in days between the start and end date time</param>
/// <param name="maxDataAgeDays">The max time that Amazon retains the data for, in days</param>
/// <exception cref="Exception"></exception>
protected void DownloadTimePeriodReport(DateTime utcDataStartTime, DateTime utcDataEndTime, int maxDateRangeDays, int maxDataAgeDays = 0)
{
if (utcDataStartTime.Kind != DateTimeKind.Utc || utcDataEndTime.Kind != DateTimeKind.Utc)
throw new Exception("Report period time has to be set to UTC");
if (maxDateRangeDays > 0 && (utcDataEndTime - utcDataStartTime).TotalDays > maxDateRangeDays)
throw new Exception("Date range for report is greater than the maximum allowable");
if (maxDataAgeDays < 0)
{
throw new Exception("Max data age in days cannot be less than zero");
}
//else if(maxDataAgeDays > 0)
//{
// if (utcDataStartTime < DateTime.UtcNow.AddDays(maxDataAgeDays * -1))
// {
// throw new Exception("Max historical data for " + reportType.ToString() + " is " + maxDataAgeDays + " days");
// }
//}
var specification = new ParameterCreateReportSpecification();
specification.marketplaceIds = this.MarketPlaceIds;
specification.reportType = reportType;
specification.dataStartTime = utcDataStartTime;
specification.dataEndTime = utcDataEndTime;
DownloadReport(specification, false);
}
/// <summary>
/// Use this to download reports that do not have a time period element, they are as things stand now.
/// </summary>
/// <param name="snapshotMaxAge">In minutes, the minimum time between report requests. Amazon will return 'FATAL' if a report is re-requested in too short a time period </param>
protected void DownloadReport(int snapshotMaxAge)
{
var specification = new ParameterCreateReportSpecification();
specification.marketplaceIds = this.MarketPlaceIds;
specification.reportType = reportType;
DownloadReport(specification, true, snapshotMaxAge);
}
/// <summary>
/// The main body of the class, where the all the work is done
/// </summary>
/// <param name="specification">the specification built by the supporting methods</param>
/// <param name="isSnapshotReport">ie not a time period report, but an 'as things stand now' report</param>
/// <param name="snapshotMaxAge">time in minutes</param>
/// <exception cref="Exception"></exception>
private void DownloadReport(ParameterCreateReportSpecification specification, bool isSnapshotReport, int snapshotMaxAge = 0)
{
log.LogInformation("Starting report requesting from Amazon SP-API for " + specification.reportType.ToString());
// Amazon create report is throttled to 1 report every 15 minutes
Init();
// check for existing report with same specification
string reportId = ExistingReportCheck(specification);
// no matching report? then create one
if (reportId == null)
{ reportId = amznConn.Reports.CreateReport(specification); }
WaitWhileProcessing(reportId);
// some real time report will return 'fatal' if the report has already recently been requested, test for this
if (isSnapshotReport && report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
{
bool aSuitableReportExists = SnapshotReportThrottleHanderler(ref reportId, specification, snapshotMaxAge);
if (aSuitableReportExists == true)
{
log.LogWarning("Create amazon report returned 'FATAL' due to a report with the same parameters already existing, requesting the existing report");
WaitWhileProcessing(reportId);
}
}
DownloadReport(reportId);
}
protected void DownloadByReportId(string reportId)
{
Init();
DownloadReport(reportId);
}
private void DownloadReport(string reportId)
{
if (report == null)
{
WaitWhileProcessing(reportId);
}
// test for processing status
if (report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.DONE)
{
ReportProcessingStatus = ProcessingStatus.DONE;
log.LogInformation("Report proccessing status is 'DONE' (ReportId:" + report.ReportId + ").");
if (string.IsNullOrEmpty(report.ReportDocumentId))
throw new Exception("Report processing done, yet there's no report document. Write code to handle this");
}
else if (report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.CANCELLED)
{
ReportProcessingStatus = ProcessingStatus.CANCELLED;
// From SPAPI Documentation: The report was cancelled. There are two ways a report can be cancelled:
// an explicit cancellation request before the report starts processing, or an automatic cancellation
// if there is no data to return.
log.Initialise();
log.LogInformation("ReportID:" + reportId + " returned 'CANCELLED', if a cancel request hasn't been made then there is no data in the report.");
ReportDoneNoData = true;
return;
}
else if (report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
{
ReportProcessingStatus = ProcessingStatus.FATAL;
// AMazon does sometime return a file with information as to why fatal was returned contained within, test for this
if (string.IsNullOrEmpty(report.ReportDocumentId))
{
log.LogError("ReportID:" + reportId + " returned 'FATAL', no further information was recived.");
return;
}
}
// if we get here, onto downloading the file
if (string.IsNullOrEmpty(report.ReportDocumentId))
throw new Exception("ReportDocumentId field is null or empty.");
// as file url expires after 5 minutes, request it just before download
UI.Console.WriteLine("Requesting download url for Amazon report (ReportId:" + reportId + ").");
var amazonFileInfo = amznConn.Reports.GetReportDocument(report.ReportDocumentId);
// download report from url
log.LogInformation("Downloading Amazon report #" + reportId, "Report Document ID: " + amazonFileInfo.ReportDocumentId);
byte[] response = null;
using (var webClient = new System.Net.WebClient())
{
response = webClient.DownloadData(amazonFileInfo.Url);
}
// decrypt report
UI.Console.WriteLine("Processing download (ReportId:" + reportId + ").");
if (amazonFileInfo.EncryptionDetails != null)
{
UI.Console.WriteLine("Decrypting report ReportId:" + reportId + ").", false);
byte[] key = Encoding.ASCII.GetBytes(amazonFileInfo.EncryptionDetails.Key);
byte[] iv = Encoding.ASCII.GetBytes(amazonFileInfo.EncryptionDetails.InitializationVector);
response = Logic.Utilities.File.DecryptByte(key, iv, response);
}
// decompress
if (amazonFileInfo.CompressionAlgorithm != null)
{
UI.Console.WriteLine("Decompressing report ReportId:" + reportId + ").", false);
response = Logic.Utilities.File.Decompress(response);
}
string reportString = Encoding.ASCII.GetString(response);
// if fatal returned, give file contents in log
if (report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
{
log.LogError("Downloading reportId:" + report.ReportId + " returned 'FATAL'. See long detail for further details", reportString);
return;
}
// save to file
string dirPath = Config.GetTempFileDirectoryPath() + @"\SP-API-Reports\";
System.IO.Directory.CreateDirectory(dirPath);
string reportFilePath = dirPath + report.ReportType.ToString() + " reportId_" + reportId + ".txt";
System.IO.File.WriteAllText(reportFilePath, reportString);
log.LogInformation("Amazon report #" + reportId + " sucessfully saved to disk.");
this.ReportFilePath = reportFilePath;
}
/// <summary>
/// If a duplicate report has been recently requested, Amazon may return 'FATAL'. This method tests for, and attempts to retrive the duplicate report that is causing the error.
/// </summary>
/// <param name="report">Report to test for throttled response</param>
/// <param name="specification">The specification that created to throttle report.</param>
private bool SnapshotReportThrottleHanderler(ref string reportId, ParameterCreateReportSpecification specification, int snapshotMaxAgeMinutes)
{
if (report.ProcessingStatus != FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
throw new Exception("Incorrect use of class, processing status must be fatal");
if (snapshotMaxAgeMinutes <= 0)
{
// report not avaiable
throw new Exception( reportType.ToString() + " report not avaibale for requested timeframe");
}
// search for valid reports with required timeframe
var parameters = new ParameterReportList();
parameters.reportTypes = new List<ReportTypes> { specification.reportType };
parameters.createdSince = report.CreatedTime.Value.AddMinutes(-snapshotMaxAgeMinutes);
parameters.marketplaceIds = specification.marketplaceIds;
var reports = amznConn.Reports.GetReports(parameters);
if (reports == null || !reports.Any())
{
return false;
}
foreach (var item in reports)
{
if (item.ProcessingStatus != FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.DONE
|| item.ProcessingStatus != FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.INPROGRESS
|| item.ProcessingStatus != FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.INQUEUE)
{
log.LogInformation("Amazon declinded requested report:" + item.ReportType.ToString() + " as another with same parameters already existes, substituting reportId " + reportId + " for " + item.ReportId);
reportId = item.ReportId;
report = item;
return true;
}
}
return false;
}
private string ExistingReportCheck(ParameterCreateReportSpecification specification)
{
// amazon may return 'fatal' due to report already existing and/or report request matches an recent existing request
// search for valid reports with required timeframe
var parameters = new ParameterReportList();
parameters.reportTypes = new List<ReportTypes> { specification.reportType };
parameters.marketplaceIds = specification.marketplaceIds;
var reportList = amznConn.Reports.GetReports(parameters);
// list is ordered with the most recent first
foreach (var item in reportList)
{
if (item.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.DONE
|| item.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.INPROGRESS
|| item.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.INQUEUE)
{
if(item.DataStartTime == specification.dataStartTime
&& item.DataEndTime == specification.dataEndTime)
{
return item.ReportId;
}
}
}
return null;
}
private void WaitWhileProcessing(string reportId)
{
// set accordingly
int waitPeriodIncrement = (1000 * 10);
int waitPeriodIncrementMax = (1000 * 60);
int waitPeriod = 0;
int waitPeriodTotal = 0;
int waitPeriodTotalTimeout = (1000 * 1200); // 20 minutes
while (waitPeriodTotal < waitPeriodTotalTimeout)
{
report = amznConn.Reports.GetReport(reportId);
if (report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.INQUEUE)
{
ReportProcessingStatus = ProcessingStatus.INQUEUE;
}
else if (report.ProcessingStatus == FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report.ProcessingStatusEnum.INPROGRESS)
{
ReportProcessingStatus = ProcessingStatus.INPROGRESS;
}
else
{
return;
}
waitPeriod = waitPeriod + waitPeriodIncrement;
if (waitPeriod > waitPeriodIncrementMax)
waitPeriod = waitPeriodIncrementMax;
UI.Console.Wait("Report processing status " + ReportProcessingStatus + ". Check in {0} seconds...", waitPeriod);
waitPeriodTotal = waitPeriodTotal + waitPeriod;
}
throw new Exception("Amazon report processing for reportId:" + report.ReportId + " timeout after " + (waitPeriodTotal / 60000) + " minutes.");
}
private void LogReportError(FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report report, string errorTitle)
{
log.Initialise();
log.LogError(errorTitle,
"ReportType: " + report.ReportType + "\r\n"
+ "ReportId: " + report.ReportId + "\r\n"
+ "MarketplaceIds: " + report.MarketplaceIds + "\r\n"
+ "CreatedTime: " + report.CreatedTime + "\r\n"
+ "ReportScheduleId: " + report.ReportScheduleId + "\r\n"
+ "ReportDocumentId: " + report.ReportDocumentId + "\r\n"
+ "DataStartTime: " + report.DataStartTime + "\r\n"
+ "DataEndTime: " + report.DataEndTime + "\r\n"
+ "ProcessingStartTime: " + report.ProcessingStartTime + "\r\n"
+ "ProcessingEndTime: " + report.ProcessingEndTime + "\r\n"
+ "ProcessingStatus: " + report.ProcessingStatus + "\r\n"
);
}
}
}
@@ -0,0 +1,45 @@
using bnhtrade.Core.Data.Amazon.SellingPartnerAPI;
using FikaAmazonAPI;
using FikaAmazonAPI.Parameter.Report;
using FikaAmazonAPI.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.Utils.Constants;
namespace bnhtrade.Core.Data.Amazon.Report
{
public class SettlementReport : ReportLogic
{
public SettlementReport () : base(ReportTypes.GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_V2)
{
}
/// <summary>
/// Gets a list of reportId (not settlement report Id) for settlement reports available on the amazon api
/// </summary>
/// <returns>ReportId list</returns>
public List<string> ListAvaliableReports()
{
UI.Console.WriteLine("Requesting list of avaliable settlement reports form Amazon SP-API");
var reportList = ListAvailableReports();
var reportIdList = new List<string>();
foreach (var report in reportList)
{
reportIdList.Add(report.ReportId);
}
UI.Console.WriteLine(reportIdList.Count().ToString() + " Settlement reports avaible on Amazon SP-API");
return reportIdList;
}
public string GetReportFile(string reportId)
{
DownloadByReportId(reportId);
return ReportFilePath;
}
}
}
@@ -0,0 +1,23 @@
using FikaAmazonAPI.Utils;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI
{
public class Defaults
{
public MarketPlace MarketPlaceId()
{
return MarketPlace.GetMarketPlaceByID(MarketPlaceIdAsString());
}
public string MarketPlaceIdAsString()
{
var config = new Config().GetConfiguration();
return config.AppSettings.Settings["SpapiMarketplaceId"].Value;
}
}
}
@@ -0,0 +1,318 @@
//using System;
//using System.Collections.Generic;
//using System.IO;
//using System.Text;
//namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI.Services
//{
// public class ReportService : RequestService
// {
// private Dictionary<string, RestSharp.RestResponse<FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report>> reportList;
// private Dictionary<string, string> filePath;
// private bool fatalEncounter = false;
// protected Logic.Log.LogEvent log = new Logic.Log.LogEvent();
// private int reportRequestCount = 0;
// public ReportService() : base(new AmazonCredential())
// {
// Innit();
// }
// public ReportService(AmazonCredential amazonCredential) : base(amazonCredential)
// {
// Innit();
// }
// public void Innit()
// {
// reportList = new Dictionary<string, RestSharp.RestResponse<FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report>>();
// filePath = new Dictionary<string, string>();
// }
// public FikaAmazonAPI.AmazonSpApiSDK.Models.Reports.Report GetReport(string reportId, bool forceRequery = false)
// {
// // Rate limit: 2.0 requests per second, 15 burst
// int rateLimitMilliseconds = 500;
// if (reportList.ContainsKey(reportId))
// {
// if (forceRequery)
// {
// reportList.Remove(reportId);
// }
// else
// {
// return reportList[reportId].Data;
// }
// }
// // request report form amaozn
// if (reportRequestCount == 0)
// {
// UI.Console.WriteLine("Requesting report from amazon SPAPI (ReportId:" + reportId + ").");
// reportRequestCount = reportRequestCount + 1;
// }
// CreateAuthorizedRequest(ReportApiUrls.GetReport(reportId), RestSharp.Method.Get);
// var response = ExecuteRequestWithHttpInfo<SDK.Models.Reports.Report>(rateLimitMilliseconds);
// if (response == null)
// { return null; }
// reportList.Add(response.Data.ReportId, response);
// return response.Data;
// }
// public List<SDK.Models.Reports.Report> GetReports(ParameterReportList parameterReportList)
// {
// var parameters = parameterReportList.getParameters();
// CreateAuthorizedRequest(ReportApiUrls.GetReports, RestSharp.Method.Get, parameters);
// var response = ExecuteRequest<GetReportsResponseV00>();
// parameterReportList.nextToken = response.NextToken;
// var list = response.Reports;
// while (!string.IsNullOrEmpty(parameterReportList.nextToken))
// {
// var nextTokenResponse = GetReportsByNextToken(parameterReportList);
// list.AddRange(nextTokenResponse.Reports);
// parameterReportList.nextToken = nextTokenResponse.NextToken;
// }
// return list;
// }
// public bool CancelReport(string reportId)
// {
// CreateAuthorizedRequest(ReportApiUrls.CancelReport(reportId), RestSharp.Method.Delete);
// var response = ExecuteRequest<CancelReportResponse>();
// if (response != null && response.Errors != null)
// return false;
// return true;
// }
// public ReportScheduleList GetReportSchedules(ParameterReportSchedules parametersSchedules)
// {
// var parameters = parametersSchedules.getParameters();
// CreateAuthorizedRequest(ReportApiUrls.GetReportSchedules, RestSharp.Method.Get, parameters);
// var response = ExecuteRequest<GetReportSchedulesResponseV00>();
// if (response != null && response.ReportSchedules != null)
// return response.ReportSchedules;
// return null;
// }
// private GetReportsResponseV00 GetReportsByNextToken(ParameterReportList parameterReportList)
// {
// var parameterReportListNew = new ParameterReportList();
// parameterReportListNew.nextToken = parameterReportList.nextToken;
// var parameters = parameterReportListNew.getParameters();
// CreateAuthorizedRequest(ReportApiUrls.GetReports, RestSharp.Method.Get, parameters);
// var response = ExecuteRequest<GetReportsResponseV00>();
// return response;
// }
// public string CreateReport(ParameterCreateReportSpecification createReportSpecification)
// {
// CreateAuthorizedRequest(ReportApiUrls.CreateReport, RestSharp.Method.Post, null, createReportSpecification);
// var response = ExecuteRequest<SDK.Models.Reports.CreateReportResult>();
// if (response == null)
// return null;
// string reportId = response.ReportId;
// return response.ReportId;
// }
// public string CreateReportSchedule(ParameterCreateReportScheduleSpecification createReportScheduleSpecification)
// {
// CreateAuthorizedRequest(ReportApiUrls.CreateReportSchedule, RestSharp.Method.Post, null, createReportScheduleSpecification);
// var response = ExecuteRequest<CreateReportScheduleResult>();
// if (response == null)
// return null;
// return response.ReportScheduleId;
// }
// public ReportSchedule GetReportSchedule(string reportScheduleId)
// {
// CreateAuthorizedRequest(ReportApiUrls.GetReportSchedule(reportScheduleId), RestSharp.Method.Get);
// var response = ExecuteRequest<ReportSchedule>();
// if (response != null)
// return response;
// return null;
// }
// public ReportDocument GetReportDocument(string reportDocumentId, IParameterBasedPII ParameterBasedPII = null)
// {
// CreateAuthorizedRequest(ReportApiUrls.GetReportDocument(reportDocumentId), RestSharp.Method.Get, parameter: ParameterBasedPII);
// var response = ExecuteRequest<ReportDocument>();
// if (response != null)
// return response;
// return null;
// }
// public bool WaitForReportProcessing(SDK.Models.Reports.Report report)
// {
// // wait for report processing loop
// int checkCount = 0;
// int checkRequency = 10000;
// while (true)
// {
// checkCount++;
// if (checkCount > 60)
// {
// throw new Exception("GetReport timedout requesting reportId:" + report.ReportId + ".");
// }
// if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.DONE)
// {
// UI.Console.WriteLine("Report proccessing status is 'DONE' (ReportId:" + report.ReportId + ").");
// return true;
// }
// else if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.INPROGRESS)
// {
// // wait for 10 seconds between chacks
// UI.Console.Wait("Report processing 'In Progress'. Updating in {0} seconds...", checkRequency);
// report = GetReport(report.ReportId, true);
// }
// else if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.INQUEUE)
// {
// // wait for 10 seconds between chacks
// UI.Console.Wait("Report processing 'In Queue'. Updating in {0} seconds...", checkRequency);
// report = GetReport(report.ReportId, true);
// }
// else if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.CANCELLED)
// {
// // when report has been cancelled by client or amazon (no data)
// return false;
// }
// else if (report.ProcessingStatus == SDK.Models.Reports.Report.ProcessingStatusEnum.FATAL)
// {
// // some report requests will return a 'FATAL' if they have already been requsted recently (15 minutes).
// return false;
// }
// else
// {
// throw new Exception("New ReportProcessingStatusEnum '" + report.ProcessingStatus + "' "
// + " found for reportid:" + report.ReportId);
// }
// }
// }
// /// <summary>
// /// Retrives file containing Amazon SP-API report
// /// </summary>
// /// <param name="reportId">Amazon SP-API unique report id</param>
// /// <returns>File path for report</returns>
// public string GetReportFile(string reportId)
// {
// if (string.IsNullOrWhiteSpace(reportId))
// {
// throw new Exception("invalid Report ID");
// }
// // check for cached filepath
// if (!filePath.ContainsKey(reportId))
// {
// var report = GetReport(reportId); // this can return null, need to deal with this
// if (WaitForReportProcessing(report))
// {
// // download report from url
// string reportFilePath = GetFile(reportId);
// filePath.Add(reportId, reportFilePath);
// return reportFilePath;
// }
// else
// {
// return null;
// }
// }
// return filePath[reportId];
// }
// private string GetFile(string reportId)
// {
// // fatal error and reportDoument Id check
// if (fatalEncounter)
// {
// if (string.IsNullOrWhiteSpace(reportList[reportId].Data.ReportDocumentId))
// {
// log.LogError("Fatal error from Amazon SPAPI when requesting reportId:" + reportId
// , "The reason for the fatal error is unknown, no document was available for further information.");
// return "FATAL";
// }
// else
// {
// log.LogError("Fatal error from Amazon SPAPI when requesting reportId:" + reportId
// , "The report was aborted due to a fatal error and a reportDocumentId is present. Check reportDocumentId as it may explain why the report processing ended.");
// }
// fatalEncounter = false;
// }
// // as file url expires after 5 minutes, request just before download
// UI.Console.WriteLine("Requesting download url for Amazon report (ReportId:" + reportId + ").");
// var amazonFileInfo = GetReportDocument(reportList[reportId].Data.ReportDocumentId);
// // download report from url
// log.LogInformation("Downloading Amazon report #" + reportId, "Report Document ID: " + amazonFileInfo.ReportDocumentId);
// var response = new byte[0];
// using (var webClient = new System.Net.WebClient())
// {
// response = webClient.DownloadData(amazonFileInfo.Url);
// }
// string report = null;
// // decrypt report
// UI.Console.WriteLine("Processing download (ReportId:" + reportId + ").");
// if (amazonFileInfo.EncryptionDetails != null)
// {
// byte[] key = Encoding.ASCII.GetBytes(amazonFileInfo.EncryptionDetails.Key);
// byte[] iv = Encoding.ASCII.GetBytes(amazonFileInfo.EncryptionDetails.InitializationVector);
// report = Logic.Utilities.File.DecryptString(key, iv, response);
// }
// else
// {
// report = Encoding.ASCII.GetString(response);
// }
// // decompress
// if (amazonFileInfo.CompressionAlgorithm != null)
// {
// report = Logic.Utilities.File.Decompress(report);
// }
// // save to file
// string reportFilePath = MiscFunction.GetTempFilePath(reportId + ".txt");
// System.IO.File.WriteAllText(reportFilePath, report);
// log.LogInformation("Amazon report #" + reportId + " sucessfully saved to disk.");
// return reportFilePath;
// }
// public bool CancelReportSchedule(string reportScheduleId)
// {
// CreateAuthorizedRequest(ReportApiUrls.CancelReportSchedule(reportScheduleId), RestSharp.Method.Delete);
// var response = ExecuteRequest<CancelReportScheduleResponse>();
// if (response != null && response.Errors != null)
// return false;
// return true;
// }
// protected void SleepForRateLimit(IList<RestSharp.Parameter> headers)
// {
// // get report has limit rate 0.0222 per second (1 every 45 seconds) and a burst of 10
// int defaultTime = 46000;
// SleepForRateLimit(headers, defaultTime);
// }
// }
//}
@@ -0,0 +1,53 @@
using FikaAmazonAPI;
using FikaAmazonAPI.Utils;
using FikaAmazonAPI.AmazonSpApiSDK.Models.Token;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static FikaAmazonAPI.AmazonSpApiSDK.Services.EnvironemntManager;
namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI
{
class SpApiConnection
{
public AmazonConnection Connection { get; private set; }
//public MarketPlace MarketPlace { get; private set; }
//public string MarketPlaceId { get; private set; }
public SpApiConnection()
{
InnitConnection();
}
private void InnitConnection()
{
// attempt to create credential object from app.local.config
var credential = new FikaAmazonAPI.AmazonCredential();
var config = new Config().GetConfiguration();
try
{
string dataSource = config.AppSettings.Settings["DbDataSource"].Value;
credential = new FikaAmazonAPI.AmazonCredential();
//credential.AccessKey = config.AppSettings.Settings["SpapiAccessKey"].Value;
//credential.SecretKey = config.AppSettings.Settings["SpapiSecretKey"].Value;
//credential.RoleArn = config.AppSettings.Settings["SpapiRoleArn"].Value;
credential.ClientId = config.AppSettings.Settings["SpapiClientId"].Value;
credential.ClientSecret = config.AppSettings.Settings["SpapiClientSecret"].Value;
credential.RefreshToken = config.AppSettings.Settings["SpapiRefreshToken"].Value;
credential.MarketPlaceID = config.AppSettings.Settings["SpapiMarketplaceId"].Value;
//credential.IsDebugMode = true;
credential.MaxThrottledRetryCount = 3;
}
catch (Exception ex)
{
throw new Exception("Unable to retirve Amazon SP API credentials: " + ex.Message);
}
this.Connection = new AmazonConnection(credential);
}
}
}
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Xml;
namespace bnhtrade.Core.Data.Amazon.SellingPartnerAPI.Utils
{
public class CurrentDateTime
{
public DateTime GetUtc()
{
var xmlDoc = new XmlDocument();
xmlDoc.Load("https://mws.amazonservices.com/");
DateTime returnTime = default(DateTime);
XmlNodeList elemList = xmlDoc.GetElementsByTagName("Timestamp");
for (int i = 0; i < elemList.Count; i++)
{
string attrVal = elemList[i].Attributes["timestamp"].Value;
if (!string.IsNullOrWhiteSpace(attrVal))
{
returnTime = DateTime.SpecifyKind(DateTime.Parse(attrVal), DateTimeKind.Utc);
break;
}
}
if (returnTime == default(DateTime))
{
throw new Exception("Error requesting time from Amazon");
}
returnTime = returnTime.AddTicks(-(returnTime.Ticks % TimeSpan.TicksPerSecond));
return returnTime;
}
public DateTime GetLocal()
{
return GetUtc().ToLocalTime();
}
}
}
@@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace bnhtrade.Core.Data.Database.Account
{
internal class CreateJournal : Connection
{
/// <summary>
/// Old code needs sorting
/// </summary>
public int AccountJournalInsert(int journalTypeId, DateTime entryDate, string currencyCode,
decimal amount, int debitAccountId = 0, int creditAccountId = 0, bool lockEntry = false)
{
int defaultDebit = 0;
int defaultCredit = 0;
// ensure date is UTC
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
// debit and credit locks are checked in journal post method
using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
// insert the journal entry
int journalId;
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblAccountJournal
(AccountJournalTypeID, EntryDate, IsLocked)
OUTPUT INSERTED.AccountJournalID
VALUES
(@journalTypeId, @entryDate, @lockEntry)
", conn))
{
// add parameters
cmd.Parameters.AddWithValue("@journalTypeId", journalTypeId);
cmd.Parameters.AddWithValue("@entryDate", entryDate.ToUniversalTime());
cmd.Parameters.AddWithValue("@lockEntry", lockEntry);
//execute
journalId = (int)cmd.ExecuteScalar();
}
// insert journal entries
//bool postResult = AccountJournalPostInsert(sqlConnectionString, journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
bool postResult = AccountJournalPostInsert(journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
scope.Complete();
return journalId;
}
}
/// <summary>
/// Old code needs sorting
/// </summary>
internal bool AccountJournalPostInsert(int journalId, DateTime entryDate,
string currencyCode, decimal amount, int debitAccountId = 0, int creditAccountId = 0)
{
int defaultDebit;
int defaultCredit;
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
// ensure their are no other entries
using (SqlCommand cmd = new SqlCommand(@"
SELECT
Count(tblAccountJournalPost.AccountJournalPostID) AS CountOfAccountJournalPostID
FROM
tblAccountJournalPost
WHERE
(((tblAccountJournalPost.AccountJournalID)=@AccountJournalID));
", conn))
{
cmd.Parameters.AddWithValue("@AccountJournalID", journalId);
int count = (int)cmd.ExecuteScalar();
if (count > 0)
{
throw new Exception("Unable the insert journal posts, post already present AccountJournalID=" + journalId);
}
}
//checks
using (SqlCommand cmd = new SqlCommand(@"
SELECT
tblAccountJournalType.ChartOfAccountID_Debit, tblAccountJournalType.ChartOfAccountID_Credit
FROM
tblAccountJournal
INNER JOIN tblAccountJournalType
ON tblAccountJournal.AccountJournalTypeID = tblAccountJournalType.AccountJournalTypeID
WHERE
(((tblAccountJournal.AccountJournalID)=@journalId));
", conn))
{
cmd.Parameters.AddWithValue("@journalId", journalId);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
// debit check
if (reader.IsDBNull(0))
{
if (debitAccountId == 0)
{
throw new Exception("Debit Account ID required, default not set for journal type");
}
}
else
{
defaultDebit = reader.GetInt32(0);
if (debitAccountId == 0)
{
debitAccountId = defaultDebit;
}
else if (debitAccountId != defaultDebit)
{
throw new Exception("Debit Account ID supplied does not match default set for journal type");
}
}
// credit check
if (reader.IsDBNull(1))
{
if (creditAccountId == 0)
{
throw new Exception("Credit Account ID required, default not set for journal type");
}
}
else
{
defaultCredit = reader.GetInt32(1);
if (creditAccountId == 0)
{
creditAccountId = defaultCredit;
}
else if (creditAccountId != defaultCredit)
{
throw new Exception("Credit Account ID supplied does not match default set for journal type");
}
}
}
else
{
throw new Exception("AccountJournalID '" + journalId + "' does not exist.");
}
}
}
// currency conversion
if (currencyCode != "GBP")
{
amount = new Logic.Account.CurrencyService().CurrencyConvertToGbp(currencyCode, amount, entryDate);
}
// ensure decimal is rounded
amount = Math.Round(amount, 2);
// insert debit post
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblAccountJournalPost
(AccountJournalID, AccountChartOfID, AmountGbp)
VALUES
(@AccountJournalId, @AccountChartOfId, @AmountGbp)
", conn))
{
// add parameters
cmd.Parameters.AddWithValue("@AccountJournalId", journalId);
cmd.Parameters.AddWithValue("@AccountChartOfId", debitAccountId);
cmd.Parameters.AddWithValue("@AmountGbp", amount);
cmd.ExecuteNonQuery();
}
// insert credit post
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblAccountJournalPost
(AccountJournalID, AccountChartOfID, AmountGbp)
VALUES
(@AccountJournalId, @AccountChartOfId, @AmountGbp)
", conn))
{
// add parameters
cmd.Parameters.AddWithValue("@AccountJournalId", journalId);
cmd.Parameters.AddWithValue("@AccountChartOfId", creditAccountId);
cmd.Parameters.AddWithValue("@AmountGbp", (amount * -1));
cmd.ExecuteNonQuery();
}
scope.Complete();
return true;
}
}
}
}
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Account
{
internal class ReadContact : Connection
{
private bnhtrade.Core.Data.Database.SqlWhereBuilder sqlBuilder;
public List<int> ContactIdList { get; set; }
public ReadContact()
{
Init();
}
public void Init()
{
sqlBuilder = new SqlWhereBuilder();
ContactIdList = new List<int>();
}
public Dictionary<int, Model.Account.Contact> Read()
{
var returnList = new Dictionary<int, Model.Account.Contact>();
sqlBuilder.Init();
//build sql query
string sql = @"
SELECT [ContactID]
,[ContactName]
,[PaypalName]
,[PaypalEmail]
,[EbayUsername]
,[EbayEmail]
,[RecordCreated]
,[RecordModified]
FROM [e2A].[dbo].[tblContact]
WHERE 1=1 ";
// build the where statments
if (ContactIdList.Any())
{
sqlBuilder.In("[ContactID]", ContactIdList, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int contactId = reader.GetInt32(0);
string contactName = null;
if (!reader.IsDBNull(1)) { contactName = reader.GetString(1); }
string paypalName = null;
if (!reader.IsDBNull(2)) { paypalName = reader.GetString(2); }
string paypalEmail = null;
if (!reader.IsDBNull(3)) { paypalEmail = reader.GetString(3); }
string ebayUsername = null;
if (!reader.IsDBNull(4)) { ebayUsername = reader.GetString(4); }
string ebayEmail = null;
if (!reader.IsDBNull(5)) { ebayEmail = reader.GetString(5); }
DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(6), DateTimeKind.Utc);
DateTime? recordModified = null;
if (!reader.IsDBNull(7)) { recordModified = DateTime.SpecifyKind(reader.GetDateTime(7), DateTimeKind.Utc); }
var contact = new Model.Account.Contact();
contact.ContactId = contactId;
contact.ContantName = contactName;
contact.ContactPaypalName = paypalName;
contact.ContactPaypalEmail = paypalEmail;
contact.ContactEbayName = ebayUsername;
contact.ContactEbayEmail = ebayEmail;
contact.Created = recordCreated;
contact.Modified = recordModified;
returnList.Add(contactId, contact);
}
}
}
}
}
return returnList;
}
}
}
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace bnhtrade.Core.Data.Database.Account
{
internal class UpdateJournal : Connection
{
public bool AccountJournalPostUpdate(int journalId, string currencyCode, decimal amount, int debitAccountId = 0, int creditAccountId = 0)
{
using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
// retrive journal entry date
DateTime entryDate;
using (SqlCommand cmd = new SqlCommand(@"
SELECT
tblAccountJournal.EntryDate
FROM
tblAccountJournal
WHERE
(((tblAccountJournal.AccountJournalID)=@accountJournalId));
", conn))
{
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
entryDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc);
}
// delete the original posts
using (SqlCommand cmd = new SqlCommand(@"
DELETE FROM
tblAccountJournalPost
WHERE
(((tblAccountJournalPost.AccountJournalID)=@accountJournalId));
", conn))
{
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
cmd.ExecuteNonQuery();
}
//insert new posts
//bool postResult = AccountJournalPostInsert(sqlConnectionString, journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
bool postResult = new Data.Database.Account.CreateJournal().AccountJournalPostInsert(journalId, entryDate, currencyCode, amount, debitAccountId, creditAccountId);
// update modified date on journal
using (SqlCommand cmd = new SqlCommand(@"
UPDATE
tblAccountJournal
SET
tblAccountJournal.LastModified=@utcNow
WHERE
(((tblAccountJournal.AccountJournalID)=@accountJournalId));
", conn))
{
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
cmd.Parameters.AddWithValue("@utcNow", DateTime.UtcNow);
cmd.ExecuteNonQuery();
}
scope.Complete();
}
return true;
}
}
}
@@ -0,0 +1,62 @@
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.Amazon
{
public class FeeEstimate : Connection
{
/// <summary>
/// Update the tblAmazonFeeEstimate table (a new record will be created if it does not already exist to update)
/// </summary>
/// <param name="feeEstimate">Record to be updated/inserted into database</param>
public void UpdateProductFeeEstimate(Model.Amazon.ProductFeeEstimate feeEstimate)
{
using (SqlConnection sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (SqlCommand sqlCommand = new SqlCommand(@"
UPDATE tblAmazonFeeEstimate SET
ProductIdentifier=@productIdentifier, IsAmazonFulfilled=@isAmazonFulfilled, TimeOfFeeEstimation=@timeOfFeeEstimation,
TotalFeeEstimate=@totalFeeEstimate, PriceToEstimateFeeListingPrice=@priceToEstimateFeeListingPrice,
PriceToEstimateFeeShipping=@priceToEstimateFeeShipping, PriceToEstimateFeePoints=@priceToEstimateFeePoints,
ReferralFee=@referralFee, VariableClosingFee=@variableClosingFee, PerItemFee=@perItemFee, FBAFee=@fbaFee,
OtherFee_Exception=@otherFee_Exception, currencyCode=CurrencyCode
WHERE AmazonASIN=@asin
IF @@ROWCOUNT = 0
INSERT INTO tblAmazonFeeEstimate ( AmazonASIN,
ProductIdentifier, IsAmazonFulfilled, TimeOfFeeEstimation, TotalFeeEstimate, PriceToEstimateFeeListingPrice,
PriceToEstimateFeeShipping, PriceToEstimateFeePoints, ReferralFee, VariableClosingFee, PerItemFee, FBAFee,
OtherFee_Exception, CurrencyCode
) VALUES ( @asin,
@productIdentifier, @isAmazonFulfilled, @timeOfFeeEstimation, @totalFeeEstimate, @priceToEstimateFeeListingPrice,
@priceToEstimateFeeShipping, @priceToEstimateFeePoints, @referralFee, @variableClosingFee, @perItemFee, @fbaFee,
@otherFee_Exception, @currencyCode
)
", sqlConn))
{
sqlCommand.Parameters.AddWithValue("@asin", feeEstimate.Asin);
sqlCommand.Parameters.AddWithValue("@productIdentifier", feeEstimate.ProductId);
sqlCommand.Parameters.AddWithValue("@isAmazonFulfilled", feeEstimate.IsAmazonFulfilled);
sqlCommand.Parameters.AddWithValue("@timeOfFeeEstimation", feeEstimate.TimeOfFeeEstimation);
sqlCommand.Parameters.AddWithValue("@totalFeeEstimate", feeEstimate.TotalFeeEstimate);
sqlCommand.Parameters.AddWithValue("@priceToEstimateFeeListingPrice", feeEstimate.PriceToEstimateFeeListingPrice);
sqlCommand.Parameters.AddWithValue("@priceToEstimateFeeShipping", feeEstimate.PriceToEstimateFeeShipping);
sqlCommand.Parameters.AddWithValue("@priceToEstimateFeePoints", feeEstimate.PriceToEstimateFeePoints);
sqlCommand.Parameters.AddWithValue("@referralFee", feeEstimate.ReferralFee);
sqlCommand.Parameters.AddWithValue("@variableClosingFee", feeEstimate.VariableClosingFee);
sqlCommand.Parameters.AddWithValue("@perItemFee", feeEstimate.PerItemFee);
sqlCommand.Parameters.AddWithValue("@fbaFee", feeEstimate.FulfillmentFees);
sqlCommand.Parameters.AddWithValue("@otherFee_Exception", feeEstimate.OtherFee_Exception);
sqlCommand.Parameters.AddWithValue("@currencyCode", feeEstimate.CurrencyCode);
sqlCommand.ExecuteNonQuery();
}
}
}
}
}
@@ -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()
{
}
/// <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;
}
}
}
}
@@ -0,0 +1,121 @@
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.AmazonShipment
{
public class ReadShipmentPrimaryKey : Connection
{
private bool enableCache = false;
private Dictionary<string, int> shipmentPKByAmazonShipmentIdDic;
private Dictionary<int, string> amazonShipmentIdByShipmentPKDic;
public ReadShipmentPrimaryKey()
{
}
public bool CacheEnabled
{
get { return enableCache; }
set
{
if (value && enableCache == false)
{
shipmentPKByAmazonShipmentIdDic = new Dictionary<string, int>();
amazonShipmentIdByShipmentPKDic = new Dictionary<int, string>();
}
else
{
shipmentPKByAmazonShipmentIdDic = null;
amazonShipmentIdByShipmentPKDic = null;
}
}
}
private void ClearCache()
{
if (CacheEnabled)
{
shipmentPKByAmazonShipmentIdDic.Clear();
amazonShipmentIdByShipmentPKDic.Clear();
}
}
private void DeleteCachedShipmentPK(int shipmentPrimaryKey)
{
if (CacheEnabled)
{
if (amazonShipmentIdByShipmentPKDic.ContainsKey(shipmentPrimaryKey))
{
string amazonShipmentId = amazonShipmentIdByShipmentPKDic[shipmentPrimaryKey];
shipmentPKByAmazonShipmentIdDic.Remove(amazonShipmentId);
amazonShipmentIdByShipmentPKDic.Remove(shipmentPrimaryKey);
}
}
}
/// <summary>
/// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
/// </summary>
/// <param name="amazonShipmentId">Amazon's inbound FBA shipment Id.</param>
/// <param name="forceDBQuery">Forces a database query when cache is enabled.</param>
/// <returns>Primary key or -1 if match isn't found.</returns>
public int ByAmazonShipmentId(string amazonShipmentId, bool forceDBQuery = false)
{
if (amazonShipmentId.Length < 5)
{
throw new Exception("Incorrect Amazon shipment if supplied '" + amazonShipmentId + "'");
}
// first, query class dictionary before sql call
if (CacheEnabled
&& forceDBQuery == false
&& shipmentPKByAmazonShipmentIdDic.ContainsKey(amazonShipmentId))
{
return shipmentPKByAmazonShipmentIdDic[amazonShipmentId];
}
int shipmentPK = -1;
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
SELECT AmazonShipmentID
FROM tblAmazonShipment
WHERE (((tblAmazonShipment.ShipmentId)=@amazonShipmentId));
", conn))
{
cmd.Parameters.AddWithValue("@amazonShipmentId", amazonShipmentId);
object obj = cmd.ExecuteScalar();
if (obj == null || obj == DBNull.Value)
{
return shipmentPK;
}
else
{
shipmentPK = (int)obj;
}
}
}
UpdateCache(shipmentPK, amazonShipmentId);
return shipmentPK;
}
private void UpdateCache(int shipmentPK, string amazonShipmentId)
{
if (CacheEnabled)
{
DeleteCachedShipmentPK(shipmentPK);
shipmentPKByAmazonShipmentIdDic.Add(amazonShipmentId, shipmentPK);
amazonShipmentIdByShipmentPKDic.Add(shipmentPK, amazonShipmentId);
}
}
}
}
@@ -0,0 +1,252 @@
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.AmazonShipment
{
public class SetShipmentInfo : Connection
{
private ReadShipmentPrimaryKey getPK;
private Data.Database.Sku.GetSkuId skuIdLoopkup;
public SetShipmentInfo()
{
}
private ReadShipmentPrimaryKey GetPK
{
get
{
if (getPK == null)
{
getPK = new ReadShipmentPrimaryKey();
}
return getPK;
}
set
{
getPK = value;
}
}
private Data.Database.Sku.GetSkuId SkuIdLoopkup
{
get
{
if (skuIdLoopkup == null)
{
skuIdLoopkup = new Sku.GetSkuId();
}
return skuIdLoopkup;
}
}
public void Excecute(Model.AmazonFba.ShipmentInfo info)
{
using (var scope = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
// input checks
if (!info.IsSetAll())
{
throw new Exception("Insurficent ShipmentInfo parameters.");
}
// get tablePK
int shipmentPK = GetPK.ByAmazonShipmentId(info.FbaShipmentId);
// add or update shipment header info
if (shipmentPK == -1)
{
shipmentPK = InsertShipmentHeaderInfo(info);
}
else
{
UpdateShipmentHeaderInfo(info);
DeleteShipmentItems(shipmentPK);
}
// insert new shipment item info
foreach (var item in info.ShipmentItemInfoList)
{
int skuId = SkuIdLoopkup.BySKUNumber(item.SKUNumber);
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblAmazonShipmentItem (
AmazonShipmentID
,SkuID
,QuantityAllocated
,QuantityReceived
)
VALUES (
@amazonShipmentID
,@skuID
,@quantityAllocated
,@quantityReceived
)
", conn))
{
cmd.Parameters.AddWithValue("@amazonShipmentID", shipmentPK);
cmd.Parameters.AddWithValue("@skuID", skuId);
cmd.Parameters.AddWithValue("@quantityAllocated", item.QuantityAllocated);
cmd.Parameters.AddWithValue("@quantityReceived", item.QuantityReceived);
int effected = (int)cmd.ExecuteNonQuery();
if (effected == 0)
{
throw new Exception("Error, no tblAmazonShipment was not updated.");
}
}
}
}
scope.Complete();
}
}
public void ExcecuteByList(List<Model.AmazonFba.ShipmentInfo> infoList)
{
using (var scope = new TransactionScope())
{
foreach (var item in infoList)
{
Excecute(item);
}
scope.Complete();
}
}
private void DeleteShipmentItems(int shipmentId)
{
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
DELETE FROM
tblAmazonShipmentItem
WHERE
AmazonShipmentId = @shipmentId
", conn))
{
cmd.Parameters.AddWithValue("@shipmentId", shipmentId);
cmd.ExecuteNonQuery();
}
}
}
private int InsertShipmentHeaderInfo(Model.AmazonFba.ShipmentInfo info)
{
if (!info.IsSetAll())
{
throw new Exception("Unsuficent properties set in Shipment Header Info.");
}
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
if (GetPK.ByAmazonShipmentId(info.FbaShipmentId) != -1)
{
throw new Exception("Shipment insert failed, shipment with same Amazon Id already exists.");
}
// get next shipment Number in sequence and create shipment name
int sequenceNumber;
using (SqlCommand cmd = new SqlCommand(@"
SELECT NEXT VALUE FOR dbo.ShipmentCountSequence AS SequenceNumber
", conn))
{
sequenceNumber = (int)cmd.ExecuteScalar();
}
// info.ShipmentName = "FBA_Shipment_" + sequenceNumber.ToString().PadLeft(4, '0') + "_" + info.DestinationFulfillmentCenterId;
// make the insert
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblAmazonShipment (
AmazonShipmentCount
,ShipmentName
,ShipmentId
,CenterId
,ShipmentStatus
,LastUpdated
,IsClosed
)
OUTPUT INSERTED.AmazonShipmentID
VALUES (
@amazonShipmentCount
,@shipmentName
,@shipmentId
,@centerId
,@shipmentStatus
,@lastUpdated
,@isClosed
)
", conn))
{
cmd.Parameters.AddWithValue("@amazonShipmentCount", sequenceNumber);
cmd.Parameters.AddWithValue("@shipmentName", info.ShipmentName);
cmd.Parameters.AddWithValue("@shipmentId", info.FbaShipmentId);
cmd.Parameters.AddWithValue("@centerId", info.DestinationFulfillmentCenterId);
cmd.Parameters.AddWithValue("@shipmentStatus", info.ShipmentStatus);
cmd.Parameters.AddWithValue("@lastUpdated", info.LastUpdated.ToUniversalTime());
cmd.Parameters.AddWithValue("@isClosed", info.ShipmentIsClosed);
int tablePk = (int)cmd.ExecuteScalar();
// update cache and return
return tablePk;
}
}
}
private void UpdateShipmentHeaderInfo(Model.AmazonFba.ShipmentInfo info)
{
int tablePK = GetPK.ByAmazonShipmentId(info.FbaShipmentId);
if (tablePK == -1)
{
throw new Exception("Shipment insert failed, shipment with same Amazon Id already exists.");
}
// make the update
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
UPDATE tblAmazonShipment
SET
ShipmentName = @shipmentName
,ShipmentStatus = @shipmentStatus
,LastUpdated = @lastUpdated
,IsClosed = @isClosed
WHERE
AmazonShipmentID = @tablePK
", conn))
{
cmd.Parameters.AddWithValue("@shipmentName", info.ShipmentName);
cmd.Parameters.AddWithValue("@shipmentStatus", info.ShipmentStatus);
cmd.Parameters.AddWithValue("@lastUpdated", info.LastUpdated.ToUniversalTime());
cmd.Parameters.AddWithValue("@isClosed", info.ShipmentIsClosed);
cmd.Parameters.AddWithValue("@tablePK", tablePK);
int count = cmd.ExecuteNonQuery();
if (count == 0)
{
throw new Exception("No records updated");
}
}
}
}
}
}
@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Configuration;
namespace bnhtrade.Core.Data.Database
{
public class Connection
{
//protected readonly string SqlConnectionString;
private Model.Credentials.bnhtradeDB _dbCredentials;
protected string SqlConnectionString
{
get { return _dbCredentials.ConnectionString; }
}
public Connection()
{
var config = new Config().GetConfiguration();
// attempt to retrive credentials from app.local.config
try
{
string dataSource = config.AppSettings.Settings["DbDataSource"].Value;
string userId = config.AppSettings.Settings["DbUserId"].Value;
string pass = config.AppSettings.Settings["DbUserPassword"].Value;
// check
if (string.IsNullOrEmpty(dataSource))
{
throw new ArgumentException("Could not retrive 'DbDataSource' from config file");
}
else if (string.IsNullOrEmpty(userId))
{
throw new ArgumentException("Could not retrive 'DbUserId' from config file");
}
else if (string.IsNullOrEmpty(pass))
{
throw new ArgumentException("Could not retrive 'DbUserPassword' from config file");
}
var dbCredentials = new bnhtrade.Core.Model.Credentials.bnhtradeDB(dataSource, userId, pass);
this._dbCredentials = dbCredentials;
}
catch (Exception ex)
{
throw new Exception("Unable to retirve DB credentials: " + ex.Message);
}
}
private void ConnectionOld()
{
// attempt to retrive credentials from app.local.config
try
{
string dataSource = ConfigurationManager.AppSettings["DbDataSource"];
string userId = ConfigurationManager.AppSettings["DbUserId"];
string pass = ConfigurationManager.AppSettings["DbUserPassword"];
// check
if (string.IsNullOrEmpty(dataSource))
{
throw new ArgumentException("Could not retrive 'DbDataSource' from config file");
}
else if (string.IsNullOrEmpty(userId))
{
throw new ArgumentException("Could not retrive 'DbUserId' from config file");
}
else if (string.IsNullOrEmpty(pass))
{
throw new ArgumentException("Could not retrive 'DbUserPassword' from config file");
}
var dbCredentials = new bnhtrade.Core.Model.Credentials.bnhtradeDB(dataSource, userId, pass);
this._dbCredentials = dbCredentials;
}
catch(Exception ex)
{
throw new Exception("Unable to retirve DB credentials: " + ex.Message);
}
}
public Connection(Model.Credentials.bnhtradeDB dbCredentials)
{
// setup sql parameters
if (dbCredentials == null)
{
throw new Exception("DB credentials object is null");
}
this._dbCredentials = dbCredentials;
}
}
}
@@ -0,0 +1,102 @@
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
{
/// <summary>
/// Gets the date bnhtrade started trading, UK time (datetime kind unspecified).
/// </summary>
/// <returns>The UK date and time the business started (datetime kind unspecified)</returns>
public static DateTime GetBusinessStartUk()
{
return new Logic.Utilities.DateTime().ConvertUtcToUk(GetBusinessStartUtc());
}
/// <summary>
/// Gets the date bnhtrade started trading, as UTC time
/// </summary>
/// <returns>The UTC date and time the business started (datetime kind UTC)</returns>
public static DateTime GetBusinessStartUtc()
{
DateTime businessStart = new DateTime(2014, 08, 31, 23, 00, 00); // 2014-09-01 uk date time
return DateTime.SpecifyKind(businessStart, DateTimeKind.Utc);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static string GetMarginSchemeTaxCode()
{
return "T190";
}
public static string GetOrderChannelAmazonUk()
{
return "Amazon.co.uk";
}
/// <summary>
/// Returns the sql table ID for a condition type
/// </summary>
public enum SkuCondition
{
New = 10,
LikeNew = 11,
VeryGood = 12,
Good = 13,
Acceptable = 14,
// add the rest as needed
}
/// <summary>
/// Returns the sql table ID for a Stock Journal Type
/// </summary>
public enum StockJournalType
{
SkuReconciliationFbaReceipt = 6,
SkuReconciliationFbaShipment = 7,
SkuReconciliationFbaAdjustment = 8,
SkuReconciliationFbaCustomerReturn = 9,
SkuReconciliationFbaVendorReturn = 10,
SkuReconciliationFbaReimbursement = 11,
}
/// <summary>
/// Returns the sql table ID for a stock status
/// </summary>
public enum StockStatus
{
FbaFulfillable = 15,
FbaSold = 12,
ReservedGarageStock = 16,
Reserved = 11,
}
/// <summary>
/// Returns the sql table ID for a stock status type
/// </summary>
public enum StockStatusType
{
FbaInventoryActive = 3,
FbaShipment = 4,
FbaShippingPlan = 5,
// add the rest as needed
}
public enum OrderChannel
{
US = 1,
UK = 2,
De = 3,
Fr = 4,
It = 5,
Es = 6,
}
}
}
@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Export
{
internal class AmazonFeedSubmissionInsert : Connection
{
public AmazonFeedSubmissionInsert ()
{
}
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;
}
}
}
}
}
@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
namespace bnhtrade.Core.Data.Database.Export
{
internal class AmazonFeedSubmissionRead : Connection
{
public AmazonFeedSubmissionRead()
{
}
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;
}
}
}
@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Export
{
internal class AmazonFeedSubmissionUpdate : Connection
{
public AmazonFeedSubmissionUpdate()
{
}
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.");
}
}
}
}
}
}
@@ -0,0 +1,244 @@
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.Import
{
public class AmazonFbaCustomerReturn : Connection
{
Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public AmazonFbaCustomerReturn()
{
}
public bool UpdateByFlatFile(string filePath)
{
SqlConnection sqlConn;
SqlTransaction trans;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (trans = sqlConn.BeginTransaction())
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
int lineNumber = 1;
int lineErrorSkip = 0;
int lineDuplicateSkip = 0;
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
int index01 = Array.IndexOf(headers, "return-date");
int index02 = Array.IndexOf(headers, "order-id");
int index03 = Array.IndexOf(headers, "sku");
int index04 = Array.IndexOf(headers, "asin");
int index05 = Array.IndexOf(headers, "fnsku");
int index06 = Array.IndexOf(headers, "quantity");
int index07 = Array.IndexOf(headers, "fulfillment-center-id");
int index08 = Array.IndexOf(headers, "detailed-disposition");
int index09 = Array.IndexOf(headers, "reason");
int index10 = Array.IndexOf(headers, "status");
int index11 = Array.IndexOf(headers, "license-plate-number");
int index12 = Array.IndexOf(headers, "customer-comments");
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
lineNumber = lineNumber + 1;
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineErrorSkip = lineErrorSkip + 1;
log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else
{
//read values
string returnDate = items[index01];
string orderId = items[index02];
string sku = items[index03];
string asin = items[index04];
string fnsku = items[index05];
string quantity = items[index06];
string fulfillmentCenterId = items[index07];
string detailedDisposition = items[index08];
string reason = items[index09];
string status = items[index10];
string licensePlateNumber = items[index11];
string customerComments = items[index12];
// check number of times line conbination appears in file
int fileCount = 0;
int dbCount = 0;
using (var dupReader = new StreamReader(filePath))
{
dupReader.ReadLine(); // read header row
string dupFileRow;
while ((dupFileRow = dupReader.ReadLine()) != null)
{
string[] dupItems = dupFileRow.Split('\t');
if (dupItems.Length != columnCount)
{
// skip
}
else
{
if (items[index01] == dupItems[index01] &&
items[index02] == dupItems[index02] &&
items[index05] == dupItems[index05] &&
items[index11] == dupItems[index11])
{
// count will always find at least one (itself)
fileCount = fileCount + 1;
}
}
}
}
//check for duplicate line in db
using (SqlCommand cmd = new SqlCommand(
"SELECT COUNT(ImportFbaCustomerReturnID) FROM tblImportFbaCustomerReturn " +
"WHERE [return-date]=@returnDate AND [order-id]=@orderId AND [fnsku]=@fnsku " +
"AND ([license-plate-number]=@licensePlateNumber OR [license-plate-number] IS NULL) ;"
, sqlConn, trans))
{
if (returnDate == "") { cmd.Parameters.AddWithValue("@returnDate", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@returnDate", DateTime.Parse(returnDate).ToUniversalTime()); }
if (orderId == "") { cmd.Parameters.AddWithValue("@orderId", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@orderId", orderId); }
if (fnsku == "") { cmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@fnsku", fnsku); }
if (licensePlateNumber == "") { cmd.Parameters.AddWithValue("@licensePlateNumber", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@licensePlateNumber", licensePlateNumber); }
dbCount = (int)cmd.ExecuteScalar();
}
if (fileCount <= dbCount)
{
//skip
lineDuplicateSkip = lineDuplicateSkip + 1;
}
else
{
//insert report items
using (SqlCommand insertCmd = new SqlCommand(
"INSERT INTO tblImportFbaCustomerReturn ( " +
"[return-date], [order-id], sku, asin, fnsku, " +
"quantity, [fulfillment-center-id], [detailed-disposition], reason, status, " +
"[license-plate-number], [customer-comments] ) " +
"VALUES ( " +
"@returnDate, @orderId, @sku, @asin, @fnsku, " +
"@quantity, @fulfillmentCenterId, @detailedDisposition, @reason, @status, " +
"@licensePlateNumber, @customerComments );"
, sqlConn, trans))
{
// add parameters
if (returnDate == "") { insertCmd.Parameters.AddWithValue("@returnDate", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@returnDate", DateTime.Parse(returnDate).ToUniversalTime()); }
if (orderId == "") { insertCmd.Parameters.AddWithValue("@orderId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@orderId", orderId); }
if (sku == "") { insertCmd.Parameters.AddWithValue("@sku", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@sku", sku); }
if (asin == "") { insertCmd.Parameters.AddWithValue("@asin", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@asin", asin); }
if (fnsku == "") { insertCmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@fnsku", fnsku); }
if (quantity == "") { insertCmd.Parameters.AddWithValue("@quantity", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@quantity", int.Parse(quantity)); }
if (fulfillmentCenterId == "") { insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", fulfillmentCenterId); }
if (detailedDisposition == "") { insertCmd.Parameters.AddWithValue("@detailedDisposition", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@detailedDisposition", detailedDisposition); }
if (reason == "") { insertCmd.Parameters.AddWithValue("@reason", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@reason", reason); }
if (status == "") { insertCmd.Parameters.AddWithValue("@status", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@status", status); }
if (licensePlateNumber == "") { insertCmd.Parameters.AddWithValue("@licensePlateNumber", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@licensePlateNumber", licensePlateNumber); }
if (customerComments == "") { insertCmd.Parameters.AddWithValue("@customerComments", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@customerComments", customerComments); }
insertCmd.ExecuteNonQuery();
}
}
}
}
trans.Commit();
Console.Write("\r");
log.LogInformation((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
if (lineErrorSkip > 0)
{
log.LogWarning(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
}
}
}
catch (Exception ex)
{
log.LogError("Error running FbaInventoryReceiptReportImport, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
return true;
}
public DateTime ReadRecentDate()
{
DateTime lastRecordDate;
SqlConnection sqlConn;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (SqlCommand cmd = new SqlCommand(
"SELECT Max([return-date]) AS MaxDate FROM tblImportFbaCustomerReturn;"
, sqlConn))
{
if (cmd.ExecuteScalar() == DBNull.Value)
{
// use first month started selling on Amazon
lastRecordDate = lastRecordDate = Constants.GetBusinessStartUtc();
}
else
{
lastRecordDate = ((DateTime)cmd.ExecuteScalar());
lastRecordDate = DateTime.SpecifyKind(lastRecordDate, DateTimeKind.Utc);
}
return lastRecordDate;
}
}
}
catch (Exception ex)
{
log.LogError("Error running GetFbaReturnsReport, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
}
}
}
@@ -0,0 +1,242 @@
using System;
using System.Data.SqlClient;
using System.IO;
namespace bnhtrade.Core.Data.Database.Import
{
public class AmazonFbaInventoryAdjustment : Connection
{
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public AmazonFbaInventoryAdjustment()
{
}
public bool InsertByFlatFile(string filePath)
{
SqlConnection sqlConn;
SqlTransaction trans;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (trans = sqlConn.BeginTransaction())
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
int lineNumber = 1;
int lineErrorSkip = 0;
int lineDuplicateSkip = 0;
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
int index01 = Array.IndexOf(headers, "adjusted-date");
int index02 = Array.IndexOf(headers, "transaction-item-id");
int index03 = Array.IndexOf(headers, "fnsku");
int index04 = Array.IndexOf(headers, "sku");
int index05 = Array.IndexOf(headers, "product-name");
int index06 = Array.IndexOf(headers, "fulfillment-center-id");
int index07 = Array.IndexOf(headers, "quantity");
int index08 = Array.IndexOf(headers, "reason");
int index09 = Array.IndexOf(headers, "disposition");
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
lineNumber = lineNumber + 1;
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineErrorSkip = lineErrorSkip + 1;
log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else
{
//read values
string adjustmentDate = items[index01];
string transactionItemId = items[index02];
string fnsku = items[index03];
string sku = items[index04];
string fulfillmentCenterId = items[index06];
string quantity = items[index07];
string reason = items[index08];
string disposition = items[index09];
// check number of times line combination appears in file
// don't think is a nesseary step, the transactionItemId is a unique identifier, I'm 99% sure
int fileCount = 0;
int dbCount = 0;
using (var dupReader = new StreamReader(filePath))
{
dupReader.ReadLine(); // read header row
string dupFileRow;
while ((dupFileRow = dupReader.ReadLine()) != null)
{
string[] dupItems = dupFileRow.Split('\t');
if (dupItems.Length != columnCount)
{
// skip
}
else
{
if (items[index01] == dupItems[index01] &&
items[index02] == dupItems[index02] &&
items[index03] == dupItems[index03] &&
items[index06] == dupItems[index06] &&
items[index08] == dupItems[index08] &&
items[index09] == dupItems[index09]
)
{
// count will always find at least one (itself)
fileCount = fileCount + 1;
}
}
}
}
//check for duplicate line in db
//using (SqlCommand cmd = new SqlCommand(
// "SELECT COUNT(ImportFbaInventoryAdjustmentReportID) FROM tblImportFbaInventoryAdjustmentReport " +
// "WHERE [adjusted-date]=@adjustmentDate AND [transaction-item-id]=@transactionItemId AND [fnsku]=@fnsku " +
// " AND [fulfillment-center-id]=@fulfillmentCenterId AND [reason]=@reason AND [disposition]=@disposition;"
// , sqlConn, trans))
//{
// if (adjustmentDate == "") { cmd.Parameters.AddWithValue("@adjustmentDate", DBNull.Value); }
// else { cmd.Parameters.AddWithValue("@adjustmentDate", DateTime.Parse(adjustmentDate).ToUniversalTime()); }
// if (transactionItemId == "") { cmd.Parameters.AddWithValue("@transactionItemId", DBNull.Value); }
// else { cmd.Parameters.AddWithValue("@transactionItemId", transactionItemId); }
// if (fnsku == "") { cmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
// else { cmd.Parameters.AddWithValue("@fnsku", fnsku); }
// if (fulfillmentCenterId == "") { cmd.Parameters.AddWithValue("@fulfillmentCenterId", DBNull.Value); }
// else { cmd.Parameters.AddWithValue("@fulfillmentCenterId", fulfillmentCenterId); }
// if (reason == "") { cmd.Parameters.AddWithValue("@reason", DBNull.Value); }
// else { cmd.Parameters.AddWithValue("@reason", reason); }
// if (disposition == "") { cmd.Parameters.AddWithValue("@disposition", DBNull.Value); }
// else { cmd.Parameters.AddWithValue("@disposition", disposition); }
// dbCount = (int)cmd.ExecuteScalar();
//}
using (SqlCommand cmd = new SqlCommand(
"SELECT COUNT(ImportFbaInventoryAdjustmentReportID) FROM tblImportFbaInventoryAdjustmentReport " +
"WHERE [transaction-item-id]=@transactionItemId;"
, sqlConn, trans))
{
cmd.Parameters.AddWithValue("@transactionItemId", transactionItemId);
dbCount = (int)cmd.ExecuteScalar();
}
if (fileCount <= dbCount)
{
//skip
lineDuplicateSkip = lineDuplicateSkip + 1;
}
else
{
//insert report items
using (SqlCommand insertCmd = new SqlCommand(
"INSERT INTO tblImportFbaInventoryAdjustmentReport ( " +
"[adjusted-date], [transaction-item-id], fnsku, sku, " +
"[fulfillment-center-id], quantity, reason, disposition ) " +
"VALUES ( " +
"@adjustmentDate, @transactionItemId, @fnsku, @sku, " +
"@fulfillmentCenterId, @quantity, @reason, @disposition );"
, sqlConn, trans))
{
// add parameters
if (adjustmentDate == "") { insertCmd.Parameters.AddWithValue("@adjustmentDate", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@adjustmentDate", DateTime.Parse(adjustmentDate).ToUniversalTime()); }
if (transactionItemId == "") { insertCmd.Parameters.AddWithValue("@transactionItemId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@transactionItemId", transactionItemId); }
if (fnsku == "") { insertCmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@fnsku", fnsku); }
if (sku == "") { insertCmd.Parameters.AddWithValue("@sku", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@sku", sku); }
if (fulfillmentCenterId == "") { insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", fulfillmentCenterId); }
if (quantity == "") { insertCmd.Parameters.AddWithValue("@quantity", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@quantity", int.Parse(quantity)); }
if (reason == "") { insertCmd.Parameters.AddWithValue("@reason", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@reason", reason); }
if (disposition == "") { insertCmd.Parameters.AddWithValue("@disposition", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@disposition", disposition); }
insertCmd.ExecuteNonQuery();
}
}
}
}
trans.Commit();
Console.Write("\r");
log.LogInformation((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
if (lineErrorSkip > 0)
{
log.LogError(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
}
}
}
catch (Exception ex)
{
log.LogError("Error running ImportFbaAdustmentReport method, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
return true;
}
public DateTime ReadRecentDate()
{
DateTime lastRecordDate;
SqlConnection sqlConn;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (SqlCommand cmd = new SqlCommand(
"SELECT Max([adjusted-date]) AS MaxDate FROM tblImportFbaInventoryAdjustmentReport;"
, sqlConn))
{
if (cmd.ExecuteScalar() == DBNull.Value)
{
// use first month started selling on Amazon
lastRecordDate = lastRecordDate = Constants.GetBusinessStartUtc();
}
else
{
lastRecordDate = ((DateTime)cmd.ExecuteScalar());
lastRecordDate = DateTime.SpecifyKind(lastRecordDate, DateTimeKind.Utc);
}
return lastRecordDate;
}
}
}
catch (Exception ex)
{
log.LogError("Error running GetFbaAdustmentData, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
}
}
}
@@ -0,0 +1,299 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Transactions;
namespace bnhtrade.Core.Data.Database.Import
{
public class AmazonFbaInventoryAgeData : Connection
{
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public AmazonFbaInventoryAgeData()
{
}
public void InsertByFlatFile(string filePath)
{
SqlConnection sqlConn;
try
{
using (TransactionScope scope = new TransactionScope())
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
//clear table data
using (SqlCommand cmd = new SqlCommand(@"
DELETE FROM tblImportFbaInventoryAgeReport;
", sqlConn))
{
cmd.ExecuteNonQuery();
}
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
int lineNumber = 1;
int lineErrorSkip = 0;
int lineNoStockSkip = 0;
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
if (columnCount != 38)
{
throw new Exception("Chnages found to 'Fba Inventory Age Data' flatfile structure");
}
int index01 = Array.IndexOf(headers, "snapshot-date");
int index02 = Array.IndexOf(headers, "marketplace");
int index03 = Array.IndexOf(headers, "sku");
int index04 = Array.IndexOf(headers, "fnsku");
int index05 = Array.IndexOf(headers, "asin");
int index06 = Array.IndexOf(headers, "product-name");
int index07 = Array.IndexOf(headers, "condition");
int index08 = Array.IndexOf(headers, "avaliable-quantity(sellable)");
int index09 = Array.IndexOf(headers, "qty-with-removals-in-progress");
int index10 = Array.IndexOf(headers, "inv-age-0-to-90-days");
int index11 = Array.IndexOf(headers, "inv-age-91-to-180-days");
int index12 = Array.IndexOf(headers, "inv-age-181-to-270-days");
int index13 = Array.IndexOf(headers, "inv-age-271-to-365-days");
int index14 = Array.IndexOf(headers, "inv-age-365-plus-days");
int index15 = Array.IndexOf(headers, "currency");
int index16 = Array.IndexOf(headers, "qty-to-be-charged-ltsf-6-mo");
int index17 = Array.IndexOf(headers, "projected-ltsf-6-mo");
int index18 = Array.IndexOf(headers, "qty-to-be-charged-ltsf-12-mo");
int index19 = Array.IndexOf(headers, "projected-ltsf-12-mo");
int index20 = Array.IndexOf(headers, "units-shipped-last-7-days");
int index21 = Array.IndexOf(headers, "units-shipped-last-30-days");
int index22 = Array.IndexOf(headers, "units-shipped-last-60-days");
int index23 = Array.IndexOf(headers, "units-shipped-last-90-days");
int index24 = Array.IndexOf(headers, "alert");
int index25 = Array.IndexOf(headers, "your-price");
int index26 = Array.IndexOf(headers, "sales_price");
int index27 = Array.IndexOf(headers, "lowest_price_new");
int index28 = Array.IndexOf(headers, "lowest_price_used");
int index29 = Array.IndexOf(headers, "Recommended action");
int index30 = Array.IndexOf(headers, "Healthy Inventory Level");
int index31 = Array.IndexOf(headers, "Recommended sales price");
int index32 = Array.IndexOf(headers, "Recommended sale duration (days)");
int index33 = Array.IndexOf(headers, "Recommended Removal Quantity");
int index34 = Array.IndexOf(headers, "estimated-cost-savings-of-recommended-actions");
int index35 = Array.IndexOf(headers, "sell-through");
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
lineNumber = lineNumber + 1;
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineErrorSkip = lineErrorSkip + 1;
log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else
{
//read values
string snapshotDate = items[index01];
string marketplace = items[index02];
string sku = items[index03];
string fnsku = items[index04];
string asin = items[index05];
string productName = items[index06];
string condition = items[index07];
string avaliableQuantity = items[index08];
string qtyWithRemovalsInProgress = items[index09];
string invAge0To90Days = items[index10];
string invAge91To180Days = items[index11];
string invAge181To270Days = items[index12];
string invAge271To365Days = items[index13];
string invAge365PlusDays = items[index14];
string currency = items[index15];
string qtyToBeChargedLtsf6Mo = items[index16];
string projectedLtsf6Mo = Regex.Replace(items[index17], "[^.0-9]", ""); // strip currency code prefix
string qtyToBeChargedLtsf12Mo = items[index18];
string projectedLtsf12Mo = Regex.Replace(items[index19], "[^.0-9]", ""); // strip currency code prefix
string unitsShippedLast7Days = items[index20];
string unitsShippedLast30Days = items[index21];
string unitsShippedLast60Days = items[index22];
string unitsShippedLast90Days = items[index23];
string alert = items[index24];
string yourPrice = Regex.Replace(items[index25], "[^.0-9]", ""); // strip currency code prefix
string salesPrice = Regex.Replace(items[index26], "[^.0-9]", ""); // strip currency code prefix
string lowestPriceNew = Regex.Replace(items[index27], "[^.0-9]", ""); // strip currency code prefix
string lowestPriceUsed = Regex.Replace(items[index28], "[^.0-9]", ""); // strip currency code prefix
string recommendedAction = items[index29];
string healthyInventoryLevel = items[index30];
string recommendedSalesPrice = Regex.Replace(items[index31], "[^.0-9]", ""); // strip currency code prefix
string recommendedSaleDuration = items[index32];
string recommendedRemovalQuantity = items[index33];
string estimatedCostSavingsOfRecommendedActions = items[index34];
string sellThrough = items[index35];
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblImportFbaInventoryAgeReport(
[snapshot-date], marketplace, sku, fnsku, asin, [product-name], condition, [avaliable-quantity(sellable)],
[qty-with-removals-in-progress], [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], currency, [qty-to-be-charged-ltsf-6-mo], [projected-ltsf-6-mo],
[qty-to-be-charged-ltsf-12-mo], [projected-ltsf-12-mo], [units-shipped-last-7-days], [units-shipped-last-30-days],
[units-shipped-last-60-days], [units-shipped-last-90-days], alert, [your-price], sales_price, lowest_price_new,
lowest_price_used, [Recommended action], [Healthy Inventory Level], [Recommended sales price],
[Recommended sale duration (days)], [Recommended Removal Quantity], [estimated-cost-savings-of-recommended-actions],
[sell-through] )
VALUES (
@snapshotDate, @marketplace, @sku, @fnsku, @asin, @productName, @condition, @avaliableQuantity,
@qtyWithRemovalsInProgress, @invAge0To90Days, @invAge91To180Days, @invAge181To270Days, @invAge271To365Days, @invAge365PlusDays, @currency, @qtyToBeChargedLtsf6Mo,
@projectedLtsf6Mo, @qtyToBeChargedLtsf12Mo, @projectedLtsf12Mo, @unitsShippedLast7Days, @unitsShippedLast30Days, @unitsShippedLast60Days, @unitsShippedLast90Days, @alert,
@yourPrice, @salesPrice, @lowestPriceNew, @lowestPriceUsed, @recommendedAction, @healthyInventoryLevel, @recommendedSalesPrice,
@recommendedSaleDuration, @recommendedRemovalQuantity, @estimatedCostSavingsOfRecommendedActions,
@sellThrough );
", sqlConn))
{
// add parameters
if (snapshotDate.Length == 0) { cmd.Parameters.AddWithValue("@snapshotDate", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@snapshotDate", DateTime.Parse(snapshotDate).ToUniversalTime()); }
if (marketplace.Length == 0) { cmd.Parameters.AddWithValue("@marketplace", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@marketplace", marketplace); }
if (sku.Length == 0) { cmd.Parameters.AddWithValue("@sku", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@sku", sku); }
if (fnsku.Length == 0) { cmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@fnsku", fnsku); }
if (asin.Length == 0) { cmd.Parameters.AddWithValue("@asin", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@asin", asin); }
if (productName.Length == 0) { cmd.Parameters.AddWithValue("@productName", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@productName", productName); }
if (condition.Length == 0) { cmd.Parameters.AddWithValue("@condition", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@condition", condition); }
if (avaliableQuantity.Length == 0) { cmd.Parameters.AddWithValue("@avaliableQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@avaliableQuantity", int.Parse(avaliableQuantity)); }
if (qtyWithRemovalsInProgress.Length == 0) { cmd.Parameters.AddWithValue("@qtyWithRemovalsInProgress", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@qtyWithRemovalsInProgress", int.Parse(qtyWithRemovalsInProgress)); }
if (invAge0To90Days.Length == 0) { cmd.Parameters.AddWithValue("@invAge0To90Days", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@invAge0To90Days", int.Parse(invAge0To90Days)); }
if (invAge91To180Days.Length == 0) { cmd.Parameters.AddWithValue("@invAge91To180Days", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@invAge91To180Days", int.Parse(invAge91To180Days)); }
if (invAge181To270Days.Length == 0) { cmd.Parameters.AddWithValue("@invAge181To270Days", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@invAge181To270Days", int.Parse(invAge181To270Days)); }
if (invAge271To365Days.Length == 0) { cmd.Parameters.AddWithValue("@invAge271To365Days", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@invAge271To365Days", int.Parse(invAge271To365Days)); }
if (invAge365PlusDays.Length == 0) { cmd.Parameters.AddWithValue("@invAge365PlusDays", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@invAge365PlusDays", int.Parse(invAge365PlusDays)); }
if (currency.Length == 0) { cmd.Parameters.AddWithValue("@currency", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@currency", currency); }
if (qtyToBeChargedLtsf6Mo.Length == 0) { cmd.Parameters.AddWithValue("@qtyToBeChargedLtsf6Mo", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@qtyToBeChargedLtsf6Mo", int.Parse(qtyToBeChargedLtsf6Mo)); }
if (projectedLtsf6Mo.Length == 0) { cmd.Parameters.AddWithValue("@projectedLtsf6Mo", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@projectedLtsf6Mo", decimal.Parse(projectedLtsf6Mo)); }
if (qtyToBeChargedLtsf12Mo.Length == 0) { cmd.Parameters.AddWithValue("@qtyToBeChargedLtsf12Mo", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@qtyToBeChargedLtsf12Mo", int.Parse(qtyToBeChargedLtsf12Mo)); }
if (projectedLtsf12Mo.Length == 0) { cmd.Parameters.AddWithValue("@projectedLtsf12Mo", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@projectedLtsf12Mo", decimal.Parse(projectedLtsf12Mo)); }
if (unitsShippedLast7Days.Length == 0) { cmd.Parameters.AddWithValue("@unitsShippedLast7Days", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@unitsShippedLast7Days", int.Parse(unitsShippedLast7Days)); }
if (unitsShippedLast30Days.Length == 0) { cmd.Parameters.AddWithValue("@unitsShippedLast30Days", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@unitsShippedLast30Days", int.Parse(unitsShippedLast30Days)); }
if (unitsShippedLast60Days.Length == 0) { cmd.Parameters.AddWithValue("@unitsShippedLast60Days", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@unitsShippedLast60Days", int.Parse(unitsShippedLast60Days)); }
if (unitsShippedLast90Days.Length == 0) { cmd.Parameters.AddWithValue("@unitsShippedLast90Days", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@unitsShippedLast90Days", int.Parse(unitsShippedLast90Days)); }
if (alert.Length == 0) { cmd.Parameters.AddWithValue("@alert", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@alert", alert); }
if (yourPrice.Length == 0) { cmd.Parameters.AddWithValue("@yourPrice", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@yourPrice", decimal.Parse(yourPrice)); }
if (salesPrice.Length == 0) { cmd.Parameters.AddWithValue("@salesPrice", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@salesPrice", decimal.Parse(salesPrice)); }
if (lowestPriceNew.Length == 0) { cmd.Parameters.AddWithValue("@lowestPriceNew", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@lowestPriceNew", decimal.Parse(lowestPriceNew)); }
if (lowestPriceUsed.Length == 0) { cmd.Parameters.AddWithValue("@lowestPriceUsed", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@lowestPriceUsed", decimal.Parse(lowestPriceUsed)); }
if (recommendedAction.Length == 0) { cmd.Parameters.AddWithValue("@recommendedAction", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@recommendedAction", recommendedAction); }
if (healthyInventoryLevel.Length == 0) { cmd.Parameters.AddWithValue("@healthyInventoryLevel", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@healthyInventoryLevel", int.Parse(healthyInventoryLevel)); }
if (recommendedSalesPrice.Length == 0) { cmd.Parameters.AddWithValue("@recommendedSalesPrice", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@recommendedSalesPrice", decimal.Parse(recommendedSalesPrice)); }
if (recommendedSaleDuration.Length == 0) { cmd.Parameters.AddWithValue("@recommendedSaleDuration", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@recommendedSaleDuration", int.Parse(recommendedSaleDuration)); }
if (recommendedRemovalQuantity.Length == 0) { cmd.Parameters.AddWithValue("@recommendedRemovalQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@recommendedRemovalQuantity", int.Parse(recommendedRemovalQuantity)); }
if (estimatedCostSavingsOfRecommendedActions.Length == 0) { cmd.Parameters.AddWithValue("@estimatedCostSavingsOfRemoval", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@estimatedCostSavingsOfRecommendedActions", decimal.Parse(estimatedCostSavingsOfRecommendedActions)); }
if (sellThrough.Length == 0) { cmd.Parameters.AddWithValue("@sellThrough", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@sellThrough", decimal.Parse(sellThrough)); }
// execute the query
cmd.ExecuteNonQuery();
}
}
}
Console.Write("\r");
log.LogInformation(
"Operation complete. " + lineNumber + " items processes. " + (lineNumber - lineErrorSkip - lineNoStockSkip) + " total new items inserted, "
+ lineNoStockSkip + " 'No Stock' records were skipped.");
if (lineErrorSkip > 0)
{
log.LogError(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
}
}
scope.Complete();
}
}
catch (Exception ex)
{
log.LogError("Something went wrong during import, check details for more.", ex.ToString());
Console.WriteLine(ex.ToString());
}
}
}
}
@@ -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 AmazonFbaInventoryAgeRead : Connection
{
public AmazonFbaInventoryAgeRead()
{
}
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);
}
}
}
@@ -0,0 +1,195 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace bnhtrade.Core.Data.Database.Import
{
public class AmazonFbaInventoryData : Connection
{
Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public AmazonFbaInventoryData()
{
}
public void InsertByFlatFile(string filePath)
{
SqlConnection sqlConn;
try
{
using (TransactionScope scope = new TransactionScope())
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
//clear table data
using (SqlCommand cmd = new SqlCommand(@"
DELETE FROM tblImportFbaManageInventory;
", sqlConn))
{
cmd.ExecuteNonQuery();
}
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
int lineNumber = 1;
int lineErrorSkip = 0;
int lineNoStockSkip = 0;
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
int index01 = Array.IndexOf(headers, "sku");
int index02 = Array.IndexOf(headers, "fnsku");
int index03 = Array.IndexOf(headers, "asin");
int index04 = Array.IndexOf(headers, "product-name");
int index05 = Array.IndexOf(headers, "condition");
int index06 = Array.IndexOf(headers, "your-price");
int index07 = Array.IndexOf(headers, "mfn-listing-exists");
int index08 = Array.IndexOf(headers, "mfn-fulfillable-quantity");
int index09 = Array.IndexOf(headers, "afn-listing-exists");
int index10 = Array.IndexOf(headers, "afn-warehouse-quantity");
int index11 = Array.IndexOf(headers, "afn-fulfillable-quantity");
int index12 = Array.IndexOf(headers, "afn-unsellable-quantity");
int index13 = Array.IndexOf(headers, "afn-reserved-quantity");
int index14 = Array.IndexOf(headers, "afn-total-quantity");
int index15 = Array.IndexOf(headers, "per-unit-volume");
int index16 = Array.IndexOf(headers, "afn-inbound-working-quantity");
int index17 = Array.IndexOf(headers, "afn-inbound-shipped-quantity");
int index18 = Array.IndexOf(headers, "afn-inbound-receiving-quantity");
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
lineNumber = lineNumber + 1;
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineErrorSkip = lineErrorSkip + 1;
log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else
{
// only import sku with stock
// afnTotalQuantity includes fba stock and inbound shipments
string afnTotalQuantity = items[index14];
//if (int.Parse(afnTotalQuantity) == 0)
//{
// lineNoStockSkip = lineNoStockSkip + 1;
// continue;
//}
//read values
string sku = items[index01];
string fnsku = items[index02];
string asin = items[index03];
string productName = items[index04];
string condition = items[index05];
string yourPrice = items[index06];
string mfnListingExists = items[index07];
string mfnFulfillableQuantity = items[index08];
string afnListingExists = items[index09];
string afnWarehouseQuantity = items[index10];
string afnFulfillableQuantity = items[index11];
string afnUnsellableQuantity = items[index12];
string afnReservedQuantity = items[index13];
string perUnitVolume = items[index15];
string afnInboundWorkingQuantity = items[index16];
string afnInboundShippedQuantity = items[index17];
string afnInboundReceivingQuantity = items[index18];
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblImportFbaManageInventory(
sku, fnsku, asin, [product-name], condition, [your-price], [mfn-listing-exists], [mfn-fulfillable-quantity],
[afn-listing-exists], [afn-warehouse-quantity], [afn-fulfillable-quantity], [afn-unsellable-quantity],
[afn-reserved-quantity], [afn-total-quantity], [per-unit-volume], [afn-inbound-working-quantity],
[afn-inbound-shipped-quantity], [afn-inbound-receiving-quantity] )
VALUES (
@sku, @fnsku, @asin, @productName, @condition, @yourPrice, @mfnListingExists, @mfnFulfillableQuantity,
@afnListingExists, @afnWarehouseQuantity, @afnFulfillableQuantity, @afnUnsellableQuantity,
@afnReservedQuantity, @afnTotalQuantity, @perUnitVolume, @afnInboundWorkingQuantity,
@afnInboundShippedQuantity, @afnInboundReceivingQuantity );
", sqlConn))
{
// add parameters
cmd.Parameters.AddWithValue("@sku", sku);
if (fnsku.Length == 0) { cmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@fnsku", fnsku); }
if (asin.Length == 0) { cmd.Parameters.AddWithValue("@asin", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@asin", asin); }
if (productName.Length == 0) { cmd.Parameters.AddWithValue("@productName", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@productName", productName); }
if (condition.Length == 0) { cmd.Parameters.AddWithValue("@condition", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@condition", condition); }
if (yourPrice.Length == 0) { cmd.Parameters.AddWithValue("@yourPrice", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@yourPrice", decimal.Parse(yourPrice)); }
if (mfnListingExists.Length == 0) { cmd.Parameters.AddWithValue("@mfnListingExists", DBNull.Value); }
else if (mfnListingExists == "Yes") { cmd.Parameters.AddWithValue("@mfnListingExists", true); }
else { cmd.Parameters.AddWithValue("@mfnListingExists", false); }
if (mfnFulfillableQuantity.Length == 0) { cmd.Parameters.AddWithValue("@mfnFulfillableQuantity", 0); }
else { cmd.Parameters.AddWithValue("@mfnFulfillableQuantity", int.Parse(mfnFulfillableQuantity)); }
if (afnListingExists.Length == 0) { cmd.Parameters.AddWithValue("@afnListingExists", DBNull.Value); }
else if (afnListingExists == "Yes") { cmd.Parameters.AddWithValue("@afnListingExists", true); }
else { cmd.Parameters.AddWithValue("@afnListingExists", false); }
if (afnWarehouseQuantity.Length == 0) { cmd.Parameters.AddWithValue("@afnWarehouseQuantity", 0); }
else { cmd.Parameters.AddWithValue("@afnWarehouseQuantity", int.Parse(afnWarehouseQuantity)); }
if (afnFulfillableQuantity.Length == 0) { cmd.Parameters.AddWithValue("@afnFulfillableQuantity", 0); }
else { cmd.Parameters.AddWithValue("@afnFulfillableQuantity", int.Parse(afnFulfillableQuantity)); }
if (afnUnsellableQuantity.Length == 0) { cmd.Parameters.AddWithValue("@afnUnsellableQuantity", 0); }
else { cmd.Parameters.AddWithValue("@afnUnsellableQuantity", int.Parse(afnUnsellableQuantity)); }
if (afnReservedQuantity.Length == 0) { cmd.Parameters.AddWithValue("@afnReservedQuantity", 0); }
else { cmd.Parameters.AddWithValue("@afnReservedQuantity", int.Parse(afnReservedQuantity)); }
if (afnTotalQuantity.Length == 0) { cmd.Parameters.AddWithValue("@afnTotalQuantity", 0); }
else { cmd.Parameters.AddWithValue("@afnTotalQuantity", int.Parse(afnTotalQuantity)); }
if (perUnitVolume.Length == 0) { cmd.Parameters.AddWithValue("@perUnitVolume", 0); }
else { cmd.Parameters.AddWithValue("@perUnitVolume", decimal.Parse(perUnitVolume)); }
if (afnInboundWorkingQuantity.Length == 0) { cmd.Parameters.AddWithValue("@afnInboundWorkingQuantity", 0); }
else { cmd.Parameters.AddWithValue("@afnInboundWorkingQuantity", int.Parse(afnInboundWorkingQuantity)); }
if (afnInboundShippedQuantity.Length == 0) { cmd.Parameters.AddWithValue("@afnInboundShippedQuantity", 0); }
else { cmd.Parameters.AddWithValue("@afnInboundShippedQuantity", int.Parse(afnInboundShippedQuantity)); }
if (afnInboundReceivingQuantity.Length == 0) { cmd.Parameters.AddWithValue("@afnInboundReceivingQuantity", 0); }
else { cmd.Parameters.AddWithValue("@afnInboundReceivingQuantity", int.Parse(afnInboundReceivingQuantity)); }
// execute the query
cmd.ExecuteNonQuery();
}
}
}
Console.Write("\r");
log.LogInformation(
"Operation complete. " + lineNumber + " items processes. " + (lineNumber - lineErrorSkip - lineNoStockSkip) + " total new items inserted, "
+ lineNoStockSkip + " 'No Stock' records were skipped.");
if (lineErrorSkip > 0)
{
log.LogError(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
}
}
scope.Complete();
}
}
catch (Exception ex)
{
log.LogError("Something went wrong during import, check details for more.", ex.ToString());
Console.WriteLine(ex.ToString());
}
}
}
}
@@ -0,0 +1,256 @@
using Amazon.Runtime.Internal.Transform;
using bnhtrade.Core.Logic.Amazon.Fba;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Linq;
namespace bnhtrade.Core.Data.Database.Import
{
public class AmazonFbaInventoryLedgerDetail : Connection
{
public AmazonFbaInventoryLedgerDetail()
{
}
public Dictionary<int, Model.Import.AmazonFbaInventoryLedgerDetail> Insert(List<Model.Import.AmazonFbaInventoryLedgerDetail> insertList)
{
var returnDict = new Dictionary<int, Model.Import.AmazonFbaInventoryLedgerDetail>();
if (insertList == null || insertList.Any() == false)
return returnDict;
SqlConnection conn;
SqlTransaction trans;
using (conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (trans = conn.BeginTransaction())
{
foreach (var item in insertList)
{
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblImportFbaInventoryLedgerDetail (
FNSKU
,ASIN
,MSKU
,Title
,[Event Type]
,[Reference ID]
,Quantity
,[Fulfillment Center]
,Disposition
,Reason
,Country
,[Reconciled Quantity]
,[Unreconciled Quantity]
,[Date and Time]
)
OUTPUT INSERTED.ImportFbaInventoryLedgerDetailID
VALUES (
@fnsku
,@asin
,@msku
,@title
,@eventType
,@referenceid
,@quantity
,@fulfillmentCenter
,@disposition
,@reason
,@country
,@reconciledQuantity
,@unreconciledQuantity
,@dateAndTime
)
", conn, trans))
{
cmd.Parameters.AddWithValue("@fnsku", item.Fnsku);
cmd.Parameters.AddWithValue("@asin", item.Asin);
cmd.Parameters.AddWithValue("@msku", item.Msku);
cmd.Parameters.AddWithValue("@title", item.Title);
cmd.Parameters.AddWithValue("@eventType", item.EventType);
cmd.Parameters.AddWithValue("@referenceid", item.ReferenceId);
cmd.Parameters.AddWithValue("@quantity", item.Quantity);
cmd.Parameters.AddWithValue("@fulfillmentCenter", item.FulfillmentCenter);
cmd.Parameters.AddWithValue("@disposition", item.Disposition);
cmd.Parameters.AddWithValue("@reason", item.Reason);
cmd.Parameters.AddWithValue("@country", item.Country);
if (item.ReconciledQuantity == null) { cmd.Parameters.AddWithValue("@reconciledQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@reconciledQuantity", item.ReconciledQuantity); }
if (item.UnreconciledQuantity == null) { cmd.Parameters.AddWithValue("@unreconciledQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@unreconciledQuantity", item.UnreconciledQuantity); }
cmd.Parameters.AddWithValue("@dateAndTime", item.DateAndTime);
object obj = cmd.ExecuteScalar();
if (obj == null || obj == DBNull.Value)
{
throw new Exception("Error inserting new defalt invoice line item into database");
}
returnDict.Add((int)obj, item);
}
}
if (insertList.Count != returnDict.Count)
throw new Exception("AmazonFbaInventoryLedgerDetail db insert failed, not all records could be commmitted. Transaction rolled back");
trans.Commit();
return returnDict;
}
}
}
/// <summary>
/// Retrives the AmazonFbaInventoryLedgerDetail object from the database
/// </summary>
/// <param name="utcFrom">date time filter</param>
/// <param name="utcTo">date time filter</param>
/// <param name="isProcessed">isprocessed filter</param>
/// <returns>dictionary key=AmazonFbaInventoryLedgerDetailIs, value=AmazonFbaInventoryLedgerDetail object</returns>
public Dictionary<int, Model.Import.AmazonFbaInventoryLedgerDetail> Read(DateTime? utcFrom = null, DateTime? utcTo = null, bool? isProcessed = null)
{
var resultList = new Dictionary<int, Model.Import.AmazonFbaInventoryLedgerDetail>();
string sql = @"
SELECT TOP (1000) [ImportFbaInventoryLedgerDetailId]
,[FNSKU]
,[ASIN]
,[MSKU]
,[Title]
,[Event Type]
,[Reference ID]
,[Quantity]
,[Fulfillment Center]
,[Disposition]
,[Reason]
,[Country]
,[Reconciled Quantity]
,[Unreconciled Quantity]
,[Date and Time]
,[IsProcessed]
,[StockSkuTransactionID]
FROM [e2A].[dbo].[tblImportFbaInventoryLedgerDetail]
WHERE 1=1";
if (utcFrom != null)
sql = sql + " AND [Date and Time] >= @utcFrom";
if (utcTo != null)
sql = sql + " AND [Date and Time] <= @utcFrom";
if (isProcessed != null)
sql = sql + " AND [IsProcessed] = @isProcessed";
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
if (utcFrom != null)
cmd.Parameters.AddWithValue("@utcFrom", utcFrom);
if (utcTo != null)
cmd.Parameters.AddWithValue("@utcFrom", utcTo);
if (isProcessed != null)
cmd.Parameters.AddWithValue("@isProcessed", isProcessed);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
var result = new Model.Import.AmazonFbaInventoryLedgerDetail();
result.Fnsku = reader.GetString(1);
result.Asin = reader.GetString(2);
result.Msku = reader.GetString(3);
result.Title = reader.GetString(4);
result.EventType = reader.GetString(5);
if (!reader.IsDBNull(6))
result.ReferenceId = reader.GetString(6);
result.Quantity = reader.GetInt32(7);
result.FulfillmentCenter = reader.GetString(8);
result.Disposition = reader.GetString(9);
if (!reader.IsDBNull(10))
result.Reason = reader.GetString(10);
result.Country = reader.GetString(11);
if (!reader.IsDBNull(12))
result.ReconciledQuantity = reader.GetInt32(12);
if (!reader.IsDBNull(13))
result.UnreconciledQuantity = reader.GetInt32(13);
result.DateAndTime = DateTime.SpecifyKind(reader.GetDateTime(14), DateTimeKind.Utc);
resultList.Add(reader.GetInt32(0), result);
}
}
return resultList;
}
}
}
}
/// <summary>
/// Set the record as processed, where no entry has been made into the stock sku transaction table
/// </summary>
public void UpdateIsProcessed(int fbaInventoryLedgerDetailId, bool isProcessed)
{
UpdateIsProcessed(fbaInventoryLedgerDetailId, isProcessed, null);
}
/// <summary>
/// Set the record as processed, and an entry has been made into the stock sku transaction table
/// </summary>
public void UpdateIsProcessed(int fbaInventoryLedgerDetailId, int stockSkuTransactionId)
{
UpdateIsProcessed(fbaInventoryLedgerDetailId, true, stockSkuTransactionId);
}
/// <summary>
/// Use of the two methods above ensures that the transactionId can not be set when the isProcessed is false
/// </summary>
private void UpdateIsProcessed(int fbaInventoryLedgerDetailId, bool? isProcessed, int? stockSkuTransactionId)
{
string sql = @"
UPDATE
tblImportFbaInventoryLedgerDetail
SET
IsProcessed = @isProcessed
, StockSkuTransactionID = @stockSkuTransactionId
WHERE
(ImportFbaInventoryLedgerDetailID = @fbaInventoryLedgerDetailId)";
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
if (isProcessed == null) { cmd.Parameters.AddWithValue("@isProcessed", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@isProcessed", isProcessed); }
if (stockSkuTransactionId == null) { cmd.Parameters.AddWithValue("@stockSkuTransactionId", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@stockSkuTransactionId", stockSkuTransactionId); }
cmd.Parameters.AddWithValue("@fbaInventoryLedgerDetailId", fbaInventoryLedgerDetailId);
int i = cmd.ExecuteNonQuery();
if (i < 1)
throw new Exception("No row were effected by the update operation");
if (i > 1)
throw new Exception("Multiple rows were effected by the update operation");
}
}
}
}
}
@@ -0,0 +1,203 @@
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;
namespace bnhtrade.Core.Data.Database.Import
{
public class AmazonFbaInventoryReceipt : Connection
{
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public AmazonFbaInventoryReceipt()
{
}
public bool InsertByFlatFile(string filePath, DateTime startDate)
{
SqlConnection sqlConn;
SqlTransaction trans;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (trans = sqlConn.BeginTransaction())
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
int lineNumber = 1;
int lineErrorSkip = 0;
int lineOutsideScope = 0;
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
// create notification if amazon add extra headers
if (columnCount > 7)
{
log.LogWarning(
"Amazon have added a new column to their 'Fba Inventory Receipt' report, you may want to check this out."
);
}
int indexOfReceivedDate = Array.IndexOf(headers, "received-date");
int indexOfFnsku = Array.IndexOf(headers, "fnsku");
int indexOfSku = Array.IndexOf(headers, "sku");
int indexOfProductName = Array.IndexOf(headers, "product-name");
int indexOfQuantity = Array.IndexOf(headers, "quantity");
int indexOfFbaShipmentId = Array.IndexOf(headers, "fba-shipment-id");
int indexOfFulfillmentCenterId = Array.IndexOf(headers, "fulfillment-center-id");
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
lineNumber = lineNumber + 1;
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineErrorSkip = lineErrorSkip + 1;
log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else
{
//read values
DateTime receivedDate = DateTime.Parse(
items[indexOfReceivedDate],
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal);
//ensure line has recieved date <= startdate
// due to mws bug, downloaded report can contain records outside of the requested scope
if (receivedDate < startDate)
{
lineOutsideScope = lineOutsideScope + 1;
continue;
}
string fnsku = items[indexOfFnsku];
string sku = items[indexOfSku];
int quantity = int.Parse(items[indexOfQuantity]);
string fbaShipemntId = items[indexOfFbaShipmentId];
string fulfillmentCenterId = items[indexOfFulfillmentCenterId];
//insert report items
using (SqlCommand insertCmd = new SqlCommand(
"INSERT INTO tblImportFbaInventoryReceiptReport ( " +
"[received-date], [fnsku], [sku], [quantity], [fba-shipment-id], [fulfillment-center-id] ) " +
"VALUES ( " +
"@receivedDate, @fnsku, @sku, @quantity, @FbaShipmentId, @FulfillmentCenterId );"
, sqlConn, trans))
{
// add parameters
insertCmd.Parameters.AddWithValue("@receivedDate", receivedDate.ToUniversalTime());
insertCmd.Parameters.AddWithValue("@fnsku", fnsku);
insertCmd.Parameters.AddWithValue("@sku", sku);
insertCmd.Parameters.AddWithValue("@quantity", quantity);
insertCmd.Parameters.AddWithValue("@fbaShipmentId", fbaShipemntId);
insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", fulfillmentCenterId);
insertCmd.ExecuteNonQuery();
}
////check for duplicate line in db
//using (SqlCommand cmd = new SqlCommand(
// "SELECT ImportFbaInventoryReceiptReportID FROM tblImportFbaInventoryReceiptReport " +
// "WHERE [received-date]=@receivedDate AND [fnsku]=@fnsku AND [fba-shipment-id]=@fbaShipmentId AND [fulfillment-center-id]=@fulfillmentCenterId;"
// , sqlConn, trans))
//{
// cmd.Parameters.AddWithValue("@receivedDate", receivedDate);
// cmd.Parameters.AddWithValue("@fnsku", fnsku);
// cmd.Parameters.AddWithValue("@fbaShipmentId", fbaShipemntId);
// cmd.Parameters.AddWithValue("@fulfillmentCenterId", fulfillmentCenterId);
// using (SqlDataReader sqlReader = cmd.ExecuteReader())
// {
// if (sqlReader.HasRows == true)
// {
// lineDuplicateSkip = lineDuplicateSkip + 1;
// }
// else
// {
// }
// }
//}
}
}
// only commit if records all complete with no errors -- ommiting duplcates relies on all records from one day being committed together
trans.Commit();
Console.Write("\r");
log.LogInformation((lineNumber - (1 + lineErrorSkip + lineOutsideScope)) + " total report items inserted into db, " + lineOutsideScope + " item(s) outside of requested time scope where skipped.");
if (lineErrorSkip > 0)
{
log.LogError(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
}
}
}
catch (Exception ex)
{
log.LogError("Error running FbaInventoryReceiptReportImport, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
return true;
}
public DateTime ReadRecentDate()
{
DateTime lastRecordDate;
SqlConnection conn;
try
{
using (conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(
"SELECT Max([received-date]) AS MaxDate FROM tblImportFbaInventoryReceiptReport;"
, conn))
{
if (cmd.ExecuteScalar() == DBNull.Value)
{
// use first month started selling on Amazon
lastRecordDate = lastRecordDate = Constants.GetBusinessStartUtc();
}
else
{
lastRecordDate = ((DateTime)cmd.ExecuteScalar());
lastRecordDate = DateTime.SpecifyKind(lastRecordDate, DateTimeKind.Utc);
}
return lastRecordDate;
}
}
}
catch (Exception ex)
{
log.LogError("Error running FbaInventoryReceiptReportImport, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
}
}
}
@@ -0,0 +1,407 @@
using FikaAmazonAPI.AmazonSpApiSDK.Models.Finances;
using FikaAmazonAPI.ConstructFeed.Messages;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
//using System.Web.UI.WebControls;
namespace bnhtrade.Core.Data.Database.Import
{
public class AmazonFbaReimbursement : Connection
{
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public AmazonFbaReimbursement()
{
}
public bool InsertByFlatFile(string filePath)
{
SqlConnection sqlConn;
SqlTransaction trans;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (trans = sqlConn.BeginTransaction())
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
int lineNumber = 1;
int lineErrorSkip = 0;
int lineDuplicateSkip = 0;
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
int index01 = Array.IndexOf(headers, "approval-date");
int index02 = Array.IndexOf(headers, "reimbursement-id");
int index03 = Array.IndexOf(headers, "case-id");
int index04 = Array.IndexOf(headers, "amazon-order-id");
int index05 = Array.IndexOf(headers, "reason");
int index06 = Array.IndexOf(headers, "sku");
int index07 = Array.IndexOf(headers, "fnsku");
int index08 = Array.IndexOf(headers, "asin");
int index09 = Array.IndexOf(headers, "product-name");
int index10 = Array.IndexOf(headers, "condition");
int index11 = Array.IndexOf(headers, "currency-unit");
int index12 = Array.IndexOf(headers, "amount-per-unit");
int index13 = Array.IndexOf(headers, "amount-total");
int index14 = Array.IndexOf(headers, "quantity-reimbursed-cash");
int index15 = Array.IndexOf(headers, "quantity-reimbursed-inventory");
int index16 = Array.IndexOf(headers, "quantity-reimbursed-total");
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
lineNumber = lineNumber + 1;
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineErrorSkip = lineErrorSkip + 1;
log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else
{
//read values
string approvalDate = items[index01];
string reimbursementid = items[index02];
string caseid = items[index03];
string amazonOrderId = items[index04];
string reason = items[index05];
string sku = items[index06];
string fnsku = items[index07];
string asin = items[index08];
string productName = items[index09];
string condition = items[index10];
string currencyUnit = items[index11];
string amountPerUnit = items[index12];
string amountTotal = items[index13];
int quantityReimbursedCash = 0;
if (items[index14] != "")
{ quantityReimbursedCash = int.Parse(items[index14]); }
int quantityReimbursedInventory = 0;
if (items[index15] != "")
{ quantityReimbursedInventory = int.Parse(items[index15]); }
int quantityReimbursedTotal = 0;
if (items[index16] != "")
{ quantityReimbursedTotal = int.Parse(items[index16]); }
// totals checks
if (quantityReimbursedTotal == 0)
{
throw new Exception("Total Reimbursed total cannot be zero.");
}
if (quantityReimbursedCash + quantityReimbursedInventory != quantityReimbursedTotal)
{
throw new Exception("Reimbursed totals do not tally.");
}
// check number of times line conbination appears in file
int fileCount = 0;
int dbCount = 0;
using (var dupReader = new StreamReader(filePath))
{
dupReader.ReadLine(); // read header row
string dupFileRow;
while ((dupFileRow = dupReader.ReadLine()) != null)
{
string[] dupItems = dupFileRow.Split('\t');
if (dupItems.Length != columnCount)
{
// skip
}
else
{
if (items[index01] == dupItems[index01] &&
items[index02] == dupItems[index02] &&
items[index03] == dupItems[index03] &&
items[index04] == dupItems[index04] &&
items[index05] == dupItems[index05] &&
items[index07] == dupItems[index07] &&
items[index13] == dupItems[index13]
)
{
// count will always find at least one (itself)
fileCount = fileCount + 1;
}
}
}
}
//check for duplicate line in db
using (SqlCommand cmd = new SqlCommand(@"
SELECT
COUNT(ImportFbaReimbursementReportID) AS number
FROM
tblImportFbaReimbursementReport
WHERE
[reimbursement-id]=@reimbursementid
AND ([case-id]=@caseid OR [case-id] IS NULL)
AND ([amazon-order-id]=@amazonOrderId OR [amazon-order-id] IS NULL)
AND reason=@reason AND fnsku=@fnsku
AND [amount-total]=@amountTotal;
", sqlConn, trans))
{
if (reimbursementid == "") { cmd.Parameters.AddWithValue("@reimbursementid", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@reimbursementid", reimbursementid); }
if (caseid == "") { cmd.Parameters.AddWithValue("@caseid", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@caseid", caseid); }
if (amazonOrderId == "") { cmd.Parameters.AddWithValue("@amazonOrderId", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@amazonOrderId", amazonOrderId); }
if (reason == "") { cmd.Parameters.AddWithValue("@reason", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@reason", reason); }
if (fnsku == "") { cmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@fnsku", fnsku); }
if (amountTotal == "") { cmd.Parameters.AddWithValue("@amountTotal", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@amountTotal", decimal.Parse(amountTotal)); }
dbCount = (int)cmd.ExecuteScalar();
}
if (fileCount <= dbCount)
{
//skip
lineDuplicateSkip = lineDuplicateSkip + 1;
}
else
{
//insert report items
using (SqlCommand insertCmd = new SqlCommand(
"INSERT INTO tblImportFbaReimbursementReport ( " +
"[approval-date], [reimbursement-id], [case-id], [amazon-order-id], reason, " +
"sku, fnsku, asin, condition, [currency-unit], " +
"[amount-per-unit], [amount-total], [quantity-reimbursed-cash], [quantity-reimbursed-inventory], [quantity-reimbursed-total] )" +
"VALUES ( " +
"@approvalDate, @reimbursementid, @caseid, @amazonOrderId, @reason, " +
"@sku, @fnsku, @asin, @condition, @currencyUnit, " +
"@amountPerUnit, @amountTotal, @quantityReimbursedCash, @quantityReimbursedInventory, @quantityReimbursedTotal );"
, sqlConn, trans))
{
// add parameters
if (approvalDate == "") { insertCmd.Parameters.AddWithValue("@approvalDate", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@approvalDate", DateTime.Parse(approvalDate).ToUniversalTime()); }
if (reimbursementid == "") { insertCmd.Parameters.AddWithValue("@reimbursementid", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@reimbursementid", reimbursementid); }
if (caseid == "") { insertCmd.Parameters.AddWithValue("@caseid", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@caseid", caseid); }
if (amazonOrderId == "") { insertCmd.Parameters.AddWithValue("@amazonOrderId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@amazonOrderId", amazonOrderId); }
if (reason == "") { insertCmd.Parameters.AddWithValue("@reason", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@reason", reason); }
if (sku == "") { insertCmd.Parameters.AddWithValue("@sku", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@sku", sku); }
if (fnsku == "") { insertCmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@fnsku", fnsku); }
if (asin == "") { insertCmd.Parameters.AddWithValue("@asin", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@asin", asin); }
if (condition == "") { insertCmd.Parameters.AddWithValue("@condition", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@condition", condition); }
if (currencyUnit == "") { insertCmd.Parameters.AddWithValue("@currencyUnit", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@currencyUnit", currencyUnit); }
if (amountPerUnit == "") { insertCmd.Parameters.AddWithValue("@amountPerUnit", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@amountPerUnit", decimal.Parse(amountPerUnit)); }
if (amountTotal == "") { insertCmd.Parameters.AddWithValue("@amountTotal", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@amountTotal", decimal.Parse(amountTotal)); }
insertCmd.Parameters.AddWithValue("@quantityReimbursedCash", quantityReimbursedCash);
insertCmd.Parameters.AddWithValue("@quantityReimbursedInventory", quantityReimbursedInventory);
insertCmd.Parameters.AddWithValue("@quantityReimbursedTotal", quantityReimbursedTotal);
insertCmd.ExecuteNonQuery();
}
}
}
}
trans.Commit();
Console.Write("\r");
log.LogInformation((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
if (lineErrorSkip > 0)
{
log.LogError(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
}
}
}
catch (Exception ex)
{
log.LogError("Error running ImportFbaReimbursementReport method, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
return true;
}
public DateTime ReadRecentDate()
{
DateTime lastRecordDate;
SqlConnection sqlConn;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (SqlCommand cmd = new SqlCommand(
"SELECT Max([approval-date]) AS MaxDate FROM tblImportFbaReimbursementReport;"
, sqlConn))
{
if (cmd.ExecuteScalar() == DBNull.Value)
{
// use first month started selling on Amazon
lastRecordDate = lastRecordDate = Constants.GetBusinessStartUtc();
}
else
{
lastRecordDate = ((DateTime)cmd.ExecuteScalar());
lastRecordDate = DateTime.SpecifyKind(lastRecordDate, DateTimeKind.Utc);
}
return lastRecordDate;
}
}
}
catch (Exception ex)
{
log.LogError("Error running GetFbaReimbursementData, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
}
public List<Model.Import.FbaReimbursementReport> Read(bool? isProcessed = null)
{
var returnList = new List<Model.Import.FbaReimbursementReport>();
string sql = @"
SELECT
[ImportFbaReimbursementReportID]
,[approval-date]
,[reimbursement-id]
,[case-id]
,[amazon-order-id]
,[reason]
,[sku]
,[fnsku]
,[asin]
,[condition]
,[currency-unit]
,[amount-per-unit]
,[amount-total]
,[quantity-reimbursed-cash]
,[quantity-reimbursed-inventory]
,[quantity-reimbursed-total]
,[IsProcessed]
,[StockSkuTransactionID]
FROM [tblImportFbaReimbursementReport]
where (1=1) ";
if (isProcessed.HasValue)
{
if (isProcessed == true)
{
sql = sql + " AND (IsProcessed = 1) ";
}
else
{
sql = sql + " AND (IsProcessed = 0) ";
}
}
SqlConnection sqlConn;
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (SqlCommand cmd = new SqlCommand(sql, sqlConn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var item = new Model.Import.FbaReimbursementReport();
item.FbaReimbursementReportID = reader.GetInt32(0);
item.ApprovalDate = DateTime.SpecifyKind(reader.GetDateTime(1), DateTimeKind.Utc);
item.ReimbursementId = reader.GetString(2);
if (!reader.IsDBNull(3)) { item.CaseId = reader.GetString(3); }
if (!reader.IsDBNull(4)) { item.AmazonOrderId = reader.GetString(4); }
item.Reason = reader.GetString(5);
item.Sku = reader.GetString(6);
item.Fnsku = reader.GetString(7);
item.Asin = reader.GetString(8);
item.Condition = reader.GetString(9);
item.CurrencyUnit = reader.GetString(10);
item.AmountPerUnit = reader.GetDecimal(11);
item.AmountTotal = reader.GetDecimal(12);
item.QuantityReimbursedCash = reader.GetInt32(13);
item.QuantityReimbursedInventory = reader.GetInt32(14);
item.QuantityReimbursedTotal = reader.GetInt32(15);
item.IsProcessed = reader.GetBoolean(16);
if (!reader.IsDBNull(17)) { item.StockSkuTransactionID = reader.GetInt32(17); }
returnList.Add(item);
}
}
}
}
return returnList;
}
public void UpdateIsProcessed(int fbaReimbursementReportID, bool isProcessed, int? stockSkuTransactionId)
{
// consistancy checks
if (isProcessed == false && stockSkuTransactionId.HasValue)
{
throw new ArgumentException("Consistancy check error, incorrect argument combination passed to function");
}
string sql = @"
UPDATE
tblImportFbaReimbursementReport
SET
IsProcessed=@isProcessed
, StockSkuTransactionID=@transactionId
WHERE
ImportFbaReimbursementReportID=@importTableId;
";
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@importTableId", fbaReimbursementReportID);
cmd.Parameters.AddWithValue("@isProcessed", isProcessed);
if (stockSkuTransactionId.HasValue) { cmd.Parameters.AddWithValue("@transactionId", stockSkuTransactionId); }
else { cmd.Parameters.AddWithValue("@transactionId", DBNull.Value); }
cmd.ExecuteNonQuery();
}
}
}
}
}
@@ -0,0 +1,198 @@
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.Import
{
public class AmazonFbaRemovalOrder : Connection
{
Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public AmazonFbaRemovalOrder()
{
}
public bool InsertByFlatFile(string filePath)
{
SqlConnection sqlConn;
SqlTransaction trans;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (trans = sqlConn.BeginTransaction())
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
int lineNumber = 1;
int lineErrorSkip = 0;
int lineUpdate = 0;
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
int index01 = Array.IndexOf(headers, "request-date");
int index02 = Array.IndexOf(headers, "order-id");
int index03 = Array.IndexOf(headers, "order-type");
int index04 = Array.IndexOf(headers, "service-speed");
int index05 = Array.IndexOf(headers, "order-status");
int index06 = Array.IndexOf(headers, "last-updated-date");
int index07 = Array.IndexOf(headers, "sku");
int index08 = Array.IndexOf(headers, "fnsku");
int index09 = Array.IndexOf(headers, "disposition");
int index10 = Array.IndexOf(headers, "requested-quantity");
int index11 = Array.IndexOf(headers, "cancelled-quantity");
int index12 = Array.IndexOf(headers, "disposed-quantity");
int index13 = Array.IndexOf(headers, "shipped-quantity");
int index14 = Array.IndexOf(headers, "in-process-quantity");
int index15 = Array.IndexOf(headers, "removal-fee");
int index16 = Array.IndexOf(headers, "currency");
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
lineNumber = lineNumber + 1;
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineErrorSkip = lineErrorSkip + 1;
log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else
{
//read values
string requestDate = items[index01];
string orderId = items[index02];
string orderType = items[index03];
string serviceSpeed = items[index04];
string orderStatus = items[index05];
string lastUpdatedDate = items[index06];
string sku = items[index07];
string fnsku = items[index08];
string disposition = items[index09];
string requestedQuantity = items[index10];
string cancelledQuantity = items[index11];
string disposedQuantity = items[index12];
string shippedQuantity = items[index13];
string inProcessQuantity = items[index14];
string removalFee = items[index15];
string currency = items[index16];
if (orderId == "") { continue; }
int importTableId = 0;
//check for existing orderId
using (SqlCommand cmd = new SqlCommand(
"SELECT ImportFbaRemovalOrderReportID FROM tblImportFbaRemovalOrderReport WHERE [order-id]=@orderId AND fnsku=@fnsku AND disposition=@disposition;"
, sqlConn, trans))
{
cmd.Parameters.AddWithValue("@orderId", orderId);
cmd.Parameters.AddWithValue("@fnsku", fnsku);
cmd.Parameters.AddWithValue("@disposition", disposition);
importTableId = Convert.ToInt32(cmd.ExecuteScalar());
}
string sqlQuery;
if (importTableId > 0)
{
// update
lineUpdate = lineUpdate + 1;
sqlQuery =
"UPDATE tblImportFbaRemovalOrderReport SET " +
"[request-date]=@requestDate, [order-id]=@orderId, [order-type]=@orderType, [service-speed]=@serviceSpeed, " +
"[order-status]=@orderStatus, [last-updated-date]=@lastUpdatedDate, sku=@sku, fnsku=@fnsku, " +
"disposition=@disposition, [requested-quantity]=@requestedQuantity, [cancelled-quantity]=@cancelledQuantity, [disposed-quantity]=@disposedQuantity, " +
"[shipped-quantity]=@shippedQuantity, [in-process-quantity]=@inProcessQuantity, [removal-fee]=@removalFee, currency=@currency " +
"WHERE ImportFbaRemovalOrderReportID=@importTableId;";
}
else
{
// insert
sqlQuery =
"INSERT INTO tblImportFbaRemovalOrderReport ( " +
"[request-date], [order-id], [order-type], [service-speed], [order-status], [last-updated-date], sku, fnsku, " +
"disposition, [requested-quantity], [cancelled-quantity], [disposed-quantity], [shipped-quantity], [in-process-quantity], [removal-fee], currency ) " +
"VALUES ( " +
"@requestDate, @orderId, @orderType, @serviceSpeed, @orderStatus, @lastUpdatedDate, @sku, @fnsku, " +
"@disposition, @requestedQuantity, @cancelledQuantity, @disposedQuantity, @shippedQuantity, @inProcessQuantity, @removalFee, @currency );";
}
// make the update/insert
using (SqlCommand cmd = new SqlCommand(sqlQuery, sqlConn, trans))
{
// add parameters
cmd.Parameters.AddWithValue("@importTableId", importTableId);
if (requestDate == "") { cmd.Parameters.AddWithValue("@requestDate", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@requestDate", DateTime.Parse(requestDate).ToUniversalTime()); }
if (orderId == "") { cmd.Parameters.AddWithValue("@orderId", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@orderId", orderId); }
if (orderType == "") { cmd.Parameters.AddWithValue("@orderType", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@orderType", orderType); }
if (serviceSpeed == "") { cmd.Parameters.AddWithValue("@serviceSpeed", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@serviceSpeed", serviceSpeed); }
if (orderStatus == "") { cmd.Parameters.AddWithValue("@orderStatus", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@orderStatus", orderStatus); }
if (lastUpdatedDate == "") { cmd.Parameters.AddWithValue("@lastUpdatedDate", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@lastUpdatedDate", DateTime.Parse(lastUpdatedDate).ToUniversalTime()); }
if (sku == "") { cmd.Parameters.AddWithValue("@sku", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@sku", sku); }
if (fnsku == "") { cmd.Parameters.AddWithValue("@fnsku", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@fnsku", fnsku); }
if (disposition == "") { cmd.Parameters.AddWithValue("@disposition", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@disposition", disposition); }
if (requestedQuantity == "") { cmd.Parameters.AddWithValue("@requestedQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@requestedQuantity", int.Parse(requestedQuantity)); }
if (cancelledQuantity == "") { cmd.Parameters.AddWithValue("@cancelledQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@cancelledQuantity", int.Parse(cancelledQuantity)); }
if (disposedQuantity == "") { cmd.Parameters.AddWithValue("@disposedQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@disposedQuantity", int.Parse(disposedQuantity)); }
if (shippedQuantity == "") { cmd.Parameters.AddWithValue("@shippedQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@shippedQuantity", int.Parse(shippedQuantity)); }
if (inProcessQuantity == "") { cmd.Parameters.AddWithValue("@inProcessQuantity", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@inProcessQuantity", int.Parse(inProcessQuantity)); }
if (removalFee == "") { cmd.Parameters.AddWithValue("@removalFee", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@removalFee", decimal.Parse(removalFee)); }
if (currency == "") { cmd.Parameters.AddWithValue("@currency", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@currency", currency); }
cmd.ExecuteNonQuery();
}
}
}
trans.Commit();
Console.Write("\r");
log.LogInformation("ImportFbaRemovalOrderReport() " + (lineNumber - (1 + lineErrorSkip + lineUpdate)) + " records created, " + lineUpdate + " records updated.");
if (lineErrorSkip > 0)
{
log.LogInformation(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
}
}
}
catch (Exception ex)
{
log.LogError("Error running ImportFbaRemovalOrderReport method, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
return true;
}
}
}
@@ -0,0 +1,623 @@
using Dapper;
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.Import
{
public class AmazonFbaSaleShipment : Connection
{
private Logic.Log.LogEvent log = new Logic.Log.LogEvent();
public AmazonFbaSaleShipment()
{
}
// seems amazon have reduced the number of columns in the table significantly, probably due data protection. This is the
// old one
public bool InsertByFlatFile(string filePath)
{
SqlConnection sqlConn;
SqlTransaction trans;
try
{
using (sqlConn = new SqlConnection(SqlConnectionString))
{
sqlConn.Open();
using (trans = sqlConn.BeginTransaction())
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
int lineNumber = 1;
int lineErrorSkip = 0;
int lineDuplicateSkip = 0;
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
int index01 = Array.IndexOf(headers, "amazon-order-id");
int index02 = Array.IndexOf(headers, "merchant-order-id");
int index03 = Array.IndexOf(headers, "shipment-id");
int index04 = Array.IndexOf(headers, "shipment-item-id");
int index05 = Array.IndexOf(headers, "amazon-order-item-id");
int index06 = Array.IndexOf(headers, "merchant-order-item-id");
int index07 = Array.IndexOf(headers, "purchase-date");
int index08 = Array.IndexOf(headers, "payments-date");
int index09 = Array.IndexOf(headers, "shipment-date");
int index10 = Array.IndexOf(headers, "reporting-date");
int index11 = Array.IndexOf(headers, "buyer-email");
int index12 = Array.IndexOf(headers, "buyer-name");
int index13 = Array.IndexOf(headers, "sku");
int index14 = Array.IndexOf(headers, "quantity-shipped");
int index15 = Array.IndexOf(headers, "currency");
int index16 = Array.IndexOf(headers, "item-price");
int index17 = Array.IndexOf(headers, "item-tax");
int index18 = Array.IndexOf(headers, "shipping-price");
int index19 = Array.IndexOf(headers, "shipping-tax");
int index20 = Array.IndexOf(headers, "gift-wrap-price");
int index21 = Array.IndexOf(headers, "gift-wrap-tax");
int index22 = Array.IndexOf(headers, "recipient-name");
int index23 = Array.IndexOf(headers, "ship-address-1");
int index24 = Array.IndexOf(headers, "ship-address-2");
int index25 = Array.IndexOf(headers, "ship-address-3");
int index26 = Array.IndexOf(headers, "ship-city");
int index27 = Array.IndexOf(headers, "ship-state");
int index28 = Array.IndexOf(headers, "ship-postal-code");
int index29 = Array.IndexOf(headers, "ship-country");
int index30 = Array.IndexOf(headers, "ship-phone-number");
int index31 = Array.IndexOf(headers, "bill-address-1");
int index32 = Array.IndexOf(headers, "bill-address-2");
int index33 = Array.IndexOf(headers, "bill-address-3");
int index34 = Array.IndexOf(headers, "bill-city");
int index35 = Array.IndexOf(headers, "bill-state");
int index36 = Array.IndexOf(headers, "bill-postal-code");
int index37 = Array.IndexOf(headers, "bill-country");
int index38 = Array.IndexOf(headers, "item-promotion-discount");
int index39 = Array.IndexOf(headers, "ship-promotion-discount");
int index40 = Array.IndexOf(headers, "fulfillment-center-id");
int index41 = Array.IndexOf(headers, "fulfillment-channel");
int index42 = Array.IndexOf(headers, "sales-channel");
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
lineNumber = lineNumber + 1;
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineErrorSkip = lineErrorSkip + 1;
log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else
{
//read values
string amazonOrderId = items[index01];
string merchantOrderid = items[index02];
string shipmentId = items[index03];
string shipmentItemId = items[index04];
string amazonOrderItemId = items[index05];
string merchantOrderItemId = items[index06];
DateTime purchaseDate = DateTime.Parse(items[index07]);
DateTime paymentsDate = DateTime.Parse(items[index08]);
DateTime shipmentDate = DateTime.Parse(items[index09]);
DateTime reportingDate = DateTime.Parse(items[index10]);
string buyerEmail = items[index11];
string buyerName = items[index12];
string sku = items[index13];
int quantityShipped = Int32.Parse(items[index14]);
string currency = items[index15];
decimal itemPrice = decimal.Parse(items[index16]);
decimal itemTax = decimal.Parse(items[index17]);
decimal shippingPrice = decimal.Parse(items[index18]);
decimal shippingTax = decimal.Parse(items[index19]);
decimal giftWrapPrice = decimal.Parse(items[index20]);
decimal giftWrapTax = decimal.Parse(items[index21]);
string recipientName = items[index22];
string shipAddress1 = items[index23];
string shipAddress2 = items[index24];
string shipAddress3 = items[index25];
string shipCity = items[index26];
string shipState = items[index27];
string shipPostalCode = items[index28];
string shipCountry = items[index29];
string shipPhoneNumber = items[index30];
string billAddress1 = items[index31];
string billAddress2 = items[index32];
string billAddress3 = items[index33];
string billCity = items[index34];
string billState = items[index35];
string billPostalCode = items[index36];
string billCountry = items[index37];
string itemPromotionDiscount = items[index38];
string shipPromotionDiscount = items[index39];
string fulfillmentCenterId = items[index40];
string fulfillmentChannel = items[index41];
string salesChannel = items[index42];
//check for duplicate line in db
using (SqlCommand cmd = new SqlCommand(
"SELECT ImportFbaSaleShipmentID FROM tblImportFbaSaleShipment " +
"WHERE [shipment-item-id]=@shipmentItemId;"
, sqlConn, trans))
{
cmd.Parameters.AddWithValue("@shipmentItemId", shipmentItemId);
using (SqlDataReader sqlReader = cmd.ExecuteReader())
{
if (sqlReader.Read())
{
lineDuplicateSkip = lineDuplicateSkip + 1;
}
else
{
//insert report items
//start transaction
using (SqlCommand insertCmd = new SqlCommand(
"INSERT INTO tblImportFbaSaleShipment ( " +
"[amazon-order-id], [merchant-order-id], [shipment-id], [shipment-item-id], [amazon-order-item-id], " +
"[merchant-order-item-id], [purchase-date], [payments-date], [shipment-date], [reporting-date], " +
"[buyer-email], [buyer-name], sku, [quantity-shipped], currency, " +
"[item-price], [item-tax], [shipping-price], [shipping-tax], [gift-wrap-price], " +
"[gift-wrap-tax], [recipient-name], [ship-address-1], [ship-address-2], [ship-address-3], " +
"[ship-city], [ship-state], [ship-postal-code], [ship-country], [ship-phone-number], " +
"[bill-address-1], [bill-address-2], [bill-address-3], [bill-city], [bill-state], " +
"[bill-postal-code], [bill-country], [item-promotion-discount], [ship-promotion-discount], [fulfillment-center-id], " +
"[fulfillment-channel], [sales-channel] ) " +
"VALUES ( " +
"@amazonOrderId, @merchantOrderid, @shipmentId, @shipmentItemId, @amazonOrderItemId, " +
"@merchantOrderItemId, @purchaseDate, @paymentsDate, @shipmentDate, @reportingDate, " +
"@buyerEmail, @buyerName, @sku, @quantityShipped, @currency, " +
"@itemPrice, @itemTax, @shippingPrice, @shippingTax, @giftWrapPrice, " +
"@giftWrapTax, @recipientName, @shipAddress1, @shipAddress2, @shipAddress3, " +
"@shipCity, @shipState, @shipPostalCode, @shipCountry, @shipPhoneNumber, " +
"@billAddress1, @billAddress2, @billAddress3, @billCity, @billState, " +
"@billPostalCode, @billCountry, @itemPromotionDiscount, @shipPromotionDiscount, @fulfillmentCenterId, " +
"@fulfillmentChannel, @salesChannel );"
, sqlConn, trans))
{
// add parameters
if (amazonOrderId == "") { insertCmd.Parameters.AddWithValue("@amazonOrderId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@amazonOrderId", amazonOrderId); }
if (merchantOrderid == "") { insertCmd.Parameters.AddWithValue("@merchantOrderid", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@merchantOrderid", merchantOrderid); }
if (shipmentId == "") { insertCmd.Parameters.AddWithValue("@shipmentId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipmentId", shipmentId); }
if (shipmentItemId == "") { insertCmd.Parameters.AddWithValue("@shipmentItemId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipmentItemId", shipmentItemId); }
if (amazonOrderItemId == "") { insertCmd.Parameters.AddWithValue("@amazonOrderItemId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@amazonOrderItemId", amazonOrderItemId); }
if (merchantOrderItemId == "") { insertCmd.Parameters.AddWithValue("@merchantOrderItemId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@merchantOrderItemId", merchantOrderItemId); }
if (purchaseDate == DateTime.MinValue) { insertCmd.Parameters.AddWithValue("@purchaseDate", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@purchaseDate", purchaseDate.ToUniversalTime()); }
if (paymentsDate == DateTime.MinValue) { insertCmd.Parameters.AddWithValue("@paymentsDate", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@paymentsDate", paymentsDate.ToUniversalTime()); }
if (shipmentDate == DateTime.MinValue) { insertCmd.Parameters.AddWithValue("@shipmentDate", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipmentDate", shipmentDate.ToUniversalTime()); }
if (reportingDate == DateTime.MinValue) { insertCmd.Parameters.AddWithValue("@reportingDate", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@reportingDate", reportingDate.ToUniversalTime()); }
if (buyerEmail == "") { insertCmd.Parameters.AddWithValue("@buyerEmail", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@buyerEmail", buyerEmail); }
if (buyerName == "") { insertCmd.Parameters.AddWithValue("@buyerName", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@buyerName", buyerName); }
if (sku == "") { insertCmd.Parameters.AddWithValue("@sku", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@sku", sku); }
insertCmd.Parameters.AddWithValue("@quantityShipped", quantityShipped);
if (currency == "") { insertCmd.Parameters.AddWithValue("@currency", DBNull.Value); }
insertCmd.Parameters.AddWithValue("@currency", currency);
insertCmd.Parameters.AddWithValue("@itemPrice", itemPrice);
insertCmd.Parameters.AddWithValue("@itemTax", itemTax);
insertCmd.Parameters.AddWithValue("@shippingPrice", shippingPrice);
insertCmd.Parameters.AddWithValue("@shippingTax", shippingTax);
insertCmd.Parameters.AddWithValue("@giftWrapPrice", giftWrapPrice);
insertCmd.Parameters.AddWithValue("@giftWrapTax", giftWrapTax);
if (recipientName == "") { insertCmd.Parameters.AddWithValue("@recipientName", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@recipientName", recipientName); }
if (shipAddress1 == "") { insertCmd.Parameters.AddWithValue("@shipAddress1", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipAddress1", shipAddress1); }
if (shipAddress2 == "") { insertCmd.Parameters.AddWithValue("@shipAddress2", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipAddress2", shipAddress2); }
if (shipAddress3 == "") { insertCmd.Parameters.AddWithValue("@shipAddress3", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipAddress3", shipAddress3); }
if (shipCity == "") { insertCmd.Parameters.AddWithValue("@shipCity", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipCity", shipCity); }
if (shipState == "") { insertCmd.Parameters.AddWithValue("@shipState", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipState", shipState); }
if (shipPostalCode == "") { insertCmd.Parameters.AddWithValue("@shipPostalCode", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipPostalCode", shipPostalCode); }
if (shipCountry == "") { insertCmd.Parameters.AddWithValue("@shipCountry", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipCountry", shipCountry); }
if (shipPhoneNumber == "") { insertCmd.Parameters.AddWithValue("@shipPhoneNumber", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipPhoneNumber", shipPhoneNumber); }
if (billAddress1 == "") { insertCmd.Parameters.AddWithValue("@billAddress1", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@billAddress1", billAddress1); }
if (billAddress2 == "") { insertCmd.Parameters.AddWithValue("@billAddress2", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@billAddress2", billAddress2); }
if (billAddress3 == "") { insertCmd.Parameters.AddWithValue("@billAddress3", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@billAddress3", billAddress3); }
if (billCity == "") { insertCmd.Parameters.AddWithValue("@billCity", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@billCity", billCity); }
if (billState == "") { insertCmd.Parameters.AddWithValue("@billState", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@billState", billState); }
if (billPostalCode == "") { insertCmd.Parameters.AddWithValue("@billPostalCode", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@billPostalCode", billPostalCode); }
if (billCountry == "") { insertCmd.Parameters.AddWithValue("@billCountry", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@billCountry", billCountry); }
if (itemPromotionDiscount == "") { insertCmd.Parameters.AddWithValue("@itemPromotionDiscount", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@itemPromotionDiscount", itemPromotionDiscount); }
if (shipPromotionDiscount == "") { insertCmd.Parameters.AddWithValue("@shipPromotionDiscount", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@shipPromotionDiscount", shipPromotionDiscount); }
if (fulfillmentCenterId == "") { insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", fulfillmentCenterId); }
if (fulfillmentChannel == "") { insertCmd.Parameters.AddWithValue("@fulfillmentChannel", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@fulfillmentChannel", fulfillmentChannel); }
if (salesChannel == "") { insertCmd.Parameters.AddWithValue("@salesChannel", DBNull.Value); }
else { insertCmd.Parameters.AddWithValue("@salesChannel", salesChannel); }
insertCmd.ExecuteNonQuery();
}
}
}
}
}
}
trans.Commit();
Console.Write("\r");
log.LogInformation((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
if (lineErrorSkip > 0)
{
log.LogError(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
}
}
}
catch (Exception ex)
{
log.LogError("Error running FbaInventoryReceiptReportImport, no records were commited",
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
);
throw ex;
}
return true;
}
//public bool InsertByFlatFileold(string filePath)
//{
// SqlConnection sqlConn;
// SqlTransaction trans;
// //try
// //{
// using (sqlConn = new SqlConnection(SqlConnectionString))
// {
// sqlConn.Open();
// using (trans = sqlConn.BeginTransaction())
// using (var reader = new StreamReader(filePath))
// {
// //read file one line at a time and insert data into table if required
// int lineNumber = 1;
// int lineErrorSkip = 0;
// int lineDuplicateSkip = 0;
// // read header and retrive information
// string headerRow = reader.ReadLine();
// string[] headers = headerRow.Split('\t');
// int columnCount = headers.Length;
// int index01 = Array.IndexOf(headers, "amazon-order-id");
// int index09 = Array.IndexOf(headers, "shipment-date");
// int index13 = Array.IndexOf(headers, "sku");
// int index14 = Array.IndexOf(headers, "quantity");
// int index15 = Array.IndexOf(headers, "currency");
// int index16 = Array.IndexOf(headers, "item-price-per-unit");
// int index18 = Array.IndexOf(headers, "shipping-price");
// int index20 = Array.IndexOf(headers, "gift-wrap-price");
// int index26 = Array.IndexOf(headers, "ship-city");
// int index27 = Array.IndexOf(headers, "ship-state");
// int index28 = Array.IndexOf(headers, "ship-postal-code");
// int index40 = Array.IndexOf(headers, "fulfillment-center-id");
// string fileRow;
// while ((fileRow = reader.ReadLine()) != null)
// {
// lineNumber = lineNumber + 1;
// Console.Write("\rParsing record: " + lineNumber);
// //split line into array
// string[] items = fileRow.Split('\t');
// if (items.Length != columnCount)
// {
// // skip line
// lineErrorSkip = lineErrorSkip + 1;
// new Logic.Log.LogEvent().EventLogInsert(
// "Line #" + lineNumber + " skipped due to no enough element in row.",
// 2,
// filePath
// );
// }
// else
// {
// //read values
// string amazonOrderId = items[index01];
// DateTime shipmentDate = DateTime.Parse(items[index09]);
// string sku = items[index13];
// int quantityShipped = Int32.Parse(items[index14]);
// string currency = items[index15];
// decimal itemPrice = decimal.Parse(items[index16]);
// decimal shippingPrice = decimal.Parse(items[index18]);
// decimal giftWrapPrice = decimal.Parse(items[index20]);
// string shipCity = items[index26];
// string shipState = items[index27];
// string shipPostalCode = items[index28];
// string fulfillmentCenterId = items[index40];
// //check for duplicate line in db
// using (SqlCommand cmd = new SqlCommand(
// "SELECT ImportFbaSaleShipmentID FROM tblImportFbaSaleShipment " +
// "WHERE [shipment-item-id]=@shipmentItemId;"
// , sqlConn, trans))
// {
// cmd.Parameters.AddWithValue("@shipmentItemId", shipmentItemId);
// using (SqlDataReader sqlReader = cmd.ExecuteReader())
// {
// if (sqlReader.Read())
// {
// lineDuplicateSkip = lineDuplicateSkip + 1;
// }
// else
// {
// //insert report items
// //start transaction
// using (SqlCommand insertCmd = new SqlCommand(
// "INSERT INTO tblImportFbaSaleShipment ( " +
// "[amazon-order-id], [merchant-order-id], [shipment-id], [shipment-item-id], [amazon-order-item-id], " +
// "[merchant-order-item-id], [purchase-date], [payments-date], [shipment-date], [reporting-date], " +
// "[buyer-email], [buyer-name], sku, [quantity-shipped], currency, " +
// "[item-price], [item-tax], [shipping-price], [shipping-tax], [gift-wrap-price], " +
// "[gift-wrap-tax], [recipient-name], [ship-address-1], [ship-address-2], [ship-address-3], " +
// "[ship-city], [ship-state], [ship-postal-code], [ship-country], [ship-phone-number], " +
// "[bill-address-1], [bill-address-2], [bill-address-3], [bill-city], [bill-state], " +
// "[bill-postal-code], [bill-country], [item-promotion-discount], [ship-promotion-discount], [fulfillment-center-id], " +
// "[fulfillment-channel], [sales-channel] ) " +
// "VALUES ( " +
// "@amazonOrderId, @merchantOrderid, @shipmentId, @shipmentItemId, @amazonOrderItemId, " +
// "@merchantOrderItemId, @purchaseDate, @paymentsDate, @shipmentDate, @reportingDate, " +
// "@buyerEmail, @buyerName, @sku, @quantityShipped, @currency, " +
// "@itemPrice, @itemTax, @shippingPrice, @shippingTax, @giftWrapPrice, " +
// "@giftWrapTax, @recipientName, @shipAddress1, @shipAddress2, @shipAddress3, " +
// "@shipCity, @shipState, @shipPostalCode, @shipCountry, @shipPhoneNumber, " +
// "@billAddress1, @billAddress2, @billAddress3, @billCity, @billState, " +
// "@billPostalCode, @billCountry, @itemPromotionDiscount, @shipPromotionDiscount, @fulfillmentCenterId, " +
// "@fulfillmentChannel, @salesChannel );"
// , sqlConn, trans))
// {
// // add parameters
// if (amazonOrderId == "") { insertCmd.Parameters.AddWithValue("@amazonOrderId", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@amazonOrderId", amazonOrderId); }
// if (merchantOrderid == "") { insertCmd.Parameters.AddWithValue("@merchantOrderid", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@merchantOrderid", merchantOrderid); }
// if (shipmentId == "") { insertCmd.Parameters.AddWithValue("@shipmentId", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipmentId", shipmentId); }
// if (shipmentItemId == "") { insertCmd.Parameters.AddWithValue("@shipmentItemId", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipmentItemId", shipmentItemId); }
// if (amazonOrderItemId == "") { insertCmd.Parameters.AddWithValue("@amazonOrderItemId", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@amazonOrderItemId", amazonOrderItemId); }
// if (merchantOrderItemId == "") { insertCmd.Parameters.AddWithValue("@merchantOrderItemId", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@merchantOrderItemId", merchantOrderItemId); }
// if (purchaseDate == DateTime.MinValue) { insertCmd.Parameters.AddWithValue("@purchaseDate", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@purchaseDate", purchaseDate.ToUniversalTime()); }
// if (paymentsDate == DateTime.MinValue) { insertCmd.Parameters.AddWithValue("@paymentsDate", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@paymentsDate", paymentsDate.ToUniversalTime()); }
// if (shipmentDate == DateTime.MinValue) { insertCmd.Parameters.AddWithValue("@shipmentDate", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipmentDate", shipmentDate.ToUniversalTime()); }
// if (reportingDate == DateTime.MinValue) { insertCmd.Parameters.AddWithValue("@reportingDate", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@reportingDate", reportingDate.ToUniversalTime()); }
// if (buyerEmail == "") { insertCmd.Parameters.AddWithValue("@buyerEmail", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@buyerEmail", buyerEmail); }
// if (buyerName == "") { insertCmd.Parameters.AddWithValue("@buyerName", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@buyerName", buyerName); }
// if (sku == "") { insertCmd.Parameters.AddWithValue("@sku", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@sku", sku); }
// insertCmd.Parameters.AddWithValue("@quantityShipped", quantityShipped);
// if (currency == "") { insertCmd.Parameters.AddWithValue("@currency", DBNull.Value); }
// insertCmd.Parameters.AddWithValue("@currency", currency);
// insertCmd.Parameters.AddWithValue("@itemPrice", itemPrice);
// insertCmd.Parameters.AddWithValue("@itemTax", itemTax);
// insertCmd.Parameters.AddWithValue("@shippingPrice", shippingPrice);
// insertCmd.Parameters.AddWithValue("@shippingTax", shippingTax);
// insertCmd.Parameters.AddWithValue("@giftWrapPrice", giftWrapPrice);
// insertCmd.Parameters.AddWithValue("@giftWrapTax", giftWrapTax);
// if (recipientName == "") { insertCmd.Parameters.AddWithValue("@recipientName", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@recipientName", recipientName); }
// if (shipAddress1 == "") { insertCmd.Parameters.AddWithValue("@shipAddress1", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipAddress1", shipAddress1); }
// if (shipAddress2 == "") { insertCmd.Parameters.AddWithValue("@shipAddress2", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipAddress2", shipAddress2); }
// if (shipAddress3 == "") { insertCmd.Parameters.AddWithValue("@shipAddress3", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipAddress3", shipAddress3); }
// if (shipCity == "") { insertCmd.Parameters.AddWithValue("@shipCity", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipCity", shipCity); }
// if (shipState == "") { insertCmd.Parameters.AddWithValue("@shipState", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipState", shipState); }
// if (shipPostalCode == "") { insertCmd.Parameters.AddWithValue("@shipPostalCode", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipPostalCode", shipPostalCode); }
// if (shipCountry == "") { insertCmd.Parameters.AddWithValue("@shipCountry", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipCountry", shipCountry); }
// if (shipPhoneNumber == "") { insertCmd.Parameters.AddWithValue("@shipPhoneNumber", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipPhoneNumber", shipPhoneNumber); }
// if (billAddress1 == "") { insertCmd.Parameters.AddWithValue("@billAddress1", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@billAddress1", billAddress1); }
// if (billAddress2 == "") { insertCmd.Parameters.AddWithValue("@billAddress2", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@billAddress2", billAddress2); }
// if (billAddress3 == "") { insertCmd.Parameters.AddWithValue("@billAddress3", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@billAddress3", billAddress3); }
// if (billCity == "") { insertCmd.Parameters.AddWithValue("@billCity", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@billCity", billCity); }
// if (billState == "") { insertCmd.Parameters.AddWithValue("@billState", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@billState", billState); }
// if (billPostalCode == "") { insertCmd.Parameters.AddWithValue("@billPostalCode", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@billPostalCode", billPostalCode); }
// if (billCountry == "") { insertCmd.Parameters.AddWithValue("@billCountry", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@billCountry", billCountry); }
// if (itemPromotionDiscount == "") { insertCmd.Parameters.AddWithValue("@itemPromotionDiscount", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@itemPromotionDiscount", itemPromotionDiscount); }
// if (shipPromotionDiscount == "") { insertCmd.Parameters.AddWithValue("@shipPromotionDiscount", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@shipPromotionDiscount", shipPromotionDiscount); }
// if (fulfillmentCenterId == "") { insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@fulfillmentCenterId", fulfillmentCenterId); }
// if (fulfillmentChannel == "") { insertCmd.Parameters.AddWithValue("@fulfillmentChannel", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@fulfillmentChannel", fulfillmentChannel); }
// if (salesChannel == "") { insertCmd.Parameters.AddWithValue("@salesChannel", DBNull.Value); }
// else { insertCmd.Parameters.AddWithValue("@salesChannel", salesChannel); }
// insertCmd.ExecuteNonQuery();
// }
// }
// }
// }
// }
// }
// trans.Commit();
// Console.Write("\r");
// new Logic.Log.LogEvent().EventLogInsert((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
// if (lineErrorSkip > 0)
// {
// new Logic.Log.LogEvent().EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
// }
// }
// }
// //}
// //catch (Exception ex)
// //{
// // new Logic.Log.LogEvent().EventLogInsert("Error running FbaInventoryReceiptReportImport, no records were commited",
// // 1,
// // ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
// // );
// // throw ex;
// //}
// return true;
//}
public Dictionary<string, decimal> ReadMaxSalePrice(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> ReadSaleCount(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);
}
}
}
}
@@ -0,0 +1,136 @@
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.Log
{
public class DateTimeLog : Connection
{
public DateTimeLog()
{
}
/// <summary>
/// Gets the Date and Time by a unique string.
/// </summary>
/// <param name="logDateTimeId">Unique string</param>
/// <returns>UTC DateTime</returns>
public DateTime GetDateTimeUtc(string logDateTimeId)
{
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
SELECT
DateTimeUtc
FROM
tblLogDateTime
WHERE
LogDateTimeID = @logDateTimeID
", conn))
{
cmd.Parameters.AddWithValue("@logDateTimeID", logDateTimeId);
object obj = cmd.ExecuteScalar();
if (obj == null || obj == DBNull.Value)
{
throw new Exception("Id not found.");
}
else
{
DateTime returnDt = (DateTime)obj;
return DateTime.SpecifyKind(returnDt, DateTimeKind.Utc);
}
}
}
}
public void SetDateTimeUtc(string logDateTimeID, DateTime utcDateTime)
{
if (utcDateTime.Kind != DateTimeKind.Utc)
{
throw new Exception("Datetime kind is not set to UTC");
}
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
UPDATE tblLogDateTime
SET
DateTimeUtc = @utcDateTime
,RecordModified = @recordModified
WHERE
LogDateTimeID = @logDateTimeID
", conn))
{
cmd.Parameters.AddWithValue("@utcDateTime", utcDateTime.ToUniversalTime());
cmd.Parameters.AddWithValue("@recordModified", DateTime.UtcNow.ToUniversalTime());
cmd.Parameters.AddWithValue("@logDateTimeID", logDateTimeID);
int count = cmd.ExecuteNonQuery();
if (count == 0)
{
throw new Exception("Error, failed to update record.");
}
}
}
}
public void NewDateTimeUtc(string LogDateTimeId, DateTime utcDateTime, string comments = null)
{
if (string.IsNullOrWhiteSpace(LogDateTimeId))
{ throw new Exception("Invalid LogDateTimeID"); }
if (utcDateTime.Kind != DateTimeKind.Utc)
{
throw new Exception("Datetime kind is not set to UTC");
}
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblLogDateTime (
LogDateTimeID
,DateTimeUtc
,Comments
,RecordModified
,RecordCreated
)
VALUES (
@logDateTimeId
,@utcDateTime
,@comments
,@recordModified
,@recordCreated
)
", conn))
{
var nowTime = DateTime.UtcNow;
cmd.Parameters.AddWithValue("@logDateTimeId", LogDateTimeId);
cmd.Parameters.AddWithValue("@utcDateTime", utcDateTime.ToUniversalTime());
if (string.IsNullOrWhiteSpace(comments)) { cmd.Parameters.AddWithValue("@comments", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@comments", comments); }
cmd.Parameters.AddWithValue("@recordModified", nowTime.ToUniversalTime());
cmd.Parameters.AddWithValue("@recordCreated", nowTime.ToUniversalTime());
int count = cmd.ExecuteNonQuery();
if (count == 0)
{
throw new Exception("Error updating, no records where effected.");
}
}
}
}
}
}
@@ -0,0 +1,81 @@
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.Log
{
public class LogEvent : Connection
{
public LogEvent()
{
}
protected void DatabaseLogInsert
(string detailShort, int eventType, string detailLong, DateTime eventDateTime, bool consolePrint = true)
{
if (consolePrint)
{
if (string.IsNullOrWhiteSpace(detailLong))
{ UI.Console.WriteLine(detailShort); }
else { UI.Console.WriteLine(detailShort + Environment.NewLine + detailLong); }
}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// need to remove this section once code has been rewritten, writing to console will be handled
// in the business layer
// login credentials only allow insert on log table
string userId = "Log_bnhtrade";
string password = "52ya9dky55cniyynwro5e48mV9";
string sqlConnectionString =
"Data Source=SQL-Server;Initial Catalog=e2A;Persist Security Info=TRUE;User ID=" + userId +
";Password=" + password + ";MultipleActiveResultSets=TRUE";
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress))
{
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
{
sqlConn.Open();
try
{
using (SqlCommand cmd = new SqlCommand(@"
INSERT INTO tblLogEvent (
EventDateTime
,LogEventTypeID
,LogEventSourceID
,Detail
,DetailLong
)
VALUES (
@eventDateTime
,@eventType
,1
,@detailShort
,@detailLong
)
", sqlConn))
{
cmd.Parameters.AddWithValue("@eventDateTime", eventDateTime);
cmd.Parameters.AddWithValue("@eventType", eventType);
cmd.Parameters.AddWithValue("@detailShort", detailShort);
if (detailLong == null) { cmd.Parameters.AddWithValue("@detailLong", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@detailLong", detailLong); }
cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
UI.Console.WriteLine("WTF!!!! Error with error logging, jobs foooked!");
throw ex;
}
scope.Complete();
}
}
}
}
}
@@ -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()
{
}
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();
}
}
}
}
}
@@ -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()
{
}
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;
}
}
}
}
}
}
@@ -0,0 +1,215 @@
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 ReadProduct : Connection
{
private List<string> filterByAsin;
private List<int> filterByProductId;
private Data.Database.SqlWhereBuilder sqlWhereBuilder = new SqlWhereBuilder();
public ReadProduct()
{
Innit();
}
public List<string> FilterByAsin
{
get { return filterByAsin; }
set
{
if (value == null) { filterByAsin = new List<string>(); }
else { filterByAsin = value; }
}
}
public List<int> FilterByProductId
{
get { return filterByProductId; }
set
{
if (value == null) { filterByProductId = new List<int>(); }
else { filterByProductId = value; }
}
}
public void Innit()
{
FilterByProductId = new List<int>();
FilterByAsin = new List<string>();
}
public List<Model.Product.ProductInfo> ExecuteQuery()
{
var returnList = new List<Model.Product.ProductInfo>();
// build SQL string
string sqlString = @"
SELECT [prdProductID]
,[prdTitle]
,[TitleSuffix]
,[ProductCategoryID]
,[ProductCategorySubID]
,[ReleaseDate]
,[RecommendedRetailPrice]
,[prdMaxPrice]
,[prdAmazonASIN]
,[Manufacturer]
,[PackageWeightKilogram]
,[PackageDimensionHeightMeter]
,[PackageDimensionWidthMeter]
,[PackageDimensionLengthMeter]
,[CatId]
,[ProductProcurementControlID]
,[ManualCompetativePriceUpdate]
,[prdAmazonBuyBoxActive]
,[prdAmazonBuyBoxActiveUpdated]
,[prdActive]
,[prdRecordCreated]
,[prdRecordModified]
,[Draft]
FROM [e2A].[dbo].[tblProduct]
WHERE 1=1 ";
var sqlBuilder = new Database.SqlWhereBuilder();
if (FilterByProductId.Any())
{
sqlBuilder.In("prdProductID", FilterByProductId, "AND");
sqlString = sqlString + sqlBuilder.SqlWhereString;
}
if (FilterByAsin.Any())
{
sqlBuilder.In("prdAmazonASIN", FilterByAsin, "AND");
sqlString = sqlString + sqlBuilder.SqlWhereString;
}
// execute query and build result list
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
{
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
return returnList;
}
while (reader.Read())
{
// none nullable values
string title = reader.GetString(1);
int productCategoryId = reader.GetInt32(3);
int productProcurementControlId = reader.GetInt32(15);
// create model
var item = new Model.Product.ProductInfo(title, productCategoryId, productProcurementControlId);
item.ProductID = reader.GetInt32(0);
// add nullable items to model
if (!reader.IsDBNull(2))
item.TitleSuffix = reader.GetString(2);
if (!reader.IsDBNull(4))
item.ProductCategorySubID = reader.GetInt32(4);
if (!reader.IsDBNull(5))
item.ReleaseDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc);
if (!reader.IsDBNull(6))
item.RecommendedRetailPrice = reader.GetDecimal(6);
if (!reader.IsDBNull(7))
item.MaxPrice = reader.GetDecimal(7);
if (!reader.IsDBNull(8))
item.AmazonASIN = reader.GetString(8);
if (!reader.IsDBNull(9))
item.Manufacturer = reader.GetString(9);
if (!reader.IsDBNull(10))
item.PackageWeightKilogram = reader.GetDecimal(10);
if (!reader.IsDBNull(11) && !reader.IsDBNull(12) && !reader.IsDBNull(13))
item.SetPackageDimension(reader.GetDecimal(11), reader.GetDecimal(12), reader.GetDecimal(13));
if (!reader.IsDBNull(14))
item.CatId = reader.GetInt32(14);
if (!reader.IsDBNull(16))
item.ManualCompetativePriceUpdate = reader.GetBoolean(16);
if (!reader.IsDBNull(17))
item.AmazonBuyBoxActive = reader.GetBoolean(17);
if (!reader.IsDBNull(18))
item.AmazonBuyBoxActiveUpdated = DateTime.SpecifyKind(reader.GetDateTime(18), DateTimeKind.Utc);
if (!reader.IsDBNull(19))
item.IsActive = reader.GetBoolean(19);
if (!reader.IsDBNull(20))
item.RecordCreated = DateTime.SpecifyKind(reader.GetDateTime(20), DateTimeKind.Utc);
if (!reader.IsDBNull(21))
item.RecordModified = DateTime.SpecifyKind(reader.GetDateTime(21), DateTimeKind.Utc);
if (!reader.IsDBNull(22))
item.IsDraft = reader.GetBoolean(22);
returnList.Add(item);
}
}
}
}
return returnList;
}
/// <summary>
/// Get product id by sku number
/// </summary>
/// <param name="skuNumberList">List of SKU numbers to query</param>
/// <returns>Dictionary with SKU number as key and product id as value</returns>
public Dictionary<string, int> ProductIdBySkuNumber(List<string> skuNumberList)
{
var returnList = new Dictionary<string, int>();
if (skuNumberList == null || !skuNumberList.Any())
{
return returnList;
}
skuNumberList = skuNumberList.Distinct().ToList();
string sql = @"
SELECT tblProduct.prdProductID
,tblSku.skuSkuNumber
FROM tblProduct
INNER JOIN tblSku ON tblProduct.prdProductID = tblSku.skuProductID
WHERE
";
var sqlWhereBuilder = new Database.SqlWhereBuilder();
sqlWhereBuilder.Init();
sqlWhereBuilder.In("tblSku.skuSkuNumber", skuNumberList);
sql += sqlWhereBuilder.SqlWhereString;
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
sqlWhereBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
returnList.Add(reader.GetString(1), reader.GetInt32(0));
}
}
}
}
return returnList;
}
}
}
@@ -0,0 +1,49 @@
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
{
class ReadProductId : Connection
{
public Dictionary<string, int> ProductIdByAsin(List<string> asinList)
{
var productIdList = new Dictionary<string, int>();
if (asinList == null || !asinList.Any())
return productIdList;
// build SQL string
string sql =
@"SELECT prdProductID, prdAmazonASIN
FROM [e2A].[dbo].[tblProduct]
WHERE ";
var sqlBuilder = new Database.SqlWhereBuilder();
sqlBuilder.In("prdAmazonASIN", asinList);
sql = sql + sqlBuilder.SqlWhereString;
// execute query and build result list
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
productIdList.Add(reader.GetString(1), reader.GetInt32(0));
}
}
}
}
return productIdList;
}
}
}
@@ -0,0 +1,130 @@
using MarketplaceWebServiceProducts.Model;
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 UpdateAmazonFeeEstimate : Connection
{
public UpdateAmazonFeeEstimate(string sqlConnectionString) : base(sqlConnectionString)
{
}
public void ByFeesEstimateResult(FeesEstimateResult updateItem)
{
ByFeesEstimateResult(new List<FeesEstimateResult> { updateItem });
}
public void ByFeesEstimateResult(List<FeesEstimateResult> updateList)
{
foreach (var item in updateList)
{
bool isSellerSku = false;
if (item.FeesEstimateIdentifier.IdType == "SellerSKU")
{
isSellerSku = true;
}
else if (item.FeesEstimateIdentifier.IdType != "ASIN")
{
// Amazon have updated API to include other identifiers?
throw new Exception(
"New FeesEstimateIdentifier encountered/unsupported of type '" + item.FeesEstimateIdentifier + "'.");
}
string asin = item.FeesEstimateIdentifier.IdValue;
bool isAmazonFulfilled = item.FeesEstimateIdentifier.IsAmazonFulfilled;
DateTime timeOfFeeEstimation = item.FeesEstimate.TimeOfFeesEstimation;
decimal totalFeeEstimate = item.FeesEstimate.TotalFeesEstimate.Amount;
string currencyCode = item.FeesEstimate.TotalFeesEstimate.CurrencyCode;
decimal priceToEstimateFeeListingPrice = item.FeesEstimateIdentifier.PriceToEstimateFees.ListingPrice.Amount;
decimal priceToEstimateFeeShipping = 0;
if (item.FeesEstimateIdentifier.PriceToEstimateFees.Shipping != null)
{ priceToEstimateFeeShipping = item.FeesEstimateIdentifier.PriceToEstimateFees.Shipping.Amount; }
decimal priceToEstimateFeePoints = 0;
if (item.FeesEstimateIdentifier.PriceToEstimateFees.Points != null)
{ priceToEstimateFeePoints = item.FeesEstimateIdentifier.PriceToEstimateFees.Points.PointsMonetaryValue.Amount; }
decimal referralFee = 0m;
decimal variableClosingFee = 0m;
decimal fulfillmentFees = 0m;
decimal perItemFee = 0m;
decimal otherFee_Exception = 0m;
FeeDetailList feeDetailList = item.FeesEstimate.FeeDetailList;
List<FeeDetail> feeDetail = feeDetailList.FeeDetail;
foreach (FeeDetail feeDetailItem in feeDetail)
{
if (feeDetailItem.FeeType == "AmazonReferralFee" || feeDetailItem.FeeType == "ReferralFee")
{ referralFee = feeDetailItem.FinalFee.Amount; }
else if (feeDetailItem.FeeType == "VariableClosingFee")
{ variableClosingFee = feeDetailItem.FinalFee.Amount; }
else if (feeDetailItem.FeeType == "PerItemFee")
{ perItemFee = feeDetailItem.FinalFee.Amount; }
else if (feeDetailItem.FeeType == "FBAFees" || feeDetailItem.FeeType == "FulfillmentFees")
{ fulfillmentFees = feeDetailItem.FinalFee.Amount; }
else
{ otherFee_Exception = otherFee_Exception + feeDetailItem.FinalFee.Amount; }
}
// build sql statement
string sqlProductId;
if (isSellerSku)
{
sqlProductId = "(SELECT tblSku.skuProductID FROM tblSku INNER JOIN tblProduct ON tblSku.skuProductID = tblProduct.prdProductID WHERE tblProduct.prdAmazonASIN = @asin)";
}
else
{
sqlProductId = "(SELECT prdProductID FROM tblProduct WHERE prdAmazonASIN = @asin)";
}
string sql = @"
UPDATE tblAmazonFeeEstimate SET
IsAmazonFulfilled=@isAmazonFulfilled, TimeOfFeeEstimation=@timeOfFeeEstimation,
TotalFeeEstimate=@totalFeeEstimate, PriceToEstimateFeeListingPrice=@priceToEstimateFeeListingPrice,
PriceToEstimateFeeShipping=@priceToEstimateFeeShipping, PriceToEstimateFeePoints=@priceToEstimateFeePoints,
ReferralFee=@referralFee, VariableClosingFee=@variableClosingFee, PerItemFee=@perItemFee, FBAFee=@fbaFee,
OtherFee_Exception=@otherFee_Exception, currencyCode=CurrencyCode
WHERE ProductID = " + sqlProductId + @"
IF @@ROWCOUNT = 0
INSERT INTO tblAmazonFeeEstimate (
ProductID, IsAmazonFulfilled, TimeOfFeeEstimation, TotalFeeEstimate, PriceToEstimateFeeListingPrice,
PriceToEstimateFeeShipping, PriceToEstimateFeePoints, ReferralFee, VariableClosingFee, PerItemFee, FBAFee,
OtherFee_Exception, CurrencyCode
) VALUES (
" + sqlProductId + @", @isAmazonFulfilled, @timeOfFeeEstimation, @totalFeeEstimate, @priceToEstimateFeeListingPrice,
@priceToEstimateFeeShipping, @priceToEstimateFeePoints, @referralFee, @variableClosingFee, @perItemFee, @fbaFee,
@otherFee_Exception, @currencyCode
)
";
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
{
sqlConn.Open();
using (SqlCommand sqlCommand = new SqlCommand(sql, sqlConn))
{
sqlCommand.Parameters.AddWithValue("@asin", asin);
sqlCommand.Parameters.AddWithValue("@isAmazonFulfilled", isAmazonFulfilled);
sqlCommand.Parameters.AddWithValue("@timeOfFeeEstimation", timeOfFeeEstimation);
sqlCommand.Parameters.AddWithValue("@totalFeeEstimate", totalFeeEstimate);
sqlCommand.Parameters.AddWithValue("@priceToEstimateFeeListingPrice", priceToEstimateFeeListingPrice);
sqlCommand.Parameters.AddWithValue("@priceToEstimateFeeShipping", priceToEstimateFeeShipping);
sqlCommand.Parameters.AddWithValue("@priceToEstimateFeePoints", priceToEstimateFeePoints);
sqlCommand.Parameters.AddWithValue("@referralFee", referralFee);
sqlCommand.Parameters.AddWithValue("@variableClosingFee", variableClosingFee);
sqlCommand.Parameters.AddWithValue("@perItemFee", perItemFee);
sqlCommand.Parameters.AddWithValue("@fbaFee", fulfillmentFees);
sqlCommand.Parameters.AddWithValue("@otherFee_Exception", otherFee_Exception);
sqlCommand.Parameters.AddWithValue("@currencyCode", currencyCode);
sqlCommand.ExecuteNonQuery();
}
}
}
}
}
}
@@ -0,0 +1,62 @@
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
{
public class ReadRandomData : Connection
{
public List<string> GetSkuNumber(int listCount)
{
var returnList = new List<string>();
if (listCount < 1)
return returnList;
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(
"SELECT TOP "+ listCount + " [skuSkuNumber] FROM [e2A].[dbo].[tblSku] ORDER BY newid()", conn))
{
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
returnList.Add(reader.GetString(0));
}
}
}
}
return returnList;
}
public List<string> GetAsinNumber(int listCount)
{
var returnList = new List<string>();
if (listCount < 1)
return returnList;
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(
"SELECT TOP " + listCount + " prdAmazonASIN FROM [e2A].[dbo].[tblProduct] WHERE prdAmazonASIN IS NOT NULL ORDER BY newid()", conn))
{
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
returnList.Add(reader.GetString(0));
}
}
}
}
return returnList;
}
}
}
@@ -0,0 +1,82 @@
using bnhtrade.Core.Data.Database._BoilerPlate;
using bnhtrade.Core.Data.Database.Repository.Interface;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Repository.Implementation
{
internal class AccountCodeRepository : _Base, IAccountCodeRepository
{
public AccountCodeRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public Dictionary<int, Model.Account.Account> ReadAccountCode(List<int> accountIdList = null, List<int> accountCodeList = null)
{
var resultDict = new Dictionary<int, Model.Account.Account>();
var sqlWhere = new SqlWhereBuilder();
//build sql query
string sqlString = @"
SELECT tblAccountChartOf.AccountChartOfID
,tblAccountChartOf.AccountCode
,tblAccountChartOf.AccountName
,tblAccountChartOf.Description
,tblAccountChartOfType.AccountChartOfType
,tblAccountChartOfType.BasicType
,tblAccountChartOfType.Multiplier
FROM tblAccountChartOf
INNER JOIN tblAccountChartOfType ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID
WHERE 1=1 ";
if (accountIdList != null && accountIdList.Any())
{
sqlWhere.In("tblAccountChartOf.AccountChartOfID", accountIdList, " AND ");
}
if (accountCodeList != null && accountCodeList.Any())
{
sqlWhere.In("tblAccountChartOf.AccountCode", accountCodeList, " AND ");
}
if (sqlWhere.IsSetSqlWhereString)
{
sqlString = sqlString + sqlWhere.SqlWhereString;
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sqlString;
cmd.Transaction = _transaction as SqlTransaction;
if (sqlWhere.ParameterListIsSet)
{
sqlWhere.AddParametersToSqlCommand(cmd);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int tablePk = reader.GetInt32(0);
int accountCode = reader.GetInt32(1);
string title = reader.GetString(2);
string description = null;
if (!reader.IsDBNull(3)) { description = reader.GetString(3); }
string type = reader.GetString(4);
string basicType = reader.GetString(5);
int multiplier = reader.GetInt32(6);
var result = new Model.Account.Account(tablePk, accountCode, title, description, type, basicType, multiplier);
resultDict.Add(tablePk, result);
}
}
}
return resultDict;
}
}
}
@@ -0,0 +1,201 @@
using bnhtrade.Core.Data.Database._BoilerPlate;
using bnhtrade.Core.Data.Database.Repository.Interface;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Repository.Implementation
{
internal class AccountTaxRepository : _Base, IAccountTaxRepository
{
public AccountTaxRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public Dictionary<int, Model.Account.TaxCodeInfo> ReadTaxCodeInfo(bool? IsActive = null, List<string> taxcodeList = null, List<int> taxcodeIdList = null)
{
var resultList = new Dictionary<int, Model.Account.TaxCodeInfo>();
Data.Database.SqlWhereBuilder whereBuilder = new SqlWhereBuilder();
//build sql query
string sqlString = @"
SELECT
AccountTaxCodeID
,TaxCode
,TaxCodeName
,TaxCodeDescription
,TaxRatePercent
,IsMarginScheme
,IsValidOnExpense
,IsVailidOnIncome
,IsActive
,TaxType
FROM tblAccountTaxCode
WHERE 1=1 ";
// add where clauses
if (IsActive.HasValue)
{
whereBuilder.IsEqualTo("IsActive", IsActive.Value, "AND");
}
if (taxcodeList != null && taxcodeList.Count > 0)
{
whereBuilder.In("TaxCode", taxcodeList, "AND");
}
if (taxcodeIdList != null && taxcodeIdList.Count > 0)
{
whereBuilder.In("AccountTaxCodeID", taxcodeIdList, "AND");
}
if (whereBuilder.IsSetSqlWhereString)
{
sqlString = sqlString + whereBuilder.SqlWhereString;
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sqlString;
cmd.Transaction = _transaction as SqlTransaction;
if (whereBuilder.ParameterListIsSet)
{
whereBuilder.AddParametersToSqlCommand(cmd);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int taxCodeId = reader.GetByte(0);
string taxCode = reader.GetString(1);
string name = reader.GetString(2);
string description = null;
if (!reader.IsDBNull(3)) { description = reader.GetString(3); }
decimal rate = reader.GetDecimal(4);
bool isMargin = reader.GetBoolean(5);
bool isValidOnExpense = reader.GetBoolean(6);
bool isValidOnIncome = reader.GetBoolean(7);
bool isActive = reader.GetBoolean(8);
string taxType = reader.GetString(9);
var result = new Model.Account.TaxCodeInfo(
taxCode,
name,
description,
rate,
isMargin,
isValidOnExpense,
isValidOnIncome,
taxType,
isActive);
resultList.Add(taxCodeId, result);
}
}
}
return resultList;
}
public Dictionary<string, string> GetTaxCodeBySkuNumber(List<string> skuNumberList)
{
var resultList = new Dictionary<string, string>();
if (skuNumberList == null || !skuNumberList.Any())
{
return resultList;
}
skuNumberList = skuNumberList.Distinct().ToList();
string sql = @"
SELECT tblSku.skuSkuNumber
,tblAccountTaxCode.TaxCode
FROM tblSku
INNER JOIN tblAccountTaxCode ON tblSku.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID ";
var whereBuilder = new Data.Database.SqlWhereBuilder();
whereBuilder.In("tblSku.skuSkuNumber", skuNumberList, "WHERE");
sql += whereBuilder.SqlWhereString;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
if (whereBuilder.ParameterListIsSet)
{
whereBuilder.AddParametersToSqlCommand(cmd);
}
using (var reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
return resultList;
}
while (reader.Read())
{
resultList.Add(reader.GetString(0), reader.GetString(1));
}
}
}
return resultList;
}
public Dictionary<string, string> ReadTaxCodeByInvoiceLineItemCode(List<string> lineItemCode)
{
var resultList = new Dictionary<string, string>();
if (lineItemCode == null || !lineItemCode.Any())
{
return resultList;
}
lineItemCode = lineItemCode.Distinct().ToList();
string sql = @"
SELECT tblAccountInvoiceLineItem.ItemCode
,tblAccountTaxCode.TaxCode
FROM tblAccountInvoiceLineItem
LEFT OUTER JOIN tblAccountTaxCode ON tblAccountInvoiceLineItem.AccountTaxCodeID_Default = tblAccountTaxCode.AccountTaxCodeID
";
var whereBuilder = new Data.Database.SqlWhereBuilder();
whereBuilder.In("tblAccountInvoiceLineItem.ItemCode", lineItemCode, "WHERE");
sql += whereBuilder.SqlWhereString;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
if (whereBuilder.ParameterListIsSet)
{
whereBuilder.AddParametersToSqlCommand(cmd);
}
using (var reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
return resultList;
}
while (reader.Read())
{
if (reader.IsDBNull(1)) { resultList.Add(reader.GetString(0), null); }
else { resultList.Add(reader.GetString(0), reader.GetString(1)); }
}
}
}
return resultList;
}
}
}
@@ -0,0 +1,739 @@
using bnhtrade.Core.Data.Database._BoilerPlate;
using bnhtrade.Core.Data.Database.Repository.Interface;
using bnhtrade.Core.Model.Amazon;
using Microsoft.Data.SqlClient;
using Microsoft.VisualBasic.Logging;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace bnhtrade.Core.Data.Database.Repository.Implementation
{
internal class AmazonSettlementRepository : _Base, IAmazonSettlementRepository
{
Logic.Log.LogEvent _log = new Logic.Log.LogEvent();
public AmazonSettlementRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
//
// Read Amazon Settlement Header Information
//
public List<Model.Import.AmazonSettlementHeader> ReadAmazonSettlementHeaderInfoBySettlementId(List<string> settlementIdList)
{
if (settlementIdList == null || !settlementIdList.Any())
{ return new List<Model.Import.AmazonSettlementHeader>(); }
return ReadAmazonSettlementHeaders(settlementIdList);
}
public List<Model.Import.AmazonSettlementHeader> ReadAmazonSettlementHeaderInfoBySpapiReportId(List<string> spapiReportIdList)
{
if (spapiReportIdList == null || !spapiReportIdList.Any())
{ return new List<Model.Import.AmazonSettlementHeader>(); }
return ReadAmazonSettlementHeaders(null, spapiReportIdList);
}
private List<Model.Import.AmazonSettlementHeader> ReadAmazonSettlementHeaders(
List<string> settlementIdList = null, List<string> spapiReportIdList = null, bool filterOutIsProcessed = false,
bool DescendingOrder = false, int? returnTop = null)
{
var returnHeaderList = new List<Model.Import.AmazonSettlementHeader>();
Dictionary<string, int> dicTablePkBySettlementId = new Dictionary<string, int>();
// build the sql string
string sqlString = "SELECT ";
if (returnTop != null)
{
sqlString = sqlString + "TOP " + returnTop.Value + " ";
}
sqlString = sqlString + @"
ImportAmazonSettlementReportID
,[marketplace-name]
,[settlement-id]
,[settlement-start-date]
,[settlement-end-date]
,[deposit-date]
,[total-amount]
,currency
,IsProcessed
,SpapiReportId
FROM tblImportAmazonSettlementReport
WHERE 1 = 1";
if (filterOutIsProcessed)
{
sqlString = sqlString + @"
AND IsProcessed = 0";
}
// build dictionary of parameter and values for settlementid
var dicSettlementIdByParameterString = new Dictionary<string, string>();
if (settlementIdList != null)
{
int count = 0;
foreach (string item in settlementIdList)
{
if (!string.IsNullOrWhiteSpace(item))
{
count = count + 1;
string parameterString = "@settlementId" + count;
dicSettlementIdByParameterString.Add(parameterString, item);
}
}
}
if (dicSettlementIdByParameterString.Any())
{
int count = 0;
foreach (var item in dicSettlementIdByParameterString)
{
count = count + 1;
if (count == 1)
{
sqlString = sqlString + @"
AND ( [settlement-id] = " + item.Key;
}
else
{
sqlString = sqlString + @"
OR [settlement-id] = " + item.Key;
}
}
sqlString = sqlString + " )";
}
// build dictionary of parameter and values for SP-API Report Id
var dicSpapiReportIdByParameterString = new Dictionary<string, string>();
if (spapiReportIdList != null && spapiReportIdList.Any())
{
int count = 0;
foreach (string item in spapiReportIdList)
{
if (!string.IsNullOrWhiteSpace(item))
{
count = count + 1;
string parameterString = "@SpapiReportId" + count;
dicSpapiReportIdByParameterString.Add(parameterString, item);
}
}
}
if (dicSpapiReportIdByParameterString.Any())
{
int count = 0;
foreach (var item in dicSpapiReportIdByParameterString)
{
count = count + 1;
if (count == 1)
{
sqlString = sqlString + @"
AND ( SpapiReportId = " + item.Key;
}
else
{
sqlString = sqlString + @"
OR SpapiReportId = " + item.Key;
}
}
sqlString = sqlString + " )";
}
sqlString = sqlString + @"
ORDER BY [settlement-start-date] ";
if (DescendingOrder) { sqlString = sqlString + " DESC"; }
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sqlString;
cmd.Transaction = _transaction as SqlTransaction;
if (dicSettlementIdByParameterString.Any())
{
foreach (var item in dicSettlementIdByParameterString)
{
cmd.Parameters.AddWithValue(item.Key, item.Value);
}
}
if (dicSpapiReportIdByParameterString.Any())
{
foreach (var item in dicSpapiReportIdByParameterString)
{
cmd.Parameters.AddWithValue(item.Key, item.Value);
}
}
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var header = new Model.Import.AmazonSettlementHeader();
int tablePk = reader.GetInt32(0);
if (!reader.IsDBNull(1)) { header.MarketPlace = MarketPlaceEnumExtensions.FromMarketplaceUrl(reader.GetString(1)); }
header.SettlementId = reader.GetString(2);
header.StartDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc);
header.EndDate = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc);
header.DepositDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc);
header.TotalAmount = reader.GetDecimal(6);
header.CurrencyCode = reader.GetString(7);
header.IsProcessed = reader.GetBoolean(8);
if (!reader.IsDBNull(9)) { header.SpapiReportId = reader.GetString(9); }
// update dictionary
if (!dicTablePkBySettlementId.ContainsKey(header.SettlementId))
{
dicTablePkBySettlementId.Add(header.SettlementId, tablePk);
}
// add header to list
returnHeaderList.Add(header);
}
}
}
return returnHeaderList;
}
//
// Read Amazon Settlement Report
//
/// <summary>
/// Gets Amazon settlement report information from the database.
/// </summary>
/// <returns>Dictionary where key=id and value=settlement</returns>
public Dictionary<int, Model.Import.AmazonSettlement> ReadAmazonSettlements(
List<string> settlementIdList = null, List<string> marketPlaceNameList = null, bool? isProcessed = null,
bool descendingOrder = false, int? returnTop = null )
{
var returnList = new Dictionary<int, Model.Import.AmazonSettlement>();
var whereBuilder = new Data.Database.SqlWhereBuilder();
// build the sql string
string sqlString = "SELECT ";
if (returnTop != null)
{
sqlString = sqlString + "TOP " + returnTop.Value + " ";
}
sqlString = sqlString + @"
tblImportAmazonSettlementReport.ImportAmazonSettlementReportID,
tblImportAmazonSettlementReport.[marketplace-name],
tblImportAmazonSettlementReport.[settlement-id],
tblImportAmazonSettlementReport.[settlement-start-date],
tblImportAmazonSettlementReport.[settlement-end-date],
tblImportAmazonSettlementReport.[deposit-date],
tblImportAmazonSettlementReport.[total-amount],
tblImportAmazonSettlementReport.currency,
tblImportAmazonSettlementReport.IsProcessed,
tblImportAmazonSettlementReport.SpapiReportId,
tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID,
tblImportAmazonSettlementReportLine.[transaction-type],
tblImportAmazonSettlementReportLine.[order-id],
tblImportAmazonSettlementReportLine.[merchant-order-id],
tblImportAmazonSettlementReportLine.[adjustment-id],
tblImportAmazonSettlementReportLine.[shipment-id],
tblImportAmazonSettlementReportLine.[marketplace-name] AS Expr1,
tblImportAmazonSettlementReportLine.[amount-type],
tblImportAmazonSettlementReportLine.[amount-description],
tblImportAmazonSettlementReportLine.amount,
tblImportAmazonSettlementReportLine.currency,
tblImportAmazonSettlementReportLine.[fulfillment-id],
tblImportAmazonSettlementReportLine.[posted-date-time],
tblImportAmazonSettlementReportLine.[order-item-code],
tblImportAmazonSettlementReportLine.[merchant-order-item-id],
tblImportAmazonSettlementReportLine.[merchant-adjustment-item-id],
tblImportAmazonSettlementReportLine.sku,
tblImportAmazonSettlementReportLine.[quantity-purchased],
tblImportAmazonSettlementReportLine.[promotion-id],
tblImportAmazonSettlementReportLine.IsProcessed,
tblImportAmazonSettlementReportLine.ExportAccountInvoiceLineID
FROM tblImportAmazonSettlementReport
INNER JOIN
tblImportAmazonSettlementReportLine
ON tblImportAmazonSettlementReport.ImportAmazonSettlementReportID = tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportID
WHERE 1 = 1 ";
if (isProcessed != null)
{
if (isProcessed.Value == true)
{
sqlString = sqlString + @"
AND tblImportAmazonSettlementReport.IsProcessed = 1";
}
else
{
sqlString = sqlString + @"
AND tblImportAmazonSettlementReport.IsProcessed = 0";
}
}
if (settlementIdList != null && settlementIdList.Any() == true)
{
whereBuilder.In("tblImportAmazonSettlementReport.ImportAmazonSettlementReportID", settlementIdList, "AND");
}
if (marketPlaceNameList != null && marketPlaceNameList.Any() == true)
{
whereBuilder.In("tblImportAmazonSettlementReport.[marketplace-name]", marketPlaceNameList, "AND");
}
sqlString = sqlString + whereBuilder.SqlWhereString;
// add the order by clause(s)
sqlString = sqlString + @"
ORDER BY tblImportAmazonSettlementReport.[marketplace-name] ASC, tblImportAmazonSettlementReport.[settlement-start-date] ";
if (descendingOrder) { sqlString = sqlString + " DESC"; }
else { sqlString = sqlString + " ASC"; }
sqlString = sqlString + ", tblImportAmazonSettlementReport.ImportAmazonSettlementReportID ASC, tblImportAmazonSettlementReportLine.[posted-date-time] ASC, "
+ "tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID ASC;";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sqlString;
cmd.Transaction = _transaction as SqlTransaction;
whereBuilder.AddParametersToSqlCommand(cmd);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int tableId = reader.GetInt32(0);
if (returnList.ContainsKey(tableId) == false)
{
var settlement = new Model.Import.AmazonSettlement();
if (!reader.IsDBNull(1)) { settlement.MarketPlace = MarketPlaceEnumExtensions.FromMarketplaceUrl(reader.GetString(1)); }
settlement.SettlementId = reader.GetString(2);
settlement.StartDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc);
settlement.EndDate = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc);
settlement.DepositDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc);
settlement.TotalAmount = reader.GetDecimal(6);
settlement.CurrencyCode = reader.GetString(7);
settlement.IsProcessed = reader.GetBoolean(8);
if (!reader.IsDBNull(9)) { settlement.SpapiReportId = reader.GetString(9); }
returnList.Add(tableId, settlement);
}
// add lines to settlement
var line = new Model.Import.AmazonSettlement.SettlementLine();
line.TransactionType = reader.GetString(11);
if (!reader.IsDBNull(12)) { line.OrderId = reader.GetString(12); }
if (!reader.IsDBNull(13)) { line.MerchantOrderId = reader.GetString(13); }
if (!reader.IsDBNull(14)) { line.AdjustmentId = reader.GetString(14); }
if (!reader.IsDBNull(15)) { line.ShipmentId = reader.GetString(15); }
if (!reader.IsDBNull(16)) { line.MarketPlaceName = reader.GetString(16); }
line.AmountType = reader.GetString(17);
line.AmountDescription = reader.GetString(18);
line.Amount = reader.GetDecimal(19);
line.CurrenyCode = reader.GetString(20);
if (!reader.IsDBNull(21)) { line.FulfillmentId = reader.GetString(21); }
line.PostDateTime = DateTime.SpecifyKind(reader.GetDateTime(22), DateTimeKind.Utc);
if (!reader.IsDBNull(23)) { line.OrderItemCode = reader.GetString(23); }
if (!reader.IsDBNull(24)) { line.MerchantOrderItemId = reader.GetString(24); }
if (!reader.IsDBNull(25)) { line.MerchantAdjustmentItemId = reader.GetString(25); }
if (!reader.IsDBNull(26)) { line.Sku = reader.GetString(26); }
if (!reader.IsDBNull(27)) { line.QuantityPurchased = reader.GetInt32(27); }
if (!reader.IsDBNull(28)) { line.PromotionId = reader.GetString(28); }
line.IsProcessed = reader.GetBoolean(29);
if (!reader.IsDBNull(30)) { line.ExportAccountInvoiceLineId = reader.GetInt32(30); }
returnList[tableId].SettlementLineList.Add(line);
}
return returnList;
}
}
}
//
// Update Amazon Settlement Report
//
/// <summary>
/// Update the settlement report marketplace name by settlement Id (not table id)
/// </summary>
/// <param name="settlementId">Settlement id (not table/record id) of the settlement to update</param>
/// <param name="marketPlaceName">marketplace name</param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public bool UpdateAmazonSettlementMarketPlaceName (string settlementId, Model.Amazon.MarketPlaceEnum marketPlace)
{
if (string.IsNullOrWhiteSpace(settlementId) || marketPlace == null)
{
throw new Exception("Settlement id or market place is invalid.");
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = @"
UPDATE tblImportAmazonSettlementReport
SET [marketplace-name] = @marketPlaceName
WHERE [settlement-id] = @settlementId;";
cmd.Parameters.AddWithValue("@marketPlaceName", marketPlace.GetMarketplaceUrl());
cmd.Parameters.AddWithValue("@settlementId", settlementId);
cmd.Transaction = _transaction as SqlTransaction;
return cmd.ExecuteNonQuery() > 0;
}
}
/// <summary>
/// Set the IsProcessed flag to true or false for the specified settlement Ids.
/// </summary>
/// <param name="settlementIdList">List of settlement id (not table id)</param>
/// <param name="isProcessed">value to set the isProcessed to</param>
/// <returns>Number of rows effected</returns>
public int UpdateAmazonSettlementIsProcessed(List<string> settlementIdList, bool isProcessed)
{
if (settlementIdList == null || !settlementIdList.Any())
{
throw new Exception("Settlement ID list is empty.");
}
string sqlString = @"
UPDATE tblImportAmazonSettlementReport ";
sqlString = sqlString + @"
SET IsProcessed = " + (isProcessed ? "1" : "0");
var whereBuilder = new Data.Database.SqlWhereBuilder();
whereBuilder.In("tblImportAmazonSettlementReport.[settlement-id]", settlementIdList, "WHERE");
sqlString = sqlString + whereBuilder.SqlWhereString;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sqlString;
cmd.Transaction = _transaction as SqlTransaction;
whereBuilder.AddParametersToSqlCommand(cmd);
return cmd.ExecuteNonQuery();
}
}
/// <summary>
/// Takes a Settlement Report flat file from Amazon and imports it into the database.
/// </summary>
/// <param name="filePath">path to the Amazon report flat file</param>
/// <param name="reportId">The unique Amazon SP-API report id (not settlement id)</param>
/// <returns></returns>
public bool CreateAmazonSettlements(string filePath, string reportId)
{
int settlementReportId = 0;
string settlementRef = "";
bool marketPlaceUpdated = false;
decimal settlementAmount = 0m;
int lineNumber = 2;
int lineSkip = 0;
using (var reader = new StreamReader(filePath))
{
//read file one line at a time and insert data into table if required
// read header and retrive information
string headerRow = reader.ReadLine();
string[] headers = headerRow.Split('\t');
int columnCount = headers.Length;
int indexSettlementId = Array.IndexOf(headers, "settlement-id");
int indexSettlementStartDate = Array.IndexOf(headers, "settlement-start-date");
int indexSettlementEndDate = Array.IndexOf(headers, "settlement-end-date");
int indexDepositDate = Array.IndexOf(headers, "deposit-date");
int indexTotalAmount = Array.IndexOf(headers, "total-amount");
int indexCurrency = Array.IndexOf(headers, "currency");
int indexTransactionType = Array.IndexOf(headers, "transaction-type");
int indexOrderId = Array.IndexOf(headers, "order-id");
int indexMerchantOrderId = Array.IndexOf(headers, "merchant-order-id");
int indexAdjustmentId = Array.IndexOf(headers, "adjustment-id");
int indexShipmentId = Array.IndexOf(headers, "shipment-id");
int indexMarketplaceName = Array.IndexOf(headers, "marketplace-name");
int indexAmountType = Array.IndexOf(headers, "amount-type");
int indexAmountDescription = Array.IndexOf(headers, "amount-description");
int indexAmount = Array.IndexOf(headers, "amount");
int indexFulfillmentId = Array.IndexOf(headers, "fulfillment-id");
// int indexPostedDate = Array.IndexOf(headers, "posted-date");
int indexPostedDateTime = Array.IndexOf(headers, "posted-date-time");
int indexOrderItemCode = Array.IndexOf(headers, "order-item-code");
int indexMerchantOrderItemId = Array.IndexOf(headers, "merchant-order-item-id");
int indexMerchantAdjustmentItemId = Array.IndexOf(headers, "merchant-adjustment-item-id");
int indexSku = Array.IndexOf(headers, "sku");
int indexQuantityPurchased = Array.IndexOf(headers, "quantity-purchased");
int indexPromotionId = Array.IndexOf(headers, "promotion-id");
string currency = "";
string fileRow;
while ((fileRow = reader.ReadLine()) != null)
{
Console.Write("\rParsing record: " + lineNumber);
//split line into array
string[] items = fileRow.Split('\t');
if (items.Length != columnCount)
{
// skip line
lineSkip = lineSkip + 1;
_log.LogWarning(
"Line #" + lineNumber + " skipped due to no enough element in row.",
filePath
);
}
else if (lineNumber == 2)
{
// check if settlement has already been imported
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = "SELECT COUNT(*) FROM tblImportAmazonSettlementReport WHERE [settlement-id]=@settlementId;";
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@settlementId", items[indexSettlementId]);
int recordCount = (int)cmd.ExecuteScalar();
if (recordCount > 0)
{
SetSpapiReportId(items[indexSettlementId], reportId);
_log.LogInformation("Settlement report already imported, skipping...");
return true;
}
}
//set currencyId
//currencyId = GeneralQueries.GetCurrencyId(items[5]);
//set currency
currency = items[indexCurrency];
settlementAmount = decimal.Parse(items[indexTotalAmount].Replace(",", "."));
// insert
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Transaction = _transaction as SqlTransaction;
cmd.CommandText = @"
INSERT INTO tblImportAmazonSettlementReport (
[settlement-id]
,[settlement-start-date]
,[settlement-end-date]
,[deposit-date]
,[total-amount]
,[currency]
,SpapiReportId
)
OUTPUT INSERTED.ImportAmazonSettlementReportID
VALUES (
@settlementId
,@settlementStartDate
,@settlementEndDate
,@depositDate
,@settlementotalAmounttId
,@currency
,@reportId
);";
// add parameters
if (indexSettlementId == -1 || items[indexSettlementId].Length == 0) { cmd.Parameters.AddWithValue("@settlementId", DBNull.Value); }
else
{
settlementRef = items[indexSettlementId];
cmd.Parameters.AddWithValue("@settlementId", settlementRef);
}
var parseDateTime = new Core.Logic.Utilities.DateTime();
if (indexSettlementStartDate == -1 || items[indexSettlementStartDate].Length == 0) { cmd.Parameters.AddWithValue("@settlementStartDate", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@settlementStartDate", parseDateTime.ParseIsoDateTimeString(items[indexSettlementStartDate])); }
if (indexSettlementEndDate == -1 || items[indexSettlementEndDate].Length == 0) { cmd.Parameters.AddWithValue("@settlementEndDate", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@settlementEndDate", parseDateTime.ParseIsoDateTimeString(items[indexSettlementEndDate])); }
if (indexDepositDate == -1 || items[indexDepositDate].Length == 0) { cmd.Parameters.AddWithValue("@depositDate", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@depositDate", parseDateTime.ParseIsoDateTimeString(items[indexDepositDate])); }
if (indexTotalAmount == -1 || items[indexTotalAmount].Length == 0) { cmd.Parameters.AddWithValue("@totalAmount", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@settlementotalAmounttId", settlementAmount); }
if (string.IsNullOrWhiteSpace(reportId)) { cmd.Parameters.AddWithValue("@reportId", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@reportId", reportId); }
cmd.Parameters.AddWithValue("@currency", currency);
//if (currencyId == -1) { sqlCommand.Parameters.AddWithValue("@currencyId", DBNull.Value); }
//else { sqlCommand.Parameters.AddWithValue("@currencyId", currencyId); }
//execute and retrive id
settlementReportId = (int)cmd.ExecuteScalar();
}
}
else
{
//update market place name in main table, if required
if (marketPlaceUpdated == false && settlementReportId > 0 && items[indexMarketplaceName].Length > 1)
{
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Transaction = _transaction as SqlTransaction;
cmd.CommandText = @"
UPDATE tblImportAmazonSettlementReport
SET [marketplace-name]=@MarketplaceName
WHERE ImportAmazonSettlementReportID=@ImportAmazonSettlementReportID;";
cmd.Parameters.AddWithValue("@MarketplaceName", items[indexMarketplaceName]);
cmd.Parameters.AddWithValue("@ImportAmazonSettlementReportID", settlementReportId);
cmd.ExecuteNonQuery();
marketPlaceUpdated = true;
}
}
//insert report items
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Transaction = _transaction as SqlTransaction;
cmd.CommandText =
"INSERT INTO tblImportAmazonSettlementReportLine ( " +
"ImportAmazonSettlementReportID, [transaction-type], [order-id], [merchant-order-id], [adjustment-id], [shipment-id], [marketplace-name], " +
"[amount-type], [amount-description], [currency], [amount], [fulfillment-id], [posted-date-time], [order-item-code], " +
"[merchant-order-item-id], [merchant-adjustment-item-id], [sku], [quantity-purchased], [promotion-id] ) " +
"VALUES ( " +
"@ImportAmazonSettlementReportID, @TransactionType, @orderRef, @merchantOrderRef, @AdjustmentRef, @ShipmentRef, @MarketplaceName, " +
"@AmountType, @AmountDescription, @currency, @Amount, @FulfillmentRef, @PostedDateTimeUTC, @OrderItemCode, " +
"@MerchantOrderItemRef, @MerchantAdjustmentItemRef, @SkuNumber, @QuantityPurchased, @PromotionRef );";
// add parameters
cmd.Parameters.AddWithValue("@ImportAmazonSettlementReportID", settlementReportId);
cmd.Parameters.AddWithValue("@currency", currency);
if (indexTransactionType == -1 || items[indexTransactionType].Length == 0) { cmd.Parameters.AddWithValue("@TransactionType", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@TransactionType", items[indexTransactionType]); }
if (indexOrderId == -1 || items[indexOrderId].Length == 0) { cmd.Parameters.AddWithValue("@orderRef", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@orderRef", items[indexOrderId]); }
if (indexMerchantOrderId == -1 || items[indexMerchantOrderId].Length == 0) { cmd.Parameters.AddWithValue("@merchantOrderRef", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@merchantOrderRef", items[indexMerchantOrderId]); }
if (indexAdjustmentId == -1 || items[indexAdjustmentId].Length == 0) { cmd.Parameters.AddWithValue("@AdjustmentRef", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@AdjustmentRef", items[indexAdjustmentId]); }
if (indexShipmentId == -1 || items[indexShipmentId].Length == 0) { cmd.Parameters.AddWithValue("@ShipmentRef", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@ShipmentRef", items[indexShipmentId]); }
if (indexMarketplaceName == -1 || items[indexMarketplaceName].Length == 0) { cmd.Parameters.AddWithValue("@MarketplaceName", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@MarketplaceName", items[indexMarketplaceName]); }
if (indexAmountType == -1 || items[indexAmountType].Length == 0) { cmd.Parameters.AddWithValue("@AmountType", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@AmountType", items[indexAmountType]); }
if (indexAmountDescription == -1 || items[indexAmountDescription].Length == 0) { cmd.Parameters.AddWithValue("@AmountDescription", DBNull.Value); }
else
{
string amountDescription = items[indexAmountDescription];
if (amountDescription.Length > 100) { amountDescription = amountDescription.Substring(0, 100); }
cmd.Parameters.AddWithValue("@AmountDescription", amountDescription);
}
if (indexAmount == -1 || items[indexAmount].Length == 0) { cmd.Parameters.AddWithValue("@Amount", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@Amount", decimal.Parse(items[indexAmount].Replace(",", "."))); }
if (indexFulfillmentId == -1 || items[indexFulfillmentId].Length == 0) { cmd.Parameters.AddWithValue("@FulfillmentRef", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@FulfillmentRef", items[indexFulfillmentId]); }
if (indexPostedDateTime == -1 || items[indexPostedDateTime].Length == 0) { cmd.Parameters.AddWithValue("@PostedDateTimeUTC", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@PostedDateTimeUTC", new Logic.Utilities.DateTime().ParseIsoDateTimeString(items[indexPostedDateTime])); }
if (indexOrderItemCode == -1 || items[indexOrderItemCode].Length == 0) { cmd.Parameters.AddWithValue("@OrderItemCode", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@OrderItemCode", long.Parse(items[indexOrderItemCode])); }
if (indexMerchantOrderItemId == -1 || items[indexMerchantOrderItemId].Length == 0) { cmd.Parameters.AddWithValue("@MerchantOrderItemRef", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@MerchantOrderItemRef", long.Parse(items[indexMerchantOrderItemId])); }
if (indexMerchantAdjustmentItemId == -1 || items[indexMerchantAdjustmentItemId].Length == 0) { cmd.Parameters.AddWithValue("@MerchantAdjustmentItemRef", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@MerchantAdjustmentItemRef", items[indexMerchantAdjustmentItemId]); }
if (indexSku == -1 || items[indexSku].Length == 0) { cmd.Parameters.AddWithValue("@SkuNumber", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@SkuNumber", items[indexSku]); }
if (indexQuantityPurchased == -1 || items[indexQuantityPurchased].Length == 0) { cmd.Parameters.AddWithValue("@QuantityPurchased", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@QuantityPurchased", int.Parse(items[indexQuantityPurchased])); }
if (indexPromotionId == -1 || items[indexPromotionId].Length == 0) { cmd.Parameters.AddWithValue("@PromotionRef", DBNull.Value); }
else { cmd.Parameters.AddWithValue("@PromotionRef", items[indexPromotionId]); }
cmd.ExecuteNonQuery();
}
}
lineNumber = lineNumber + 1;
}
}
//final check - settlement amount matches sum of inserted settlement lines
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Transaction = _transaction as SqlTransaction;
cmd.CommandText = @"
SELECT Sum(tblImportAmazonSettlementReportLine.amount) AS SumOfAmount
FROM tblImportAmazonSettlementReportLine
WHERE ImportAmazonSettlementReportID=@ImportAmazonSettlementReportID;";
decimal sumOfAmount = -1.12345m;
cmd.Parameters.AddWithValue("@ImportAmazonSettlementReportID", settlementReportId);
sumOfAmount = (decimal)cmd.ExecuteScalar();
if (sumOfAmount != settlementAmount)
{
_log.LogError("Error importing settlement id'" + settlementRef + "'. Sum of inserted settlement lines (" + sumOfAmount +
") does not match settlement amount (" + settlementAmount + ").");
return false;
}
}
Console.Write("\r");
_log.LogInformation((lineNumber - (2 + lineSkip)) + " total settlement items inserted");
if (lineSkip > 0)
{
_log.LogError(lineSkip + " total line(s) where skipped due to insufficent number of cells on row");
}
return true;
}
public int SetSpapiReportId(string settlementId, string spapiReportId)
{
string sqlString = @"
UPDATE
tblImportAmazonSettlementReport
SET
SpapiReportId = @spapiReportId
WHERE
[settlement-id] = @settlementId;";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sqlString;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@spapiReportId", spapiReportId);
cmd.Parameters.AddWithValue("@settlementId", settlementId);
return cmd.ExecuteNonQuery();
}
}
}
}
@@ -0,0 +1,267 @@
using bnhtrade.Core.Data.Database.Repository.Interface;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Repository.Implementation
{
internal class CurrencyRepository : _Base, ICurrencyRepository
{
public CurrencyRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
/// <summary>
/// Returns excahnge rate, in decimal format, for a given currency and datetime
/// </summary>
/// <param name="currencyCode">currency code</param>
/// <param name="date">dat and time</param>
/// <returns></returns>
public decimal? ReadExchangeRate(Model.Account.CurrencyCode currencyCode, DateTime date)
{
string sql = @"
SELECT CurrencyUnitsPerGBP
FROM tblAccountExchangeRate
WHERE CurrencyCode=@currencyCode AND StartDate<=@conversionDate AND EndDate>@conversionDate
";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@currencyCode", currencyCode.ToString());
cmd.Parameters.AddWithValue("@conversionDate", date);
object result = cmd.ExecuteScalar();
if (result != null)
{
return Convert.ToDecimal(result);
}
else
{
return null;
}
}
}
public List<Model.Account.CurrencyExchangeRate> ReadExchangeRate(List<Model.Account.CurrencyCode> currencyCodeList = null, DateTime date = default(DateTime))
{
//throw new NotImplementedException("Complete, but untested");
var returnList = new List<Model.Account.CurrencyExchangeRate>();
string sql = @"
SELECT AccountExchangeRateID, ExchangeRateSource, CurrencyCode, CurrencyUnitsPerGBP, StartDate, EndDate
FROM tblAccountExchangeRate
WHERE 1=1 ";
if (date != default(DateTime))
{
sql = sql + " AND (@dateTime >= StartDate AND @dateTime < endDate) ";
}
var sqlWhere = new Data.Database.SqlWhereBuilder();
// create string list
List<string> stringList = new List<string>();
if (currencyCodeList != null)
{
stringList = currencyCodeList.ConvertAll(f => f.ToString());
if (stringList.Any())
{
sqlWhere.In("CurrencyCode", stringList, "AND");
}
}
sql = sql + sqlWhere.SqlWhereString;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
if (date != default(DateTime))
{
cmd.Parameters.AddWithValue("@dateTime", date);
}
if (stringList.Any())
{
sqlWhere.AddParametersToSqlCommand(cmd);
}
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int id = reader.GetInt32(0);
int exchangeRateSource = reader.GetInt32(1);
string currencyCodeString = reader.GetString(2);
decimal currencyUnitsPerGBP = reader.GetDecimal(3);
DateTime startDate = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc);
DateTime endDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc);
// convert string to enum
if (Enum.TryParse(currencyCodeString, out Model.Account.CurrencyCode currencyCode) == false)
{
throw new Exception("Failed converting database string to enum");
}
var item = new Model.Account.CurrencyExchangeRate(
currencyCode
, exchangeRateSource
, currencyUnitsPerGBP
, startDate
, endDate
);
returnList.Add(item);
}
}
}
return returnList;
}
public List<Model.Account.CurrencyExchangeRate> ReadExchangeRateLatest(List<Model.Account.CurrencyCode> currencyCodeList = null)
{
var returnList = new List<Model.Account.CurrencyExchangeRate>();
string sql = @"
SELECT t1.AccountExchangeRateID, t1.ExchangeRateSource, t1.CurrencyCode, t1.CurrencyUnitsPerGBP, t1.StartDate, t1.EndDate,
t2.maxdate
FROM tblAccountExchangeRate AS t1
INNER JOIN
(SELECT max(StartDate) AS maxdate,
CurrencyCode
FROM tblAccountExchangeRate
GROUP BY CurrencyCode
";
// add any filters
var sqlWhere = new Data.Database.SqlWhereBuilder();
var codeStringList = new List<string>();
if (currencyCodeList != null && currencyCodeList.Any() == true)
{
// convert to string list
foreach (var currencyCode in currencyCodeList)
{
codeStringList.Add(currencyCode.ToString());
}
// add to where statement
sqlWhere.In("CurrencyCode", codeStringList, "HAVING");
sql = sql + sqlWhere.SqlWhereString;
}
sql = sql + @" ) AS t2
ON t1.CurrencyCode = t2.CurrencyCode
AND t1.StartDate = t2.maxdate
ORDER BY t1.CurrencyCode;";
//query db
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
if (codeStringList.Any())
{
sqlWhere.AddParametersToSqlCommand(cmd);
}
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
int id = reader.GetInt32(0);
int exchangeRateSource = reader.GetInt32(1);
string currencyCodeString = reader.GetString(2);
decimal currencyUnitsPerGBP = reader.GetDecimal(3);
DateTime startDate = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc);
DateTime endDate = DateTime.SpecifyKind(reader.GetDateTime(5), DateTimeKind.Utc);
// convert string to enum
if (Enum.TryParse(currencyCodeString, out Model.Account.CurrencyCode currencyCode) == false)
{
throw new Exception("Failed converting database string to enum");
}
var item = new Model.Account.CurrencyExchangeRate(
currencyCode
, exchangeRateSource
, currencyUnitsPerGBP
, startDate
, endDate
);
returnList.Add(item);
}
}
}
return returnList;
}
public int InsertExchangeRate(int exchangeRateSource, Model.Account.CurrencyCode currencyCode,
decimal currencyUnitsPerGbp, DateTime periodStartUtc, DateTime periodEnd, bool checkOverride = false)
{
// checks
if (periodStartUtc.Kind != DateTimeKind.Utc || periodEnd.Kind != DateTimeKind.Utc)
{
throw new FormatException("Currency date time kind must be UTC");
}
currencyUnitsPerGbp = decimal.Round(currencyUnitsPerGbp, 4);
// CHECKS
if (periodEnd <= periodStartUtc)
{
throw new Exception("Invalid date period.");
}
if (checkOverride == false && (periodEnd - periodStartUtc).Days > 31)
{
throw new Exception("Date period is greater than 31 days.");
}
string sql = @"
INSERT INTO tblAccountExchangeRate (ExchangeRateSource, CurrencyCode, CurrencyUnitsPerGBP, StartDate, EndDate)
OUTPUT INSERTED.AccountExchangeRateID
VALUES (@exchangeRateSource, @currencyCode, @currencyUnitsPerGbp, @periodStart, @periodEnd);
";
// make the insert
DateTime? periodEndLast = null;
int recordId = 0;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@exchangeRateSource", exchangeRateSource);
cmd.Parameters.AddWithValue("@currencyCode", currencyCode.ToString());
cmd.Parameters.AddWithValue("@currencyUnitsPerGbp", currencyUnitsPerGbp);
cmd.Parameters.AddWithValue("@periodStart", periodStartUtc);
cmd.Parameters.AddWithValue("@periodEnd", periodEnd);
recordId = (int)cmd.ExecuteScalar();
if (recordId < 1)
{
throw new Exception("Error inserting record, did not retrive new record ID.");
}
}
return recordId;
}
}
}
@@ -0,0 +1,472 @@
using bnhtrade.Core.Data.Database.Repository.Interface;
using bnhtrade.Core.Logic.Account;
using bnhtrade.Core.Logic.Validate;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace bnhtrade.Core.Data.Database.Repository.Implementation
{
internal class ExportInvoiceRepository : _Base, IExportInvoiceRepository
{
public ExportInvoiceRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
//
// invoice Insert methods
//
/// <summary>
/// Don't call this directly, use the logic layer instead (for validation and other checks).
/// </summary>
/// <param name="invoiceList">list of sales invoices to insert</param>
/// <returns>dectionary, key= invoice id, value= new invoice </returns>
public Dictionary<int, Model.Account.SalesInvoice> InsertSalesInvoices(IEnumerable<Model.Account.SalesInvoice> invoiceList)
{
var result = InsertBaseExecute(invoiceList);
var returnList = new Dictionary<int, Model.Account.SalesInvoice>();
foreach (var item in result)
{
returnList.Add(item.Key, (Model.Account.SalesInvoice)item.Value);
}
return returnList;
}
private Dictionary<int, Model.Account.Invoice> InsertBaseExecute(IEnumerable<Model.Account.Invoice> invoiceList)
{
if (invoiceList == null)
{
throw new ArgumentException("Invoice list is null");
}
var returnList = new Dictionary<int, Model.Account.Invoice>();
int invoiceCount = invoiceList.Count();
// make the inserts
foreach (var invoice in invoiceList)
{
int? invoiceId = null;
string sql = @"
INSERT INTO tblExportAccountInvoice (
ExportAccountInvoiceTypeID
,Contact
,InvoiceDate
,InvoiceDueDate
,InvoiceNumber
,Reference
,CurrencyCode
,LineUnitAmountIsTaxExclusive
,InvoiceAmount
,IsComplete
)
OUTPUT INSERTED.ExportAccountInvoiceID
VALUES (
@invoiceTypeId
,@contact
,@invoiceDate
,@invoiceDueDate
,@invoiceNumber
,@reference
,@currencyCode
,@lineUnitAmountIsTaxExclusive
,@invoiceAmount
,@markComplete
);";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@invoiceTypeId", (int)invoice.InvoiceType);
cmd.Parameters.AddWithValue("@contact", invoice.ContactName);
cmd.Parameters.AddWithValue("@invoiceDate", invoice.InvoiceDate);
cmd.Parameters.AddWithValue("@invoiceDueDate", invoice.InvoiceDueDate);
cmd.Parameters.AddWithValue("@reference", invoice.InvoiceReference);
cmd.Parameters.AddWithValue("@currencyCode", invoice.InvoiceCurrencyCode.ToString());
cmd.Parameters.AddWithValue("@lineUnitAmountIsTaxExclusive", invoice.InvoiceLineUnitAmountIsTaxExclusive);
cmd.Parameters.AddWithValue("@markComplete", false);
cmd.Parameters.AddWithValue("@invoiceNumber", invoice.InvoiceNumber);
cmd.Parameters.AddWithValue("@invoiceAmount", invoice.InvoiceTotalAmount);
invoiceId = (int)cmd.ExecuteScalar();
}
foreach (var line in invoice.InvoiceLineList)
{
string lineSql = @"
INSERT INTO tblExportAccountInvoiceLine (
ExportAccountInvoiceID
,AccountInvoiceLineItemID
,NetAmount
,AccountChartOfID
,TaxAmount
,AccountTaxCodeID
)
OUTPUT INSERTED.ExportAccountInvoiceLineID
VALUES (
@invoiceId
,(
SELECT AccountInvoiceLineItemID
FROM tblAccountInvoiceLineItem
WHERE ItemCode = @itemCode
)
,@netAmount
,(
SELECT AccountChartOfID
FROM tblAccountChartOf
WHERE AccountCode = @accountCode
)
,@taxAmount
,(
SELECT AccountTaxCodeID
FROM tblAccountTaxCode
WHERE TaxCode = @taxCode
)
);";
// insert record
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand) // Use _connection.CreateCommand()
{
cmd.CommandText = lineSql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@invoiceID", invoiceId);
cmd.Parameters.AddWithValue("@itemCode", line.ItemCode);
cmd.Parameters.AddWithValue("@netAmount", line.UnitAmount);
cmd.Parameters.AddWithValue("@accountCode", (int)line.Account.AccountCode);
cmd.Parameters.AddWithValue("@taxAmount", line.TaxAmountTotal);
cmd.Parameters.AddWithValue("@taxCode", line.TaxCode.TaxCode);
int lineId = (int)cmd.ExecuteScalar();
}
}
returnList.Add(invoiceId.Value, invoice);
}
if (returnList.Count != invoiceCount)
{
throw new Exception("Not all invoices were inserted into the export table. Expected: " + invoiceCount + ", Actual: " + returnList.Count);
}
else
{
return returnList;
}
}
//
// invoice read methods
//
/// <summary>
/// Returns list of invoice numbers that have not yet been exported (i.e. IsComplete=True), in InvoiceNumber asending order.
/// </summary>
/// <param name="invoiceType">Sales or Purchase</param>
/// <returns>Dictionary where key=ExportAccountInvoiceID, value=InvoiceNumber</returns>
public Dictionary<int, string> GetNewInvoiceNumbers(Model.Account.InvoiceType invoiceType)
{
var returnList = new Dictionary<int, string>();
string sql = @"
SELECT tblExportAccountInvoice.ExportAccountInvoiceID, [InvoiceNumber]
FROM tblExportAccountInvoice
WHERE (tblExportAccountInvoice.IsComplete = 0)
AND (tblExportAccountInvoice.ExportAccountInvoiceTypeID = @invoiceType)
ORDER BY [InvoiceNumber];";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@invoiceType", (int)invoiceType);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
returnList.Add(reader.GetInt32(0), reader.GetString(1));
}
}
}
return returnList;
}
/// <summary>
/// Get list of invoices by invoice id
/// </summary>
/// <param name="idList">list of invoice ids</param>
/// <returns>dictionary key=id, value=invoice-model</returns>
public Dictionary<int, Model.Account.SalesInvoice> GetSalesInvoiceById(IEnumerable<int> idList)
{
var returnList = new Dictionary<int, Model.Account.SalesInvoice>();
if (idList.Any() == false)
{
return returnList;
}
// get the account and tax code objects
//var taxcode = new Data.Database.Account.ReadTaxCode().GetAllActive();
//var account = new Data.Database.Account.ReadAccountCode().All();
var taxcodeIds = new Dictionary<int, int>();
var accountIds = new Dictionary<int, int>();
var lineItemIds = new Dictionary<int, int>();
// build sql string
string sql = @"
SELECT tblExportAccountInvoice.ExportAccountInvoiceID,
tblExportAccountInvoice.ExportAccountInvoiceTypeID,
tblExportAccountInvoice.Contact,
tblExportAccountInvoice.InvoiceNumber,
tblExportAccountInvoice.InvoiceDate,
tblExportAccountInvoice.InvoiceDueDate,
tblExportAccountInvoice.Reference,
tblExportAccountInvoice.CurrencyCode,
tblExportAccountInvoice.InvoiceAmount,
tblExportAccountInvoice.IsComplete,
tblExportAccountInvoiceLine.ExportAccountInvoiceLineID,
tblExportAccountInvoiceLine.AccountInvoiceLineItemID,
tblExportAccountInvoiceLine.AccountChartOfID,
tblExportAccountInvoiceLine.NetAmount,
tblExportAccountInvoiceLine.AccountTaxCodeID,
tblExportAccountInvoiceLine.TaxAmount,
tblExportAccountInvoice.LineUnitAmountIsTaxExclusive
FROM tblExportAccountInvoice
INNER JOIN
tblExportAccountInvoiceLine
ON tblExportAccountInvoice.ExportAccountInvoiceID = tblExportAccountInvoiceLine.ExportAccountInvoiceID
";
var sqlWhere = new Data.Database.SqlWhereBuilder();
sqlWhere.In("tblExportAccountInvoice.ExportAccountInvoiceID", idList, "WHERE");
sql = sql + sqlWhere.SqlWhereString + " ORDER BY tblExportAccountInvoice.ExportAccountInvoiceID, tblExportAccountInvoiceLine.ExportAccountInvoiceLineID; ";
int i = 0;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
sqlWhere.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows == false)
{
return returnList;
}
int? invoiceId = null;
int? previousInvoiceId = null;
Model.Account.SalesInvoice invoice = null;
i = -1;
while (reader.Read())
{
i++;
invoiceId = reader.GetInt32(0);
// test for first/next invoice
if (invoice == null || previousInvoiceId.Value != invoiceId.Value)
{
// if next invoice, add previous to return list
if (previousInvoiceId.HasValue)
{
// invoice complete, add to return list
returnList.Add(previousInvoiceId.Value, invoice);
}
// add header info to new invoice
invoice = new Model.Account.SalesInvoice(reader.GetBoolean(16));
int invoiceType = reader.GetInt32(1);
invoice.ContactName = reader.GetString(2);
invoice.InvoiceNumber = reader.GetString(3);
invoice.InvoiceDate = reader.GetDateTime(4);
invoice.InvoiceDueDate = reader.GetDateTime(5);
if (!reader.IsDBNull(6)) { invoice.InvoiceReference = reader.GetString(6); }
invoice.InvoiceCurrencyCode = Enum.Parse<Model.Account.CurrencyCode>(reader.GetString(7));
if (!reader.IsDBNull(8)) { invoice.InvoiceTotalAmount = reader.GetDecimal(8); }
bool isComplete = reader.GetBoolean(9);
// set credit note
if (invoice.InvoiceTotalAmount < 0)
{
invoice.IsCreditNote = true;
}
}
// add line info
var invoiceLine = new Model.Account.SalesInvoice.InvoiceLine(invoice);
int lineId = reader.GetInt32(10);
lineItemIds.Add(i, reader.GetInt32(11));
accountIds.Add(i, reader.GetInt32(12));
invoiceLine.UnitAmount = reader.GetDecimal(13);
invoiceLine.Quantity = 1;
taxcodeIds.Add(i, reader.GetByte(14));
invoiceLine.SetTaxAdjustmentByTaxTotal(reader.GetDecimal(15));
invoice.InvoiceLineList.Add(invoiceLine);
previousInvoiceId = invoiceId.Value;
}
// complete final invoice and add to list
returnList.Add(invoiceId.Value, invoice);
}
}
// get and add account/tax/item objects to invoice
var dbTaxCodes = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, null, taxcodeIds.Values.ToList());
var dbAccountCodes = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIds.Values.ToList());
var dbLineItems = new InvoiceRepository(_connection, _transaction).GetInvoiceLineItem(lineItemIds.Values.ToList());
i = -1;
foreach (var invoice in returnList.Values)
{
foreach (var line in invoice.InvoiceLineList)
{
i++;
line.TaxCode = dbTaxCodes[taxcodeIds[i]];
line.Account = dbAccountCodes[accountIds[i]];
// fill in missing data for line item, if required
var invoiceLineItem = dbLineItems[lineItemIds[i]];
line.ItemCode = invoiceLineItem.ItemCode;
if (string.IsNullOrEmpty(line.Description))
{
line.Description = invoiceLineItem.Name;
}
}
}
return returnList;
}
//
// invoice update methods
//
public int UpdateInvoiceHeaderDetail(int invoiceId, string invoiceNumber = null, bool? isComplete = null)
{
if (invoiceNumber == null && isComplete == null)
{
throw new ArgumentException("At least one of the parameters must be set to update invoice header details.");
}
// build the statement with my helper
var sqlupdate = new Core.Data.Database.SqlUpdateBuilder();
sqlupdate.SetTableName("tblExportAccountInvoice");
if (invoiceNumber != null)
sqlupdate.AddUpdateArugment("InvoiceNumber", invoiceNumber);
if (isComplete.HasValue)
sqlupdate.AddUpdateArugment("IsComplete", isComplete);
sqlupdate.AddWhereArugment("ExportAccountInvoiceID", invoiceId);
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.Transaction = _transaction as SqlTransaction;
cmd.CommandText = sqlupdate.GetSqlString();
sqlupdate.AddParametersToSqlCommand(cmd);
return cmd.ExecuteNonQuery();
}
}
//
// Invoice Delete Methods
//
public int DeleteInvoice(IEnumerable<int> invoiceIdList)
{
if (invoiceIdList == null || invoiceIdList.Count() == 0)
{
throw new ArgumentException("InvoiceIdList is empty, nothing to delete.");
}
int invoiceToDelete = invoiceIdList.Distinct().Count();
int invoiceEffected = 0;
// delete lines first
Core.Data.Database.SqlWhereBuilder sqlWhereBuilder = new Core.Data.Database.SqlWhereBuilder();
sqlWhereBuilder.In("ExportAccountInvoiceID", invoiceIdList);
int lineCount = DeleteInvoiceExecuteInvoiceLine(sqlWhereBuilder);
// then delete invoice
sqlWhereBuilder = new Core.Data.Database.SqlWhereBuilder();
sqlWhereBuilder.In("ExportAccountInvoiceID", invoiceIdList);
invoiceEffected = DeleteInvoiceExecuteInvoice(sqlWhereBuilder);
if (invoiceEffected == invoiceToDelete)
{
return invoiceEffected;
}
else
{
throw new Exception("Error: "
+ invoiceToDelete + " number invoices requested for deletion, "
+ invoiceEffected + " number invoices effected. Changes rolled back.");
}
}
public int DeleteInvoiceLine(int invoiceLineId)
{
// only being able to delete one line at a time is a design/safety decision
// otherwise, delete whole invoice
if (invoiceLineId <= 0)
{
throw new ArgumentException("InvoiceLineId must be greater than zero.");
}
Core.Data.Database.SqlWhereBuilder sqlWhereBuilder = new Core.Data.Database.SqlWhereBuilder();
sqlWhereBuilder.In("ExportAccountInvoiceLineID", new List<int> { invoiceLineId });
return DeleteInvoiceExecuteInvoiceLine(sqlWhereBuilder);
}
/// <summary>
/// Helper method Only intended for use with ExecuteInvoice() or ExecuteInvoiceLine()
/// </summary>
/// <param name="sql">the full sql statement</param>
/// <param name="sqlWhereBuilder">instance of the sql where builder helper</param>
/// <returns>Number of row effected (deleted)</returns>
private int DeleteInvoiceExecuteHelper(string sql, Core.Data.Database.SqlWhereBuilder sqlWhereBuilder)
{
// Only intended for ExecuteInvoice() or ExecuteInvoiceLine()
// important checks
if (sqlWhereBuilder.IsSetSqlWhereString == false)
{
throw new ArgumentException("SqlWhereBuilder is not set, set the SqlWhereBuilder before calling this method.");
}
if (sqlWhereBuilder.ParameterListCount == 0)
{
throw new Exception("Parameter list count is zero, this could delete all records in table, operation cancelled");
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction; // Assign the shared transaction
sqlWhereBuilder.AddParametersToSqlCommand(cmd);
return cmd.ExecuteNonQuery();
}
}
private int DeleteInvoiceExecuteInvoice(Core.Data.Database.SqlWhereBuilder sqlWhereBuilder)
{
string sql = "DELETE FROM tblExportAccountInvoice WHERE " + sqlWhereBuilder.SqlWhereString;
return DeleteInvoiceExecuteHelper(sql, sqlWhereBuilder);
}
private int DeleteInvoiceExecuteInvoiceLine(Core.Data.Database.SqlWhereBuilder sqlWhereBuilder)
{
string sql = "DELETE FROM tblExportAccountInvoiceLine WHERE " + sqlWhereBuilder.SqlWhereString;
return DeleteInvoiceExecuteHelper(sql, sqlWhereBuilder);
}
}
}
@@ -0,0 +1,585 @@
using bnhtrade.Core.Data.Database.Repository.Interface;
using FikaAmazonAPI.AmazonSpApiSDK.Models.EasyShip20220323;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace bnhtrade.Core.Data.Database.Repository.Implementation
{
internal class InvoiceRepository : _Base, IInvoiceRepository
{
public InvoiceRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public int CreateDefaultInvoiceLineItem(string itemCode)
{
string sql = @"
INSERT INTO tblAccountInvoiceLineItem ( ItemName, ItemCode )
OUTPUT INSERTED.AccountInvoiceLineItemID
VALUES ( @itemName, @itemCode )
";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@itemName", itemCode);
cmd.Parameters.AddWithValue("@itemCode", itemCode);
object obj = cmd.ExecuteScalar();
if (obj == null || obj == DBNull.Value)
{
throw new Exception("Error inserting new defalt invoice line item into database");
}
return (int)obj;
}
}
/// <summary>
/// Retrieves a collection of invoice line items, optionally including account and tax information.
/// </summary>
/// <remarks>This method queries the database to retrieve invoice line items. If <paramref
/// name="includeAccountInfo"/> or <paramref name="includeTaxInfo"/> is set to <see langword="true"/>,
/// additional queries are performed to fetch the corresponding account and tax information, which may impact
/// performance.</remarks>
/// <param name="itemCodes">An optional collection of item codes to filter the results. If <see langword="null"/> or empty, all invoice
/// line items are retrieved.</param>
/// <param name="includeAccountInfo">A value indicating whether to include account information for each invoice line item. If <see
/// langword="true"/>, the default account code is populated for each item. Defaults to <see langword="true"/>.</param>
/// <param name="includeTaxInfo">A value indicating whether to include tax information for each invoice line item. If <see
/// langword="true"/>, the default tax code is populated for each item. Defaults to <see langword="true"/>.</param>
/// <returns>A dictionary where the key is the table record id of the invoice line item, and the value is the
/// corresponding <see cref="Model.Account.InvoiceLineItem"/> object. The dictionary will be empty if no
/// matching items are found.</returns>
public Dictionary<int, Model.Account.InvoiceLineItem> GetInvoiceLineItem(
IEnumerable<int> itemIds = null, IEnumerable<string> itemCodes = null, bool includeAccountInfo = true, bool includeTaxInfo = true
)
{
var sqlwhere = new SqlWhereBuilder();
var returnList = new Dictionary<int, Model.Account.InvoiceLineItem>();
var accountCodeIdList = new Dictionary<int, int>(); // key=LineItemID, value=AccountChartOfID
var taxCodeIdList = new Dictionary<int, int>(); // key=LineItemID, value=AccountTaxCodeID
string sql = @"
SELECT [AccountInvoiceLineItemID]
,[ItemName]
,[ItemCode]
,[ItemDescription]
,[IsNewReviewRequired]
,[InvoiceLineEntryEnable]
,[AccountChartOfID_Default]
,[AccountTaxCodeID_Default]
FROM [e2A].[dbo].[tblAccountInvoiceLineItem]
WHERE 1=1 ";
if (itemCodes != null && itemCodes.Any())
{
sqlwhere.In("ItemCode", itemCodes, "AND");
sql += sqlwhere.SqlWhereString;
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
sqlwhere.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var lineItem = new Model.Account.InvoiceLineItem();
int recordId = reader.GetInt32(0);
lineItem.Name = reader.GetString(1);
lineItem.ItemCode = reader.GetString(2);
if (!reader.IsDBNull(3)) { lineItem.Description = reader.GetString(3); }
lineItem.IsNewReviewRequired = reader.GetBoolean(4);
lineItem.InvoiceLineEntryEnabled = reader.GetBoolean(5);
if (!reader.IsDBNull(6))
{
accountCodeIdList.Add(recordId, reader.GetInt32(6));
}
if (!reader.IsDBNull(7))
{
taxCodeIdList.Add(recordId, reader.GetInt32(7));
}
returnList.Add(recordId, lineItem);
}
}
}
// get account codes and add to result list
if (includeAccountInfo)
{
var accountCodeDictionary = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountCodeIdList.Values.ToList());
foreach (var accountCode in accountCodeIdList)
{
returnList[accountCode.Key].DefaultAccountCode = accountCodeDictionary[accountCode.Value];
}
}
// get tax codes
if (includeTaxInfo)
{
var taxCodeDictionary = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, null, taxCodeIdList.Values.ToList());
foreach (var taxCode in taxCodeIdList)
{
returnList[taxCode.Key].DefaultTaxCode = taxCodeDictionary[taxCode.Value];
}
}
return returnList;
}
public Dictionary<int, Model.Account.PurchaseInvoice> ReadPurchaseInvoice(IEnumerable<int> purchaseInvoiceIdList)
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoice>();
SqlWhereBuilder sqlBuilder = new SqlWhereBuilder();
//build sql query
string sql = @"
SELECT tblPurchase.PurchaseID
,tblPurchase.PurchaseNumber
,tblPurchase.RecordID
,tblPurchase.PurchaseDate
,tblPurchase.ContactID
,tblPurchase.SupplierRef
,tblPurchase.PurchaseTotalAmount
,tblPurchase.VatInclusiveAmounts
,tblPurchase.RecordCreated
,tblPurchase.RecordModified
,tblPurchase.IsActive
,tblAccountCurrency.CurrencyCode
,tblPurchaseChannel.PurchaseChannelName
,tblPurchaseStatus.PurchaseStatus
FROM tblPurchase
LEFT OUTER JOIN tblAccountCurrency ON tblPurchase.AccountCurrencyID = tblAccountCurrency.AccountCurrencyID
LEFT OUTER JOIN tblPurchaseStatus ON tblPurchase.PurchaseStatusID = tblPurchaseStatus.PurchaseStatusID
LEFT OUTER JOIN tblPurchaseChannel ON tblPurchase.PurchaseChannelID = tblPurchaseChannel.PurchaseChannelID
WHERE 1 = 1
";
// build the where statments
if (purchaseInvoiceIdList.Any())
{
sqlBuilder.In("[PurchaseID]", purchaseInvoiceIdList, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// dictionary so we can fill in details afterwards
var invoiceContactDict = new Dictionary<int, int>();
var purchaseIdList = new List<int>();
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int purchaseID = reader.GetInt32(0);
int purchaseNumber = reader.GetInt32(1);
int? recordID = null;
if (!reader.IsDBNull(2)) { recordID = reader.GetInt32(2); }
DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc);
int? contactID = null;
if (!reader.IsDBNull(4)) { contactID = reader.GetInt32(4); }
string supplierRef = null;
if (!reader.IsDBNull(5)) { supplierRef = reader.GetString(5); }
decimal? purchaseTotalAmount = null;
if (!reader.IsDBNull(6)) { purchaseTotalAmount = reader.GetDecimal(6); }
bool vatInclusiveAmounts = reader.GetBoolean(7);
DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(8), DateTimeKind.Utc);
DateTime recordModified = DateTime.SpecifyKind(reader.GetDateTime(9), DateTimeKind.Utc);
bool isActive = reader.GetBoolean(10);
string currencyCode = reader.GetString(11);
string purchaseChannelName = reader.GetString(12);
string purchaseStatus = null;
if (!reader.IsDBNull(13)) { purchaseStatus = reader.GetString(13); }
var invoice = new Model.Account.PurchaseInvoice();
invoice.PurchaseID = purchaseID;
invoice.PurchaseNumber = purchaseNumber;
invoice.RecordID = recordID;
invoice.PurchaseDate = purchaseDate;
invoice.SupplierRef = supplierRef;
//invoice.PurchaseTotalAmount = purchaseTotalAmount;
invoice.VatInclusiveAmounts = vatInclusiveAmounts;
invoice.RecordCreated = recordCreated;
invoice.RecordModified = recordModified;
invoice.IsActive = isActive;
invoice.CurrencyCode = currencyCode;
invoice.PurchaseChannel = purchaseChannelName;
// is there contact info that needs to be added?
if (contactID != null)
{
invoiceContactDict.Add(purchaseID, (int)contactID);
}
purchaseIdList.Add(purchaseID);
returnList.Add(purchaseID, invoice);
}
}
}
}
// add contact info
if (invoiceContactDict.Any())
{
var readContact = new Data.Database.Account.ReadContact();
readContact.ContactIdList = invoiceContactDict.Values.ToList();
var contactDict = readContact.Read();
if (contactDict.Any())
{
foreach (var invoice in returnList)
{
if (invoiceContactDict.ContainsKey(invoice.Value.PurchaseID))
{
int contactId = invoiceContactDict[invoice.Value.PurchaseID];
invoice.Value.Contact = contactDict[contactId];
}
}
}
}
// add invoice lines
var lines = ReadPurchaseInvoiceLine(purchaseIdList);
foreach (var invoice in returnList.Values)
{
foreach (var line in lines.Values)
{
if (line.PurchaseId == invoice.PurchaseID)
{
if (invoice.InvoiceLines == null)
{
invoice.InvoiceLines = new List<Model.Account.PurchaseInvoice.Line>();
}
invoice.InvoiceLines.Add(line);
}
}
}
return returnList;
}
/// <summary>
/// Retrieves purchase invoice lines based on specified filters.
/// </summary>
/// <remarks>This method queries the database to retrieve purchase invoice line details that match
/// the provided filters. The filters include invoice IDs, invoice line IDs, statuses, and item descriptions.
/// The returned dictionary maps the purchase line ID to its corresponding <see
/// cref="Model.Account.PurchaseInvoice.Line"/> object.</remarks>
/// <param name="invoiceIdList">A list of purchase invoice IDs to filter the results. If empty, no filtering is applied.</param>
/// <param name="invoiceLineIdList">A list of purchase invoice line IDs to filter the results. If empty, no filtering is applied.</param>
/// <param name="statusList">A list of statuses to filter the results. If empty, no filtering is applied.</param>
/// <param name="itemDescription">Searches for the specificed phases within the item description. Uses the LIKE AND sql function. Partial matches are supported. If empty, no filtering is
/// applied.</param>
/// <returns>A dictionary where the key is the purchase line ID and the value is the corresponding
/// Model.Account.PurchaseInvoice.Line object containing detailed information about the purchase invoice line.</returns>
/// <exception cref="Exception">Thrown if a fail-safe condition is triggered, indicating an unexpected issue with tax code assignment.</exception>
public Dictionary<int, Model.Account.PurchaseInvoice.Line> ReadPurchaseInvoiceLine
(List<int> invoiceIdList = null, List<int> invoiceLineIdList = null, List<string> statusList = null, List<string> itemDescriptionList = null)
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoice.Line>();
var sqlBuilder = new SqlWhereBuilder();
//build sql query
string sql = @"
SELECT tblPurchaseLine.PurchaseLineID
,tblPurchaseLine.PurchaseID
,tblPurchaseLineStatus.PurchaseLineStatus
,tblPurchaseLine.SupplierRef
,tblPurchaseLine.CheckedIn
,tblPurchaseLine.ItemDescription
,tblPurchaseLine.ItemQuantity
,tblPurchaseLine.ItemGross
,tblPurchaseLine.ItemTax
,tblPurchaseLine.ShippingGross
,tblPurchaseLine.ShippingTax
,tblPurchaseLine.OtherGross
,tblPurchaseLine.OtherTax
,tblPurchaseLine.AccountTaxCodeID
,tblPurchaseLine.Tax_AccountTransactionID
,tblPurchaseLine.Net_AccountChartOfID
,tblPurchaseLine.Net_AccountTransactionID
,tblPurchaseLine.RecordCreated
,tblPurchaseLine.RecordModified
,tblPurchaseLine.IsActive
,tblAccountTaxCode.TaxCode
FROM tblPurchaseLine
INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID
LEFT OUTER JOIN tblAccountTaxCode ON tblPurchaseLine.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID
WHERE 1 = 1 ";
// build the where statments
if (invoiceIdList != null || invoiceIdList.Any())
{
sqlBuilder.In("PurchaseID", invoiceLineIdList, "AND");
}
if (invoiceLineIdList != null || invoiceLineIdList.Any())
{
sqlBuilder.In("PurchaseLineID", invoiceLineIdList, "AND");
}
if (statusList != null || statusList.Any())
{
sqlBuilder.In("PurchaseLineStatus", invoiceLineIdList, "AND");
}
if (itemDescriptionList != null || itemDescriptionList.Any())
{
sqlBuilder.LikeAnd("ItemDescription", itemDescriptionList, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// catch taxcode to add in after db read
var lineTaxCodeDict = new Dictionary<int, string>();
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
int purchaseLineID = reader.GetInt32(0);
int purchaseID = reader.GetInt32(1);
string purchaseLineStatus = reader.GetString(2);
string supplierRef = null;
if (!reader.IsDBNull(3)) { supplierRef = reader.GetString(3); }
DateTime? checkedIn = null;
if (!reader.IsDBNull(4)) { checkedIn = DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc); }
string itemDescription = null;
if (!reader.IsDBNull(5)) { itemDescription = reader.GetString(5); }
int itemQuantity = reader.GetInt32(6);
decimal itemGross = 0;
if (!reader.IsDBNull(7)) { itemGross = reader.GetDecimal(7); }
decimal itemTax = 0;
if (!reader.IsDBNull(8)) { itemTax = reader.GetDecimal(8); }
decimal shippingGross = 0;
if (!reader.IsDBNull(9)) { shippingGross = reader.GetDecimal(9); }
decimal shippingTax = 0;
if (!reader.IsDBNull(10)) { shippingTax = reader.GetDecimal(10); }
decimal otherGross = 0;
if (!reader.IsDBNull(11)) { otherGross = reader.GetDecimal(11); }
decimal otherTax = 0;
if (!reader.IsDBNull(12)) { otherTax = reader.GetDecimal(12); }
int accountTaxCodeID = reader.GetInt32(13);
int? tax_AccountTransactionID = null;
if (!reader.IsDBNull(14)) { tax_AccountTransactionID = reader.GetInt32(14); }
int net_AccountChartOfID = reader.GetInt32(15);
int? net_AccountTransactionID = null;
if (!reader.IsDBNull(16)) { net_AccountTransactionID = reader.GetInt32(16); }
DateTime recordModified;
DateTime recordCreated = DateTime.SpecifyKind(reader.GetDateTime(17), DateTimeKind.Utc);
if (reader.IsDBNull(18)) { recordModified = recordCreated; }
else { recordModified = DateTime.SpecifyKind(reader.GetDateTime(18), DateTimeKind.Utc); }
bool isActive = reader.GetBoolean(19);
string accountTaxCode = reader.GetString(20);
var line = new Model.Account.PurchaseInvoice.Line();
line.PurchaseLineId = purchaseLineID;
line.PurchaseId = purchaseID;
line.Status = purchaseLineStatus;
line.SupplierRef = supplierRef;
line.CheckedIn = checkedIn;
line.ItemDescription = itemDescription;
line.ItemQuantity = itemQuantity;
line.ItemGross = itemGross;
line.ItemTax = itemTax;
line.ShippingGross = shippingGross;
line.ShippingTax = shippingTax;
line.OtherGross = otherGross;
line.OtherTax = otherTax;
line.Tax_AccountTransactionId = tax_AccountTransactionID;
line.Net_AccountChartOfId = net_AccountChartOfID;
line.Net_AccountTransactionId = net_AccountTransactionID;
line.RecordModified = recordModified;
line.RecordCreated = recordCreated;
line.IsActive = isActive;
returnList.Add(purchaseLineID, line);
lineTaxCodeDict.Add(purchaseLineID, accountTaxCode);
}
}
}
}
// read tax codes form db and add to return object
var taxcodeList = new AccountTaxRepository(_connection, _transaction).ReadTaxCodeInfo(null, lineTaxCodeDict.Values.ToList()).Values.ToList();
foreach (var line in returnList.Values)
{
foreach (var taxcode in taxcodeList)
{
if (taxcode.TaxCode == lineTaxCodeDict[line.PurchaseLineId])
{
line.AccountTaxCode = taxcode;
break;
}
}
if (line.AccountTaxCode == null)
{
throw new Exception("Fail safe, this really shouodn't happen");
}
}
// all done
return returnList;
}
public Dictionary<int, Model.Account.PurchaseInvoiceLineStatus> ReadPurchaseInvoiceLineStatus()
{
var returnList = new Dictionary<int, Model.Account.PurchaseInvoiceLineStatus>();
string sql = @"
SELECT [PurchaseLineStatusID]
,[PurchaseLineStatus]
,[ListSort]
,[TimeStamp]
FROM [e2A].[dbo].[tblPurchaseLineStatus]
ORDER BY [ListSort]";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
// do something
}
else
{
while (reader.Read())
{
int id = reader.GetInt32(0);
string name = reader.GetString(1);
int lineSort = reader.GetInt32(2);
var returnItem = new Model.Account.PurchaseInvoiceLineStatus(id, name, lineSort);
returnList.Add(id, returnItem);
}
}
}
}
return returnList;
}
public List<Model.Account.PurchaseInvoiceLineSummary> ReadPurchaseInvoiceLineSummary(DateTime periodTo, string lineStatus, List<string> descriptionSearch)
{
var returnList = new List<Model.Account.PurchaseInvoiceLineSummary>();
var sqlBuilder = new bnhtrade.Core.Data.Database.SqlWhereBuilder();
//build sql query
string sql = @"
SELECT tblPurchase.PurchaseDate
,tblPurchase.PurchaseID
,tblPurchase.PurchaseNumber
,tblPurchaseLine.PurchaseLineID
,tblPurchaseLine.ItemDescription
,tblPurchaseLineStatus.PurchaseLineStatus
FROM tblPurchase
INNER JOIN tblPurchaseLine ON tblPurchase.PurchaseID = tblPurchaseLine.PurchaseID
INNER JOIN tblPurchaseLineStatus ON tblPurchaseLine.PurchaseLineStatusID = tblPurchaseLineStatus.PurchaseLineStatusID
WHERE tblPurchase.PurchaseDate <= @purchaseDate
";
if (lineStatus != null)
{
sql = sql + " AND PurchaseLineStatus = @purchaseLineStatus ";
}
// build the where statments
if (descriptionSearch.Any())
{
sqlBuilder.LikeAnd("ItemDescription", descriptionSearch, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@purchaseDate", periodTo);
if (lineStatus != null)
{
cmd.Parameters.AddWithValue("@purchaseLineStatus", lineStatus);
}
sqlBuilder.AddParametersToSqlCommand(cmd);
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
DateTime purchaseDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc);
int purchaseID = reader.GetInt32(1);
int purchaseNumber = reader.GetInt32(2);
int purchaseLineID = reader.GetInt32(3);
string itemDescription = reader.GetString(4);
string purchaseLineStatus = reader.GetString(5);
var item = new Model.Account.PurchaseInvoiceLineSummary();
item.PurchaseDate = purchaseDate;
item.PurchaseId = purchaseID;
item.PurchaseNumber = purchaseNumber;
item.PurchaseLineId = purchaseLineID;
item.ItemDescription = itemDescription;
item.LineStatus = purchaseLineStatus;
returnList.Add(item);
}
}
}
return returnList;
}
}
}
@@ -0,0 +1,372 @@
using bnhtrade.Core.Data.Database._BoilerPlate;
using bnhtrade.Core.Data.Database.Repository.Interface;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
namespace bnhtrade.Core.Data.Database.Repository.Implementation
{
internal class JournalRepository : _Base, IJournalRepository
{
public JournalRepository(IDbConnection connection, IDbTransaction transaction) : base(connection, transaction)
{
}
public Dictionary<int, Core.Model.Account.Journal> ReadJournal(List<int> journalIdList)
{
var sqlBuilder = new SqlWhereBuilder();
//build sql query
string sql = @"
SELECT tblAccountJournal.AccountJournalID
,tblAccountJournal.AccountJournalTypeID
,tblAccountJournal.EntryDate
,tblAccountJournal.PostDate
,tblAccountJournal.LastModified
,tblAccountJournal.IsLocked
,tblAccountJournalPost.AccountJournalPostID
,tblAccountJournalPost.AccountChartOfID
,tblAccountJournalPost.AmountGbp
FROM tblAccountJournal
INNER JOIN tblAccountJournalPost ON tblAccountJournal.AccountJournalID = tblAccountJournalPost.AccountJournalID
WHERE 1 = 1 ";
// build the where statments
if (journalIdList.Any())
{
sqlBuilder.In("tblAccountJournal.AccountJournalID", journalIdList, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// build tuple list
var dbJournalList = new List<(
int AccountJournalId
, int AccountJournalTypeId
, DateTime EntryDate
, DateTime PostDate
, DateTime LastModified
, bool IsLocked
)>();
var dbJournalPostList = new List<(
int AccountJournalId
, int AccountJournalPostId
, int AccountChartOfId
, decimal AmountGbp
)>();
bool hasRows = false;
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
if (sqlBuilder.ParameterListIsSet)
{
sqlBuilder.AddParametersToSqlCommand(cmd);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
hasRows = true;
int lastJournalId = 0;
while (reader.Read())
{
// read journal header
int journalId = reader.GetInt32(0);
if (journalId != lastJournalId)
{
lastJournalId = journalId;
(int AccountJournalId
, int AccountJournalTypeId
, DateTime EntryDate
, DateTime PostDate
, DateTime LastModified
, bool IsLocked
)
journal =
(journalId
, reader.GetInt32(1)
, DateTime.SpecifyKind(reader.GetDateTime(2), DateTimeKind.Utc)
, DateTime.SpecifyKind(reader.GetDateTime(3), DateTimeKind.Utc)
, DateTime.SpecifyKind(reader.GetDateTime(4), DateTimeKind.Utc)
, reader.GetBoolean(5)
);
dbJournalList.Add(journal);
}
// read journal posts
(int AccountJournalId
, int AccountJournalPostId
, int AccountChartOfId
, decimal AmountGbp
)
journalPost =
(journalId
, reader.GetInt32(6)
, reader.GetInt32(7)
, reader.GetDecimal(8)
);
dbJournalPostList.Add(journalPost);
}
}
}
}
var returnList = new Dictionary<int, Core.Model.Account.Journal>();
if (hasRows)
{
// build lists to filter db results by
var journalTypeIdList = new List<int>();
var accountIdList = new List<int>();
foreach (var item in dbJournalList)
{
journalTypeIdList.Add(item.AccountJournalTypeId);
}
foreach (var item in dbJournalPostList)
{
accountIdList.Add(item.AccountChartOfId);
}
// get journalTypes from db
var journalTypeDict = new JournalRepository(_connection, _transaction).ReadJournalType(journalTypeIdList);
// get accounts from db
var accountDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIdList);
// build final return dictionary
foreach (var dbJournal in dbJournalList)
{
// build posts
var newPosts = new List<Core.Model.Account.Journal.Post>();
foreach (var dbJournalPost in dbJournalPostList)
{
if (dbJournalPost.AccountJournalId == dbJournal.AccountJournalId)
{
var newPost = new Core.Model.Account.Journal.Post(
dbJournalPost.AccountJournalPostId
, accountDict[dbJournalPost.AccountChartOfId]
, dbJournalPost.AmountGbp);
newPosts.Add(newPost);
}
}
// create the journal
var newJournal = new Core.Model.Account.Journal(
dbJournal.AccountJournalId
, journalTypeDict[dbJournal.AccountJournalTypeId]
, newPosts
, dbJournal.EntryDate
, dbJournal.PostDate
, dbJournal.LastModified
, dbJournal.IsLocked);
returnList.Add(dbJournal.AccountJournalId, newJournal);
}
}
// all done, return the list herevar
return returnList;
}
/// <summary>
/// Test for locked journal entry
/// </summary>
/// <returns>False on locked journal entry</returns>
public bool ReadJournalIsLocked(int journalId)
{
string sql = @"
SELECT
tblAccountJournal.IsLocked
FROM
tblAccountJournal
WHERE
tblAccountJournal.AccountJournalID=@accountJournalId;";
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
object obj = cmd.ExecuteScalar();
if (obj == null)
{
throw new Exception("Journal entry not found for AccountJournalID=" + journalId);
}
else
{
return (bool)obj;
}
}
}
public Dictionary<int, Model.Account.JournalType> ReadJournalType(List<int> journalTypeIds = null, List<string> typeTitles = null)
{
var sqlBuilder = new SqlWhereBuilder();
// create the return (emptyP list) here
var returnList = new Dictionary<int, Model.Account.JournalType>();
sqlBuilder.Init();
//build sql query
string sql = @"
SELECT [AccountJournalTypeID]
,[TypeTitle]
,[ChartOfAccountID_Debit]
,[ChartOfAccountID_Credit]
FROM [e2A].[dbo].[tblAccountJournalType]
WHERE 1 = 1 ";
// build the where statments
if (journalTypeIds.Any())
{
sqlBuilder.In("AccountJournalTypeID", journalTypeIds, "AND");
}
if (typeTitles.Any())
{
sqlBuilder.In("TypeTitle", typeTitles, "AND");
}
// append where string to the sql
if (sqlBuilder.IsSetSqlWhereString)
{
sql = sql + sqlBuilder.SqlWhereString;
}
// create dictionary to add credit/debit accounts on after db read
var creditDict = new Dictionary<int, int>();
var debitDict = new Dictionary<int, int>();
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = sql;
cmd.Transaction = _transaction as SqlTransaction;
if (sqlBuilder.ParameterListIsSet)
{
sqlBuilder.AddParametersToSqlCommand(cmd);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
// read from db and create object
int journalTypeId = reader.GetInt32(0);
string title = reader.GetString(1);
int? debitAccountId = null;
if (!reader.IsDBNull(2)) { debitAccountId = reader.GetInt32(2); }
int? creditAccountId = null;
if (!reader.IsDBNull(3)) { creditAccountId = reader.GetInt32(3); }
// build return list
var item = new Model.Account.JournalType(journalTypeId, title);
returnList.Add(journalTypeId, item);
// build dictionaries
if (debitAccountId != null)
{
debitDict.Add(journalTypeId, debitAccountId.Value);
}
if (creditAccountId != null)
{
creditDict.Add(journalTypeId, creditAccountId.Value);
}
}
}
}
}
// get account objects from db
var accountIdList = debitDict.Values.ToList();
accountIdList.AddRange(creditDict.Values.ToList());
var dbDict = new AccountCodeRepository(_connection, _transaction).ReadAccountCode(accountIdList);
// add to the returnlist
foreach (var account in returnList.Values)
{
Model.Account.Account debitAccount = null;
if (debitDict.ContainsKey(account.JournalTypeId))
{
debitAccount = dbDict[debitDict[account.JournalTypeId]];
}
Model.Account.Account creditAccount = null;
if (creditDict.ContainsKey(account.JournalTypeId))
{
creditAccount = dbDict[creditDict[account.JournalTypeId]]; // key of 59 needed
}
account.AddDefaultAccounts(creditAccount, debitAccount);
}
// all done, return the list here
return returnList;
}
/// <summary>
/// Old code needs sorting
/// </summary>
public bool DeleteJournal(int accountJournalId)
{
bool IsLocked = ReadJournalIsLocked(accountJournalId);
if (IsLocked == true)
{
return false;
}
// make the delete
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = @"
DELETE FROM tblAccountJournalPost
WHERE AccountJournalID=@accountJournalId;";
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
int rows = cmd.ExecuteNonQuery();
if (rows == 0)
{
throw new Exception("Journal entry and/or entry posts do not exist for AccountJournalId=" + accountJournalId);
}
}
using (SqlCommand cmd = _connection.CreateCommand() as SqlCommand)
{
cmd.CommandText = @"
DELETE FROM tblAccountJournal
WHERE AccountJournalID=@accountJournalId;";
cmd.Transaction = _transaction as SqlTransaction;
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
cmd.ExecuteNonQuery();
}
return true;
}
}
}

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