mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-03-19 06:27:15 +00:00
Added feature to handle different tax types when creating Xero sales invoice from Amazon settlement reports. (#1)
9678 lines
544 KiB
C#
9678 lines
544 KiB
C#
using MarketplaceWebService;
|
|
using MarketplaceWebService.Model;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data.SqlClient;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using MWSFinancesService;
|
|
using MWSFinancesService.Model;
|
|
using System.Xml.Linq;
|
|
using System.IO.Compression;
|
|
using System.Threading;
|
|
using System.Transactions;
|
|
using System.Text.RegularExpressions;
|
|
using MarketplaceWebServiceProducts.Model;
|
|
using MarketplaceWebServiceProducts;
|
|
using System.Data.SqlTypes;
|
|
using System.Security.Cryptography;
|
|
using bnhtradeDatabaseClient.AmazonMWS;
|
|
|
|
namespace bnhtradeDatabaseClient
|
|
{
|
|
namespace Database
|
|
{
|
|
public class Connection
|
|
{
|
|
public class DatabaseConnectionDetail
|
|
{
|
|
public string DataSource { get; } = "SQL-Server";
|
|
public string InitialCatalogue { get; } = "e2A";
|
|
public string UserId { get; set; }
|
|
public string Password { get; set; }
|
|
public bool PersistSecurityInfo { get; set; } = true;
|
|
public bool MultipleActiveResults { get; set; } = true;
|
|
public string ConnectionString
|
|
{
|
|
get
|
|
{
|
|
return "Data Source=" + DataSource + ";Initial Catalog=" + InitialCatalogue + ";Persist Security Info=" + PersistSecurityInfo.ToString()
|
|
+ ";User ID=" + UserId + ";Password=" + Password + ";MultipleActiveResultSets=" + MultipleActiveResults.ToString();
|
|
}
|
|
}
|
|
}
|
|
public SqlConnection DatabaseConnection(DatabaseConnectionDetail connDetails)
|
|
{
|
|
if (connDetails.InitialCatalogue == "" || connDetails.DataSource == "" || connDetails.UserId == "" || connDetails.Password == "")
|
|
{
|
|
throw new Exception("Insuficent info supplied for sql connection string");
|
|
}
|
|
SqlConnection sqlConn = new SqlConnection(connDetails.ConnectionString);
|
|
|
|
return sqlConn;
|
|
}
|
|
}
|
|
|
|
public class Consistancy
|
|
{
|
|
// add some database consistancy checkes here as and when needed
|
|
|
|
public static void ConsistancyCheckRunAll(string sqlConnectionString)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace EbayQuery
|
|
{
|
|
public class Ebay
|
|
{
|
|
/// <summary>
|
|
/// Function returns records ID if a matching listing is found, 0 if not
|
|
/// </summary>
|
|
/// <param name="itemNumber"></param> 12 digit number string
|
|
/// <param name="listingEnd"></param> Allows for an error of +/- 2 days in supplied end datetime -- function will accept date with no time
|
|
/// <param name="sqlConn"></param>
|
|
/// <returns></returns>
|
|
public int EbayListingItemGet(string sqlConnectionString, string itemNumber, DateTime listingEnd)
|
|
{
|
|
if (itemNumber.Length != 12)
|
|
{ throw new Exception("Error, eBay item number must consist of a 12 charater numeric string."); }
|
|
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT EbayListingItemID
|
|
FROM tblEbayListingItem
|
|
WHERE EbayItemNumber=@itemNumber
|
|
AND ListingEndDateTime > DATEADD(day, -2, @listingEnd) AND ListingEndDateTime < DATEADD(day, +2, @listingEnd)"
|
|
, sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@itemNumber", itemNumber);
|
|
cmd.Parameters.AddWithValue("@listingEnd", listingEnd.ToUniversalTime());
|
|
|
|
object result = cmd.ExecuteScalar();
|
|
if (result == null)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return Convert.ToInt32(result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public (int listingId, bool isNewListingItem, bool isNewListing) EbayListingItemInsert
|
|
(
|
|
string sqlConnectionString, string itemNumber, DateTime listingEnd, string listingTitle, string listingDescription, string ebayUser,
|
|
bool isAuction, decimal price, DateTime priceTime, decimal shipping, string itemLocation, string category,
|
|
FileStream imageFile, string imageFileExtension
|
|
)
|
|
{
|
|
// first off, check if listing-item already exists, return id if it does
|
|
int listingItemId = EbayListingItemGet(sqlConnectionString, itemNumber, listingEnd);
|
|
if (listingItemId > 0)
|
|
{ return (listingItemId, false, false); }
|
|
|
|
// continue if there is no listing
|
|
bool newListing = false;
|
|
|
|
// settings/checks
|
|
if (listingTitle.Length == 0 || ebayUser.Length == 0 || itemLocation.Length == 0 || category.Length == 0)
|
|
{ throw new Exception("Required parameter(s) missing."); }
|
|
|
|
if (string.IsNullOrWhiteSpace(listingDescription))
|
|
{ listingDescription = ""; }
|
|
|
|
int imageFileSize;
|
|
if (imageFile == null)
|
|
{ imageFileSize = 0; }
|
|
else
|
|
{ imageFileSize = Convert.ToInt32(imageFile.Length); } // long to int -- good for files up to 2.14 GB
|
|
|
|
byte[] md5ByteArray = new byte[0];
|
|
if (imageFileSize > 0)
|
|
{
|
|
using (var md5 = MD5.Create())
|
|
{
|
|
md5ByteArray = md5.ComputeHash(imageFile);
|
|
}
|
|
}
|
|
|
|
// file extention checks
|
|
if (imageFileExtension.Length > 0)
|
|
{
|
|
if (imageFileExtension.Substring(0, 1) == ".")
|
|
{ imageFileExtension = imageFileExtension.Substring(1, imageFileExtension.Length - 1); }
|
|
if (imageFileExtension.Length < 3 & imageFileSize > 0)
|
|
{ throw new Exception("Image file extension required if image file is present."); }
|
|
}
|
|
|
|
listingEnd = DateTime.SpecifyKind(listingEnd, DateTimeKind.Utc);
|
|
priceTime = DateTime.SpecifyKind(priceTime, DateTimeKind.Utc);
|
|
|
|
// if listing-item does not exist, look for matching 'Listing'
|
|
// for speed, do this in two stages as description field on sql server cannot be indexed
|
|
// >> first stage
|
|
int listingId = 0;
|
|
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT EbayListingID " +
|
|
"FROM tblEbayListing " +
|
|
"WHERE ListingTitle=@listingTitle AND EbayUser=@ebayUser AND ItemLocation=@itemLocation AND Category=@category " +
|
|
"AND ListingImageHashMD5=@listingImageHashMD5"
|
|
, sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@listingTitle", listingTitle);
|
|
cmd.Parameters.AddWithValue("@ebayUser", ebayUser);
|
|
cmd.Parameters.AddWithValue("@itemLocation", itemLocation);
|
|
cmd.Parameters.AddWithValue("@category", category);
|
|
//cmd.Parameters.Add("@listingImageHashMD5", SqlDbType.VarBinary).Value = md5ByteArray;
|
|
cmd.Parameters.AddWithValue("@listingImageHashMD5", md5ByteArray);
|
|
if (imageFileSize > 0)
|
|
{
|
|
//cmd.Parameters.AddWithValue("@listingImageHashMD5", md5ByteArray);
|
|
//cmd.Parameters.AddWithValue("@listingImageFileExtension", imageFileExtension);
|
|
}
|
|
else
|
|
{
|
|
//cmd.Parameters.AddWithValue("@listingImageHashMD5", DBNull.Value);
|
|
//cmd.Parameters.AddWithValue("@listingImageFileExtension", DBNull.Value);
|
|
}
|
|
|
|
object result = cmd.ExecuteScalar();
|
|
if (result != null)
|
|
{
|
|
listingId = Convert.ToInt32(result);
|
|
}
|
|
}
|
|
|
|
// >> second stage
|
|
if (listingId > 0)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT EbayListingID
|
|
FROM tblEbayListing
|
|
WHERE EbayListingID=@ebayListingID AND ListingDescription=@listingDescription
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@ebayListingID", listingId);
|
|
cmd.Parameters.AddWithValue("@listingDescription", listingDescription);
|
|
|
|
object result = cmd.ExecuteScalar();
|
|
if (result == null)
|
|
{
|
|
// match not found, set variable to 0 and add listing to db
|
|
listingId = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
// add listing if not
|
|
if (listingId == 0)
|
|
{
|
|
newListing = true;
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"INSERT INTO tblEbayListing (ListingTitle, ListingDescription, EbayUser, ItemLocation, Category, " +
|
|
" ListingImage, ListingImageSizeByte, ListingImageFileExtension, ListingImageHashMD5) " +
|
|
"OUTPUT INSERTED.EbayListingID " +
|
|
"VALUES (@listingTitle, @listingDescription, @ebayUser, @itemLocation, @category, " +
|
|
" @listingImage, @listingImageSizeByte, @listingImageFileExtension, @listingImageHashMD5)"
|
|
, sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@listingTitle", listingTitle);
|
|
cmd.Parameters.AddWithValue("@listingDescription", listingDescription);
|
|
cmd.Parameters.AddWithValue("@ebayUser", ebayUser);
|
|
cmd.Parameters.AddWithValue("@itemLocation", itemLocation);
|
|
cmd.Parameters.AddWithValue("@category", category);
|
|
cmd.Parameters.AddWithValue("@listingImageSizeByte", imageFileSize);
|
|
cmd.Parameters.AddWithValue("@listingImageHashMD5", md5ByteArray);
|
|
cmd.Parameters.AddWithValue("@listingImageFileExtension", imageFileExtension);
|
|
if (imageFileSize > 0)
|
|
{
|
|
// open the file and map it to an SqlBytes instance that we use as the parameter value.
|
|
SqlBytes bytesImageFile = new SqlBytes(imageFile);
|
|
cmd.Parameters.AddWithValue("@listingImage", bytesImageFile);
|
|
}
|
|
else
|
|
{
|
|
cmd.Parameters.AddWithValue("@listingImage", new byte[0]);
|
|
}
|
|
|
|
listingId = (int)cmd.ExecuteScalar();
|
|
}
|
|
}
|
|
|
|
// add listing-item
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"INSERT INTO tblEbayListingItem (EbayListingID, EbayItemNumber, ListingEndDateTime, IsAuction, Price, PriceDateTime, Shipping) " +
|
|
"OUTPUT INSERTED.EbayListingItemID " +
|
|
"VALUES (@listingId, @itemNumber, @listingEnd, @isAuction, @price, @priceTime, @shipping)"
|
|
, sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@listingId", listingId);
|
|
cmd.Parameters.AddWithValue("@itemNumber", itemNumber);
|
|
cmd.Parameters.AddWithValue("@listingEnd", listingEnd);
|
|
cmd.Parameters.AddWithValue("@isAuction", isAuction);
|
|
cmd.Parameters.AddWithValue("@price", price);
|
|
cmd.Parameters.AddWithValue("@priceTime", priceTime);
|
|
cmd.Parameters.AddWithValue("@shipping", shipping);
|
|
|
|
listingItemId = (int)cmd.ExecuteScalar();
|
|
}
|
|
scope.Complete();
|
|
}
|
|
}
|
|
return (listingItemId, true, newListing);
|
|
}
|
|
}
|
|
}
|
|
namespace Export
|
|
{
|
|
public class ExportQuery
|
|
{
|
|
public static int WIP_ExportAccountInvoiceInsert(string sqlConnectionString, int invoiceTypeId, string contact, DateTime invoiceDate,
|
|
DateTime invoiceDueDate, string reference, string currencyCode, string invoiceNumber = "", bool markComplete = false)
|
|
{
|
|
//checks
|
|
if (currencyCode.Length != 3)
|
|
{
|
|
throw new Exception("Incorrect currency code");
|
|
}
|
|
|
|
// onto business
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblExportAccountInvoice
|
|
(ExportAccountInvoiceTypeID, Contact, InvoiceDate, InvoiceDueDate, InvoiceNumber, Reference, CurrencyCode, IsComplete)
|
|
OUTPUT
|
|
INSERTED.ExportAccountInvoiceID
|
|
VALUES
|
|
(@invoiceTypeId, @contact, @invoiceDate, @invoiceDueDate, @invoiceNumber, @reference, @currencyCode, @markComplete);
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@invoiceTypeId", invoiceTypeId);
|
|
cmd.Parameters.AddWithValue("@contact", contact);
|
|
cmd.Parameters.AddWithValue("@invoiceDate", invoiceDate);
|
|
cmd.Parameters.AddWithValue("@invoiceDueDate", invoiceDueDate);
|
|
cmd.Parameters.AddWithValue("@reference", reference);
|
|
cmd.Parameters.AddWithValue("@currencyCode", currencyCode);
|
|
//cmd.Parameters.AddWithValue("@invoiceTotal", invoiceTotal);
|
|
cmd.Parameters.AddWithValue("@markComplete", markComplete);
|
|
if (invoiceNumber == "")
|
|
{ cmd.Parameters.AddWithValue("@invoiceNumber", DBNull.Value); }
|
|
else
|
|
{ cmd.Parameters.AddWithValue("@invoiceNumber", invoiceNumber); }
|
|
|
|
return (int)cmd.ExecuteScalar();
|
|
}
|
|
}
|
|
}
|
|
|
|
// function returns Id of inserted line, 0 for lineInsert disabled, exception for IsNew
|
|
public static int WIP_ExportAccountInvoiceLineInsert(string sqlConnectionString, int invoiceId, int invoiceLineTypeId,
|
|
decimal netAmount, decimal taxAmount)
|
|
{
|
|
int netAccountId;
|
|
int taxAccountId;
|
|
|
|
// get default net and tax account IDs
|
|
// suppress any ambient transactions, can cause locks on table inserts
|
|
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress))
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
IsNewReviewRequired, InvoiceLineEntryEnable, AccountChartOfID_Default, AccountTaxCodeID_Default
|
|
FROM
|
|
tblExportAccountInvoiceLineType
|
|
WHERE
|
|
ExportAccountInvoiceLineTypeID=@invoiceLineTypeId;
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@invoiceLineTypeId", invoiceLineTypeId);
|
|
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
// checks
|
|
if (reader.GetBoolean(0) == true)
|
|
{
|
|
throw new Exception("New Type requires review where ExportAccountInvoiceLineTypeID=" + invoiceLineTypeId);
|
|
}
|
|
//// any invoice lines that shouldn't be entered will be taken out after the fact
|
|
//if (reader.GetBoolean(1) == false)
|
|
//{
|
|
// return 0;
|
|
//}
|
|
if (reader.IsDBNull(2) || reader.IsDBNull(3))
|
|
{
|
|
throw new Exception("Default account values missing where ExportAccountInvoiceLineTypeID=" + invoiceLineTypeId);
|
|
}
|
|
|
|
netAccountId = reader.GetInt32(2);
|
|
taxAccountId = reader.GetInt32(3);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Supplied TypeId does not exist in table, where ExportAccountInvoiceLineTypeID=" + invoiceLineTypeId);
|
|
}
|
|
}
|
|
}
|
|
scope.Complete();
|
|
}
|
|
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
// insert record
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblExportAccountInvoiceLine
|
|
(ExportAccountInvoiceID, ExportAccountInvoiceLineTypeID, NetAmount, AccountChartOfID, TaxAmount, AccountTaxCodeID)
|
|
OUTPUT
|
|
INSERTED.ExportAccountInvoiceLineID
|
|
VALUES
|
|
(@invoiceId, @invoiceLineTypeId, @netAmount, @netAccountId, @taxAmount, @taxAccountId);
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@invoiceID", invoiceId);
|
|
cmd.Parameters.AddWithValue("@invoiceLineTypeID", invoiceLineTypeId);
|
|
cmd.Parameters.AddWithValue("@netAmount", netAmount);
|
|
cmd.Parameters.AddWithValue("@netAccountId", netAccountId);
|
|
cmd.Parameters.AddWithValue("@taxAmount", taxAmount);
|
|
cmd.Parameters.AddWithValue("@taxAccountId", taxAccountId);
|
|
|
|
return (int)cmd.ExecuteScalar();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public static int WIP_GetImportInvoiceLineTypeId(string sqlConnectionString, string matchString)
|
|
{
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 Skip transpose, type is new or has not been reviewed yet */
|
|
|
|
if (matchString.Length == 0)
|
|
{
|
|
throw new Exception("Matchstring is of zero lenth");
|
|
}
|
|
|
|
bool insertNew = false;
|
|
using (TransactionScope scopeSupress = new TransactionScope(TransactionScopeOption.Suppress))
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT ExportAccountInvoiceLineTypeID, IsNewReviewRequired, InvoiceLineEntryEnable
|
|
FROM tblExportAccountInvoiceLineType
|
|
WHERE MatchString=@matchString;
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@matchString", matchString);
|
|
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
int transactionTypeId = reader.GetInt32(0);
|
|
bool isNew = reader.GetBoolean(1);
|
|
bool? importEnabled = reader.GetBoolean(2);
|
|
|
|
if (isNew == true)
|
|
{
|
|
// return null and 'skip' item
|
|
return 0;
|
|
}
|
|
//else if (importEnabled == false)
|
|
//{
|
|
// // mark IsProcessed=true and leave transactionId=null
|
|
// return -1;
|
|
//}
|
|
else if (transactionTypeId > 0)
|
|
{
|
|
return transactionTypeId;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Account TransactionTypeId lookup method went wrong, is one of the 'enabled' boolean on table set to null?");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
insertNew = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// insert new and retrive new value, if required
|
|
if (insertNew)
|
|
{
|
|
|
|
using (SqlCommand insertCmd = new SqlCommand(
|
|
"INSERT INTO tblExportAccountInvoiceLineType ( TypeTitle, MatchString ) " +
|
|
"OUTPUT INSERTED.ExportAccountInvoiceLineTypeID " +
|
|
"VALUES ( @typeTitle, @matchString );"
|
|
, sqlConn))
|
|
{
|
|
insertCmd.Parameters.AddWithValue("@typeTitle", "NEW TYPE");
|
|
insertCmd.Parameters.AddWithValue("@matchString", matchString);
|
|
|
|
int transactionTypeId = (int)insertCmd.ExecuteScalar();
|
|
|
|
scopeSupress.Complete();
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("This is only here so 'all code paths return a value', this can never be reached!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
namespace Purchase
|
|
{
|
|
public class PurchaseQuery
|
|
{
|
|
private static int accountJournalTypeIdNet = 1;
|
|
private static int accountJournalTypeIdTax = 2;
|
|
private static int stockJournalTypeId = 1;
|
|
private static int creditAccountId = 59;
|
|
private static int creditStatusId = 13;
|
|
private static int defaultAccountId = 138;
|
|
|
|
public static void WIP_PurchaseLineTransactionNetInsert(string sqlConnectionString, int purchaseLineId,
|
|
string currencyCode, decimal amountNet, DateTime entryDate, int debitAccountId = 0)
|
|
{
|
|
// default to 'Inventory, Receivable/Processing'
|
|
if (debitAccountId < 1)
|
|
{
|
|
debitAccountId = defaultAccountId;
|
|
}
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// create account journal entry
|
|
int journalId = Account.AccountQuery.AccountJournalInsert(
|
|
sqlConnectionString, accountJournalTypeIdNet, entryDate, currencyCode, amountNet, debitAccountId);
|
|
|
|
// add transaction to purchase line transaction table
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO
|
|
tblPurchaseLineTransaction
|
|
( PurchaseLineID, AccountJournalID )
|
|
VALUES
|
|
( @purchaseLineID, @accountJournalID );
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@purchaseLineID", purchaseLineId);
|
|
cmd.Parameters.AddWithValue("@accountJournalID", journalId);
|
|
|
|
int count = cmd.ExecuteNonQuery();
|
|
|
|
if (count != 1)
|
|
{
|
|
throw new Exception("Operation cancelled, failed to update tblPurchaseLineTransaction!");
|
|
}
|
|
}
|
|
|
|
//commit the transaction and return value
|
|
scope.Complete();
|
|
}
|
|
}
|
|
|
|
public static void WIP_PurchaseLineTransactionNetUpdate(string sqlConnectionString, int accountJouranlId,
|
|
string currencyCode, decimal amountNet, int debitAccountId)
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// stock accountId check
|
|
if (debitAccountId == 86)
|
|
{
|
|
int count = 0;
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT Count(tblStock.StockID) AS CountOfStockID
|
|
FROM tblStock
|
|
WHERE (((tblStock.AccountJournalID)=@accountJouranlId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJouranlId", accountJouranlId);
|
|
|
|
count = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
if (count == 0)
|
|
{
|
|
throw new Exception("Add account journal entry to stock before attempting this operation.");
|
|
}
|
|
else if(count > 1)
|
|
{
|
|
throw new Exception("Houston we have a problem! An account journal entry is assigned to " + count + " stock lines.");
|
|
}
|
|
}
|
|
|
|
// make the update
|
|
bool result = bnhtradeDatabaseClient.Account.AccountQuery.AccountJournalPostUpdate(sqlConnectionString,
|
|
accountJouranlId, currencyCode, amountNet, debitAccountId, creditAccountId);
|
|
|
|
scope.Complete();
|
|
}
|
|
}
|
|
|
|
// delete after testing....
|
|
|
|
//public static void WIP_PurchaseLineTransactionStockDelete(string sqlConnectionString, int accountJournalId, int stockId)
|
|
//{
|
|
// using (TransactionScope scope = new TransactionScope())
|
|
// using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
// {
|
|
// conn.Open();
|
|
|
|
// // get stock cost
|
|
// (int quantity, decimal totalCost) result = Stock.StockJournal.StockGetTotalQuantityAndCost(sqlConnectionString, stockId);
|
|
// decimal amount = result.totalCost;
|
|
|
|
// // delete accountJournalId from stock table
|
|
// using (SqlCommand cmd = new SqlCommand(@"
|
|
// UPDATE tblStock
|
|
// SET AccountJournalID=Null
|
|
// WHERE StockID=@stockId AND AccountJournalID=@accountJournalId;
|
|
// ", conn))
|
|
// {
|
|
// cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
// cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
// int count = cmd.ExecuteNonQuery();
|
|
|
|
// if (count != 1)
|
|
// {
|
|
// throw new Exception("Integrity check failure! StockID=" + stockId + ", AccountJournalID=" + accountJournalId +
|
|
// " combination not found on stock table.");
|
|
// }
|
|
// }
|
|
|
|
// // reset the account journal to default
|
|
// Account.AccountQuery.AccountJournalPostUpdate(sqlConnectionString, accountJournalId, "GBP", amount, defaultAccountId, creditAccountId);
|
|
|
|
// // delete the stock entry
|
|
// Stock.StockCreate.WIP_StockDeleteSub(sqlConnectionString, stockId);
|
|
|
|
// scope.Complete();
|
|
// }
|
|
//}
|
|
|
|
public static void WIP_PurchaseLineTransactionDelete(string sqlConnectionString, int purchaseLineId, int accountJournalId)
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// check accountJournalId does not exist in stock table
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT StockID
|
|
FROM tblStock
|
|
WHERE AccountJournalID=@accountJournalId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
throw new Exception("Integrity check failure! AccountJournalID=" + accountJournalId + " exists multiple time in stock table!");
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Delete stock first before proceeding, AccountJournalID=" + accountJournalId );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// delete line in purchase line transaction table
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
DELETE FROM tblPurchaseLineTransaction
|
|
WHERE AccountJournalID=@accountJournalId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
int count = cmd.ExecuteNonQuery();
|
|
|
|
if (count != 1)
|
|
{
|
|
throw new Exception("Operation cancelled, failed to delete entry in tblPurchaseLineTransaction WHERE AccountJournalID=" + accountJournalId);
|
|
}
|
|
}
|
|
|
|
// delete account journal entry
|
|
Account.AccountQuery.AccountJournalDelete(sqlConnectionString, accountJournalId);
|
|
|
|
scope.Complete();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
namespace Account
|
|
{
|
|
public class AccountQuery
|
|
{
|
|
public static int GetCurrencyId(string sqlConnectionString, string currencyCode)
|
|
{
|
|
if (currencyCode == "GBP")
|
|
{
|
|
return 53;
|
|
}
|
|
if (currencyCode == "EUR")
|
|
{
|
|
return 50;
|
|
}
|
|
|
|
try
|
|
{
|
|
if (currencyCode.Length == 3)
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand sqlCommand = new SqlCommand(
|
|
"SELECT AccountCurrencyID FROM tblAccountCurrency WHERE CurrencyCode=@currencyCode;"
|
|
, sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@currencyCode", currencyCode);
|
|
object obj = sqlCommand.ExecuteScalar();
|
|
if (!(obj == null))
|
|
{
|
|
return (int)sqlCommand.ExecuteScalar();
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
public static decimal CurrencyConvertToGbp(string sqlConnectionString, string currencyCode, decimal amount, DateTime conversionDate)
|
|
{
|
|
if (currencyCode == "GBP" || amount == 0M)
|
|
{
|
|
return amount;
|
|
}
|
|
|
|
if (currencyCode.Length != 3)
|
|
{
|
|
throw new Exception("Invalid currency code '" + currencyCode + "'");
|
|
}
|
|
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT CurrencyUnitsPerGBP
|
|
FROM tblAccountExchangeRate
|
|
WHERE CurrencyCode=@currencyCode AND StartDate<=@conversionDate AND EndDate>@conversionDate
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@currencyCode", currencyCode);
|
|
cmd.Parameters.AddWithValue("@conversionDate", conversionDate);
|
|
|
|
object result = cmd.ExecuteScalar();
|
|
if (result != null)
|
|
{
|
|
return amount / Convert.ToDecimal(result);
|
|
}
|
|
}
|
|
|
|
// return reason for no record found
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT CurrencyUnitsPerGBP
|
|
FROM tblAccountExchangeRate
|
|
WHERE CurrencyCode=@currencyCode
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@currencyCode", currencyCode);
|
|
|
|
object result = cmd.ExecuteScalar();
|
|
if (result == null)
|
|
{
|
|
throw new Exception("Currency code '" + currencyCode + "' does not exist in Exchange Rate table");
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Date range for " + currencyCode + " " + conversionDate.ToShortDateString() + " " +
|
|
conversionDate.ToLongTimeString() + "' does not exist in Exchange Rate table");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public static int CurrencyExchangeRateInsert(string sqlConnectionString, int exchangeRateSource, string currencyCode,
|
|
decimal currencyUnitsPerGbp, DateTime periodStart, DateTime periodEnd, bool checkOverride = false)
|
|
{
|
|
currencyUnitsPerGbp = decimal.Round(currencyUnitsPerGbp, 4);
|
|
periodStart = DateTime.SpecifyKind(periodStart, DateTimeKind.Utc);
|
|
periodEnd = DateTime.SpecifyKind(periodEnd, DateTimeKind.Utc);
|
|
|
|
// CHECKS
|
|
// HMRC source only
|
|
if (exchangeRateSource != 1)
|
|
{
|
|
throw new Exception("Function does not currently accept exchange rates from sources other than HMRC");
|
|
}
|
|
// currency code upper case only
|
|
currencyCode = currencyCode.ToUpper();
|
|
if (currencyCode.Length != 3)
|
|
{
|
|
throw new Exception("Invalid currency code '" + currencyCode +"'");
|
|
}
|
|
|
|
if (periodEnd <= periodStart)
|
|
{
|
|
throw new Exception("Invalid date period.");
|
|
}
|
|
|
|
if (checkOverride == false && (periodEnd - periodStart).Days > 31)
|
|
{
|
|
throw new Exception("Date period is greater than 31 days.");
|
|
}
|
|
|
|
// retirve previous data
|
|
DateTime? periodEndLast = null;
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT Max(tblAccountExchangeRate.EndDate) AS MaxOfEndDate
|
|
FROM tblAccountExchangeRate
|
|
WHERE (((tblAccountExchangeRate.CurrencyCode) = @currencyCode))
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@currencyCode", currencyCode);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
|
|
// currency code not existing
|
|
if (obj == DBNull.Value && checkOverride == false)
|
|
{
|
|
throw new Exception("Currency code '" + currencyCode + "' does not exist in table");
|
|
}
|
|
// currency code exists
|
|
else
|
|
{
|
|
periodEndLast = DateTime.SpecifyKind(Convert.ToDateTime(obj), DateTimeKind.Utc);
|
|
|
|
if (periodStart != periodEndLast)
|
|
{
|
|
throw new Exception("Invalid period start date -- must equal previous period end-date.");
|
|
}
|
|
}
|
|
}
|
|
|
|
// retrive previous exchange rate and check
|
|
decimal currencyUnitsPerGbpLast = 0;
|
|
if (periodEndLast != null)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblAccountExchangeRate.AccountExchangeRateID, tblAccountExchangeRate.CurrencyUnitsPerGBP
|
|
FROM tblAccountExchangeRate
|
|
WHERE (tblAccountExchangeRate.EndDate = @periodEndLast)
|
|
AND (CurrencyCode = @currencyCode);
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@periodEndLast", periodEndLast);
|
|
cmd.Parameters.AddWithValue("@currencyCode", currencyCode);
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
currencyUnitsPerGbpLast = reader.GetDecimal(1);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Error that shouldn't happen! Check code @ 5129f3e6-2f7e-4883-bc73-b317d8fa4050");
|
|
}
|
|
// error if >1 line
|
|
if (reader.Read())
|
|
{
|
|
string errText = "Multiple lines in currency exchange table for '" + currencyCode + "' where [EndDate]=" + periodEndLast.ToString();
|
|
MiscFunction.EventLogInsert(errText, 1);
|
|
throw new Exception(errText);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// check difference between current and previous exchange rates isn't too great
|
|
if (checkOverride == false &&
|
|
(currencyUnitsPerGbpLast > (currencyUnitsPerGbp * 1.05m) || currencyUnitsPerGbpLast < (currencyUnitsPerGbp * 0.95m))
|
|
)
|
|
{
|
|
throw new Exception("Difference between supplied and previous exchange rates is greater than 5%");
|
|
}
|
|
|
|
// MAKE THE INSERT
|
|
int recordId = 0;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblAccountExchangeRate (ExchangeRateSource, CurrencyCode, CurrencyUnitsPerGBP, StartDate, EndDate)
|
|
OUTPUT INSERTED.AccountExchangeRateID
|
|
VALUES (@exchangeRateSource, @currencyCode, @currencyUnitsPerGbp, @periodStart, @periodEnd);
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@exchangeRateSource", exchangeRateSource);
|
|
cmd.Parameters.AddWithValue("@currencyCode", currencyCode);
|
|
cmd.Parameters.AddWithValue("@currencyUnitsPerGbp", currencyUnitsPerGbp);
|
|
cmd.Parameters.AddWithValue("@periodStart", periodStart);
|
|
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;
|
|
}
|
|
}
|
|
|
|
public static int WIP_GetAccountTransactionTypeId(string sqlConnectionString, string matchString, bool onNewReturnId = false, bool onNewDisableInsert = false)
|
|
{
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 Skip transpose, type is new or has not been reviewed yet
|
|
* -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
|
|
|
|
if (matchString.Length == 0)
|
|
{
|
|
throw new Exception("matchstring is of zero lenth");
|
|
}
|
|
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT AccountTransactionTypeID, IsNewReviewRequired, TransactionImportEnabled FROM tblAccountTransactionType WHERE MatchString=@matchString;"
|
|
, sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@matchString", matchString);
|
|
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
int index01 = reader.GetOrdinal("AccountTransactionTypeID");
|
|
int index02 = reader.GetOrdinal("IsNewReviewRequired");
|
|
int index03 = reader.GetOrdinal("TransactionImportEnabled");
|
|
|
|
int transactionTypeId = reader.GetInt32(index01);
|
|
bool isNew = reader.GetBoolean(index02);
|
|
bool? importEnabled = reader.GetBoolean(index03);
|
|
|
|
if (isNew == true || importEnabled == null)
|
|
{
|
|
// return null and 'skip' item
|
|
return 0;
|
|
}
|
|
else if (importEnabled == false)
|
|
{
|
|
// mark IsProcessed=true and leave transactionId=null
|
|
return -1;
|
|
}
|
|
else if (transactionTypeId > 0)
|
|
{
|
|
return transactionTypeId;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Account TransactionTypeId lookup method went wrong, is one of the 'enabled' boolean on table set to null?");
|
|
}
|
|
}
|
|
else if (onNewDisableInsert == false)
|
|
{
|
|
// insert new and retrive new value
|
|
using (SqlConnection scopeConn = new SqlConnection(sqlConnectionString))
|
|
using (TransactionScope scopeSupress = new TransactionScope(TransactionScopeOption.Suppress))
|
|
{
|
|
scopeConn.Open();
|
|
|
|
using (SqlCommand insertCmd = new SqlCommand(@"
|
|
INSERT INTO tblAccountTransactionType ( MatchString )
|
|
OUTPUT INSERTED.AccountTransactionTypeID
|
|
VALUES ( @matchString );
|
|
", scopeConn))
|
|
{
|
|
insertCmd.Parameters.AddWithValue("@matchString", matchString);
|
|
int transactionTypeId = (int)insertCmd.ExecuteScalar();
|
|
scopeSupress.Complete();
|
|
|
|
if (onNewReturnId == true)
|
|
{
|
|
return transactionTypeId;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
// function returns tuple with debit and credit Id or 0,0 if none present
|
|
public static (int debitId, int creditId) WIP_GetAccountTransactionTypeDebitIdCreditId(string sqlConnectionString, int accountTransactionTypeId)
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblAccountTransactionTypeGroup.DebitAccountChartOfID,
|
|
tblAccountTransactionTypeGroup.CreditAccountChartOfID
|
|
FROM
|
|
tblAccountTransactionType
|
|
INNER JOIN tblAccountTransactionTypeGroup
|
|
ON tblAccountTransactionType.AccountTransactionTypeGroupID = tblAccountTransactionTypeGroup.AccountTransactionTypeGroupID
|
|
WHERE (((tblAccountTransactionType.AccountTransactionTypeID)=@accountTransactionTypeId));
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountTransactionTypeId", accountTransactionTypeId);
|
|
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
(int debitId, int creditId) returnTuple;
|
|
|
|
if (reader.Read())
|
|
{
|
|
|
|
returnTuple.debitId = reader.GetInt32(0);
|
|
returnTuple.creditId = reader.GetInt32(1);
|
|
|
|
return returnTuple;
|
|
}
|
|
else
|
|
{
|
|
returnTuple.debitId = 0;
|
|
returnTuple.creditId = 0;
|
|
|
|
return returnTuple;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static int AccountTransactionInsert(string sqlConnectionString, DateTime transactionUtcDate, int transactionTypeId,
|
|
string currencyCode, decimal amount, int foreignKey = 0, string reference = "", string detail = "",
|
|
int accountJournalId = 0, bool isProcessed = false, int stockId = 0)
|
|
{
|
|
transactionUtcDate = DateTime.SpecifyKind(transactionUtcDate, DateTimeKind.Utc);
|
|
|
|
// checks
|
|
if (currencyCode.Length != 3)
|
|
{
|
|
if (currencyCode.Length == 0)
|
|
{
|
|
MiscFunction.EventLogInsert("No CurrencyCode string passed to InsertAccountTransaction(), item insert skipped.", 1);
|
|
}
|
|
else
|
|
{
|
|
MiscFunction.EventLogInsert("CurrencyCode '" + currencyCode + "' passed to InsertAccountTransaction() is incorrect length, item insert skipped.", 1);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// onto business....
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"INSERT INTO tblAccountTransaction ( TransactionDate, AccountTransactionTypeID, CurrencyCode, Amount, ForeignKey, Reference, Detail, AccountJournalID, IsProcessed, StockID ) " +
|
|
"OUTPUT INSERTED.AccountTransactionID " +
|
|
"VALUES (@transactionDate, @transactionTypeId, @currencyCode, @amount, @foreignKey, @reference, @detail, @AccountJournalId, @isProcessed, @stockId);",
|
|
sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@transactionDate", transactionUtcDate.ToUniversalTime());
|
|
cmd.Parameters.AddWithValue("@transactionTypeId", transactionTypeId);
|
|
cmd.Parameters.AddWithValue("@currencyCode", currencyCode.ToUpper());
|
|
cmd.Parameters.AddWithValue("@amount", amount);
|
|
if (foreignKey == 0) { cmd.Parameters.AddWithValue("@foreignKey", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@foreignKey", foreignKey); }
|
|
if (reference == "") { cmd.Parameters.AddWithValue("@reference", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@reference", reference); }
|
|
if (detail == "") { cmd.Parameters.AddWithValue("@detail", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@detail", detail); }
|
|
if (accountJournalId == 0) { cmd.Parameters.AddWithValue("@AccountJournalId", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@AccountJournalId", accountJournalId); }
|
|
cmd.Parameters.AddWithValue("@isProcessed", isProcessed);
|
|
if (stockId < 1) { cmd.Parameters.AddWithValue("@stockId", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@stockId", stockId); }
|
|
|
|
int transactionId = Convert.ToInt32(cmd.ExecuteScalar());
|
|
return transactionId;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
// return 0 if no journal id is attached
|
|
public static int AccountTransactionGetJournalId(string sqlConnectionString, int transactionId)
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
AccountJournalID
|
|
FROM
|
|
tblAccountTransaction
|
|
WHERE
|
|
AccountTransactionID=@transactionId
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@transactionId", transactionId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
if (obj == null)
|
|
{
|
|
throw new Exception("AccountTransactionID=" + transactionId + " does not exist in tblAccountTransaction.");
|
|
}
|
|
else if (obj == DBNull.Value)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return (int)obj;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool AccountJournalEntryIsLocked(string sqlConnectionString, int journalId)
|
|
{
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblAccountJournal.IsLocked
|
|
FROM
|
|
tblAccountJournal
|
|
WHERE
|
|
tblAccountJournal.AccountJournalID=@accountJournalId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", journalId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
if (obj == null)
|
|
{
|
|
throw new Exception("Journal entry not found for AccountJournalID=" + journalId);
|
|
}
|
|
else
|
|
{
|
|
return (bool)obj;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// returns total of debits
|
|
public static decimal WIP_AccountJournalDebitBalance(string sqlConnectionString, int accountJournalId)
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
Sum(tblAccountJournalPost.AmountGbp) AS SumOfAmountGbp
|
|
FROM
|
|
tblAccountJournalPost
|
|
WHERE
|
|
(((tblAccountJournalPost.AccountJournalID)=@AccountJournalId)
|
|
AND ((tblAccountJournalPost.AmountGbp)>=0));
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@AccountJournalId", accountJournalId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
|
|
if (obj == null)
|
|
{
|
|
throw new Exception("No records found for AccountJournalID=" + accountJournalId);
|
|
}
|
|
|
|
return (decimal)obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static int DEPRECIATED_AccountJournalInsert(string sqlConnectionString, int journalTypeId, List<(int accountId, decimal Amount)> journalPosts,
|
|
DateTime entryDate, string currencyCode)
|
|
{
|
|
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
|
|
|
|
//disable split transactions
|
|
if (journalPosts.Count > 2)
|
|
{
|
|
throw new Exception("Split transactions not supported.");
|
|
}
|
|
|
|
// checks
|
|
|
|
// number of posts
|
|
if (journalPosts.Count < 2)
|
|
{
|
|
// list not long enough
|
|
throw new Exception("Method requires an minumum of two posts in any one journal entry.");
|
|
}
|
|
|
|
// equal debits to credits
|
|
if (journalPosts.Sum(item => item.Amount) != 0)
|
|
{
|
|
// credits and debits do not match
|
|
throw new Exception("Sum of debits and credits do not match.");
|
|
}
|
|
|
|
// convert currency, if required
|
|
if (currencyCode != "GBP")
|
|
{
|
|
List<(int accountId, decimal Amount)> tempList = new List<(int accountId, decimal Amount)>();
|
|
|
|
foreach ((int accountId, decimal Amount) item in journalPosts)
|
|
{
|
|
(int accountId, decimal Amount) tempTuple;
|
|
|
|
tempTuple.accountId = item.accountId;
|
|
tempTuple.Amount = Math.Round(Account.AccountQuery.CurrencyConvertToGbp(sqlConnectionString, currencyCode, item.Amount, entryDate), 2);
|
|
|
|
tempList.Add(tempTuple);
|
|
}
|
|
journalPosts.Clear();
|
|
journalPosts = new List<(int accountId, decimal Amount)>(tempList);
|
|
tempList.Clear();
|
|
|
|
// check and, if required, correct for rounding differences
|
|
decimal diff = journalPosts.Sum(item => item.Amount);
|
|
if (diff != 0)
|
|
{
|
|
// get largest amount to apply difference to (wether + or -)
|
|
decimal maxDebit = journalPosts.Where(item => item.Amount >= 0).Max(item => item.Amount);
|
|
decimal maxCredit = journalPosts.Where(item => item.Amount <= 0).Min(item => item.Amount);
|
|
|
|
decimal maxValue = maxCredit;
|
|
if (maxDebit > (maxCredit * -1))
|
|
{
|
|
maxValue = maxDebit;
|
|
}
|
|
|
|
// rebuild the post list with difference +/- from the max debit/credit value
|
|
bool valueUpdated = false;
|
|
foreach ((int accountId, decimal Amount) item in journalPosts)
|
|
{
|
|
(int accountId, decimal Amount) tempTuple;
|
|
|
|
tempTuple.accountId = item.accountId;
|
|
|
|
if (valueUpdated == false && maxValue == item.Amount)
|
|
{
|
|
tempTuple.Amount = item.Amount - diff;
|
|
valueUpdated = true;
|
|
}
|
|
else
|
|
{
|
|
tempTuple.Amount = item.Amount;
|
|
}
|
|
|
|
tempList.Add(tempTuple);
|
|
}
|
|
journalPosts.Clear();
|
|
journalPosts = new List<(int accountId, decimal Amount)>(tempList);
|
|
tempList.Clear();
|
|
}
|
|
}
|
|
|
|
// last fail-safe check before database insert
|
|
if (journalPosts.Sum(item => item.Amount) != 0)
|
|
{
|
|
// credits and debits do not match
|
|
throw new Exception("Sum of debits and credits do not match (after attempting to convert currency).");
|
|
}
|
|
|
|
//write entry to database
|
|
int accountJournalId = new int();
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand sqlCommand = new SqlCommand(
|
|
"INSERT INTO tblAccountJournal ( EntryDate ) " +
|
|
"OUTPUT INSERTED.AccountJournalID " +
|
|
"VALUES ( @EntryDate );"
|
|
, sqlConn))
|
|
{
|
|
// add parameters
|
|
sqlCommand.Parameters.AddWithValue("@EntryDate", entryDate.ToUniversalTime());
|
|
|
|
//execute
|
|
accountJournalId = (int)sqlCommand.ExecuteScalar();
|
|
}
|
|
|
|
// insert journal posts into database
|
|
foreach (var post in journalPosts)
|
|
{
|
|
using (SqlCommand sqlCommand = new SqlCommand(
|
|
"INSERT INTO tblAccountJournalPost ( AccountJournalID, AccountChartOfID, AmountGbp ) " +
|
|
"VALUES ( @AccountJournalID, @AccountChartOfID, @AmountGbp );"
|
|
, sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@AccountJournalID", accountJournalId);
|
|
sqlCommand.Parameters.AddWithValue("@AccountChartOfID", post.accountId);
|
|
sqlCommand.Parameters.AddWithValue("@AmountGbp", post.Amount);
|
|
|
|
// execute
|
|
sqlCommand.ExecuteNonQuery();
|
|
}
|
|
}
|
|
}
|
|
//commit the transaction
|
|
scope.Complete();
|
|
}
|
|
return accountJournalId;
|
|
}
|
|
|
|
public static int AccountJournalInsert(string sqlConnectionString, 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);
|
|
|
|
scope.Complete();
|
|
return journalId;
|
|
}
|
|
}
|
|
|
|
// return false on locked journal entry
|
|
public static bool AccountJournalDelete(string sqlConnectionString, int accountJournalId)
|
|
{
|
|
// check if journal entry is locked
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
bool IsLocked = Account.AccountQuery.AccountJournalEntryIsLocked(sqlConnectionString, accountJournalId);
|
|
if (IsLocked == true)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// make the delete
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
DELETE FROM tblAccountJournalPost
|
|
WHERE AccountJournalID=@accountJournalId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
int rows = cmd.ExecuteNonQuery();
|
|
|
|
if (rows == 0)
|
|
{
|
|
throw new Exception("Journal entry and/or entry posts do not exist for AccountJournalId=" + accountJournalId);
|
|
}
|
|
}
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
DELETE FROM tblAccountJournal
|
|
WHERE AccountJournalID=@accountJournalId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
|
|
scope.Complete();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static bool AccountJournalPostInsert(string sqlConnectionString, 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 = bnhtradeDatabaseClient.Account.AccountQuery.CurrencyConvertToGbp(sqlConnectionString, 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;
|
|
}
|
|
}
|
|
|
|
public static bool AccountJournalPostUpdate(string sqlConnectionString, 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);
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace Product
|
|
{
|
|
public class ProductQuery
|
|
{
|
|
public static void ProductUpdateAmazonEstimateFee(string sqlConnectionString, List<(string asin, decimal PriceToEstimate)> inputList)
|
|
{
|
|
// add product id to list
|
|
List<(string asin, string productRef, decimal PriceToEstimate)> outputList = new List<(string asin, string productRef, decimal PriceToEstimate)>();
|
|
foreach ((string asin, decimal PriceToEstimate) item in inputList)
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand sqlCommand = new SqlCommand(@"
|
|
SELECT prdProductID FROM tblProduct WHERE prdAmazonAsin=@asin
|
|
", sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@asin", item.asin);
|
|
|
|
object obj = sqlCommand.ExecuteScalar();
|
|
if (!(obj == null))
|
|
{
|
|
int productId = (int)sqlCommand.ExecuteScalar();
|
|
(string asin, string productRef, decimal PriceToEstimate) tempTuple = (item.asin, productId.ToString(), item.PriceToEstimate);
|
|
outputList.Add(tempTuple);
|
|
}
|
|
else
|
|
{
|
|
(string asin, string productRef, decimal PriceToEstimate) tempTuple = (item.asin, "0", item.PriceToEstimate);
|
|
outputList.Add(tempTuple);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// request info from MWS and import
|
|
int i = 0;
|
|
int count = 0;
|
|
int total = inputList.Count;
|
|
FeesEstimateRequestList requestList = new FeesEstimateRequestList();
|
|
|
|
foreach (var item in outputList)
|
|
{
|
|
i++;
|
|
count++;
|
|
|
|
// build and (after 20 iterations) send the mws request
|
|
if (i == 1 && count != 1)
|
|
{
|
|
requestList = new FeesEstimateRequestList();
|
|
}
|
|
requestList.FeesEstimateRequest.Add(new FeesEstimateRequest
|
|
{
|
|
MarketplaceId = "A1F83G8C2ARO7P", // .co.uk
|
|
IdType = "ASIN",
|
|
IdValue = item.asin,
|
|
PriceToEstimateFees = new PriceToEstimateFees
|
|
{
|
|
ListingPrice = new MoneyType { Amount = item.PriceToEstimate, CurrencyCode = "GBP" },
|
|
//Shipping = new MoneyType { Amount = 0M, CurrencyCode = "GBP" },
|
|
//Points = new Points { PointsNumber = 0 }
|
|
},
|
|
Identifier = item.productRef,
|
|
IsAmazonFulfilled = true
|
|
});
|
|
|
|
// request data and import into database
|
|
if (i == 20 || count == total)
|
|
{
|
|
AmazonMwsProduct mws = new AmazonMwsProduct();
|
|
List<FeesEstimateResult> returnList = mws.WIP_GetProductEstimateFee(requestList);
|
|
foreach (FeesEstimateResult returnItem in returnList)
|
|
{
|
|
// get me values
|
|
string asin = returnItem.FeesEstimateIdentifier.IdValue;
|
|
int productId = int.Parse(returnItem.FeesEstimateIdentifier.SellerInputIdentifier);
|
|
//int productId;
|
|
//try
|
|
//{ productId = int.Parse(returnItem.FeesEstimateIdentifier.SellerInputIdentifier); }
|
|
//catch
|
|
//{ throw new Exception("Could not parse the return ProductID string '" + returnItem.FeesEstimateIdentifier.SellerInputIdentifier + "'"); }
|
|
|
|
// test for error
|
|
if (returnItem.Error != null)
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine("ASIN: " + asin);
|
|
sb.AppendLine("Error Code: " + returnItem.Error.Code);
|
|
if (returnItem.Error.Detail != null)
|
|
{ sb.AppendLine("Detail: " + returnItem.Error.Detail); }
|
|
if (returnItem.Error.Message != null)
|
|
{ sb.AppendLine("Message: " + returnItem.Error.Message); }
|
|
if (returnItem.Error.Type != null)
|
|
{ sb.AppendLine("Type: " + returnItem.Error.Type); }
|
|
|
|
MiscFunction.EventLogInsert("Error running GetProductEstimateFee for ASIN:" + asin + ", further details attached.", 1, sb.ToString());
|
|
|
|
continue;
|
|
}
|
|
|
|
bool isAmazonFulfilled = returnItem.FeesEstimateIdentifier.IsAmazonFulfilled;
|
|
DateTime timeOfFeeEstimation = returnItem.FeesEstimate.TimeOfFeesEstimation;
|
|
decimal totalFeeEstimate = returnItem.FeesEstimate.TotalFeesEstimate.Amount;
|
|
string currencyCode = returnItem.FeesEstimate.TotalFeesEstimate.CurrencyCode;
|
|
decimal priceToEstimateFeeListingPrice = returnItem.FeesEstimateIdentifier.PriceToEstimateFees.ListingPrice.Amount;
|
|
decimal priceToEstimateFeeShipping = 0;
|
|
if (returnItem.FeesEstimateIdentifier.PriceToEstimateFees.Shipping != null)
|
|
{ priceToEstimateFeeShipping = returnItem.FeesEstimateIdentifier.PriceToEstimateFees.Shipping.Amount; }
|
|
decimal priceToEstimateFeePoints = 0;
|
|
if (returnItem.FeesEstimateIdentifier.PriceToEstimateFees.Points != null)
|
|
{ priceToEstimateFeePoints = returnItem.FeesEstimateIdentifier.PriceToEstimateFees.Points.PointsMonetaryValue.Amount; }
|
|
|
|
decimal referralFee = 0m;
|
|
decimal variableClosingFee = 0m;
|
|
decimal fulfillmentFees = 0m;
|
|
decimal perItemFee = 0m;
|
|
decimal otherFee_Exception = 0m;
|
|
|
|
FeeDetailList feeDetailList = returnItem.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; }
|
|
|
|
}
|
|
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", asin);
|
|
sqlCommand.Parameters.AddWithValue("@productIdentifier", productId);
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
i = 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public int? ProductGetProductIdByCatId(string sqlConnectionString, int catId)
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT prdProductID " +
|
|
"FROM tblProduct " +
|
|
"WHERE CatId=@catId"
|
|
, sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@catId", catId);
|
|
|
|
object result = cmd.ExecuteScalar();
|
|
if (result != null)
|
|
{
|
|
return Convert.ToInt32(result);
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public (decimal? price, DateTime? priceDate) ProductCompetitivePriceGet(string sqlConnectionString, int productId, int conditionId)
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT t.CompetitivePrice, t.PriceDate " +
|
|
"FROM tblProductPriceCompetitive AS t INNER JOIN (SELECT ProductID, Max(PriceDate) AS MaxOfPriceDate " +
|
|
"FROM tblProductPriceCompetitive " +
|
|
"WHERE ProductID=" + productId + " AND SkuConditionID=" + conditionId +
|
|
"GROUP BY ProductID) AS a ON (t.PriceDate = a.MaxOfPriceDate) AND (t.ProductID = a.ProductID)"
|
|
, sqlConn))
|
|
{
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
DateTime dt = reader.GetDateTime(1);
|
|
dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
|
|
return (reader.GetDecimal(0), dt);
|
|
}
|
|
else
|
|
{
|
|
return (null, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public int ProductCompetitivePriceSet(string sqlConnectionString, int productId, int conditionId, decimal price, bool isBuyBoxPrice, DateTime? priceDate = null)
|
|
{
|
|
if (priceDate == null)
|
|
{
|
|
priceDate = DateTime.UtcNow;
|
|
}
|
|
DateTime dt = DateTime.SpecifyKind(priceDate.Value, DateTimeKind.Utc);
|
|
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"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();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
public int testing(string sqlConnectionString)
|
|
{
|
|
int id = 0;
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand sqlCommand = new SqlCommand(
|
|
"SELECT skuSkuID " +
|
|
"FROM tblSku " +
|
|
"WHERE skuSkuNumber='006449-10'"
|
|
, sqlConn))
|
|
{
|
|
//execute sql
|
|
id = (int)sqlCommand.ExecuteScalar();
|
|
}
|
|
}
|
|
return id;
|
|
}
|
|
}
|
|
}
|
|
namespace Stock
|
|
{
|
|
public class StockCreate
|
|
{
|
|
private static int WIP_StockInsert(string sqlConnectionString, int accountJournalType, int stockJournalType, string currencyCode, decimal amount,
|
|
int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// add account journal entry
|
|
int accountJournalId = Account.AccountQuery.AccountJournalInsert(sqlConnectionString, accountJournalType, entryDate, currencyCode, amount);
|
|
|
|
// make the stock insert
|
|
int stockId = StockCreate.WIP_StockInsertSub(sqlConnectionString, productId, conditionId, accountTaxCodeId,
|
|
accountJournalId, stockJournalType, entryDate, quantity, debitStatusId);
|
|
|
|
scope.Complete();
|
|
return stockId;
|
|
}
|
|
}
|
|
|
|
private static int WIP_StockInsertSub(string sqlConnectionString, int productId, int conditionId, int accountTaxCodeId,
|
|
int accountJournalId, int stockJournalTypeId, DateTime stockJournalEntryDate, int quantity, int statusDebitId)
|
|
{
|
|
stockJournalEntryDate = DateTime.SpecifyKind(stockJournalEntryDate, DateTimeKind.Utc);
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// ensure account journal id hasn't already been added to stock table
|
|
int count = 0;
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT Count(tblStock.StockID) AS CountOfID
|
|
FROM tblStock
|
|
WHERE (((tblStock.AccountJournalID)=@accountJouranlId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJouranlId", accountJournalId);
|
|
|
|
count = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
if (count == 1)
|
|
{
|
|
throw new Exception("Add account journal entry already assigned to stock line.");
|
|
}
|
|
else if (count > 1)
|
|
{
|
|
throw new Exception("Houston we have a problem! An account journal entry is assigned to " + count + " stock lines.");
|
|
}
|
|
|
|
// ensure the debit for the account journal transaction is to an 'Asset' account type
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
Count(tblAccountJournalPost.AccountJournalPostID) AS CountOfAccountJournalPostID
|
|
FROM
|
|
(tblAccountJournalPost
|
|
INNER JOIN tblAccountChartOf
|
|
ON tblAccountJournalPost.AccountChartOfID = tblAccountChartOf.AccountChartOfID)
|
|
INNER JOIN tblAccountChartOfType
|
|
ON tblAccountChartOf.AccountChartOfTypeID = tblAccountChartOfType.AccountChartOfTypeID
|
|
WHERE
|
|
tblAccountJournalPost.AmountGbp>=0
|
|
AND tblAccountChartOfType.BasicType='Asset'
|
|
AND tblAccountJournalPost.AccountJournalID=@accountJournalId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
if ((int)cmd.ExecuteScalar() < 1)
|
|
{
|
|
throw new Exception("Supplied AccountJournal entry must debit an 'Asset' account type.");
|
|
}
|
|
}
|
|
|
|
// get statusCreditId for stock journal type
|
|
int statusCreditId;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblStockJournalType.StockStatusID_Credit
|
|
FROM
|
|
tblStockJournalType
|
|
WHERE
|
|
tblStockJournalType.StockJournalTypeID=@stockJournalTypeId
|
|
AND tblStockJournalType.StockStatusID_Credit Is Not Null;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockJournalTypeId", stockJournalTypeId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
|
|
if (obj == null)
|
|
{
|
|
throw new Exception("Default credit status not set for StockJournalTypeID=" + stockJournalTypeId);
|
|
}
|
|
else
|
|
{
|
|
statusCreditId = (int)obj;
|
|
}
|
|
}
|
|
|
|
// get/set an skuId
|
|
int skuId = bnhtradeDatabaseClient.Sku.SkuQuery.WIP_SkuGetSet(sqlConnectionString, productId, conditionId, accountTaxCodeId, true);
|
|
|
|
// add the entry to the stock table (minus stockJournalId)
|
|
int stockId = 0;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblStock
|
|
(SkuID, AccountJournalID)
|
|
OUTPUT INSERTED.StockID
|
|
VALUES
|
|
(@skuId, @accountJournalId);
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@skuId", skuId);
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
stockId = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
// insert stock journal entry
|
|
var journalPosts = new List<(int statusId, int quantity)>();
|
|
journalPosts.Add((statusDebitId, quantity));
|
|
journalPosts.Add((statusCreditId, (quantity * -1)));
|
|
int stockJournalId = Stock.StockJournal.StockJournalInsert(sqlConnectionString, stockJournalTypeId, stockId, journalPosts, stockJournalEntryDate, true);
|
|
|
|
// update the stock table
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
UPDATE tblStock
|
|
SET StockJournalID=@stockJournalId
|
|
WHERE StockID=@stockId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockJournalId", stockJournalId);
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
count = cmd.ExecuteNonQuery();
|
|
|
|
if (count < 1)
|
|
{
|
|
throw new Exception("New stock insert cancelled, failed to update StockJournalID");
|
|
}
|
|
}
|
|
|
|
scope.Complete();
|
|
return stockId;
|
|
}
|
|
}
|
|
|
|
private static void WIP_StockDelete(string sqlConnectionString, int stockId)
|
|
{
|
|
int accountJournalType = 0;
|
|
int stockJournalType = 0;
|
|
|
|
// get stock and account types
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// ensure stockId is owner-introduced
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblStockJournal.StockJournalTypeID, tblAccountJournal.AccountJournalTypeID
|
|
FROM
|
|
(tblStock INNER JOIN tblAccountJournal
|
|
ON tblStock.AccountJournalID = tblAccountJournal.AccountJournalID)
|
|
INNER JOIN tblStockJournal
|
|
ON tblStock.StockJournalID = tblStockJournal.StockJournalID
|
|
WHERE
|
|
(((tblStock.StockID)=@stockId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
accountJournalType = reader.GetInt32(1);
|
|
stockJournalType = reader.GetInt32(0);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Integrity check failed, cancelling StockDeleteOwnerIntroduced");
|
|
}
|
|
}
|
|
}
|
|
|
|
// check stock journal type is not restricted
|
|
// owner inventory introduced
|
|
if (stockJournalType == 2)
|
|
{
|
|
// no dramas
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Manual delete of this stock type is not supported, use the moethod that created it!");
|
|
}
|
|
|
|
// check there is only one stock journal entry for stock item
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT Count(tblStockJournal.StockJournalID) AS CountOfStockJournalID
|
|
FROM tblStockJournal
|
|
WHERE (((tblStockJournal.StockID)=@stockId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
int count = (int)cmd.ExecuteScalar();
|
|
|
|
if (count > 1)
|
|
{
|
|
throw new Exception("Delete " + count + " stock journal entries (other than source entry), before peforming this operation.");
|
|
}
|
|
}
|
|
|
|
// remove account journal entry
|
|
Stock.StockCreate.WIP_StockDeleteSubAccountJournalEntry(sqlConnectionString, stockId);
|
|
|
|
// remove stock
|
|
Stock.StockCreate.WIP_StockDeleteSub(sqlConnectionString, stockId);
|
|
|
|
scope.Complete();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static void WIP_StockDeleteSub(string sqlConnectionString, int stockId)
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// check for accountJournalId on stock table
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT AccountJournalID
|
|
FROM tblStock
|
|
WHERE StockID=@stockId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
|
|
if (obj == null)
|
|
{
|
|
throw new Exception("StockID=" + stockId + " does not exist.");
|
|
}
|
|
else if (obj == DBNull.Value)
|
|
{
|
|
// nothing to do all is good
|
|
}
|
|
else
|
|
{
|
|
int id = (int)obj;
|
|
if (id > 0)
|
|
{
|
|
throw new Exception("StockID=" + stockId + " remove account journal entry using method that created it first.");
|
|
}
|
|
}
|
|
}
|
|
|
|
// get stockJournalId
|
|
int stockJournalId;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT StockJournalID
|
|
FROM tblStock
|
|
WHERE StockID=@stockId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
try
|
|
{
|
|
stockJournalId = (int)cmd.ExecuteScalar();
|
|
}
|
|
catch
|
|
{
|
|
throw new Exception("Could not retrive StockJournalID for StockID=" + stockId);
|
|
}
|
|
}
|
|
|
|
// remove stockJournalId from stock table
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
UPDATE tblStock
|
|
SET StockJournalID=NULL
|
|
WHERE StockID=@stockId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
int count = cmd.ExecuteNonQuery();
|
|
|
|
if (count != 2) // we need to count the LastUpdated trigger!
|
|
{
|
|
throw new Exception("Failed to remove StockJournalID from stock table StockID=" + stockId);
|
|
}
|
|
}
|
|
|
|
// delete stock journal entry
|
|
Stock.StockJournal.StockJournalDelete(sqlConnectionString, stockJournalId);
|
|
|
|
// delete stock table entry
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
DELETE FROM tblStock
|
|
WHERE StockID=@stockId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
int count = cmd.ExecuteNonQuery();
|
|
|
|
if (count != 1)
|
|
{
|
|
throw new Exception("StockID = " + stockId + " delete failed");
|
|
}
|
|
else
|
|
{
|
|
scope.Complete();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// to be used by other methods within a transaction scope
|
|
private static void WIP_StockDeleteSubAccountJournalEntry(string sqlConnectionString, int stockId)
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// get the account journal id
|
|
int accountJournalId = 0;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT AccountJournalID
|
|
FROM tblStock
|
|
WHERE StockID=@stockId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
|
|
if (obj == null)
|
|
{
|
|
throw new Exception("StockID=" + stockId + " does not exist.");
|
|
}
|
|
else if (obj == DBNull.Value)
|
|
{
|
|
throw new Exception("AccountJournalID not found for StockID=" + stockId);
|
|
}
|
|
else
|
|
{
|
|
accountJournalId = (int)obj;
|
|
}
|
|
}
|
|
|
|
// remove entry from stock table
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
UPDATE tblStock
|
|
SET AccountJournalID=NULL
|
|
WHERE StockID=@stockId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
int count = cmd.ExecuteNonQuery();
|
|
|
|
if (count != 2) // must include last modified trigger
|
|
{
|
|
throw new Exception("Failed to set AccountJournalID to NULL on stock table for StockID=" + stockId);
|
|
}
|
|
}
|
|
|
|
// delete account journal entry
|
|
Account.AccountQuery.AccountJournalDelete(sqlConnectionString, accountJournalId);
|
|
|
|
scope.Complete();
|
|
}
|
|
}
|
|
|
|
public static int WIP_StockInsertPurchase(string sqlConnectionString, int productId, int conditionId, int accountTaxCodeId, int accountJournalId, int quantity, int statusDebitId)
|
|
{
|
|
DateTime stockJournalEntryDate;
|
|
int stockJournalTypeId = 1;
|
|
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// retrive info from purchase invoice line/transaction
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblAccountJournal.EntryDate
|
|
FROM tblAccountJournal
|
|
WHERE (((tblAccountJournal.AccountJournalID)=@accountJournalId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountJournalId", accountJournalId);
|
|
|
|
stockJournalEntryDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc);
|
|
}
|
|
}
|
|
|
|
return WIP_StockInsertSub(sqlConnectionString, productId, conditionId, accountTaxCodeId, accountJournalId, stockJournalTypeId, stockJournalEntryDate, quantity, statusDebitId);
|
|
}
|
|
|
|
public static int WIP_StockInsertOwnerIntroduced(string sqlConnectionString, decimal amount, int quantity, int productId, int conditionId, int accountTaxCodeId, DateTime entryDate, int debitStatusId)
|
|
{
|
|
int accountJournalType = 3;
|
|
int stockJournalType = 2;
|
|
string currencyCode = "GBP";
|
|
|
|
return WIP_StockInsert(sqlConnectionString, accountJournalType, stockJournalType, currencyCode, amount, quantity, productId, conditionId, accountTaxCodeId, entryDate, debitStatusId);
|
|
}
|
|
|
|
public static void WIP_StockDeletePurchase(string sqlConnectionString, int stockId)
|
|
{
|
|
WIP_StockDeleteSub(sqlConnectionString, stockId);
|
|
}
|
|
|
|
public static void WIP_StockDeleteOwnerIntroduced(string sqlConnectionString, int stockId)
|
|
{
|
|
WIP_StockDelete(sqlConnectionString, stockId);
|
|
}
|
|
|
|
}
|
|
|
|
public class StockJournal
|
|
{
|
|
// only to be assessable via code, use stock relocate to move stock bewtween status'
|
|
public static int StockJournalInsert(string sqlConnectionString, int journalTypeId, int stockId, List<(int statusId, int quantity)> journalPosts,
|
|
DateTime entryDate, bool isNewStock = false)
|
|
{
|
|
// balance and status IsCredit checks made by post insert function
|
|
|
|
// make entrydate utc
|
|
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
|
|
|
|
// create the journal entry
|
|
int stockJournalId;
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
//consitancy check is required?
|
|
bool consistencyRequired = true;
|
|
// get date of most recent debit for status' that I will be crediting
|
|
if (isNewStock == false)
|
|
{
|
|
// build sql string
|
|
string stringSql = @"
|
|
SELECT
|
|
tblStockJournal.EntryDate
|
|
FROM
|
|
tblStockJournal
|
|
INNER JOIN tblStockJournalPost
|
|
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
WHERE
|
|
tblStockJournal.StockID=@stockId
|
|
AND EntryDate>=@entryDate
|
|
AND tblStockJournalPost.Quantity>0
|
|
AND (";
|
|
|
|
bool firstDone = false;
|
|
foreach (var item in journalPosts)
|
|
{
|
|
if (item.quantity < 0)
|
|
{
|
|
if (firstDone)
|
|
{
|
|
stringSql = stringSql + " OR ";
|
|
}
|
|
stringSql = stringSql + "tblStockJournalPost.StockStatusID=" + item.statusId;
|
|
firstDone = true;
|
|
}
|
|
}
|
|
stringSql = stringSql + ");";
|
|
|
|
using (SqlCommand cmd = new SqlCommand(stringSql, conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
cmd.Parameters.AddWithValue("@entryDate", entryDate.ToUniversalTime());
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
consistencyRequired = true;
|
|
}
|
|
else
|
|
{
|
|
consistencyRequired = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// create journal entry
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblStockJournal ( EntryDate, StockJournalTypeID, StockID, IsLocked )
|
|
OUTPUT INSERTED.StockJournalID
|
|
VALUES ( @EntryDate, @journalTypeId, @stockID, @isLocked );
|
|
", conn))
|
|
{
|
|
// add parameters
|
|
cmd.Parameters.AddWithValue("@stockID", stockId);
|
|
cmd.Parameters.AddWithValue("@journalTypeId", journalTypeId);
|
|
cmd.Parameters.AddWithValue("@EntryDate", entryDate.ToUniversalTime());
|
|
cmd.Parameters.AddWithValue("@isLocked", isNewStock);
|
|
|
|
//execute
|
|
stockJournalId = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
// insert journal posts into database
|
|
bnhtradeDatabaseClient.Stock.StockJournal.StockJournalPostInsert(conn, stockId, stockJournalId, journalPosts, isNewStock);
|
|
|
|
// consistency check
|
|
bool consistencyResult = true;
|
|
if (consistencyRequired)
|
|
{
|
|
// build list of effected status'
|
|
var statusIdEffected = new List<int>();
|
|
foreach (var item in journalPosts)
|
|
{
|
|
if (item.quantity < 0)
|
|
{
|
|
statusIdEffected.Add(item.statusId);
|
|
}
|
|
}
|
|
// run check
|
|
consistencyResult = Stock.StockJournal.WIP_StockJournalConsistencyCheck(sqlConnectionString, stockId, statusIdEffected);
|
|
}
|
|
|
|
if (consistencyResult)
|
|
{
|
|
// commit
|
|
scope.Complete();
|
|
return stockJournalId;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Unable to insert stock journal entry, consistancy check failed.");
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void StockJournalDelete(string sqlConnectionString, int stockJournalId)
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// get date for journal entry
|
|
DateTime entryDate;
|
|
int stockId;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblStockJournal.EntryDate, StockID
|
|
FROM tblStockJournal
|
|
WHERE (((tblStockJournal.StockJournalID)=@stockJournalId));
|
|
", conn))
|
|
{
|
|
// add parameters
|
|
cmd.Parameters.AddWithValue("@stockJournalId", stockJournalId);
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
entryDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc);
|
|
stockId = reader.GetInt32(1);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("StockJournalID=" + stockJournalId + " does not exist!");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// is consistancy check required
|
|
bool consistancyCheck;
|
|
// build list of debits that are to be deleted
|
|
var debitList = new List<int>();
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblStockJournalPost.StockStatusID
|
|
FROM tblStockJournalPost
|
|
WHERE (((tblStockJournalPost.StockJournalID)=@stockJournalId) AND ((tblStockJournalPost.Quantity)>0));
|
|
", conn))
|
|
{
|
|
// add parameters
|
|
cmd.Parameters.AddWithValue("@stockJournalId", stockJournalId);
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
while (reader.Read())
|
|
{
|
|
debitList.Add(reader.GetInt32(0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("StockJournalID=" + stockJournalId + " has no debits with quantity greater than zero!");
|
|
}
|
|
}
|
|
}
|
|
|
|
// check no credits for stockId & debit combination have been made since delete entry
|
|
string stringSql = @"
|
|
SELECT
|
|
tblStockJournal.EntryDate
|
|
FROM
|
|
tblStockJournal
|
|
INNER JOIN tblStockJournalPost
|
|
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
WHERE
|
|
tblStockJournal.StockID=@stockId
|
|
AND tblStockJournalPost.Quantity<0
|
|
AND EntryDate>=@entryDate
|
|
AND (";
|
|
|
|
bool firstDone = false;
|
|
foreach (var item in debitList)
|
|
{
|
|
if (firstDone)
|
|
{
|
|
stringSql = stringSql + " OR ";
|
|
}
|
|
stringSql = stringSql + "tblStockJournalPost.StockStatusID=" + item;
|
|
firstDone = true;
|
|
}
|
|
stringSql = stringSql + ");";
|
|
|
|
using (SqlCommand cmd = new SqlCommand(stringSql, conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
cmd.Parameters.AddWithValue("@entryDate", entryDate.ToUniversalTime());
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
consistancyCheck = true;
|
|
}
|
|
else
|
|
{
|
|
consistancyCheck = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// delete the posts
|
|
StockJournalPostDelete(conn, stockJournalId);
|
|
|
|
// delete journal entry
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
DELETE FROM tblStockJournal
|
|
WHERE StockJournalID=@stockJournalId;
|
|
", conn))
|
|
{
|
|
// add parameters
|
|
cmd.Parameters.AddWithValue("@stockJournalId", stockJournalId);
|
|
|
|
int count = cmd.ExecuteNonQuery();
|
|
|
|
if (count != 1)
|
|
{
|
|
throw new Exception("Failed to delete stock journal header.");
|
|
}
|
|
}
|
|
|
|
// consistanct check
|
|
bool consistencyResult = true;
|
|
if (consistancyCheck)
|
|
{
|
|
// run check
|
|
consistencyResult = Stock.StockJournal.WIP_StockJournalConsistencyCheck(sqlConnectionString, stockId, debitList);
|
|
}
|
|
|
|
if (consistencyResult)
|
|
{
|
|
// commit
|
|
scope.Complete();
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Unable to delete stock journal entry, consistancy check failed.");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private static void StockJournalPostInsert(SqlConnection conn, int stockId, int stockJournalId,
|
|
List<(int statusId, int quantity)> journalPosts, bool isNewStock = false)
|
|
{
|
|
//checks
|
|
if (journalPosts.Count > 2)
|
|
{
|
|
// I have purposely made the code to accept split transaction incase of future requirements, however, db design is simpler this way.
|
|
throw new Exception("Stock journal does not currently support split transactions (greater than two posts)." + journalPosts.Count + " number posts attempted.");
|
|
}
|
|
else if (journalPosts.Count < 2)
|
|
{
|
|
// list not long enough
|
|
throw new Exception("Stock journal entry requires minium of two posts, entry of " + journalPosts.Count + " number posts attempted.");
|
|
}
|
|
|
|
if (journalPosts.Sum(item => item.quantity) != 0)
|
|
{
|
|
// credits and debits do not match
|
|
throw new Exception("Sum of credits and debits do not resolve to zero.");
|
|
}
|
|
|
|
// group credits and debits by status
|
|
var dicStatusQty = new Dictionary<int, int>();
|
|
foreach (var post in journalPosts)
|
|
{
|
|
if (dicStatusQty.ContainsKey(post.statusId) == false)
|
|
{
|
|
dicStatusQty.Add(post.statusId, post.quantity);
|
|
}
|
|
else
|
|
{
|
|
dicStatusQty[post.statusId] = dicStatusQty[post.statusId] + post.quantity;
|
|
}
|
|
}
|
|
|
|
// get isCreditOnly for each status
|
|
var dicStatusIsCreditOnly = new Dictionary<int, bool>();
|
|
foreach (var item in dicStatusQty)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT IsCreditOnly FROM tblStockStatus WHERE StockStatusID=@statusId;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@statusId", item.Key);
|
|
|
|
dicStatusIsCreditOnly.Add(item.Key, (bool)cmd.ExecuteScalar());
|
|
}
|
|
}
|
|
|
|
// check there is only one IsCreditOnly in list and it is allowed in this instance
|
|
int isCreditOnlyCount = 0;
|
|
foreach (var item in dicStatusIsCreditOnly)
|
|
{
|
|
if (item.Value)
|
|
{
|
|
isCreditOnlyCount = isCreditOnlyCount + 1;
|
|
}
|
|
}
|
|
if (isNewStock == false && isCreditOnlyCount > 0)
|
|
{
|
|
throw new Exception("Attempted credit or debit to 'Is Credit Only' status not allowed, in this instance.");
|
|
}
|
|
if (isNewStock == true && isCreditOnlyCount != 1)
|
|
{
|
|
throw new Exception("StockID=" + stockId + ", each stock line must have only have one IsCreditOnly=True status assigned to it.");
|
|
}
|
|
|
|
// ensure debit (or zero credit) isn't made to credit only status
|
|
// need to do this check via original post list (i.e. journalPosts)
|
|
foreach (var post in journalPosts)
|
|
{
|
|
// debit check
|
|
if (post.quantity >= 0)
|
|
{
|
|
if (dicStatusIsCreditOnly[post.statusId] == true)
|
|
{
|
|
throw new Exception("Cannot make debit, or zero quantity credit, to credit only status. StatusID=" + post.statusId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// balance check for any credits (that are not isCreditOnly=true)
|
|
foreach (var item in dicStatusQty)
|
|
{
|
|
if (item.Value < 0 && dicStatusIsCreditOnly[item.Key] == false)
|
|
{
|
|
int quantity = Stock.StockJournal.StockStatusBalanceByStockId(conn.ConnectionString, stockId, item.Key);
|
|
|
|
if (quantity + item.Value < 0)
|
|
{
|
|
throw new Exception("Credit status balance check failed. Available balance " + quantity + ", attempted credit " + item.Value * -1 + ".");
|
|
}
|
|
}
|
|
}
|
|
|
|
// get this far...
|
|
// insert journal posts into database
|
|
foreach (var post in journalPosts)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblStockJournalPost ( StockJournalID, StockStatusID, Quantity )
|
|
VALUES ( @StockJournalId, @stockStatudId, @quantity );
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@StockJournalId", stockJournalId);
|
|
cmd.Parameters.AddWithValue("@stockStatudId", post.statusId);
|
|
cmd.Parameters.AddWithValue("@quantity", post.quantity);
|
|
|
|
// execute
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void StockJournalPostDelete(SqlConnection conn, int stockJournalId)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
DELETE FROM tblStockJournalPost
|
|
WHERE StockJournalID=@stockJournalId
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@StockJournalId", stockJournalId);
|
|
|
|
// execute
|
|
cmd.ExecuteNonQuery();
|
|
|
|
// the calling method must compete any transaction-scope on the connection
|
|
}
|
|
}
|
|
|
|
// can be used before commiting an sql insert, update or delete to the stock journal to ensure a status does not fall below 0
|
|
// (unless the status is enabled to do so)
|
|
// set empty list or statusIdEffected to null to check entier stock entries for consistency
|
|
public static bool WIP_StockJournalConsistencyCheck(string sqlConnectionString, int stockId, List<int> statusIdEffected = null)
|
|
{
|
|
if (statusIdEffected == null)
|
|
{
|
|
statusIdEffected = new List<int>();
|
|
}
|
|
|
|
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// if no list supplied, build list of all used status' for stockId
|
|
if (statusIdEffected.Count == 0)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblStockJournalPost.StockStatusID
|
|
FROM
|
|
tblStockJournal
|
|
INNER JOIN tblStockJournalPost
|
|
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
WHERE
|
|
tblStockJournal.StockID=@stockId
|
|
GROUP BY
|
|
tblStockJournalPost.StockStatusID;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
while (reader.Read())
|
|
{
|
|
statusIdEffected.Add(reader.GetInt32(0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("No stock journal entries exist for StockID=" + stockId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// build the sql string to build creditCreate bool
|
|
var dicStatusCreditOnly = new Dictionary<int, bool>();
|
|
string sqlString = @"
|
|
SELECT
|
|
tblStockStatus.StockStatusID, tblStockStatus.IsCreditOnly
|
|
FROM
|
|
tblStockStatus ";
|
|
|
|
for (var i = 0; i < statusIdEffected.Count; i++)
|
|
{
|
|
if (i == 0)
|
|
{
|
|
sqlString = sqlString + " WHERE tblStockStatus.StockStatusID=" + statusIdEffected[i];
|
|
}
|
|
else
|
|
{
|
|
sqlString = sqlString + " OR tblStockStatus.StockStatusID=" + statusIdEffected[i];
|
|
}
|
|
|
|
//if (i == (statusIdEffected.Count - 1))
|
|
//{
|
|
// sqlString = sqlString + ";";
|
|
//}
|
|
}
|
|
sqlString = sqlString + " GROUP BY tblStockStatus.StockStatusID, tblStockStatus.IsCreditOnly;";
|
|
|
|
// run query & build dictionaries
|
|
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
dicStatusCreditOnly.Add(reader.GetInt32(0), reader.GetBoolean(1));
|
|
|
|
while (reader.Read())
|
|
{
|
|
dicStatusCreditOnly.Add(reader.GetInt32(0), reader.GetBoolean(1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Error, no journal entries found for StockID=" + stockId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check integrity of supplied statusIds
|
|
foreach (int statusId in statusIdEffected)
|
|
{
|
|
if (!dicStatusCreditOnly.ContainsKey(statusId))
|
|
{
|
|
throw new Exception("Supplied StatusId (" + statusId + ") doesn't exist for StockId=" + stockId);
|
|
}
|
|
}
|
|
|
|
// loop through each statudId and check integrity, if createdEnabled=false
|
|
foreach (int statudId in statusIdEffected)
|
|
{
|
|
if (dicStatusCreditOnly[statudId] == false)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblStockJournal.EntryDate, tblStockJournalPost.Quantity
|
|
FROM
|
|
tblStockJournal
|
|
INNER JOIN tblStockJournalPost
|
|
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
WHERE
|
|
tblStockJournal.StockID=@stockId
|
|
AND tblStockJournalPost.StockStatusID=@statudId
|
|
ORDER BY
|
|
tblStockJournal.EntryDate;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
cmd.Parameters.AddWithValue("@statudId", statudId);
|
|
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
// read first line into variables
|
|
reader.Read();
|
|
int quantity = reader.GetInt32(1);
|
|
DateTime entryDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc);
|
|
|
|
while (true)
|
|
{
|
|
// compare to next values
|
|
if (reader.Read())
|
|
{
|
|
DateTime nextEntryDate = DateTime.SpecifyKind(reader.GetDateTime(0), DateTimeKind.Utc);
|
|
// don't check quantites for transactions on same date
|
|
if (entryDate == nextEntryDate)
|
|
{
|
|
entryDate = nextEntryDate;
|
|
quantity = quantity + reader.GetInt32(1);
|
|
}
|
|
// check if dates are different
|
|
else
|
|
{
|
|
if (quantity < 0)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
entryDate = nextEntryDate;
|
|
quantity = quantity + reader.GetInt32(1);
|
|
}
|
|
}
|
|
}
|
|
// end if no records, check quantity
|
|
else
|
|
{
|
|
if (quantity < 0)
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// get this far, all good
|
|
return true;
|
|
}
|
|
|
|
public static int StockStatusBalanceByStockId(string sqlConnectionString, int stockId, int statusId)
|
|
{
|
|
int statusBalance = new int();
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
SUM(tblStockJournalPost.Quantity) AS Balance
|
|
FROM
|
|
tblStockJournal
|
|
INNER JOIN tblStockJournalPost
|
|
ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
WHERE
|
|
(tblStockJournal.StockID = @stockId )
|
|
AND (tblStockJournalPost.StockStatusID = @statusId )
|
|
", conn))
|
|
{
|
|
// add parameters
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
cmd.Parameters.AddWithValue("@statusId", statusId);
|
|
|
|
// execute
|
|
object obj = cmd.ExecuteScalar();
|
|
if (obj == null || obj == DBNull.Value)
|
|
{
|
|
statusBalance = 0;
|
|
}
|
|
else
|
|
{
|
|
statusBalance = (int)obj;
|
|
}
|
|
}
|
|
}
|
|
return statusBalance;
|
|
}
|
|
|
|
// Function returns a list with balance of stock avaiable by individual stockId ordered by earliest added to status (stock journal entrydate)
|
|
// beforeDate - used to filter results, useful when reallocating stock retrospectivly (i.e. avoid case were stock is
|
|
// moved out of status, ahead of it being moved into that status) -- really this should be the calling function that does this!!
|
|
public static List<Tuple<int, DateTime, int>> GetStockStatusBalanceBySkuId
|
|
(string sqlConnectionString, int skuId, int stockStatusId, DateTime? maxDateUtc = null, bool sortAgeAscending = true)
|
|
{
|
|
|
|
//build sql statement
|
|
string strSQL = @"
|
|
SELECT a.JournalDate, a.balance, a.stockID
|
|
FROM (
|
|
SELECT MIN(tblStockJournal.EntryDate) AS JournalDate, SUM(tblStockJournalPost.Quantity) AS Balance, tblStock.StockID
|
|
FROM tblStockJournal INNER JOIN
|
|
tblStock ON tblStockJournal.StockID = tblStock.StockID INNER JOIN
|
|
tblStockJournalPost ON tblStockJournal.StockJournalID = tblStockJournalPost.StockJournalID
|
|
WHERE (tblStock.SkuID = @skuId ) AND (tblStockJournalPost.StockStatusID = @stockStatusId )
|
|
GROUP BY tblStock.StockID
|
|
HAVING (SUM(tblStockJournalPost.Quantity)) > 0
|
|
) a
|
|
";
|
|
if (maxDateUtc != null)
|
|
{
|
|
strSQL = strSQL + @"
|
|
WHERE a.JournalDate <= @beforeDateUtc
|
|
";
|
|
}
|
|
strSQL = strSQL + @"
|
|
ORDER BY a.JournalDate;
|
|
";
|
|
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(strSQL, sqlConn))
|
|
{
|
|
// add parameters
|
|
cmd.Parameters.AddWithValue("@skuId", skuId);
|
|
cmd.Parameters.AddWithValue("@stockStatusId", stockStatusId);
|
|
if (maxDateUtc != null)
|
|
{ cmd.Parameters.AddWithValue("@beforeDateUtc", maxDateUtc.Value.ToUniversalTime()); }
|
|
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
List<Tuple<int, DateTime, int>> list = new List<Tuple<int, DateTime, int>>();
|
|
|
|
int index01 = reader.GetOrdinal("StockID");
|
|
int index02 = reader.GetOrdinal("JournalDate");
|
|
int index03 = reader.GetOrdinal("Balance");
|
|
|
|
while (reader.Read())
|
|
{
|
|
int stockId = reader.GetInt32(index01);
|
|
DateTime journalDate = reader.GetDateTime(index02);
|
|
int balance = reader.GetInt32(index03);
|
|
journalDate = DateTime.SpecifyKind(journalDate, DateTimeKind.Utc);
|
|
|
|
list.Add(new Tuple<int, DateTime, int>(stockId, journalDate, balance));
|
|
}
|
|
if (sortAgeAscending == false)
|
|
{
|
|
list.Reverse();
|
|
}
|
|
|
|
return list;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public static int StockReallocateByStockId(string sqlConnectionString, int journalTypeId, int stockId, int quantity, int debitStatusId, int creditStatusId,
|
|
DateTime entryDate = default(DateTime))
|
|
{
|
|
if (entryDate == default(DateTime))
|
|
{
|
|
entryDate = DateTime.UtcNow;
|
|
}
|
|
entryDate = DateTime.SpecifyKind(entryDate, DateTimeKind.Utc);
|
|
|
|
// create the list
|
|
var posts = new List<(int statusId, int quantity)>();
|
|
posts.Add((debitStatusId, quantity));
|
|
posts.Add((creditStatusId, (quantity * -1)));
|
|
|
|
// execute
|
|
return StockJournal.StockJournalInsert(sqlConnectionString, journalTypeId, stockId, posts, entryDate, false);
|
|
}
|
|
|
|
public static List<Tuple<int, int>> StockReallocateBySkuId(string sqlConnectionString, int journalTypeId, int skuId, int quantity, int debitStatusId, int creditStatusId,
|
|
bool moveOldestFirst = true, DateTime entryDate = default(DateTime), bool reallocatePartialQuantity = false)
|
|
{
|
|
// feed an skuId and quantity into function and the stock will be reallocated
|
|
// return tuple list
|
|
// Item1 = StockJournalId
|
|
// Item2 = Quantity
|
|
|
|
List<Tuple<int, DateTime, int>> list = GetStockStatusBalanceBySkuId(sqlConnectionString, skuId, creditStatusId, entryDate, moveOldestFirst);
|
|
if (list == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
List<Tuple<int, int>> returnList = new List<Tuple<int, int>>();
|
|
|
|
// quantity check
|
|
int avaiableQuantity = 0;
|
|
foreach (Tuple<int, DateTime, int> item in list)
|
|
{
|
|
avaiableQuantity = avaiableQuantity + item.Item3;
|
|
}
|
|
if (avaiableQuantity < quantity && reallocatePartialQuantity == false)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// make the changes
|
|
try
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
foreach (Tuple<int, DateTime, int> item in list)
|
|
{
|
|
if (quantity > item.Item3)
|
|
{
|
|
int tempInt = StockReallocateByStockId(sqlConnectionString, journalTypeId, item.Item1, item.Item3, debitStatusId, creditStatusId, entryDate);
|
|
quantity = quantity - item.Item3;
|
|
returnList.Add(new Tuple<int, int>(tempInt, item.Item3));
|
|
}
|
|
else
|
|
{
|
|
int tempInt = StockReallocateByStockId(sqlConnectionString, journalTypeId, item.Item1, quantity, debitStatusId, creditStatusId, entryDate);
|
|
returnList.Add(new Tuple<int, int>(tempInt, quantity));
|
|
break;
|
|
}
|
|
}
|
|
scope.Complete();
|
|
return returnList;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
public static int GetStockIdByStockJournalId(string sqlConnectionString, int stockJournalId)
|
|
{
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT StockID FROM tblStockJournal WHERE StockJournalID=@StockJournalId
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@StockJournalId", stockJournalId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
if (obj == null)
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
return Convert.ToInt32(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (Exception)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public static int StockTransactionTypeIdSelect(string sqlConnectionString, string matchString)
|
|
{
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 Skip transpose, type doesn't exist or is new (not reviewed yet)
|
|
* -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
|
|
|
|
// old optional parameters
|
|
// , bool onNewReturnId = false, bool onNewDisableInsert = false
|
|
|
|
if (matchString.Length == 0)
|
|
{
|
|
throw new Exception("Empty match string passed to method");
|
|
}
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
StockTransactionTypeID,
|
|
IsNewReviewRequired,
|
|
TransactionImportEnabled
|
|
FROM
|
|
tblStockTransactionType
|
|
WHERE
|
|
MatchString=@matchString;
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@matchString", matchString);
|
|
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
int index01 = reader.GetOrdinal("StockTransactionTypeID");
|
|
int index02 = reader.GetOrdinal("IsNewReviewRequired");
|
|
int index03 = reader.GetOrdinal("TransactionImportEnabled");
|
|
|
|
int transactionTypeId = reader.GetInt32(index01);
|
|
bool isNew = reader.GetBoolean(index02);
|
|
bool? importEnabled = reader[index03] as bool? ?? null; // column can be null
|
|
|
|
if (isNew == true || importEnabled == null)
|
|
{
|
|
// return 0 and 'skip' item
|
|
return 0;
|
|
}
|
|
else if (importEnabled == false)
|
|
{
|
|
// mark IsProcessed=true and leave transactionId=null
|
|
return -1;
|
|
}
|
|
else if (transactionTypeId > 0)
|
|
{
|
|
|
|
return transactionTypeId;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Stock TransactionTypeId lookup method went wrong, is one of the 'enabled' boolean on table set to null?");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
public static int StockTransactionTypeIdInsert(string sqlConnectionString, int stockJournalTypeId, string matchString, bool transScopeSuppress = true)
|
|
{
|
|
int transactionTypeId;
|
|
var scopeOption = new TransactionScopeOption();
|
|
if (transScopeSuppress)
|
|
{
|
|
scopeOption = TransactionScopeOption.Suppress;
|
|
}
|
|
else
|
|
{
|
|
scopeOption = TransactionScopeOption.Required;
|
|
}
|
|
|
|
using (TransactionScope scope = new TransactionScope(scopeOption))
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
//check to see if type already exists, return id of that if it does
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblStockTransactionType.StockTransactionTypeID
|
|
FROM
|
|
tblStockTransactionType
|
|
WHERE
|
|
tblStockTransactionType.StockJournalTypeID=@stockJournalTypeId
|
|
AND tblStockTransactionType.MatchString=@matchString;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@matchString", matchString);
|
|
cmd.Parameters.AddWithValue("@stockJournalTypeId", stockJournalTypeId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
|
|
if (!(obj == null || obj == DBNull.Value))
|
|
{
|
|
return (int)obj;
|
|
}
|
|
}
|
|
|
|
// insert new and retrive new value
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblStockTransactionType
|
|
( StockJournalTypeID, MatchString )
|
|
OUTPUT
|
|
INSERTED.StockTransactionTypeID
|
|
VALUES
|
|
( @stockJournalTypeId, @matchString );
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@matchString", matchString);
|
|
cmd.Parameters.AddWithValue("@stockJournalTypeId", stockJournalTypeId);
|
|
|
|
transactionTypeId = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
scope.Complete();
|
|
}
|
|
return transactionTypeId;
|
|
}
|
|
|
|
public static (int quantity, decimal totalAmount) StockGetTotalQuantityAndCost(string sqlConnectionString, int stockId)
|
|
{
|
|
(int quantity, decimal totalAmount) result;
|
|
|
|
using (var conn = new SqlConnection())
|
|
{
|
|
conn.Open();
|
|
|
|
using (var cmd = new SqlCommand(@"
|
|
SELECT tblAccountStockCost.Quantity, tblAccountStockCost.AmountTotal
|
|
FROM tblAccountStockCost
|
|
WHERE tblAccountStockCost.StockID=@stockId;
|
|
"))
|
|
{
|
|
cmd.Parameters.AddWithValue("@stockId", stockId);
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.Read())
|
|
{
|
|
result = (reader.GetInt32(0), reader.GetDecimal(1));
|
|
if (reader.Read())
|
|
{
|
|
throw new Exception("StockID=" + stockId + " found more than once in tblAccountStockCost!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("StockID=" + stockId + " not found in tblAccountStockCost!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void TMP_AddAccountJournalEntriesToStockMovement(string sqlConnectionString)
|
|
{
|
|
// redundant code
|
|
// going to track stock costing by adding quanity and total cost to stock table
|
|
// each stock status will be assigned an accountId, from this I can calculate account balance from stock balance and value
|
|
//
|
|
// the way below would be far too complex for the only added gain of being able to reduce the value of a stock line
|
|
// at a given point in time.
|
|
// going with sending stock to a write-down status and creating new a stock line from that status.
|
|
|
|
return;
|
|
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
// load list to iterate through
|
|
using (SqlCommand cmdSelect = new SqlCommand(@"
|
|
SELECT
|
|
tblStockJournal.StockJournalID, tblStockJournal.EntryDate, tblStockJournal.StockID
|
|
FROM
|
|
tblStockJournal
|
|
WHERE
|
|
(((tblStockJournal.AccountIsProcessed)=@false))
|
|
ORDER BY
|
|
tblStockJournal.EntryDate, tblStockJournal.StockJournalID;
|
|
", sqlConn))
|
|
{
|
|
cmdSelect.Parameters.AddWithValue("@false", false);
|
|
|
|
using (SqlDataReader reader = cmdSelect.ExecuteReader())
|
|
{
|
|
while (reader.Read())
|
|
{
|
|
int StockJournalId = reader.GetInt32(0);
|
|
DateTime entryDate = DateTime.SpecifyKind(reader.GetDateTime(1), DateTimeKind.Utc);
|
|
int stockId = reader.GetInt32(2);
|
|
|
|
// get credit and debits
|
|
int qtyDebit = 0;
|
|
int qtyCredit = 0;
|
|
int statusDebit = 0;
|
|
int statusCredit = 0;
|
|
int i = 0;
|
|
|
|
using (SqlCommand cmdSelectPost = new SqlCommand(@"
|
|
SELECT
|
|
tblStockJournalPost.StockStatusID, tblStockJournalPost.Quantity
|
|
FROM
|
|
tblStockJournalPost
|
|
WHERE
|
|
(((tblStockJournalPost.StockJournalID)=@StockJournalId));
|
|
", sqlConn))
|
|
{
|
|
using (SqlDataReader readerPost = cmdSelect.ExecuteReader())
|
|
{
|
|
while (readerPost.Read())
|
|
{
|
|
i = i + 1;
|
|
int qty = readerPost.GetInt32(1);
|
|
int statusId = readerPost.GetInt32(0);
|
|
|
|
if (qty > 0)
|
|
{
|
|
qtyDebit = qty;
|
|
statusDebit = statusId;
|
|
}
|
|
else
|
|
{
|
|
qtyCredit = qty;
|
|
statusCredit = statusId;
|
|
}
|
|
}
|
|
if (i > 2)
|
|
{
|
|
throw new Exception("more than two post for journal entry StockJournalId=" + StockJournalId + ".");
|
|
}
|
|
}
|
|
}
|
|
|
|
// get account chart id for each status and compare
|
|
int accountIdDebitId;
|
|
int accountIdCreditId;
|
|
|
|
//debit
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblStockStatusType.AccountChartOfID
|
|
FROM tblStockStatus INNER JOIN tblStockStatusType ON tblStockStatus.StockStatusTypeID = tblStockStatusType.StockStatusTypeID
|
|
WHERE (((tblStockStatus.StockStatusID)=@stockStatusId));
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("stockStatusId", statusDebit);
|
|
|
|
accountIdDebitId = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
//credit
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblStockStatusType.AccountChartOfID
|
|
FROM tblStockStatus INNER JOIN tblStockStatusType ON tblStockStatus.StockStatusTypeID = tblStockStatusType.StockStatusTypeID
|
|
WHERE (((tblStockStatus.StockStatusID)=@stockStatusId));
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("stockStatusId", statusCredit);
|
|
|
|
accountIdCreditId = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
using (SqlConnection connScope = new SqlConnection(sqlConnectionString))
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
connScope.Open();
|
|
|
|
// add account journal entry if they are different
|
|
if (accountIdDebitId != accountIdCreditId)
|
|
{
|
|
// get stock value and balance by account Id
|
|
|
|
|
|
|
|
|
|
// insert account journal entry
|
|
|
|
|
|
|
|
// do something with the account journal id
|
|
|
|
|
|
|
|
}
|
|
|
|
// finish up, mark stock journal entry as done
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
UPDATE tblStockJournal SET tblStockJournal.AccountIsProcessed = True
|
|
WHERE (((tblStockJournal.StockJournalID)=@StockJournalId));
|
|
", connScope))
|
|
{
|
|
cmd.Parameters.AddWithValue("StockJournalId", StockJournalId);
|
|
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
scope.Complete();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class StockReconciliation
|
|
{
|
|
public class ReconcileStockTransactionsResult
|
|
{
|
|
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; }
|
|
}
|
|
|
|
// downloads new inventory data from mws and updates stock import tables
|
|
public void UpdateFbaStockImportData(string sqlConnectionString)
|
|
{
|
|
|
|
bool inventoryReceiptUpdate = false;
|
|
bool fbaShipmentsUpdate = false;
|
|
bool fbaReturnsUpdate = false;
|
|
bool fbaAdjustmentUpdate = false;
|
|
bool fbaReimbursementUpdate = false;
|
|
bool fbaRemovalOrderUpdate = false;
|
|
bool fbaInventoryAgeUpdate = false;
|
|
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
var mwsReports = new AmazonReport();
|
|
|
|
if (inventoryReceiptUpdate == false) { inventoryReceiptUpdate = true; mwsReports.UpdateFbaInventoryReceiptData(sqlConnectionString); }
|
|
if (fbaShipmentsUpdate == false) { fbaShipmentsUpdate = true; mwsReports.UpdateFbaSaleShipmentData(sqlConnectionString); }
|
|
if (fbaReturnsUpdate == false) { fbaReturnsUpdate = true; mwsReports.UpdateFbaReturnData(sqlConnectionString); }
|
|
if (fbaAdjustmentUpdate == false) { fbaAdjustmentUpdate = true; mwsReports.UpdateFbaAdustmentData(sqlConnectionString); }
|
|
if (fbaReimbursementUpdate == false) { fbaReimbursementUpdate = true; mwsReports.UpdateFbaReimbursementData(sqlConnectionString); }
|
|
if (fbaRemovalOrderUpdate == false) { fbaRemovalOrderUpdate = true; mwsReports.UpdateFbaRemovalOrderReport(sqlConnectionString); }
|
|
if (fbaInventoryAgeUpdate == false) { fbaInventoryAgeUpdate = true; mwsReports.UpdateFbaInventoryAgeData(sqlConnectionString); }
|
|
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Exception caught running UpdateFbaStockImportData, see for further details",
|
|
1,
|
|
ex.ToString()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// transposes data from report import tables to stock transaction table
|
|
public void ProcessFbaStockImportData(string sqlConnectionString)
|
|
{
|
|
bool inventoryReceiptProcess = false;
|
|
bool fbaShipmentsProcess = false;
|
|
bool fbaReturnsProcess = false;
|
|
bool fbaAdjustmentProcess = false;
|
|
bool fbaReimbursementProcess = false;
|
|
bool fbaRemovalOrderProcess = false;
|
|
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
var mwsReports = new Stock.StockReconciliation();
|
|
|
|
if (inventoryReceiptProcess == false) { inventoryReceiptProcess = true; mwsReports.ProcessFbaInventoryReceiptData(sqlConnectionString); }
|
|
if (fbaShipmentsProcess == false) { fbaShipmentsProcess = true; mwsReports.ProcessFbaSaleShipmentData(sqlConnectionString); }
|
|
if (fbaReturnsProcess == false) { fbaReturnsProcess = true; mwsReports.ProcessFbaReturnsData(sqlConnectionString); }
|
|
if (fbaAdjustmentProcess == false) { fbaAdjustmentProcess = true; mwsReports.ProcessFbaAdustmentData(sqlConnectionString); }
|
|
if (fbaReimbursementProcess == false) { fbaReimbursementProcess = true; mwsReports.WIP_ProcessFbaReimbursementData(sqlConnectionString); }
|
|
if (fbaRemovalOrderProcess == false) { fbaRemovalOrderProcess = true; mwsReports.ProcessReportFbaRemovalOrder(sqlConnectionString); }
|
|
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Exception caught running ProcessFbaStockImportData, see for further details",
|
|
1,
|
|
ex.ToString()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void WIP_ProcessAmazonSettlementData(string sqlConnectionString)
|
|
{
|
|
|
|
MiscFunction.EventLogInsert("Starting import of Amazon settlement data into account transaction table...");
|
|
int reportCount = 0;
|
|
int reportLineCount = 0;
|
|
int lineCount = 0;
|
|
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
try
|
|
{
|
|
// test wether there are records to process
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
Count(ImportAmazonSettlementReportID) AS CountOfID
|
|
FROM
|
|
tblImportAmazonSettlementReport
|
|
WHERE
|
|
(((tblImportAmazonSettlementReport.IsProcessed)=0));
|
|
", sqlConn))
|
|
{
|
|
int records = (int)cmd.ExecuteScalar();
|
|
|
|
if (records == 0)
|
|
{
|
|
MiscFunction.EventLogInsert("No new settlements to process, exiting import...");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// ensure settlement lines have not been processed or had transactions added
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
Count(tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID) AS CountOfID
|
|
FROM
|
|
tblImportAmazonSettlementReportLine
|
|
INNER JOIN tblImportAmazonSettlementReport
|
|
ON tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportID = tblImportAmazonSettlementReport.ImportAmazonSettlementReportID
|
|
WHERE
|
|
(((tblImportAmazonSettlementReport.IsProcessed)=0) AND ((tblImportAmazonSettlementReportLine.AccountTransactionID) Is Not Null))
|
|
OR (((tblImportAmazonSettlementReport.IsProcessed)=0) AND ((tblImportAmazonSettlementReportLine.IsProcessed)=1));
|
|
", sqlConn))
|
|
{
|
|
int count = Convert.ToInt32(cmd.ExecuteScalar());
|
|
if (count != 0)
|
|
{
|
|
throw new Exception("Error, " + count + " settlement report lines have transactionId/IsProcessed set on an unprocessed settlement");
|
|
}
|
|
}
|
|
|
|
// build dictionary of SKU's and Vat type
|
|
var dicSkuToTaxCodeId = new Dictionary<string, int>();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblImportAmazonSettlementReportLine.sku,
|
|
tblSku.AccountTaxCodeID
|
|
FROM
|
|
(tblImportAmazonSettlementReport INNER JOIN tblImportAmazonSettlementReportLine
|
|
ON tblImportAmazonSettlementReport.ImportAmazonSettlementReportID = tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportID)
|
|
INNER JOIN tblSku ON tblImportAmazonSettlementReportLine.sku = tblSku.skuSkuNumber
|
|
WHERE
|
|
(((tblImportAmazonSettlementReport.IsProcessed)=0))
|
|
GROUP BY
|
|
tblImportAmazonSettlementReportLine.sku,
|
|
tblSku.AccountTaxCodeID;
|
|
", sqlConn))
|
|
{
|
|
int i = 0;
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
while (reader.Read())
|
|
{
|
|
i = i + 1;
|
|
Console.Write("\rBuilding SKU list... " + i);
|
|
dicSkuToTaxCodeId.Add(reader.GetString(0), reader.GetInt32(1));
|
|
}
|
|
}
|
|
}
|
|
|
|
// get list of unprocessed settlements to loop thorugh
|
|
using (SqlCommand selectCmd = new SqlCommand(@"
|
|
SELECT * FROM tblImportAmazonSettlementReport
|
|
WHERE IsProcessed=0
|
|
ORDER BY [settlement-end-date]
|
|
", sqlConn))
|
|
using (var reader = selectCmd.ExecuteReader())
|
|
{
|
|
int index01 = reader.GetOrdinal("ImportAmazonSettlementReportID");
|
|
int index02 = reader.GetOrdinal("settlement-id");
|
|
int index03 = reader.GetOrdinal("settlement-end-date");
|
|
int index04 = reader.GetOrdinal("total-amount");
|
|
int index05 = reader.GetOrdinal("currency");
|
|
int index06 = reader.GetOrdinal("marketplace-name");
|
|
int index07 = reader.GetOrdinal("deposit-date");
|
|
|
|
while (reader.Read())
|
|
{
|
|
reportCount = reportCount + 1;
|
|
string consoleLine = "\rProcessing report #" + reportCount + " ";
|
|
Console.Write("\r ");
|
|
Console.Write(consoleLine);
|
|
|
|
int settlementId = reader.GetInt32(index01);
|
|
string settlementRef = reader.GetString(index02);
|
|
DateTime settlementEndDate = DateTime.SpecifyKind(reader.GetDateTime(index03), DateTimeKind.Utc);
|
|
decimal settlementAmount = reader.GetDecimal(index04);
|
|
string currency = reader.GetString(index05);
|
|
DateTime depositDate = DateTime.SpecifyKind(reader.GetDateTime(index07), DateTimeKind.Utc);
|
|
string marketPlace = "";
|
|
List<int> insertedInvoiceIds = new List<int>();
|
|
|
|
// test marketplace-name has been sucsessfully entered into settlement table --
|
|
// this is not supplied in the original report from Amazon and has to be inferred from settlement line data
|
|
if (!reader.IsDBNull(index06))
|
|
{
|
|
marketPlace = reader.GetString(index06);
|
|
}
|
|
else
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Action required: Enter market place name for settlelment report (ImportAmazonSettlementReportID=" + settlementId + ")."
|
|
, 1
|
|
, "Unable to process settlement data from one settlement report '"+ settlementRef +
|
|
"'. Report header table requires a market place name, which is not supplied in original " +
|
|
"report from Amazon. This is useually inferred from settlement lines. " +
|
|
"However, in this case it was not not possible. Manual edit/entry for database table required."
|
|
);
|
|
reportCount = reportCount - 1;
|
|
continue;
|
|
}
|
|
|
|
// build list of cut off dates (multiple when date range straddles two months)
|
|
DateTime maxDate;
|
|
DateTime minDate;
|
|
List<DateTime> dateList = new List<DateTime>();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT Max([posted-date-time]) AS ReturnDate
|
|
FROM tblImportAmazonSettlementReportLine
|
|
WHERE ImportAmazonSettlementReportID=@settlementReportId;
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@settlementReportId", settlementId);
|
|
|
|
maxDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc);
|
|
}
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT Min([posted-date-time]) AS ReturnDate
|
|
FROM tblImportAmazonSettlementReportLine
|
|
WHERE ImportAmazonSettlementReportID=@settlementReportId;
|
|
", sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@settlementReportId", settlementId);
|
|
|
|
minDate = DateTime.SpecifyKind((DateTime)cmd.ExecuteScalar(), DateTimeKind.Utc);
|
|
}
|
|
|
|
for (int i = 1; true; i++)
|
|
{
|
|
DateTime splitDate = new DateTime(minDate.Year, minDate.Month, 1, 0, 0, 0, DateTimeKind.Utc);
|
|
splitDate = splitDate.AddMonths(i);
|
|
splitDate = splitDate.AddSeconds(-1);
|
|
if (splitDate < maxDate)
|
|
{
|
|
dateList.Add(splitDate);
|
|
}
|
|
else
|
|
{
|
|
dateList.Add(maxDate);
|
|
break;
|
|
}
|
|
if (i > 10)
|
|
{
|
|
throw new Exception("Error when building Date list, too many loops.");
|
|
}
|
|
}
|
|
|
|
// shouldn't normally be more than 2 date ranges
|
|
if (dateList.Count > 2 || dateList.Count == 0)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
dateList.Count + " total numner of items in date list (ImportAmazonSettlementReportID=" + settlementId + ")."
|
|
, 1,
|
|
"Settlement period appears to span more 3 months or more. Whilst this is possible, it is unsual. Confirm his is correct.");
|
|
}
|
|
|
|
// loop through settlement lines
|
|
using (SqlConnection transConn = new SqlConnection(sqlConnectionString))
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
transConn.Open();
|
|
|
|
decimal settlementLineTotal = 0;
|
|
|
|
for (int i = 0; i < dateList.Count; i++)
|
|
{
|
|
Console.Write("\r ");
|
|
Console.Write(consoleLine + "- creating export invoice and invoice lines...");
|
|
|
|
//setup dictionaries for this round
|
|
var dicMatchToLineType = new Dictionary<string, int>();
|
|
var dicSettlementLineToLineType = new Dictionary<int, int>();
|
|
var dicLineTypeTotal = new Dictionary<int, decimal>();
|
|
//var dicTransTypeToJournal = new Dictionary<int, int>();
|
|
var dicLineTypeToLineId = new Dictionary<int, int>();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID,
|
|
tblImportAmazonSettlementReportLine.[transaction-type],
|
|
tblImportAmazonSettlementReportLine.[amount-type],
|
|
tblImportAmazonSettlementReportLine.[amount-description],
|
|
tblImportAmazonSettlementReportLine.amount,
|
|
tblImportAmazonSettlementReportLine.currency,
|
|
tblImportAmazonSettlementReportLine.sku
|
|
FROM
|
|
tblImportAmazonSettlementReportLine
|
|
WHERE
|
|
(((tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportID)=@settlementReportId)
|
|
AND ((tblImportAmazonSettlementReportLine.[posted-date-time])<=@maxDate)
|
|
AND tblImportAmazonSettlementReportLine.IsProcessed=0);
|
|
", transConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@settlementReportId", settlementId);
|
|
cmd.Parameters.AddWithValue("@maxDate", dateList[i].ToUniversalTime());
|
|
|
|
using (var readerLine = cmd.ExecuteReader())
|
|
{
|
|
// settlement period can, on occasion, span multiple months. Some months having no transactions
|
|
// account for this here
|
|
if (!readerLine.HasRows)
|
|
{ continue; }
|
|
|
|
while (readerLine.Read())
|
|
{
|
|
reportLineCount = reportLineCount + 1;
|
|
|
|
int settlementLineId = readerLine.GetInt32(0);
|
|
string match01 = readerLine.GetString(1);
|
|
string match02 = readerLine.GetString(2);
|
|
string match03 = readerLine.GetString(3);
|
|
decimal lineAmount = readerLine.GetDecimal(4);
|
|
string lineCurrency = readerLine.GetString(5);
|
|
string lineSku = "";
|
|
if (!readerLine.IsDBNull(6))
|
|
{
|
|
lineSku = readerLine.GetString(6);
|
|
}
|
|
|
|
// double check currency matches settlement parent table
|
|
if (lineCurrency != currency)
|
|
{
|
|
throw new Exception("Currency code of settlement-line does not match parent settlement (ImportAmazonReportSettlementID=" + settlementId + ").");
|
|
}
|
|
|
|
// get transaction type id for line
|
|
// build the match string
|
|
// NB special case for global accounting sale and refunds (also note Goodlwill is included) and sku's where tax is included
|
|
string matchString = "<AmazonReport><SettlementReportLine><" + match01 + "><" + match02 + ">";
|
|
if ((match01 == "Order" || match01 == "Refund") && match02 == "ItemPrice" && (match03 == "Principal" || match03 == "Goodwill" || match03 == "Tax"))
|
|
{
|
|
if (lineSku == "")
|
|
{
|
|
throw new Exception("Could not retrive Sku from SettleLineId=" + settlementLineId);
|
|
}
|
|
|
|
if (match03 == "Goodwill")
|
|
{
|
|
matchString = matchString + "<Principal>";
|
|
}
|
|
else
|
|
{
|
|
matchString = matchString + "<" + match03 + ">";
|
|
}
|
|
|
|
if (dicSkuToTaxCodeId.ContainsKey(lineSku))
|
|
{
|
|
matchString = matchString + "<AccountTaxCodeID=" + dicSkuToTaxCodeId[lineSku] + ">";
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Sku '" + lineSku + "' not found in dictionary list.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
matchString = matchString + "<" + match03 + ">";
|
|
}
|
|
|
|
// get/set linetypeid
|
|
int lineTypeId = 0;
|
|
if (dicMatchToLineType.ContainsKey(matchString))
|
|
{
|
|
lineTypeId = dicMatchToLineType[matchString];
|
|
}
|
|
else
|
|
{
|
|
lineTypeId = Export.ExportQuery.WIP_GetImportInvoiceLineTypeId(sqlConnectionString, matchString);
|
|
// new type item, requires review before continue
|
|
if (lineTypeId == 0)
|
|
{
|
|
MiscFunction.EventLogInsert("New type found for Export Invoice Line Type. Update table!", 1, matchString,
|
|
DateTime.UtcNow, true);
|
|
return;
|
|
}
|
|
|
|
dicMatchToLineType.Add(matchString, lineTypeId);
|
|
}
|
|
|
|
// line type amount total & invoice total
|
|
if (dicLineTypeTotal.ContainsKey(lineTypeId))
|
|
{
|
|
dicLineTypeTotal[lineTypeId] = dicLineTypeTotal[lineTypeId] + lineAmount;
|
|
}
|
|
else
|
|
{
|
|
dicLineTypeTotal.Add(lineTypeId, lineAmount);
|
|
}
|
|
|
|
// set line type for settlement report line
|
|
dicSettlementLineToLineType.Add(settlementLineId, lineTypeId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// finish looping though settlement records (building dictionaries)
|
|
|
|
// build info for invoice header
|
|
|
|
// set transaction/journal entry date, if last in dateList use settlement end date (minus 1 second)
|
|
DateTime invoiceDate;
|
|
if ((i + 1) == dateList.Count)
|
|
{
|
|
invoiceDate = DateTime.SpecifyKind(settlementEndDate, DateTimeKind.Utc);
|
|
invoiceDate = invoiceDate.AddSeconds(-1);
|
|
}
|
|
else
|
|
{
|
|
invoiceDate = DateTime.SpecifyKind(dateList[i], DateTimeKind.Utc);
|
|
}
|
|
|
|
//// set invoice total
|
|
//decimal invoiceTotal = 0;
|
|
//foreach (KeyValuePair<int, decimal> entry in dicLineTypeTotal)
|
|
//{
|
|
// invoiceTotal = invoiceTotal + entry.Value;
|
|
//}
|
|
|
|
|
|
// insert invoice header details
|
|
int invoiceId = bnhtradeDatabaseClient.Export.ExportQuery.WIP_ExportAccountInvoiceInsert(sqlConnectionString,
|
|
2, marketPlace, invoiceDate, depositDate, settlementRef, currency, "");
|
|
insertedInvoiceIds.Add(invoiceId);
|
|
|
|
// insert invoice lines
|
|
foreach (KeyValuePair<int, decimal> entry in dicLineTypeTotal)
|
|
{
|
|
int lineId = bnhtradeDatabaseClient.Export.ExportQuery.WIP_ExportAccountInvoiceLineInsert(sqlConnectionString,
|
|
invoiceId, entry.Key, entry.Value, 0);
|
|
if (lineId < 1)
|
|
{
|
|
throw new Exception("Error inserting invoice line");
|
|
}
|
|
lineCount = lineCount + 1;
|
|
|
|
// add lineId to transtypeId dictionary
|
|
dicLineTypeToLineId.Add(entry.Key, lineId);
|
|
}
|
|
|
|
// update settlement lines with lineIds (if required) and IsProcessed
|
|
Console.Write("\r ");
|
|
Console.Write(consoleLine + "- Updating settlement report tables...");
|
|
|
|
foreach (KeyValuePair<int, int> entry in dicSettlementLineToLineType)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
UPDATE
|
|
tblImportAmazonSettlementReportLine
|
|
SET
|
|
tblImportAmazonSettlementReportLine.ExportAccountInvoiceLineID=@lineId,
|
|
tblImportAmazonSettlementReportLine.IsProcessed=1
|
|
WHERE
|
|
(((tblImportAmazonSettlementReportLine.ImportAmazonSettlementReportLineID)=@reportLineId));
|
|
", transConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@reportLineId", entry.Key);
|
|
|
|
int lineId = dicLineTypeToLineId[entry.Value];
|
|
if (lineId == -1) { cmd.Parameters.AddWithValue("@lineId", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@lineId", lineId); }
|
|
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
}
|
|
|
|
// total for settlement check (total of commited transactions)
|
|
foreach (KeyValuePair<int, decimal> entry in dicLineTypeTotal)
|
|
{
|
|
settlementLineTotal = settlementLineTotal + entry.Value;
|
|
}
|
|
}
|
|
// finish looping through settlement date splits
|
|
|
|
// set settlement report to IsProcessed
|
|
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
UPDATE
|
|
tblImportAmazonSettlementReport
|
|
SET
|
|
tblImportAmazonSettlementReport.IsProcessed=1
|
|
WHERE
|
|
(((tblImportAmazonSettlementReport.ImportAmazonSettlementReportID)=@settlementId));
|
|
", transConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@settlementId", settlementId);
|
|
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
|
|
// checks before commiting transactions for settlement
|
|
if (settlementLineTotal != settlementAmount)
|
|
{
|
|
throw new Exception("Totals of inserted transactions do not match settlement amount");
|
|
}
|
|
|
|
// Final stage, invoice post processing
|
|
//
|
|
// remove invoice lines with LineType invoice entry disabled
|
|
int invoiceRemoved = 0;
|
|
int invoiceLinesRemoved = 0;
|
|
|
|
// build sqlPostfix
|
|
string sqlPostfix = "";
|
|
foreach (int invoiceId in insertedInvoiceIds)
|
|
{
|
|
sqlPostfix = sqlPostfix + @"
|
|
OR (ExportAccountInvoiceID = " + invoiceId + ")";
|
|
}
|
|
sqlPostfix = sqlPostfix + ")";
|
|
|
|
// remove invoice line id from settlement line table
|
|
string sql = @"
|
|
UPDATE tblImportAmazonSettlementReportLine
|
|
SET ExportAccountInvoiceLineID = NULL
|
|
FROM tblImportAmazonSettlementReportLine
|
|
INNER JOIN tblExportAccountInvoiceLine ON tblImportAmazonSettlementReportLine.ExportAccountInvoiceLineID = tblExportAccountInvoiceLine.ExportAccountInvoiceLineID
|
|
INNER JOIN tblExportAccountInvoiceLineType ON tblExportAccountInvoiceLine.ExportAccountInvoiceLineTypeID = tblExportAccountInvoiceLineType.ExportAccountInvoiceLineTypeID
|
|
WHERE (tblExportAccountInvoiceLineType.InvoiceLineEntryEnable = 0)
|
|
AND (
|
|
(1 = 2)";
|
|
sql = sql + sqlPostfix;
|
|
|
|
using (SqlCommand cmd = new SqlCommand(sql, transConn))
|
|
{
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
|
|
// remove invoice lines
|
|
sql = @"
|
|
DELETE
|
|
FROM tblExportAccountInvoiceLine
|
|
FROM tblExportAccountInvoiceLine
|
|
INNER JOIN tblExportAccountInvoiceLineType ON tblExportAccountInvoiceLine.ExportAccountInvoiceLineTypeID = tblExportAccountInvoiceLineType.ExportAccountInvoiceLineTypeID
|
|
WHERE (tblExportAccountInvoiceLineType.IsNewReviewRequired = 0)
|
|
AND (tblExportAccountInvoiceLineType.InvoiceLineEntryEnable = 0)
|
|
AND (
|
|
(1 = 2)";
|
|
sql = sql + sqlPostfix;
|
|
|
|
using (SqlCommand cmd = new SqlCommand(sql, transConn))
|
|
{
|
|
invoiceLinesRemoved = cmd.ExecuteNonQuery();
|
|
}
|
|
|
|
// remove any invoices with no lines
|
|
sql = @"
|
|
DELETE
|
|
FROM tblExportAccountInvoice
|
|
WHERE
|
|
not exists
|
|
(
|
|
select 1 from tblExportAccountInvoiceLine where tblExportAccountInvoice.ExportAccountInvoiceID = tblExportAccountInvoiceLine.ExportAccountInvoiceID
|
|
)
|
|
AND (
|
|
(1 = 2)";
|
|
sql = sql + sqlPostfix;
|
|
|
|
using (SqlCommand cmd = new SqlCommand(sql, transConn))
|
|
{
|
|
invoiceRemoved = cmd.ExecuteNonQuery();
|
|
}
|
|
|
|
// add postfix to invoice ref, if required
|
|
var dicInvoiceIdToRef = new Dictionary<int, string>();
|
|
sql = @"
|
|
SELECT ExportAccountInvoiceID
|
|
FROM tblExportAccountInvoice
|
|
WHERE ((1 = 2) ";
|
|
sql = sql + sqlPostfix + " ORDER BY InvoiceDate";
|
|
using (SqlCommand readerCmd = new SqlCommand(sql, transConn))
|
|
{
|
|
using (var readerInvRef = readerCmd.ExecuteReader())
|
|
{
|
|
while (readerInvRef.Read())
|
|
{
|
|
dicInvoiceIdToRef.Add(readerInvRef.GetInt32(0), settlementRef);
|
|
}
|
|
}
|
|
}
|
|
if (dicInvoiceIdToRef.Count > 1)
|
|
{
|
|
int i = 0;
|
|
foreach (var item in dicInvoiceIdToRef)
|
|
{
|
|
i = i + 1;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
UPDATE tblExportAccountInvoice
|
|
SET Reference = @reference
|
|
WHERE tblExportAccountInvoice.ExportAccountInvoiceID = @invoiceId
|
|
", transConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@reference", item.Value + "-" + i);
|
|
cmd.Parameters.AddWithValue("@invoiceId", item.Key);
|
|
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
}
|
|
}
|
|
|
|
// complete the transaction and move to next settlement report
|
|
scope.Complete();
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
MiscFunction.EventLogInsert(
|
|
"Settlement report import complete. " + reportCount + " reports imported, " + lineCount + " transactions inserted, "
|
|
+ reportLineCount + " report lines processed.");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Import of Amazon settlement table data into transaction table and journal failed",
|
|
1,
|
|
ex.ToString());
|
|
}
|
|
}
|
|
}
|
|
public void ProcessFbaInventoryReceiptData(string sqlConnectionString)
|
|
{
|
|
MiscFunction.EventLogInsert("Starting TransposeFbaInventoryReceiptReport()");
|
|
int transposeCount = 0;
|
|
int transposeSkip = 0;
|
|
int transactionTypeIdPos;
|
|
int transactionTypeIdNeg;
|
|
int stockJournalTypeId = 6;
|
|
string matchStringPos = "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><+ve>";
|
|
string matchStringNeg = "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><-ve>";
|
|
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 Skip transpose, type is new or has not been reviewed yet
|
|
* -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
|
|
|
|
try
|
|
{
|
|
transactionTypeIdPos = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, matchStringPos);
|
|
transactionTypeIdNeg = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, matchStringNeg);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("TransposeFbaInventoryReceiptReport() failed to retrive 'TransactionTypeID from method, cancelling operation. More details available.", 1, ex.ToString());
|
|
return;
|
|
}
|
|
|
|
if (!(transactionTypeIdPos > 0) || !(transactionTypeIdNeg > 0))
|
|
{
|
|
// transaction import and stock journal definitions are not setup -- function requires both to be setup
|
|
int temp;
|
|
temp = Stock.StockJournal.StockTransactionTypeIdInsert(sqlConnectionString, stockJournalTypeId, matchStringPos);
|
|
temp = Stock.StockJournal.StockTransactionTypeIdInsert(sqlConnectionString, stockJournalTypeId, matchStringNeg);
|
|
MiscFunction.EventLogInsert("TransposeFbaInventoryReceiptReport() function requires that both +ve and -ve types are setup. Cancelling operation", 2);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT * FROM tblImportFbaInventoryReceiptReport WHERE IsProcessed=0 " +
|
|
"ORDER BY [received-date];"
|
|
, conn))
|
|
{
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int record = 0;
|
|
int index01 = reader.GetOrdinal("ImportFbaInventoryReceiptReportID");
|
|
int index02 = reader.GetOrdinal("received-date");
|
|
int index03 = reader.GetOrdinal("sku");
|
|
int index04 = reader.GetOrdinal("quantity");
|
|
int index05 = reader.GetOrdinal("fba-shipment-id");
|
|
|
|
while (reader.Read())
|
|
{
|
|
record = record + 1;
|
|
Console.Write("\rProcessing record: " + record);
|
|
DateTime transactionDate = reader.GetDateTime(index02);
|
|
transactionDate = DateTime.SpecifyKind(transactionDate, DateTimeKind.Utc);
|
|
int importTableId = reader.GetInt32(index01);
|
|
string sku = reader.GetString(index03);
|
|
int skuId = Sku.SkuQuery.SkuLookupId(sqlConnectionString, sku, true);
|
|
if (skuId < 1)
|
|
{
|
|
transposeSkip = transposeSkip + 1;
|
|
continue;
|
|
}
|
|
int quantity = reader.GetInt32(index04);
|
|
string reference = reader.GetString(index05);
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection transConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
transConn.Open();
|
|
int transactionId;
|
|
if (quantity > 0)
|
|
{
|
|
transactionId = Stock.StockReconciliation.StockTransactionInsert(sqlConnectionString, transactionDate, transactionTypeIdPos, skuId, quantity, 0, reference, "", false, 0);
|
|
}
|
|
else if (quantity < 0)
|
|
{
|
|
// attempt to update/correct earlier incorrect +ve StockTransaction entry
|
|
using (SqlCommand cmd2 = new SqlCommand(@"
|
|
SELECT StockTransactionID, Quantity FROM tblStockTransaction
|
|
WHERE StockTransactionTypeID=@stockTransactionTypeId AND Reference=@reference AND SkuID=@skuId AND Quantity>=@quantity AND IsProcessed=0
|
|
", transConn))
|
|
{
|
|
cmd2.Parameters.AddWithValue("stockTransactionTypeId", transactionTypeIdPos);
|
|
cmd2.Parameters.AddWithValue("reference", reference);
|
|
cmd2.Parameters.AddWithValue("skuId", skuId);
|
|
cmd2.Parameters.AddWithValue("quantity", (quantity * -1));
|
|
|
|
using (SqlDataReader reader2 = cmd2.ExecuteReader())
|
|
{
|
|
if (reader2.Read())
|
|
{
|
|
transactionId = reader2.GetInt32(0);
|
|
quantity = reader2.GetInt32(1) + quantity;
|
|
|
|
// delete stock transation entry if quantities cancel each other out
|
|
if (quantity == 0)
|
|
{
|
|
using (SqlCommand cmd3 = new SqlCommand(@"
|
|
UPDATE tblImportFbaInventoryReceiptReport
|
|
SET StockTransactionID=NULL
|
|
WHERE StockTransactionID=@transactionId
|
|
", transConn))
|
|
{
|
|
cmd3.Parameters.AddWithValue("transactionId", transactionId);
|
|
cmd3.ExecuteNonQuery();
|
|
}
|
|
using (SqlCommand cmd3 = new SqlCommand(@"
|
|
DELETE FROM tblStockTransaction
|
|
WHERE StockTransactionID=@transactionId
|
|
", transConn))
|
|
{
|
|
cmd3.Parameters.AddWithValue("transactionId", transactionId);
|
|
cmd3.ExecuteNonQuery();
|
|
}
|
|
transactionId = 0;
|
|
}
|
|
// else update transaction quantity
|
|
else
|
|
{
|
|
using (SqlCommand cmd3 = new SqlCommand(@"
|
|
UPDATE tblStockTransaction
|
|
SET Quantity=@quantity
|
|
WHERE StockTransactionID=@transactionId
|
|
", transConn))
|
|
{
|
|
cmd3.Parameters.AddWithValue("transactionId", transactionId);
|
|
cmd3.Parameters.AddWithValue("quantity", quantity);
|
|
cmd3.ExecuteNonQuery();
|
|
}
|
|
}
|
|
}
|
|
// reader returned no matching rows, add new transaction
|
|
else
|
|
{
|
|
transactionId = Stock.StockReconciliation.StockTransactionInsert(sqlConnectionString, transactionDate, transactionTypeIdNeg, skuId, (quantity * -1)
|
|
, 0, reference, "", false, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (quantity == 0)
|
|
{
|
|
transactionId = 0;
|
|
}
|
|
else
|
|
{
|
|
transposeSkip = transposeSkip + 1;
|
|
continue;
|
|
}
|
|
|
|
// update isprocessed and transactionId on import table
|
|
using (SqlCommand updateCmd = new SqlCommand(
|
|
"UPDATE tblImportFbaInventoryReceiptReport " +
|
|
"SET StockTransactionID=@transactionId, IsProcessed=1 " +
|
|
"WHERE ImportFbaInventoryReceiptReportID=@importTableId;",
|
|
transConn))
|
|
{
|
|
if (transactionId == 0) { updateCmd.Parameters.AddWithValue("@transactionId", DBNull.Value); }
|
|
else { updateCmd.Parameters.AddWithValue("@transactionId", transactionId); }
|
|
updateCmd.Parameters.AddWithValue("@importTableId", importTableId);
|
|
|
|
updateCmd.ExecuteNonQuery();
|
|
}
|
|
scope.Complete();
|
|
transposeCount = transposeCount + 1;
|
|
}
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MiscFunction.EventLogInsert("TransposeFbaInventoryReceiptReport() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped.");
|
|
if (transposeSkip > 0) { MiscFunction.EventLogInsert(transposeSkip + " number records skipped during TransposeFbaInventoryReceiptReport() operation.", 2); }
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Exception catch, aborting TransposeFbaInventoryReceiptReport(), see detailed info. "
|
|
+ transposeCount + " total records completed, " + transposeSkip + " records skipped.", 1, ex.ToString());
|
|
}
|
|
}
|
|
public void ProcessFbaSaleShipmentData(string sqlConnectionString)
|
|
{
|
|
// hack time, method requires uptodate fba order information in db order tables
|
|
// this next 'hack' method runs to get minimum required data fbaSalesShipment report table
|
|
// should not be used where persistant data is required (data is retrived from report import tables,
|
|
// which at some point may have older records deleted), but will do for this purpose
|
|
|
|
var hack = new Stock.StockReconciliation();
|
|
hack.WIP_GetSetFbaOrderRefs(sqlConnectionString);
|
|
|
|
MiscFunction.EventLogInsert("Starting TransposeFbaSaleShipmentReport()");
|
|
int transposeCount = 0;
|
|
int transposeSkip = 0;
|
|
int stockJouranlTypeId = 7;
|
|
string matchString = "<AmazonReport><_GET_AMAZON_FULFILLED_SHIPMENTS_DATA_>";
|
|
int transactionTypeId;
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 Skip transpose, yype is new or has not been reviewed yet
|
|
* -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
|
|
|
|
try
|
|
{
|
|
transactionTypeId = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, matchString);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("TransposeFbaSaleShipmentReport() failed to retrive 'TransactionTypeID from method, cancelling operation. More details available.", 1, ex.ToString());
|
|
return;
|
|
}
|
|
|
|
if (transactionTypeId == 0)
|
|
{
|
|
// transaction import and stock journal definitions are not setup, cancel
|
|
int temp = Stock.StockJournal.StockTransactionTypeIdInsert(sqlConnectionString, stockJouranlTypeId, matchString);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT * FROM tblImportFbaSaleShipment WHERE IsProcessed=0 " +
|
|
"ORDER BY [payments-date];"
|
|
, conn))
|
|
{
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int record = 0;
|
|
int index01 = reader.GetOrdinal("ImportFbaSaleShipmentID");
|
|
int index02 = reader.GetOrdinal("payments-date");
|
|
int index03 = reader.GetOrdinal("sku");
|
|
int index04 = reader.GetOrdinal("quantity-shipped");
|
|
int index05 = reader.GetOrdinal("sales-channel");
|
|
int index06 = reader.GetOrdinal("amazon-order-id");
|
|
int index07 = reader.GetOrdinal("amazon-order-item-id");
|
|
|
|
while (reader.Read())
|
|
{
|
|
record = record + 1;
|
|
Console.Write("\rProcessing record: " + record);
|
|
DateTime transactionDate = reader.GetDateTime(index02);
|
|
transactionDate = DateTime.SpecifyKind(transactionDate, DateTimeKind.Utc);
|
|
int importTableId = reader.GetInt32(index01);
|
|
string sku = reader.GetString(index03);
|
|
int skuId = Sku.SkuQuery.SkuLookupId(sqlConnectionString, sku, true);
|
|
if (skuId < 1)
|
|
{ transposeSkip = transposeSkip + 1; continue; }
|
|
int quantity = reader.GetInt32(index04);
|
|
int orderChannelId = Order.OrderQuery.GetSaleChannelIdByName(sqlConnectionString, reader.GetString(index05), true);
|
|
string amazonOrderId = reader.GetString(index06);
|
|
int orderId = Order.OrderQuery.GetOrderIdBySaleChannelRef(sqlConnectionString, orderChannelId, amazonOrderId, true);
|
|
string amazonOrderItemId = reader.GetString(index07);
|
|
int orderItemId = Order.OrderQuery.GetOrderItemIdBySaleChannelRef(sqlConnectionString, orderId, amazonOrderItemId, true);
|
|
|
|
if (quantity > 0 && transactionTypeId == 0)
|
|
{ transposeSkip = transposeSkip + 1; continue; }
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection transConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
transConn.Open();
|
|
int transactionId;
|
|
if (quantity > 0 & transactionTypeId > 0)
|
|
{ transactionId = Stock.StockReconciliation.StockTransactionInsert(sqlConnectionString, transactionDate, transactionTypeId, skuId, quantity, orderItemId, amazonOrderId, "", false, 0); }
|
|
else if (quantity == 0)
|
|
{ transactionId = 0; }
|
|
else
|
|
{ transposeSkip = transposeSkip + 1; continue; }
|
|
|
|
using (SqlCommand updateCmd = new SqlCommand(
|
|
"UPDATE tblImportFbaSaleShipment " +
|
|
"SET StockTransactionID=@transactionId, IsProcessed=1 " +
|
|
"WHERE ImportFbaSaleShipmentID=@importTableId;",
|
|
transConn))
|
|
{
|
|
if (transactionId == 0) { updateCmd.Parameters.AddWithValue("@transactionId", DBNull.Value); }
|
|
else { updateCmd.Parameters.AddWithValue("@transactionId", transactionId); }
|
|
updateCmd.Parameters.AddWithValue("@importTableId", importTableId);
|
|
|
|
updateCmd.ExecuteNonQuery();
|
|
}
|
|
}
|
|
transposeCount = transposeCount + 1;
|
|
scope.Complete();
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MiscFunction.EventLogInsert("TransposeFbaSaleShipmentReport() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped.");
|
|
if (transposeSkip > 0) { MiscFunction.EventLogInsert(transposeSkip + " number records skipped during TransposeFbaSaleShipmentReport() operation.", 2); }
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Exception catch, aborting TransposeFbaSaleShipmentReport(), see detailed info. "
|
|
+ transposeCount + " total records completed, " + transposeSkip + " records skipped.", 1, ex.ToString());
|
|
}
|
|
}
|
|
public void WIP_GetSetFbaOrderRefs(string sqlConnectionString)
|
|
{
|
|
// currently a hack, gets info from FBA sale shipment import table and has to run before the inforation is transposed to transaction table
|
|
// reqires work so app uses MWS api for order/sales data
|
|
|
|
// should not be used where persistant data is required (data is retrived from report import tables,
|
|
// which at some point may have older records deleted), but will do for this purpose
|
|
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT [amazon-order-id], [amazon-order-item-id], [sales-channel], sku
|
|
FROM tblImportFbaSaleShipment WHERE IsProcessed=0
|
|
", sqlConn))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int index01 = reader.GetOrdinal("amazon-order-id");
|
|
int index02 = reader.GetOrdinal("amazon-order-item-id");
|
|
int index03 = reader.GetOrdinal("sales-channel");
|
|
int index04 = reader.GetOrdinal("sku");
|
|
|
|
int record = 0;
|
|
while (reader.Read())
|
|
{
|
|
record = record + 1;
|
|
Console.Write("\rProcessing record: " + record);
|
|
string amazonOrderId = reader.GetString(index01);
|
|
string amazonOrderItemId = reader.GetString(index02);
|
|
string salesChannel = reader.GetString(index03);
|
|
string sku = reader.GetString(index04);
|
|
|
|
// get orderchannelId
|
|
int salesChannelId = Order.OrderQuery.GetSaleChannelIdByName(sqlConnectionString, salesChannel);
|
|
|
|
// get/set order ref
|
|
int orderId = Order.OrderQuery.GetOrderIdBySaleChannelRef(sqlConnectionString, salesChannelId, amazonOrderId, true);
|
|
|
|
// get/set order item ref
|
|
int orderItemId = Order.OrderQuery.GetOrderItemIdBySaleChannelRef(sqlConnectionString, orderId, amazonOrderItemId, true);
|
|
//
|
|
}
|
|
Console.Write("\r");
|
|
Console.WriteLine("Processed {0} total records.", record);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public void ProcessFbaReturnsData(string sqlConnectionString)
|
|
{
|
|
MiscFunction.EventLogInsert("Starting TransposeFbaReturnsReport()");
|
|
int transposeCount = 0;
|
|
int transposeSkip = 0;
|
|
int stockJournalTypeId = 9;
|
|
|
|
try
|
|
{
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT * FROM tblImportFbaCustomerReturn WHERE IsProcessed=0 " +
|
|
"ORDER BY [return-date];"
|
|
, conn))
|
|
{
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int record = 0;
|
|
int index01 = reader.GetOrdinal("ImportFbaCustomerReturnID");
|
|
int index02 = reader.GetOrdinal("return-date");
|
|
int index03 = reader.GetOrdinal("sku");
|
|
int index04 = reader.GetOrdinal("quantity");
|
|
int index05 = reader.GetOrdinal("order-id");
|
|
int index06 = reader.GetOrdinal("detailed-disposition");
|
|
int index07 = reader.GetOrdinal("status");
|
|
int index08 = reader.GetOrdinal("reason");
|
|
int index09 = reader.GetOrdinal("customer-comments");
|
|
|
|
while (reader.Read())
|
|
{
|
|
record = record + 1;
|
|
Console.Write("\rProcessing record: " + record);
|
|
|
|
// create the match string
|
|
string matchString = "<AmazonReport><_GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA_>";
|
|
string status = reader.GetString(index07);
|
|
string disposition = reader.GetString(index06);
|
|
|
|
if (string.Equals(status, "Reimbursed", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
matchString = matchString + "<Reimbursed>";
|
|
}
|
|
else
|
|
{
|
|
if (string.Equals(disposition, "SELLABLE", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
matchString = matchString + "<Sellable>";
|
|
}
|
|
else
|
|
{
|
|
matchString = matchString + "<Unsellable>";
|
|
}
|
|
}
|
|
|
|
int transactionTypeId = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, matchString);
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 Skip transpose, yype is new or has not been reviewed yet
|
|
* -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
|
|
if (transactionTypeId == 0)
|
|
{
|
|
int temp = Stock.StockJournal.StockTransactionTypeIdInsert(sqlConnectionString, stockJournalTypeId, matchString);
|
|
continue;
|
|
}
|
|
|
|
// import data
|
|
int importTableId = reader.GetInt32(index01);
|
|
DateTime transactionDate = reader.GetDateTime(index02);
|
|
transactionDate = DateTime.SpecifyKind(transactionDate, DateTimeKind.Utc);
|
|
string sku = reader.GetString(index03);
|
|
int quantity = reader.GetInt32(index04);
|
|
string reference = reader.GetString(index05);
|
|
int orderChannelId = Order.OrderQuery.GetSaleChannelIdByAmazonOrderId(sqlConnectionString, reference);
|
|
int orderId = Order.OrderQuery.GetOrderIdBySaleChannelRef(sqlConnectionString, orderChannelId, reference, true);
|
|
string detail =
|
|
"Amazon Assessment: " + disposition + Environment.NewLine +
|
|
"Status: " + reader.GetString(index07) + Environment.NewLine +
|
|
"Customer Return Reason: " + reader.GetString(index08);
|
|
if (!reader.IsDBNull(index09))
|
|
{ detail = detail + Environment.NewLine + "Customer Comments: " + reader.GetString(index09); }
|
|
|
|
int skuId = Sku.SkuQuery.SkuLookupId(sqlConnectionString, sku, true);
|
|
if (skuId < 1)
|
|
{ transposeSkip = transposeSkip + 1; continue; }
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection transConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
transConn.Open();
|
|
|
|
int transactionId = 0;
|
|
if (transactionTypeId > 0)
|
|
{ transactionId = Stock.StockReconciliation.StockTransactionInsert(sqlConnectionString, transactionDate, transactionTypeId, skuId, quantity, orderId, "", detail, false, 0); }
|
|
else if (quantity == 0)
|
|
{ transactionId = 0; }
|
|
|
|
using (SqlCommand updateCmd = new SqlCommand(
|
|
"UPDATE tblImportFbaCustomerReturn " +
|
|
"SET StockTransactionID=@transactionId, IsProcessed=1 " +
|
|
"WHERE ImportFbaCustomerReturnID=@importTableId;",
|
|
transConn))
|
|
{
|
|
if (transactionId == 0) { updateCmd.Parameters.AddWithValue("@transactionId", DBNull.Value); }
|
|
else { updateCmd.Parameters.AddWithValue("@transactionId", transactionId); }
|
|
updateCmd.Parameters.AddWithValue("@importTableId", importTableId);
|
|
|
|
updateCmd.ExecuteNonQuery();
|
|
}
|
|
scope.Complete();
|
|
transposeCount = transposeCount + 1;
|
|
}
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MiscFunction.EventLogInsert("TransposeFbaReturnsReport() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped.");
|
|
if (transposeSkip > 0) { MiscFunction.EventLogInsert(transposeSkip + " number records skipped during TransposeFbaReturnsReport() operation.", 2); }
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Exception catch, aborting TransposeFbaReturnsReport(), see detailed info. "
|
|
+ transposeCount + " total records completed, " + transposeSkip + " records skipped.", 1, ex.ToString());
|
|
}
|
|
}
|
|
public void ProcessFbaAdustmentData(string sqlConnectionString)
|
|
{
|
|
MiscFunction.EventLogInsert("Starting TransposeFbaAdustmentReport()");
|
|
int transposeCount = 0;
|
|
int transposeSkip = 0;
|
|
int stockJournalTypeId = 8;
|
|
|
|
// create dictionary of known adjustment codes and searchString
|
|
Dictionary<string, string> adjCodes = new Dictionary<string, string>();
|
|
adjCodes.Add("1", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><1><+ve><SoftwareCorrections>");
|
|
adjCodes.Add("2", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><2><-ve><SoftwareCorrections>");
|
|
adjCodes.Add("3", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><3><+ve><CatalogueManagement>");
|
|
adjCodes.Add("4", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><4><-ve><CatalogueManagement>");
|
|
adjCodes.Add("5", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><5><-ve><Unrecoverableinventory>");
|
|
adjCodes.Add("6", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><6><-ve><DamagedInventoryInboundCarrier>");
|
|
adjCodes.Add("D", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><D><-ve><DestroyedInventory>");
|
|
adjCodes.Add("E", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><E><-ve><DamagedInventoryFulfilmentCentre>");
|
|
adjCodes.Add("F", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><F><+ve><InventoryFound>");
|
|
adjCodes.Add("H", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><H><-ve><DamagedInventoryCustomerReturn>");
|
|
adjCodes.Add("J", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><J><+ve><SoftwareCorrections>");
|
|
adjCodes.Add("K", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><K><-ve><DamagedInventoryItemDefect>");
|
|
adjCodes.Add("M", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><M><-ve><InventoryMisplaced>");
|
|
adjCodes.Add("N", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><N><+ve><TransferringOwnership>");
|
|
adjCodes.Add("O", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><O><-ve><TransferringOwnership>");
|
|
adjCodes.Add("P", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><P><+ve><UnsellableInventory>");
|
|
adjCodes.Add("Q", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><Q><-ve><DamagedInventoryMiscellaneous>");
|
|
adjCodes.Add("U", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><U><-ve><DamagedInventoryMerchant>");
|
|
adjCodes.Add("X", "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><X><-ve><InboundShipmentReceiveAdjustments>");
|
|
|
|
try
|
|
{
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT * FROM tblImportFbaInventoryAdjustmentReport WHERE IsProcessed=0 " +
|
|
"ORDER BY [adjusted-date], ImportFbaInventoryAdjustmentReportID DESC;"
|
|
, conn))
|
|
{
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int record = 0;
|
|
int index01 = reader.GetOrdinal("ImportFbaInventoryAdjustmentReportID");
|
|
int index02 = reader.GetOrdinal("adjusted-date");
|
|
int index03 = reader.GetOrdinal("sku");
|
|
int index04 = reader.GetOrdinal("quantity");
|
|
int index05 = reader.GetOrdinal("transaction-item-id");
|
|
int index06 = reader.GetOrdinal("reason");
|
|
int index07 = reader.GetOrdinal("disposition");
|
|
int index08 = reader.GetOrdinal("fnsku");
|
|
int index09 = reader.GetOrdinal("fulfillment-center-id");
|
|
|
|
while (reader.Read())
|
|
{
|
|
int importTableId = reader.GetInt32(index01);
|
|
record = record + 1;
|
|
bool addTransaction = true;
|
|
Console.Write("\rProcessing record: " + record);
|
|
|
|
string matchString = "";
|
|
string reasonCode = reader.GetString(index06);
|
|
string disposition = reader.GetString(index07);
|
|
if (adjCodes.ContainsKey(reasonCode))
|
|
{
|
|
matchString = adjCodes[reasonCode] + "<" + disposition + ">";
|
|
}
|
|
else if (reasonCode.Length > 0)
|
|
{
|
|
matchString = "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><" + reasonCode + "><" + disposition + ">";
|
|
}
|
|
else
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Aborted TransposeFbaAdustmentReport(), no reason code was found in import table/file. Check imput data.",
|
|
1);
|
|
return;
|
|
}
|
|
|
|
int transactionTypeId = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, matchString);
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 By default, new unreviewed type will return 0 to skip transpose.
|
|
* if enabled, new unreviewed type will return id, data will be transposed to table, reconciliation will pickup new items
|
|
* -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
|
|
if (transactionTypeId == 0)
|
|
{
|
|
transactionTypeId = Stock.StockJournal.StockTransactionTypeIdInsert(sqlConnectionString, stockJournalTypeId, matchString);
|
|
}
|
|
|
|
// not used any more, stock reconciliation will pickup new types
|
|
//if (transactionTypeId == 0)
|
|
//{
|
|
// string errorMessage =
|
|
// "New transaction-type created/detected while running TransposeFbaAdustmentReport. Stock transaction table incomplete, update transaction-type table and run import/transpose again before stock reconciliation. WHERE ImportFbaInventoryAdjustmentReportID=" + importTableId;
|
|
// //MiscFunction.EventLogInsert(errorMessage, 1);
|
|
// throw new Exception(errorMessage);
|
|
//}
|
|
|
|
DateTime transactionDate = reader.GetDateTime(index02);
|
|
transactionDate = DateTime.SpecifyKind(transactionDate, DateTimeKind.Utc);
|
|
string sku = reader.GetString(index03);
|
|
string fnsku = reader.GetString(index08);
|
|
string fulfillmentCenterId = reader.GetString(index09);
|
|
int quantity = reader.GetInt32(index04);
|
|
if (quantity < 0) { quantity = quantity * -1; }
|
|
string reference = reader.GetString(index05);
|
|
|
|
int skuId = Sku.SkuQuery.SkuLookupId(sqlConnectionString, sku, true);
|
|
if (skuId < 1) { transposeSkip = transposeSkip + 1; continue; }
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection transConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
transConn.Open();
|
|
int transactionId = 0;
|
|
|
|
if (quantity == 0)
|
|
{
|
|
// this will set record IsProcessed=True and StockTransactionID=Null
|
|
transactionId = 0;
|
|
}
|
|
|
|
/* Special Case - Found Inventory
|
|
*
|
|
* No transaction table reconciliation issues if sku is lost before it is found. However, transactions
|
|
* will be un-reconcilable if sku is found before it is lost. In this case, hold 'found' transaction(s)
|
|
* in import table. When a corresponding sku lost is posted, transfer 'found' transaction over
|
|
* to transaction table and manually reconcile.
|
|
*
|
|
* Additional issues with points above (and how code is set up), misplaced and found do not always balance
|
|
* (i.e. F - M <> 0). An sku lost in a inbound shipment can be found, but will not get registered as misplaced.
|
|
*/
|
|
|
|
// always add 'misplaced' inventory to transaction table
|
|
else if (false) //(reasonCode == "F")
|
|
{
|
|
int misplacedTotal = 0;
|
|
int foundProcessedTotal = 0;
|
|
|
|
// retrive total misplaced (all)
|
|
using (SqlCommand cmd2 = new SqlCommand(@"
|
|
SELECT Sum(quantity) As SumOfQuantity
|
|
FROM tblImportFbaInventoryAdjustmentReport
|
|
WHERE reason='M' AND sku=@sku;
|
|
", transConn))
|
|
{
|
|
cmd2.Parameters.AddWithValue("sku", sku);
|
|
//cmd2.Parameters.AddWithValue("disposition", disposition);
|
|
|
|
object result = cmd2.ExecuteScalar();
|
|
if (!(result == DBNull.Value))
|
|
{
|
|
misplacedTotal = (int)result * -1;
|
|
}
|
|
}
|
|
|
|
// retrive total found (processed)
|
|
using (SqlCommand cmd2 = new SqlCommand(@"
|
|
SELECT Sum(quantity) As SumOfQuantity
|
|
FROM tblImportFbaInventoryAdjustmentReport
|
|
WHERE reason='F' AND sku=@sku AND IsProcessed=1;
|
|
", transConn))
|
|
{
|
|
cmd2.Parameters.AddWithValue("sku", sku);
|
|
//cmd2.Parameters.AddWithValue("disposition", disposition);
|
|
|
|
object result = cmd2.ExecuteScalar();
|
|
if (!(result == DBNull.Value))
|
|
{
|
|
foundProcessedTotal = (int)result;
|
|
}
|
|
}
|
|
|
|
int misplacedAvaliable = misplacedTotal - foundProcessedTotal;
|
|
|
|
// leave in import table, unprocessed
|
|
if (misplacedAvaliable < 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// item can be copied striaght into trans table and marked as processed
|
|
else if (misplacedAvaliable == quantity)
|
|
{
|
|
// nothing to do
|
|
}
|
|
|
|
// split record and add correct quantity to transaction table
|
|
else if (misplacedAvaliable < quantity)
|
|
{
|
|
// add new cloned record with unmatched quantity
|
|
using (SqlCommand cmd2 = new SqlCommand(@"
|
|
INSERT INTO tblImportFbaInventoryAdjustmentReport (
|
|
[adjusted-date], [transaction-item-id], fnsku, sku, [fulfillment-center-id], quantity, reason, disposition, IsProcessed )
|
|
VALUES (
|
|
@adjustedDate, @transactionItemId, @fnsku, @sku, @fulfillmentCenterId, @quantity, @reason, @disposition, 0 )
|
|
", transConn))
|
|
{
|
|
cmd2.Parameters.AddWithValue("adjustedDate", transactionDate.ToUniversalTime());
|
|
cmd2.Parameters.AddWithValue("transactionItemId", transactionTypeId);
|
|
cmd2.Parameters.AddWithValue("fnsku", fnsku);
|
|
cmd2.Parameters.AddWithValue("sku", sku);
|
|
cmd2.Parameters.AddWithValue("fulfillmentCenterId", fulfillmentCenterId);
|
|
cmd2.Parameters.AddWithValue("quantity", (quantity - misplacedAvaliable));
|
|
cmd2.Parameters.AddWithValue("reason", reasonCode);
|
|
cmd2.Parameters.AddWithValue("disposition", disposition);
|
|
|
|
cmd2.ExecuteNonQuery();
|
|
}
|
|
|
|
quantity = misplacedAvaliable;
|
|
|
|
// update quantity of soon to be processed record (added to trans table)
|
|
using (SqlCommand cmd2 = new SqlCommand(@"
|
|
UPDATE tblImportFbaInventoryAdjustmentReport
|
|
SET quantity=@quantity
|
|
WHERE ImportFbaInventoryAdjustmentReportID=@importTableId
|
|
", transConn))
|
|
{
|
|
cmd2.Parameters.AddWithValue("quantity", quantity);
|
|
cmd2.Parameters.AddWithValue("importTableId", importTableId);
|
|
|
|
cmd2.ExecuteNonQuery();
|
|
}
|
|
}
|
|
|
|
else if (misplacedAvaliable > quantity)
|
|
{
|
|
// nothing to do
|
|
}
|
|
|
|
// should never get here
|
|
else
|
|
{
|
|
throw new Exception("Shit the bed, 'unreachable' code has been reached...");
|
|
}
|
|
|
|
|
|
|
|
//// very old code
|
|
//using (SqlCommand cmd2 = new SqlCommand(@"
|
|
//SELECT StockTransactionID, Quantity FROM tblStockTransaction
|
|
//WHERE StockTransactionTypeID=@stockTransactionTypeId AND SkuID=@skuId AND Quantity>0 AND IsProcessed=0
|
|
//ORDER BY TransactionDate
|
|
//", transConn))
|
|
//{
|
|
// // retrive transaction type ids
|
|
// int oppTransactionTypeId = 0;
|
|
// if (reasonCode == "F")
|
|
// {
|
|
// oppTransactionTypeId = GeneralQueries.GetStockTransactionTypeId(sqlConnectionString, adjCodes["M"] + "<" + disposition + ">");
|
|
// }
|
|
// else
|
|
// {
|
|
// oppTransactionTypeId = GeneralQueries.GetStockTransactionTypeId(sqlConnectionString, adjCodes["F"] + "<" + disposition + ">");
|
|
// }
|
|
|
|
// if (oppTransactionTypeId < 1)
|
|
// {
|
|
// continue;
|
|
// }
|
|
|
|
// cmd2.Parameters.AddWithValue("stockTransactionTypeId", oppTransactionTypeId);
|
|
// cmd2.Parameters.AddWithValue("skuId", skuId);
|
|
// //cmd2.Parameters.AddWithValue("quantity", quantity);
|
|
|
|
// using (SqlDataReader reader2 = cmd2.ExecuteReader())
|
|
// {
|
|
// if (reader2.HasRows)
|
|
// {
|
|
// while (reader2.Read() && quantity > 0)
|
|
// {
|
|
// transactionId = reader2.GetInt32(0);
|
|
// int quantityAvaliable = reader2.GetInt32(1);
|
|
|
|
// // case: only transaction quantity requires update i.e. there is qty remaining
|
|
// if (quantityAvaliable > quantity)
|
|
// {
|
|
// quantityAvaliable = quantityAvaliable - quantity;
|
|
|
|
// using (SqlCommand cmd3 = new SqlCommand(@"
|
|
// UPDATE tblStockTransaction
|
|
// SET Quantity=@quantity
|
|
// WHERE StockTransactionID=@transactionId
|
|
// ", transConn))
|
|
// {
|
|
// cmd3.Parameters.AddWithValue("transactionId", transactionId);
|
|
// cmd3.Parameters.AddWithValue("quantity", quantityAvaliable);
|
|
// cmd3.ExecuteNonQuery();
|
|
|
|
// quantity = 0;
|
|
// }
|
|
// }
|
|
// // case: delete transaction as quantity availiable is <= quantity
|
|
// else
|
|
// {
|
|
// using (SqlCommand cmd3 = new SqlCommand(@"
|
|
// UPDATE tblImportFbaInventoryAdjustmentReport
|
|
// SET StockTransactionID=NULL
|
|
// WHERE StockTransactionID=@transactionId
|
|
// ", transConn))
|
|
// {
|
|
// cmd3.Parameters.AddWithValue("transactionId", transactionId);
|
|
// cmd3.ExecuteNonQuery();
|
|
// }
|
|
// using (SqlCommand cmd3 = new SqlCommand(@"
|
|
// DELETE FROM tblStockTransaction
|
|
// WHERE StockTransactionID=@transactionId
|
|
// ", transConn))
|
|
// {
|
|
// cmd3.Parameters.AddWithValue("transactionId", transactionId);
|
|
// cmd3.ExecuteNonQuery();
|
|
// }
|
|
// transactionId = 0;
|
|
// quantity = quantity - quantityAvaliable;
|
|
// }
|
|
// }
|
|
// if (quantity == 0)
|
|
// {
|
|
// addTransaction = false;
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// //do nothing, leave entry uneffected
|
|
// addTransaction = true;
|
|
// }
|
|
// }
|
|
//}
|
|
}
|
|
|
|
// usual case
|
|
if (transactionTypeId > 0 && addTransaction == true)
|
|
{
|
|
transactionId = Stock.StockReconciliation.StockTransactionInsert(
|
|
sqlConnectionString, transactionDate, transactionTypeId, skuId, quantity, 0, reference, "", false, 0
|
|
);
|
|
}
|
|
|
|
using (SqlCommand updateCmd = new SqlCommand(
|
|
"UPDATE tblImportFbaInventoryAdjustmentReport " +
|
|
"SET StockTransactionID=@transactionId, IsProcessed=1 " +
|
|
"WHERE ImportFbaInventoryAdjustmentReportID=@importTableId;",
|
|
transConn))
|
|
{
|
|
if (transactionId == 0) { updateCmd.Parameters.AddWithValue("@transactionId", DBNull.Value); }
|
|
else { updateCmd.Parameters.AddWithValue("@transactionId", transactionId); }
|
|
updateCmd.Parameters.AddWithValue("@importTableId", importTableId);
|
|
|
|
updateCmd.ExecuteNonQuery();
|
|
}
|
|
scope.Complete();
|
|
transposeCount = transposeCount + 1;
|
|
}
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
MiscFunction.EventLogInsert("TransposeFbaAdustmentReport() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped.");
|
|
if (transposeSkip > 0) { MiscFunction.EventLogInsert(transposeSkip + " number records skipped during TransposeFbaAdustmentReport() operation.", 2); }
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Exception catch, aborting TransposeFbaAdustmentReport(), see detailed info. "
|
|
+ transposeCount + " total records completed, " + transposeSkip + " records skipped.", 1, ex.ToString());
|
|
}
|
|
|
|
return;
|
|
}
|
|
public void WIP_ProcessFbaReimbursementData(string sqlConnectionString)
|
|
{
|
|
/*
|
|
* Not to be used for stock reconciliation! A single stock item can have multiple reimburesements aginst it.
|
|
* Only use to move lost inventory to Amazon ownership (even then, with some caveats!)
|
|
*
|
|
* generally any lost or damaged stock goes to lost and found (and is hence written off)
|
|
* once amazon have reimbursed (confitmation via this report) the stock is then move to amazon owvership
|
|
* and also the 'Cost of goods' amounts moved to the appropreate account id
|
|
*/
|
|
|
|
MiscFunction.EventLogInsert("Starting TransposeFbaRemovalOrderReport()");
|
|
int transposeCount = 0;
|
|
int transposeSkip = 0;
|
|
int stockJournalTypeId = 11;
|
|
|
|
try
|
|
{
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT * FROM tblImportFbaReimbursementReport WHERE IsProcessed=0 " +
|
|
"ORDER BY [approval-date];"
|
|
, conn))
|
|
{
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int record = 0;
|
|
int index01 = reader.GetOrdinal("ImportFbaReimbursementReportID");
|
|
int index02 = reader.GetOrdinal("approval-date");
|
|
int index03 = reader.GetOrdinal("reimbursement-id");
|
|
int index04 = reader.GetOrdinal("reason");
|
|
int index05 = reader.GetOrdinal("sku");
|
|
int index06 = reader.GetOrdinal("quantity-reimbursed-total");
|
|
int index07 = reader.GetOrdinal("quantity-reimbursed-Inventory");
|
|
|
|
while (reader.Read())
|
|
{
|
|
record = record + 1;
|
|
Console.Write("\rProcessing record: " + record);
|
|
|
|
int invRecived = reader.GetInt32(index07);
|
|
string matchStringPos = "";
|
|
int transactionTypeIdPos = 0;
|
|
|
|
// get transtypeIds for qty transaferred to amazon ownership
|
|
string matchStringNeg = "<AmazonReport><_GET_FBA_REIMBURSEMENTS_DATA_><-ve><" + reader.GetString(index04) + ">";
|
|
int transactionTypeIdNeg = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, matchStringNeg);
|
|
if (invRecived > 0)
|
|
{
|
|
matchStringPos = "<AmazonReport><_GET_FBA_REIMBURSEMENTS_DATA_><+ve><" + reader.GetString(index04) + ">";
|
|
transactionTypeIdPos = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, matchStringNeg);
|
|
}
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 Skip transpose, type is new or has not been reviewed yet
|
|
* -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
|
|
if (transactionTypeIdNeg == 0 || (transactionTypeIdPos == 0 && invRecived > 0))
|
|
{
|
|
transposeSkip = transposeSkip + 1;
|
|
int temp = Stock.StockJournal.StockTransactionTypeIdInsert(sqlConnectionString, stockJournalTypeId, matchStringNeg);
|
|
if (transactionTypeIdPos == 0 && invRecived > 0)
|
|
{
|
|
temp = Stock.StockJournal.StockTransactionTypeIdInsert(sqlConnectionString, stockJournalTypeId, matchStringPos);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
int importTableId = reader.GetInt32(index01);
|
|
DateTime transactionDate = DateTime.SpecifyKind(reader.GetDateTime(index02), DateTimeKind.Utc);
|
|
string sku = reader.GetString(index05);
|
|
string reference = reader.GetString(index03);
|
|
|
|
int quantityTotal = reader.GetInt32(index06);
|
|
int skuId = Sku.SkuQuery.SkuLookupId(sqlConnectionString, reader.GetString(index05), true);
|
|
if (skuId < 1)
|
|
{
|
|
transposeSkip = transposeSkip + 1;
|
|
continue;
|
|
}
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection transConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
transConn.Open();
|
|
|
|
int transactionId = 0;
|
|
if (transactionTypeIdNeg > 0)
|
|
{
|
|
transactionId = Stock.StockReconciliation.StockTransactionInsert(
|
|
sqlConnectionString, transactionDate, transactionTypeIdNeg, skuId, quantityTotal, 0, reference);
|
|
}
|
|
if (transactionTypeIdPos > 0)
|
|
{
|
|
int temp = Stock.StockReconciliation.StockTransactionInsert(
|
|
sqlConnectionString, transactionDate, transactionTypeIdPos, skuId, invRecived, 0, reference);
|
|
}
|
|
|
|
using (SqlCommand updateCmd = new SqlCommand(@"
|
|
UPDATE
|
|
tblImportFbaReimbursementReport
|
|
SET
|
|
StockTransactionID=@transactionId,
|
|
IsProcessed=1
|
|
WHERE
|
|
ImportFbaReimbursementReportID=@importTableId;
|
|
", transConn))
|
|
{
|
|
if (transactionId == 0) { updateCmd.Parameters.AddWithValue("@transactionId", DBNull.Value); }
|
|
else { updateCmd.Parameters.AddWithValue("@transactionId", transactionId); }
|
|
updateCmd.Parameters.AddWithValue("@importTableId", importTableId);
|
|
|
|
updateCmd.ExecuteNonQuery();
|
|
}
|
|
scope.Complete();
|
|
transposeCount = transposeCount + 1;
|
|
}
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MiscFunction.EventLogInsert("ProcessFbaReimbursementData() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped.");
|
|
if (transposeSkip > 0) { MiscFunction.EventLogInsert(transposeSkip + " number records skipped during TransposeFbaRemovalOrderReport() operation.", 2); }
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Exception catch, aborting ProcessFbaReimbursementData(), see detailed info. "
|
|
+ transposeCount + " total records completed, " + transposeSkip + " records skipped.", 1, ex.ToString());
|
|
}
|
|
}
|
|
public void ProcessReportFbaRemovalOrder(string sqlConnectionString)
|
|
{
|
|
MiscFunction.EventLogInsert("Starting TransposeFbaRemovalOrderReport()");
|
|
int transposeCount = 0;
|
|
int transposeSkip = 0;
|
|
int stockJournalTypeId = 10;
|
|
|
|
try
|
|
{
|
|
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT * FROM tblImportFbaRemovalOrderReport WHERE IsProcessed=0 " +
|
|
"ORDER BY [request-date];"
|
|
, conn))
|
|
{
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int record = 0;
|
|
int index01 = reader.GetOrdinal("ImportFbaRemovalOrderReportID");
|
|
int index02 = reader.GetOrdinal("request-date");
|
|
int index03 = reader.GetOrdinal("sku");
|
|
//int index04 = reader.GetOrdinal("requested-quantity");
|
|
int index05 = reader.GetOrdinal("order-id");
|
|
int index06 = reader.GetOrdinal("order-type");
|
|
int index07 = reader.GetOrdinal("order-status");
|
|
int index08 = reader.GetOrdinal("disposition");
|
|
int index09 = reader.GetOrdinal("disposed-quantity");
|
|
int index10 = reader.GetOrdinal("shipped-quantity");
|
|
|
|
while (reader.Read())
|
|
{
|
|
record = record + 1;
|
|
Console.Write("\rProcessing record: " + record);
|
|
|
|
// skip if order is not "Completed" status
|
|
if (!(reader.GetString(index07) == "Completed")) { continue; }
|
|
|
|
string matchString = "<AmazonReport><_GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA_><"
|
|
+ reader.GetString(index06) + "><" + reader.GetString(index08) + ">";
|
|
int transactionTypeId = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, matchString);
|
|
/* GetStockTransactionTypeId return meanings
|
|
* >0 use the as the TypeId when inserting transaction
|
|
* 0 Skip transpose, type is new or has not been reviewed yet
|
|
* -1 Type import/transpose is disabled, IsProcessed=TRUE StockTransactionID=NULL */
|
|
if (transactionTypeId == 0)
|
|
{
|
|
int temp = Stock.StockJournal.StockTransactionTypeIdInsert(sqlConnectionString, stockJournalTypeId, matchString);
|
|
transposeSkip = transposeSkip + 1;
|
|
continue;
|
|
}
|
|
|
|
int importTableId = reader.GetInt32(index01);
|
|
DateTime transactionDate = reader.GetDateTime(index02);
|
|
transactionDate = DateTime.SpecifyKind(transactionDate, DateTimeKind.Utc);
|
|
string sku = reader.GetString(index03);
|
|
string reference = reader.GetString(index05);
|
|
|
|
int quantity = 0;
|
|
int skuId = 0;
|
|
if (!reader.IsDBNull(index09))
|
|
{ quantity = reader.GetInt32(index09); }
|
|
if (!reader.IsDBNull(index10))
|
|
{ quantity = reader.GetInt32(index10); }
|
|
if (quantity == 0)
|
|
{ transactionTypeId = -1; }
|
|
else
|
|
{ skuId = Sku.SkuQuery.SkuLookupId(sqlConnectionString, sku, true); }
|
|
if (skuId < 1)
|
|
{ transposeSkip = transposeSkip + 1; continue; }
|
|
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection transConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
transConn.Open();
|
|
|
|
int transactionId = 0;
|
|
if (transactionTypeId > 0)
|
|
{ transactionId = Stock.StockReconciliation.StockTransactionInsert(sqlConnectionString, transactionDate, transactionTypeId, skuId, quantity, 0, reference, "", false, 0); }
|
|
|
|
using (SqlCommand updateCmd = new SqlCommand(
|
|
"UPDATE tblImportFbaRemovalOrderReport " +
|
|
"SET StockTransactionID=@transactionId, IsProcessed=1 " +
|
|
"WHERE ImportFbaRemovalOrderReportID=@importTableId;",
|
|
transConn))
|
|
{
|
|
if (transactionId == 0) { updateCmd.Parameters.AddWithValue("@transactionId", DBNull.Value); }
|
|
else { updateCmd.Parameters.AddWithValue("@transactionId", transactionId); }
|
|
updateCmd.Parameters.AddWithValue("@importTableId", importTableId);
|
|
|
|
updateCmd.ExecuteNonQuery();
|
|
}
|
|
scope.Complete();
|
|
transposeCount = transposeCount + 1;
|
|
}
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MiscFunction.EventLogInsert("TransposeFbaRemovalOrderReport() complete, " + transposeCount + " total records transposed, " + transposeSkip + " records skipped.");
|
|
if (transposeSkip > 0) { MiscFunction.EventLogInsert(transposeSkip + " number records skipped during TransposeFbaRemovalOrderReport() operation.", 2); }
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Exception catch, aborting TransposeFbaRemovalOrderReport(), see detailed info. "
|
|
+ transposeCount + " total records completed, " + transposeSkip + " records skipped.", 1, ex.ToString());
|
|
}
|
|
}
|
|
|
|
public static int StockTransactionInsert(string sqlConnectionString, DateTime transactionUtcDate, int transactionTypeId, int skuId, int quantity,
|
|
int foreignKey = 0, string reference = "", string detail = "", bool isProcessed = false, int stockJournalId = 0)
|
|
{
|
|
transactionUtcDate = DateTime.SpecifyKind(transactionUtcDate, DateTimeKind.Utc);
|
|
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"INSERT INTO tblStockTransaction ( TransactionDate, StockTransactionTypeID, ForeignKey, SkuID, Quantity, Reference, Detail, IsProcessed, StockJournalID ) " +
|
|
"OUTPUT INSERTED.StockTransactionID " +
|
|
"VALUES (@transactionDate, @transactionTypeId, @foreignKey, @skuId, @Quantity, @reference, @detail, @isProcessed, @StockJournalId );",
|
|
sqlConn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@transactionDate", transactionUtcDate.ToUniversalTime());
|
|
cmd.Parameters.AddWithValue("@transactionTypeId", transactionTypeId);
|
|
cmd.Parameters.AddWithValue("@skuId", skuId);
|
|
cmd.Parameters.AddWithValue("@Quantity", quantity);
|
|
if (foreignKey == 0) { cmd.Parameters.AddWithValue("@foreignKey", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@foreignKey", foreignKey); }
|
|
if (reference == "") { cmd.Parameters.AddWithValue("@reference", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@reference", reference); }
|
|
if (detail == "") { cmd.Parameters.AddWithValue("@detail", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@detail", detail); }
|
|
if (isProcessed == false) { cmd.Parameters.AddWithValue("@isProcessed", 0); }
|
|
else { cmd.Parameters.AddWithValue("@isProcessed", 1); }
|
|
if (stockJournalId == 0) { cmd.Parameters.AddWithValue("@StockJournalId", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@StockJournalId", stockJournalId); }
|
|
|
|
|
|
int transactionId = Convert.ToInt32(cmd.ExecuteScalar());
|
|
return transactionId;
|
|
}
|
|
}
|
|
}
|
|
|
|
// iterates through the stock transaction table and inserts stock journal entries, where applicable
|
|
// N.B. This function does not make allowances for status' that can create stock (i.e. if a status does not have stock available, this function will halt processing rows)
|
|
public ReconcileStockTransactionsResult ReconcileStockTransactions(string sqlConnectionString, bool updateTransactions)
|
|
{
|
|
// create the return object
|
|
ReconcileStockTransactionsResult returnResult = new ReconcileStockTransactionsResult();
|
|
|
|
string currentMethodName = nameof(ReconcileStockTransactions);
|
|
//bool returnComplete = false;
|
|
//string returnMessage = "";
|
|
//string returnDetails = "";
|
|
|
|
// ensure import table have been processed into transaction table without exception
|
|
if (updateTransactions == true)
|
|
{
|
|
try
|
|
{
|
|
var preCheck = new StockReconciliation();
|
|
preCheck.ProcessFbaStockImportData(sqlConnectionString);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
returnResult.ProgressMessage = "Precheck failed: " + ex.Message;
|
|
return returnResult;
|
|
}
|
|
}
|
|
|
|
MiscFunction.EventLogInsert("Starting ReconcileStockTransactions()");
|
|
int record = 0;
|
|
int recordSkip = 0;
|
|
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
string sqlPartString = @"
|
|
FROM tblStockTransaction INNER JOIN
|
|
tblStockTransactionType ON tblStockTransaction.StockTransactionTypeID = tblStockTransactionType.StockTransactionTypeID
|
|
WHERE tblStockTransaction.IsProcessed = 0 AND tblStockTransaction.SkuID IS NOT NULL AND tblStockTransaction.Quantity IS NOT NULL
|
|
AND ( tblStockTransactionType.StockJournalEntryEnabled = 1 OR tblStockTransactionType.IsNewReviewRequired = 1 ) ";
|
|
|
|
|
|
// get row count of record set
|
|
using (SqlCommand cmd = new SqlCommand("SELECT COUNT (tblStockTransaction.StockTransactionID) " + sqlPartString, conn))
|
|
{
|
|
returnResult.ItemsRemaining = (int)cmd.ExecuteScalar();
|
|
returnResult.ItemsCompleted = 0;
|
|
}
|
|
|
|
// order by stocktransId desc = Amazon reports are listed in datetime ASC order, some reports have date only, however I have reason to believe these are in time order
|
|
// also. adding this means they at least get processed in the correct order (maybe)!
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblStockTransaction.StockTransactionID, tblStockTransaction.TransactionDate, tblStockTransaction.StockTransactionTypeID, tblStockTransaction.ForeignKey,
|
|
tblStockTransaction.Reference, tblStockTransaction.Detail, tblStockTransaction.SkuID, tblStockTransaction.Quantity,
|
|
tblStockTransactionType.StockJournalEntryEnabled, tblStockTransactionType.DebitStockStatusID, tblStockTransactionType.CreditStockStatusID,
|
|
tblStockTransactionType.StatusBalanceCheckRequired, tblStockTransactionType.CreditStatusFirstInFirstOut, tblStockTransactionType.IsNewReviewRequired,
|
|
tblStockTransactionType.FilterStockOnDateTime, tblStockTransactionType.MatchString, StockJournalTypeID " +
|
|
sqlPartString + @"
|
|
ORDER BY tblStockTransaction.TransactionDate ASC, tblStockTransaction.StockTransactionID DESC;
|
|
", conn))
|
|
{
|
|
using (SqlDataReader reader = cmd.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int index01 = reader.GetOrdinal("StockTransactionID");
|
|
int index02 = reader.GetOrdinal("TransactionDate");
|
|
int index03 = reader.GetOrdinal("StockTransactionTypeID");
|
|
int index04 = reader.GetOrdinal("SkuID");
|
|
int index05 = reader.GetOrdinal("Quantity");
|
|
int index06 = reader.GetOrdinal("StockJournalEntryEnabled");
|
|
int index07 = reader.GetOrdinal("ForeignKey");
|
|
int index08 = reader.GetOrdinal("Reference");
|
|
int index09 = reader.GetOrdinal("Detail");
|
|
int index10 = reader.GetOrdinal("CreditStatusFirstInFirstOut");
|
|
int index11 = reader.GetOrdinal("DebitStockStatusID");
|
|
int index12 = reader.GetOrdinal("CreditStockStatusID");
|
|
int index13 = reader.GetOrdinal("IsNewReviewRequired");
|
|
int index14 = reader.GetOrdinal("FilterStockOnDateTime");
|
|
int index15 = reader.GetOrdinal("MatchString");
|
|
int index16 = reader.GetOrdinal("StockJournalTypeID");
|
|
|
|
while (reader.Read())
|
|
{
|
|
record = record + 1;
|
|
Console.Write("\rProcessing record: {0} ({1} skipped)", (record + recordSkip), recordSkip);
|
|
|
|
// read values into variables
|
|
int stockTransactionId = reader.GetInt32(index01);
|
|
DateTime transactionDate = reader.GetDateTime(index02);
|
|
transactionDate = DateTime.SpecifyKind(transactionDate, DateTimeKind.Utc);
|
|
int transactionTypeID = reader.GetInt32(index03);
|
|
int skuId = reader.GetInt32(index04);
|
|
int quantity = reader.GetInt32(index05);
|
|
bool entryEnabled = reader.GetBoolean(index06);
|
|
int foreignKey = 0;
|
|
if (reader[index07] != DBNull.Value)
|
|
{ foreignKey = reader.GetInt32(index07); }
|
|
string reference = "";
|
|
if (reader[index08] != DBNull.Value)
|
|
{ reference = reader.GetString(index08); }
|
|
string detail = "";
|
|
if (reader[index09] != DBNull.Value)
|
|
{ detail = reader.GetString(index09); }
|
|
bool orderAsc = reader.GetBoolean(index10);
|
|
// check/set debit/credit staus to 0 for special cases
|
|
int debitStatus = 0;
|
|
if (!reader.IsDBNull(index11))
|
|
{ debitStatus = reader.GetInt32(index11); }
|
|
int creditStatus = 0;
|
|
if (!reader.IsDBNull(index12))
|
|
{ creditStatus = reader.GetInt32(index12); }
|
|
bool filterStockOnDateTime = reader.GetBoolean(index14);
|
|
string matchString = "";
|
|
if (!reader.IsDBNull(index15))
|
|
{
|
|
matchString = reader.GetString(index15);
|
|
}
|
|
int journalTypeId = reader.GetInt32(index16);
|
|
|
|
// setup return values
|
|
returnResult.StockTransactionId = stockTransactionId;
|
|
returnResult.StockTransactionTypeId = transactionTypeID;
|
|
returnResult.LastItemDateTime = transactionDate;
|
|
|
|
|
|
// stop if a new transactiontype is encountered
|
|
if (reader.GetBoolean(index13) == true)
|
|
{
|
|
returnResult.ProgressMessage = "New 'Transaction-Type' encountered";
|
|
//Console.Write("\r");
|
|
//MiscFunction.EventLogInsert(errMessage, 1);
|
|
goto Finish;
|
|
}
|
|
|
|
// set debit/credit status' for special cases (i.e. NULL or 0 debit/credit ids in stockTransactionType table)
|
|
if (entryEnabled == true && (debitStatus == 0 || creditStatus == 0))
|
|
{
|
|
// FBA Shipment Receipt +ve
|
|
if (matchString == "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><+ve>"
|
|
|| matchString == "<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_><-ve>")
|
|
{
|
|
using (SqlCommand cmd2 = new SqlCommand("" +
|
|
"SELECT ShipmentStockStatusID FROM tblAmazonShipment WHERE ShipmentId=@reference", conn))
|
|
{
|
|
cmd2.Parameters.Add(new SqlParameter("reference", reference));
|
|
|
|
object temp = cmd2.ExecuteScalar();
|
|
if (temp != DBNull.Value)
|
|
{
|
|
// +ve shipment receipt
|
|
if (creditStatus == 0 && debitStatus > 0)
|
|
{ creditStatus = Convert.ToInt32(temp); }
|
|
|
|
// -ve shipment receipt
|
|
else if (debitStatus == 0 && creditStatus > 0)
|
|
{ debitStatus = Convert.ToInt32(temp); }
|
|
|
|
// something went wrong, raise error
|
|
else
|
|
{
|
|
returnResult.ProgressMessage = "Unable to retrive FBA shipment location/status from tblAmazonShipment for Amazon shipment '" + reference + "'.";
|
|
recordSkip = recordSkip + 1;
|
|
//Console.Write("\r");
|
|
//MiscFunction.EventLogInsert("Debit or credit id value missing for shipment receipt WHERE StockTransactionTypeId="
|
|
// + transactionTypeID, 1, "", default(DateTime), true, conn);
|
|
goto Finish;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// something went wrong, raise error
|
|
else
|
|
{
|
|
returnResult.ProgressMessage = "Coding required. Unhandled special case Transaction-Type encountered (Transaction-Type debit or credit is set to 0).";
|
|
recordSkip = recordSkip + 1;
|
|
goto Finish;
|
|
}
|
|
}
|
|
|
|
// make the changes
|
|
if (entryEnabled == false)
|
|
{
|
|
using (SqlCommand cmdIsProcessed = new SqlCommand(@"
|
|
UPDATE tblStockTransaction
|
|
SET IsProcessed=1
|
|
WHERE StockTransactionID=@stockTransactionId
|
|
", conn))
|
|
{
|
|
cmdIsProcessed.Parameters.AddWithValue("@stockTransactionId", stockTransactionId);
|
|
|
|
cmdIsProcessed.ExecuteNonQuery();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection transConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
transConn.Open();
|
|
List<Tuple<int, int>> list = new List<Tuple<int, int>>();
|
|
if (filterStockOnDateTime == true)
|
|
{
|
|
list = Stock.StockJournal.StockReallocateBySkuId(sqlConnectionString, journalTypeId, skuId, quantity, debitStatus, creditStatus, orderAsc,
|
|
transactionDate.ToUniversalTime(), false);
|
|
}
|
|
else
|
|
{
|
|
list = Stock.StockJournal.StockReallocateBySkuId(sqlConnectionString, journalTypeId, skuId, quantity, debitStatus, creditStatus, orderAsc,
|
|
DateTime.UtcNow, false);
|
|
}
|
|
|
|
// insufficient balance available
|
|
if (list == null)
|
|
{
|
|
// in special case (found inventory), continue
|
|
if (matchString.Contains("<AmazonReport><_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_><F>"))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
returnResult.ProgressMessage = "Insurficent status/location balance to relocate stock";
|
|
recordSkip = recordSkip + 1;
|
|
//Console.Write("\r");
|
|
//MiscFunction.EventLogInsert("StockReallocateBySkuId() returned null (i.e. no avaiable stock to relocate), WHERE StockTransactionId="
|
|
// + stockTransactionId, 2, "", default(DateTime), true, conn);
|
|
goto Finish;
|
|
}
|
|
}
|
|
|
|
// fail safe
|
|
if ((list.Sum(c => c.Item2) > quantity))
|
|
{
|
|
throw new Exception(
|
|
currentMethodName + ": StockReallocateBySkuId() returned greater quantity than passed to function"
|
|
+ stockTransactionId);
|
|
//recordSkip = recordSkip + 1;
|
|
//Console.Write("\r");
|
|
//MiscFunction.EventLogInsert("StockReallocateBySkuId() returned retuned a greater quantity than passed to function, WHERE StockTransactionId="
|
|
// + stockTransactionId, 1, "", default(DateTime), true, conn);
|
|
//goto Finish;
|
|
}
|
|
|
|
|
|
using (SqlCommand cmdUpdate = new SqlCommand(@"
|
|
UPDATE tblStockTransaction
|
|
SET Quantity=@quantity, StockJournalID=@StockJournalId, IsProcessed=1
|
|
WHERE StockTransactionID=@stockTransactionId
|
|
", transConn))
|
|
{
|
|
cmdUpdate.Parameters.AddWithValue("@StockJournalId", list[0].Item1);
|
|
cmdUpdate.Parameters.AddWithValue("@quantity", list[0].Item2);
|
|
cmdUpdate.Parameters.AddWithValue("@stockTransactionId", stockTransactionId);
|
|
|
|
cmdUpdate.ExecuteNonQuery();
|
|
}
|
|
quantity = quantity - list[0].Item2;
|
|
|
|
// only nessecary when there is more than one StockJournal entry - stockTransction row will be copied and quantities split accordingly
|
|
if (list.Count > 1)
|
|
{
|
|
for (int i = 1; i < list.Count; i++)
|
|
{
|
|
int tempInt = Stock.StockReconciliation.StockTransactionInsert(sqlConnectionString,
|
|
transactionDate.ToUniversalTime(), transactionTypeID, skuId, list[i].Item2, foreignKey, reference, detail, true, list[i].Item1);
|
|
quantity = quantity - list[i].Item2;
|
|
|
|
//fail safe
|
|
if (quantity < 0)
|
|
{
|
|
throw new Exception(
|
|
currentMethodName + ": StockReallocateBySkuId() returned greater quantity than passed to function"
|
|
+ stockTransactionId);
|
|
//MiscFunction.EventLogInsert("StockReallocateBySkuId() function assigned/returned more quantity than was passed to function",
|
|
// 1, "", default(DateTime), true, conn);
|
|
//goto Finish;
|
|
}
|
|
}
|
|
}
|
|
|
|
// any remaining quantity not reallocated is added back to transaction table with no corresponding stock journal entry
|
|
if (quantity > 0)
|
|
{
|
|
int tempInt = Stock.StockReconciliation.StockTransactionInsert(sqlConnectionString,
|
|
transactionDate.ToUniversalTime(), transactionTypeID, skuId, quantity, foreignKey, reference, detail, false, 0);
|
|
}
|
|
|
|
scope.Complete();
|
|
//}
|
|
}
|
|
}
|
|
}
|
|
returnResult.ItemsCompleted = returnResult.ItemsCompleted + 1;
|
|
returnResult.ItemsRemaining = returnResult.ItemsRemaining - 1;
|
|
}
|
|
}
|
|
// no records returned
|
|
else
|
|
{
|
|
returnResult.ReconciliationComplete = true;
|
|
returnResult.ProgressMessage = "No new transactions to process";
|
|
goto Finish;
|
|
}
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
}
|
|
|
|
returnResult.ReconciliationComplete = true;
|
|
returnResult.ProgressMessage = "Stock transactions fully reconciled!";
|
|
|
|
Finish:
|
|
|
|
MiscFunction.EventLogInsert("ProcessStockTransactions() compete. " + (record - recordSkip) + " total records processed, " + recordSkip + " rows uncompllete due to insurficent stock.");
|
|
MiscFunction.EventLogInsert("ProcessStockTransactions(), " + recordSkip + " rows skipped due to insurficent stock.", 2);
|
|
return returnResult;
|
|
}
|
|
|
|
}
|
|
}
|
|
namespace Sku
|
|
{
|
|
public class SkuQuery
|
|
{
|
|
public static int SkuLookupId(string sqlConnectionString, string sku, bool enableLegacy = false)
|
|
{
|
|
// if enableLegacy = true, function will attempt to lookup value by sku count
|
|
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT skuSkuID FROM tblSku WHERE skuSkuNumber=@sku;
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@sku", sku);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
if (!(obj == null))
|
|
{
|
|
return Convert.ToInt32(obj);
|
|
}
|
|
}
|
|
// if that didn't work, lookup buy sku count
|
|
if (sku.Length == 6 & enableLegacy == true)
|
|
{
|
|
int skucount;
|
|
bool okay = int.TryParse(sku, out skucount);
|
|
if (okay)
|
|
{
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT skuSkuID FROM tblSku WHERE skuSkuCount=@skuCount;"
|
|
, conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@skuCount", skucount);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
if (!(obj == null))
|
|
{
|
|
return Convert.ToInt32(obj);
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// used for retriving SKU that matched parameters, creates new if required, returns 0 if not found
|
|
public static int WIP_SkuGetSet(string sqlConnectionString, int productId, int conditionId, int accountTaxCodeId, bool noMatchInsertNew)
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// look for existing entry
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT
|
|
tblSku.skuSkuID
|
|
FROM
|
|
tblSku
|
|
WHERE
|
|
(((tblSku.skuProductID)=@productId) AND ((tblSku.skuSkuConditionID)=@conditionId) AND ((tblSku.AccountTaxCodeID)=@accountTaxCodeId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@productId", productId);
|
|
cmd.Parameters.AddWithValue("@conditionId", conditionId);
|
|
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
if (obj != null)
|
|
{
|
|
return (int)obj;
|
|
}
|
|
}
|
|
|
|
// value check insert bool
|
|
if (noMatchInsertNew == false)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
// get this far, check tax code id is a valid for SKU
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblAccountTaxCode.InvoiceSales
|
|
FROM tblAccountTaxCode
|
|
WHERE (((tblAccountTaxCode.AccountTaxCodeID)=@accountTaxCodeId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
|
|
|
|
object obj = cmd.ExecuteScalar();
|
|
|
|
if (obj == null)
|
|
{
|
|
throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " doesn't exist!");
|
|
}
|
|
else
|
|
{
|
|
bool result = (bool)obj;
|
|
if (result == false)
|
|
{
|
|
throw new Exception("AccountTaxCodeID=" + accountTaxCodeId + " is not a valid type for an SKU.");
|
|
}
|
|
}
|
|
}
|
|
|
|
// get info to create sku number
|
|
int skuCount;
|
|
int skuSuffix;
|
|
using (SqlCommand cmd = new SqlCommand("SELECT NEXT VALUE FOR SkuCountSequence;", conn))
|
|
{
|
|
skuCount = (int)cmd.ExecuteScalar();
|
|
}
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
SELECT tblSkuCondition.scnSkuNumberSuffix
|
|
FROM tblSkuCondition
|
|
WHERE (((tblSkuCondition.scnSkuConditionID)=@conditionId));
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@conditionId", conditionId);
|
|
|
|
try
|
|
{
|
|
skuSuffix = (int)cmd.ExecuteScalar();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new Exception("Error retriving SKU number suffix for SkuConditionID=" + conditionId + "." +
|
|
System.Environment.NewLine + "Error Message: " + ex.Message);
|
|
}
|
|
}
|
|
string skuNumber = skuCount.ToString("D6") + "-" + skuSuffix.ToString("D2");
|
|
|
|
// insert new sku
|
|
int skuId;
|
|
using (SqlCommand cmd = new SqlCommand(@"
|
|
INSERT INTO tblSku
|
|
(skuSkuNumber, skuProductID, skuSkuConditionID, AccountTaxCodeID)
|
|
OUTPUT INSERTED.skuSkuID
|
|
VALUES
|
|
(@skuNumber, @productId, @conditionId, @accountTaxCodeId)
|
|
", conn))
|
|
{
|
|
cmd.Parameters.AddWithValue("@skuNumber", skuNumber);
|
|
cmd.Parameters.AddWithValue("@productId", productId);
|
|
cmd.Parameters.AddWithValue("@conditionId", conditionId);
|
|
cmd.Parameters.AddWithValue("@accountTaxCodeId", accountTaxCodeId);
|
|
|
|
skuId = (int)cmd.ExecuteScalar();
|
|
}
|
|
|
|
scope.Complete();
|
|
return skuId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
namespace Inventory
|
|
{
|
|
public class InventoryPricing
|
|
{
|
|
|
|
public static void AmazonMinMaxTemp(string sqlConnectionString)
|
|
{
|
|
MiscFunction.ConsoleUpdate("Operation started.");
|
|
|
|
// first command line git commit and push
|
|
|
|
DateTime crTimeStamp = DateTime.SpecifyKind( DateTime.UtcNow, DateTimeKind.Utc);
|
|
int count = 0;
|
|
int exceptionSku = 0;
|
|
|
|
string stringSql = @"
|
|
SELECT
|
|
b.SkuID
|
|
,b.SkuTotalQuantity
|
|
,b.SkuTotalCost
|
|
,b.SkuAvgUnitCost
|
|
,tblSku.skuProductID
|
|
,tblSku.skuSkuConditionID
|
|
,tblSku.AccountTaxCodeID
|
|
,tblProductCategory.ProfitMinPercent
|
|
,tblProductCategory.ProfitMinAmount
|
|
,(tblAmazonFeeEstimate.ReferralFee / tblAmazonFeeEstimate.PriceToEstimateFeeListingPrice) As AmazonMargin
|
|
,(tblAmazonFeeEstimate.VariableClosingFee + tblAmazonFeeEstimate.PerItemFee + tblAmazonFeeEstimate.FBAFee + tblAmazonFeeEstimate.OtherFee_Exception) AS AmazonFees
|
|
,tblAccountTaxCode.TaxRateMultiplierNet
|
|
,tblAccountTaxCode.TaxRateNameShort
|
|
,tblSkuCondition.IsFixedPrice
|
|
,tblSkuCondition.CompetitivePriceMultiplierNew
|
|
,tblSkuCondition.CompetitivePriceMultiplierMatch
|
|
,tblSkuCondition.scnSkuNumberSuffix
|
|
FROM
|
|
(((((
|
|
SELECT
|
|
a.SkuID,
|
|
Sum(a.SumOfQuantity) AS SkuTotalQuantity,
|
|
Sum(a.QuanityTimesUnitCost) AS SkuTotalCost,
|
|
Sum(a.QuanityTimesUnitCost)/Sum(a.SumOfQuantity) AS SkuAvgUnitCost
|
|
FROM
|
|
(
|
|
SELECT
|
|
tblStock.SkuID,
|
|
Sum(tblStockJournalPost.Quantity) AS SumOfQuantity,
|
|
tblStockJournal.StockID, tblAccountStockCost.AmountUnit,
|
|
Sum([tblStockJournalPost].[Quantity])*[tblAccountStockCost].[AmountUnit] AS QuanityTimesUnitCost
|
|
FROM
|
|
(((tblStockJournalPost
|
|
INNER JOIN tblStockStatus
|
|
ON tblStockJournalPost.StockStatusID = tblStockStatus.StockStatusID)
|
|
INNER JOIN tblStockJournal ON tblStockJournalPost.StockJournalID = tblStockJournal.StockJournalID)
|
|
INNER JOIN tblAccountStockCost ON tblStockJournal.StockID = tblAccountStockCost.StockID)
|
|
INNER JOIN tblStock ON tblAccountStockCost.StockID = tblStock.StockID
|
|
WHERE
|
|
tblStockStatus.StockStatusTypeID=3
|
|
OR tblStockStatus.StockStatusTypeID=4
|
|
GROUP BY
|
|
tblStockJournal.StockID,
|
|
tblAccountStockCost.AmountUnit,
|
|
tblStock.SkuID
|
|
HAVING
|
|
Sum(tblStockJournalPost.Quantity)>0
|
|
) a
|
|
GROUP BY
|
|
a.SkuID
|
|
) b
|
|
INNER JOIN tblSku ON b.SkuID = tblSku.skuSkuID)
|
|
INNER JOIN tblProduct ON tblSku.skuProductID = tblProduct.prdProductID)
|
|
LEFT JOIN tblAmazonFeeEstimate ON tblProduct.prdProductID = tblAmazonFeeEstimate.ProductIdentifier )
|
|
INNER JOIN tblProductCategory ON tblProduct.ProductCategoryID = tblProductCategory.ProductCategoryID)
|
|
INNER JOIN tblAccountTaxCode ON tblSku.AccountTaxCodeID = tblAccountTaxCode.AccountTaxCodeID
|
|
INNER JOIN tblSkuCondition ON tblSku.skuSkuConditionID = tblSkuCondition.scnSkuConditionID
|
|
";
|
|
try
|
|
{
|
|
using (var conn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
conn.Open();
|
|
|
|
// loop through table
|
|
using (var cmd01 = new SqlCommand(stringSql, conn))
|
|
{
|
|
using (var reader01 = cmd01.ExecuteReader())
|
|
{
|
|
if (reader01.HasRows)
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Querying the database returned no records.");
|
|
}
|
|
|
|
// get ordinlals
|
|
int ordinalSkuID = reader01.GetOrdinal("SkuID");
|
|
int ordinalSkuTotalQuantity = reader01.GetOrdinal("SkuTotalQuantity");
|
|
int ordinalSkuTotalCost = reader01.GetOrdinal("SkuTotalCost");
|
|
int ordinalSkuAvgUnitCost = reader01.GetOrdinal("SkuAvgUnitCost");
|
|
int ordinalProductId = reader01.GetOrdinal("skuProductID");
|
|
int ordinalSkuConditionId = reader01.GetOrdinal("skuSkuConditionID");
|
|
int ordinalAccountTaxCodeID = reader01.GetOrdinal("AccountTaxCodeID");
|
|
int ordinalProfitMinPercent = reader01.GetOrdinal("ProfitMinPercent");
|
|
int ordinalProfitMinAmount = reader01.GetOrdinal("ProfitMinAmount");
|
|
int ordinalAmazonMargin = reader01.GetOrdinal("AmazonMargin");
|
|
int ordinalAmazonFees = reader01.GetOrdinal("AmazonFees");
|
|
int ordinalTaxRateMultiplierNet = reader01.GetOrdinal("TaxRateMultiplierNet");
|
|
int ordinalTaxRateNameShort = reader01.GetOrdinal("TaxRateNameShort");
|
|
int ordinalIsFixedPrice = reader01.GetOrdinal("IsFixedPrice");
|
|
int ordinalCompetitivePriceMultiplierNew = reader01.GetOrdinal("CompetitivePriceMultiplierNew");
|
|
int ordinalCompetitivePriceMultiplierMatch = reader01.GetOrdinal("CompetitivePriceMultiplierMatch");
|
|
int ordinalSkuNumberSuffix = reader01.GetOrdinal("scnSkuNumberSuffix");
|
|
|
|
|
|
while (reader01.Read())
|
|
{
|
|
// other required variables
|
|
int skuId = reader01.GetInt32(ordinalSkuID);
|
|
exceptionSku = skuId;
|
|
int skuProductId = reader01.GetInt32(ordinalProductId);
|
|
int skuConditionId = reader01.GetInt32(ordinalSkuConditionId);
|
|
int skuTaxCodeId = reader01.GetInt32(ordinalAccountTaxCodeID);
|
|
decimal skuProfitMargin = reader01.GetDecimal(ordinalProfitMinPercent) / 100;
|
|
decimal skuAmazonMargin = decimal.Round(reader01.GetDecimal(ordinalAmazonMargin), 3);
|
|
decimal skuVatMargin = reader01.GetDecimal(ordinalTaxRateMultiplierNet);
|
|
string skuTaxRateName = reader01.GetString(ordinalTaxRateNameShort);
|
|
bool skuIsFixedPrice = reader01.GetBoolean(ordinalIsFixedPrice);
|
|
decimal skuCompetitivePriceMultiplierNew = reader01.GetDecimal(ordinalCompetitivePriceMultiplierNew);
|
|
decimal skuCompetitivePriceMultiplierMatch = reader01.GetDecimal(ordinalCompetitivePriceMultiplierMatch);
|
|
decimal skuTotalCost = reader01.GetDecimal(ordinalSkuTotalCost);
|
|
decimal skuPriceMinProfit = reader01.GetDecimal(ordinalProfitMinAmount);
|
|
decimal skuOrderChannelFee = reader01.GetDecimal(ordinalAmazonFees);
|
|
decimal crUnitAvgCost = reader01.GetDecimal(ordinalSkuAvgUnitCost);
|
|
int skuNumberSuffix = reader01.GetInt32(ordinalSkuNumberSuffix);
|
|
|
|
|
|
// STAGE 2
|
|
// SKU current stock details (i.e. quantity, cost per unit, inventory age, etc.)
|
|
|
|
|
|
|
|
// Stage 4
|
|
// Set MIN Price
|
|
decimal crUnitAvgCostActual = crUnitAvgCost;
|
|
decimal crPriceMinAmountAuto;
|
|
decimal crPriceMinAmountFinal;
|
|
decimal crProfitMinAmount;
|
|
|
|
// used loss, sells just to cover fees
|
|
if (skuNumberSuffix >= 11 && skuNumberSuffix <= 14)
|
|
{
|
|
if (crUnitAvgCost == 0)
|
|
{
|
|
skuVatMargin = 0m;
|
|
}
|
|
crUnitAvgCost = 0m;
|
|
skuProfitMargin = 0m;
|
|
crProfitMinAmount = 0m;
|
|
skuPriceMinProfit = 0m;
|
|
}
|
|
|
|
if (skuTaxRateName == "MS" || skuTaxRateName == "GA")
|
|
{
|
|
crPriceMinAmountAuto = (5m * crUnitAvgCost + 6m * skuOrderChannelFee) / (-6m * skuProfitMargin - 6m * skuAmazonMargin + 5m);
|
|
//crPriceMinCalculatedTax = (crPriceMinAmountAuto - crUnitAvgCost) * (1 / 6);
|
|
crProfitMinAmount = crPriceMinAmountAuto * skuProfitMargin;
|
|
}
|
|
else
|
|
{
|
|
crPriceMinAmountAuto = (crUnitAvgCost + skuOrderChannelFee) / (1 - (skuProfitMargin + skuAmazonMargin + skuVatMargin));
|
|
//crPriceMinCalculatedTax = crPriceMinAmountAuto * skuVatMargin;
|
|
crProfitMinAmount = crPriceMinAmountAuto * skuProfitMargin;
|
|
}
|
|
|
|
// if profit margin is less than min required, redo
|
|
if (crProfitMinAmount < skuPriceMinProfit)
|
|
{
|
|
if (skuTaxRateName == "MS" || skuTaxRateName == "GA")
|
|
{
|
|
crPriceMinAmountAuto = (6m * skuPriceMinProfit + 5m * crUnitAvgCost + 6m * skuOrderChannelFee) / (-6m * skuAmazonMargin + 5m);
|
|
//crPriceMinCalculatedTax = (crPriceMinAmountAuto - crUnitAvgCost) * (1 / 6);
|
|
crProfitMinAmount = crPriceMinAmountAuto * skuProfitMargin;
|
|
}
|
|
else
|
|
{
|
|
crPriceMinAmountAuto = (crUnitAvgCost + skuOrderChannelFee + skuPriceMinProfit) / (1 - (skuAmazonMargin + skuVatMargin));
|
|
//crPriceMinCalculatedTax = crPriceMinAmountAuto * skuVatMargin;
|
|
crProfitMinAmount = crPriceMinAmountAuto * skuProfitMargin;
|
|
}
|
|
}
|
|
|
|
crPriceMinAmountFinal = crPriceMinAmountAuto;
|
|
|
|
|
|
// STAGE 6
|
|
// Set MAX Price
|
|
decimal crPriceMaxAmountFinal;
|
|
|
|
// CASE: Reset MAX-Price base & multiplier values (new record or switching back to auto)
|
|
// get competative price and apply multiplier
|
|
var request = new bnhtradeDatabaseClient.Product.ProductQuery();
|
|
var compPrice = request.ProductCompetitivePriceGet(sqlConnectionString, skuProductId, 10);
|
|
if (compPrice.price == null || compPrice.priceDate == null)
|
|
{
|
|
using (var cmd02 = new SqlCommand(@"
|
|
SELECT tblProduct.prdMaxPrice
|
|
FROM tblSku INNER JOIN tblProduct ON tblSku.skuProductID = tblProduct.prdProductID
|
|
WHERE (((tblSku.skuSkuID)=@skuId));
|
|
", conn))
|
|
{
|
|
cmd02.Parameters.AddWithValue("@skuId", skuId);
|
|
|
|
crPriceMaxAmountFinal = (decimal)cmd02.ExecuteNonQuery();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
crPriceMaxAmountFinal = (int)(compPrice.price * skuCompetitivePriceMultiplierNew);
|
|
}
|
|
|
|
|
|
// for fixed price items
|
|
if (skuIsFixedPrice == true)
|
|
{
|
|
using (var cmd02 = new SqlCommand(@"
|
|
SELECT tblSku.skuPriceMin, tblSku.skuPriceMax
|
|
FROM tblSku
|
|
WHERE (((tblSku.skuSkuID)=@skuId));
|
|
", conn))
|
|
{
|
|
cmd02.Parameters.AddWithValue("@skuId", skuId);
|
|
|
|
using (var reader02 = cmd02.ExecuteReader())
|
|
{
|
|
decimal? max = null;
|
|
decimal? min = null;
|
|
reader02.Read();
|
|
|
|
if (!reader02.IsDBNull(0)) { min = reader02.GetDecimal(0); }
|
|
if (!reader02.IsDBNull(1)) { max = reader02.GetDecimal(1); }
|
|
|
|
if (max == min && max != null)
|
|
{
|
|
crPriceMinAmountFinal = (decimal)min;
|
|
crPriceMaxAmountFinal = (decimal)max;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// STAGE 7
|
|
// Checks before update
|
|
|
|
// max < min
|
|
if (crPriceMaxAmountFinal < crPriceMinAmountFinal)
|
|
{
|
|
crPriceMaxAmountFinal = crPriceMinAmountFinal;
|
|
}
|
|
|
|
// this should be last check
|
|
// check for zero values (where there should not be any) -- this could be a life saver i.e. selling item for £0.00
|
|
if (crPriceMinAmountFinal * crPriceMaxAmountFinal == 0)
|
|
{
|
|
throw new Exception("Min and/or Max value has comouted to 0 for SkuId=" + skuId);
|
|
}
|
|
|
|
|
|
// STAGE 8
|
|
// Update sku table min/max values
|
|
|
|
// round decimals for db comarison
|
|
crUnitAvgCost = decimal.Round(crUnitAvgCost, 2);
|
|
crUnitAvgCostActual = decimal.Round(crUnitAvgCostActual, 2);
|
|
crPriceMinAmountAuto = decimal.Round(crPriceMinAmountAuto, 2);
|
|
crPriceMinAmountFinal = decimal.Round(crPriceMinAmountFinal, 2);
|
|
crPriceMaxAmountFinal = decimal.Round(crPriceMaxAmountFinal, 2);
|
|
|
|
// update sku table
|
|
using (var cmd03 = new SqlCommand(@"
|
|
UPDATE
|
|
tblSku
|
|
SET
|
|
tblSku.skuPriceMin = @priceMinAmountFinal
|
|
, tblSku.skuPriceMax = @priceMaxAmountFinal
|
|
,tblSku.skuMinMaxExpire = Null
|
|
,tblSku.skuSkuAvgCost = @unitAvgCost
|
|
,tblSku.skuSkuAvgCostDate = @unitAvgCostDate
|
|
,tblSku.skuPriceCompetitive = @compPrice
|
|
, tblSku.skuPriceCompetitiveDate = @compPriceDate
|
|
WHERE (((tblSku.skuSkuID)=@skuId));
|
|
", conn))
|
|
{
|
|
cmd03.Parameters.AddWithValue("@priceMinAmountFinal", crPriceMinAmountFinal);
|
|
cmd03.Parameters.AddWithValue("@priceMaxAmountFinal", crPriceMaxAmountFinal);
|
|
cmd03.Parameters.AddWithValue("@unitAvgCost", crUnitAvgCostActual);
|
|
cmd03.Parameters.AddWithValue("@unitAvgCostDate", crTimeStamp.ToUniversalTime());
|
|
if (compPrice.price == null)
|
|
{
|
|
cmd03.Parameters.AddWithValue("@compPrice", DBNull.Value);
|
|
cmd03.Parameters.AddWithValue("@compPriceDate", DBNull.Value);
|
|
}
|
|
else
|
|
{
|
|
cmd03.Parameters.AddWithValue("@compPrice", compPrice.price);
|
|
cmd03.Parameters.AddWithValue("@compPriceDate", DateTime.SpecifyKind((DateTime)compPrice.priceDate, DateTimeKind.Utc).ToUniversalTime());
|
|
}
|
|
cmd03.Parameters.AddWithValue("@skuId", skuId);
|
|
|
|
int updated = cmd03.ExecuteNonQuery();
|
|
|
|
if (!(updated > 0))
|
|
{
|
|
throw new Exception("record not updated, for some reasonq");
|
|
}
|
|
}
|
|
|
|
count = count + 1;
|
|
} // drop out of query while loop here
|
|
}
|
|
}
|
|
}
|
|
MiscFunction.ConsoleUpdate("Complete. " + count + "SKUs updated.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.ConsoleUpdate("Operation incomplete, stopped at SkuId=" + exceptionSku +". " + count + "SKUs updated.");
|
|
MiscFunction.ConsoleUpdate("Exception: " + ex.Message);
|
|
throw ex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
namespace Order
|
|
{
|
|
public class OrderQuery
|
|
{
|
|
public static int GetSaleChannelIdByName(string sqlConnectionString, string orderChannel, bool addChannel = false)
|
|
{
|
|
if (orderChannel == "Amazon.co.uk") { return 2; }
|
|
else if (orderChannel == "Amazon.de") { return 3; }
|
|
else if (orderChannel == "Amazon.fr") { return 4; }
|
|
else if (orderChannel == "Amazon.it") { return 5; }
|
|
else if (orderChannel == "Amazon.es") { return 6; }
|
|
else if (orderChannel.Length > 0)
|
|
{
|
|
int orderChannelId;
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand selectCmd = new SqlCommand(@"
|
|
SELECT OrderChannelID FROM tblOrderChannel WHERE OrderChannel=@orderChannel
|
|
", sqlConn))
|
|
{
|
|
selectCmd.Parameters.AddWithValue("@orderChannel", orderChannel);
|
|
object obj = selectCmd.ExecuteScalar();
|
|
if ((addChannel = true) & (obj == null))
|
|
{
|
|
using (SqlCommand insertCmd = new SqlCommand(@"
|
|
INSERT INTO tblOrderChannel ( OrderChannel )
|
|
OUTPUT INSERTED.OrderChannelID
|
|
VALUES ( @orderChannel )
|
|
", sqlConn))
|
|
{
|
|
insertCmd.Parameters.AddWithValue("@orderChannel", orderChannel);
|
|
object orderIdObject = selectCmd.ExecuteScalar();
|
|
orderChannelId = Convert.ToInt32(orderIdObject);
|
|
return orderChannelId;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
orderChannelId = Convert.ToInt32(obj);
|
|
return orderChannelId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else { return -1; }
|
|
}
|
|
public static int GetOrderIdBySaleChannelRef(string sqlConnectionString, int saleChannelId, string saleChannelOrderRef, Boolean autoAdd = false)
|
|
{
|
|
|
|
if (saleChannelId < 1)
|
|
{
|
|
throw new Exception("Order Channel Id must be greater than zero");
|
|
}
|
|
if (saleChannelOrderRef.Length == 0)
|
|
{
|
|
throw new Exception("Incorrect Order Reference passed to method");
|
|
}
|
|
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
using (SqlCommand sqlCommand = new SqlCommand(@"
|
|
SELECT OrderID FROM tblOrder WHERE OrderChannelID=@orderChannelId AND OrderChannelRef=@orderChannelRef
|
|
", sqlConn))
|
|
{
|
|
sqlConn.Open();
|
|
sqlCommand.Parameters.AddWithValue("@orderChannelId", saleChannelId);
|
|
sqlCommand.Parameters.AddWithValue("@orderChannelRef", saleChannelOrderRef);
|
|
int orderId = new int();
|
|
object obj = sqlCommand.ExecuteScalar();
|
|
if (!(obj == null))
|
|
{
|
|
orderId = Convert.ToInt32(obj);
|
|
return orderId;
|
|
}
|
|
else if (autoAdd == true)
|
|
{
|
|
using (SqlCommand sqlInsert = new SqlCommand(@"
|
|
INSERT INTO tblOrder ( OrderChannelID, OrderChannelRef )
|
|
OUTPUT INSERTED.OrderID
|
|
VALUES ( @orderChannelId, @orderChannelRef )
|
|
", sqlConn))
|
|
{
|
|
sqlInsert.Parameters.AddWithValue("@orderChannelId", saleChannelId);
|
|
sqlInsert.Parameters.AddWithValue("@orderChannelRef", saleChannelOrderRef);
|
|
orderId = (int)sqlInsert.ExecuteScalar();
|
|
return orderId;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
public static int GetOrderItemIdBySaleChannelRef(string sqlConnectionString, int orderId, string saleChannelOrderItemRef, Boolean autoAdd = false)
|
|
{
|
|
|
|
if (orderId < 1)
|
|
{
|
|
throw new Exception("Order Channel Id must be greater than zero");
|
|
}
|
|
if (saleChannelOrderItemRef.Length == 0)
|
|
{
|
|
throw new Exception("Incorrect Order Reference passed to method");
|
|
}
|
|
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand sqlCommand = new SqlCommand(@"
|
|
SELECT OrderItemID FROM tblOrderItem WHERE OrderID=@orderId AND OrderChannelItemRef=@orderChannelItemRef
|
|
", sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@orderId", orderId);
|
|
sqlCommand.Parameters.AddWithValue("@orderChannelItemRef", saleChannelOrderItemRef);
|
|
int orderItemId = new int();
|
|
object obj = sqlCommand.ExecuteScalar();
|
|
if (!(obj == null))
|
|
{
|
|
orderItemId = Convert.ToInt32(obj);
|
|
return orderItemId;
|
|
}
|
|
else if (autoAdd == true)
|
|
{
|
|
using (SqlCommand sqlInsert = new SqlCommand(@"
|
|
INSERT INTO tblOrderItem ( OrderID, OrderChannelItemRef )
|
|
OUTPUT INSERTED.OrderID
|
|
VALUES ( @orderId, @orderChannelItemRef )
|
|
", sqlConn))
|
|
{
|
|
sqlInsert.Parameters.AddWithValue("@orderId", orderId);
|
|
sqlInsert.Parameters.AddWithValue("@orderChannelItemRef", saleChannelOrderItemRef);
|
|
orderItemId = (int)sqlInsert.ExecuteScalar();
|
|
return orderItemId;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
public static int GetSaleChannelIdByAmazonOrderId(string sqlConnectionString, string amazonOrderId)
|
|
{
|
|
// private, as it gets sale channel from Fba order shipment table, which may only hold data for limited period of time
|
|
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
// retrive sale channel id
|
|
string saleChannelName;
|
|
using (SqlCommand sqlCommand = new SqlCommand(@"
|
|
SELECT [sales-channel] FROM tblImportFbaSaleShipment WHERE [amazon-order-id]=@amazonOrderId
|
|
", sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@amazonOrderId", amazonOrderId);
|
|
|
|
object obj = sqlCommand.ExecuteScalar();
|
|
if (!(obj == null))
|
|
{
|
|
saleChannelName = Convert.ToString(obj);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Could not retrive Amazon Order channel from imported order table, is the import table up to date?");
|
|
}
|
|
}
|
|
return Order.OrderQuery.GetSaleChannelIdByName(sqlConnectionString, saleChannelName, true);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
public static List<int> GetFbaOrderStockIdBySku(string sqlConnectionString, int orderId, int skuId)
|
|
{
|
|
// return list of stockIds that are attached to an order sku
|
|
int stockStatusId;
|
|
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
// retrive info for FbaOrders - transactionTypeId and it's debit statusId
|
|
int transactionTypeId = Stock.StockJournal.StockTransactionTypeIdSelect(sqlConnectionString, "<AmazonReport><_GET_AMAZON_FULFILLED_SHIPMENTS_DATA_>");
|
|
if (transactionTypeId < 1)
|
|
{
|
|
throw new Exception("Could not retirve stockTransactionId for amazon shipped orders");
|
|
}
|
|
using (SqlCommand sqlCommand = new SqlCommand(@"
|
|
SELECT DebitStockStatusID FROM tblStockTransactionType WHERE StockTransactionTypeID=@transactionTypeId
|
|
", sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@transactionTypeId", transactionTypeId);
|
|
|
|
object obj = sqlCommand.ExecuteScalar();
|
|
if (obj == null || obj == DBNull.Value)
|
|
{
|
|
throw new Exception("Could not retrive debit status for amazon shipped orders");
|
|
}
|
|
else
|
|
{
|
|
stockStatusId = Convert.ToInt32(obj);
|
|
}
|
|
}
|
|
|
|
// retrive orderItemId(s)
|
|
List<int> stockIdList = new List<int>();
|
|
using (SqlCommand sqlCommand = new SqlCommand(@"
|
|
SELECT StockJournalID FROM tblStockTransaction
|
|
WHERE StockTransactionTypeID=@transactionTypeId AND ForeignKey=@orderId AND SkuID=@skuId
|
|
", sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@transactionTypeId", transactionTypeId);
|
|
sqlCommand.Parameters.AddWithValue("@orderId", orderId);
|
|
sqlCommand.Parameters.AddWithValue("@skuId", skuId);
|
|
|
|
using (SqlDataReader reader = sqlCommand.ExecuteReader())
|
|
{
|
|
if (reader.HasRows)
|
|
{
|
|
int index01 = reader.GetOrdinal("StockJournalID");
|
|
|
|
while (reader.Read())
|
|
{
|
|
stockIdList.Add(Stock.StockJournal.GetStockIdByStockJournalId(sqlConnectionString, reader.GetInt32(index01)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
// any further checking of available qquantities should be done by the calling function (to reduce to amount of stautus balance sql calls/checks)
|
|
return stockIdList;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
namespace AmazonMWS
|
|
{
|
|
public class AmazonMwsCredential
|
|
{
|
|
public string merchantId { get { return "A3RUYNKLWWM5KW"; } }
|
|
public string marketPlaceId { get { return "A1F83G8C2ARO7P"; } } // Amazon.co.uk
|
|
public string accessKeyId { get { return "AKIAJU45WSYVINEN45UA"; } }
|
|
public string secretAccessKey { get { return "cpS3HnTYDIVxAPSxaJwCwUbeH6PGPnpij5Un5bWI"; } }
|
|
public string applicationName { get { return "bnhtrade Database Client"; } }
|
|
public string applicationVersion { get { return "0.1"; } }
|
|
public string serviceURL { get { return "https://mws.amazonservices.co.uk"; } }
|
|
}
|
|
|
|
public class AmazonMwsService
|
|
{
|
|
public MarketplaceWebService.MarketplaceWebService GetAmazonMwsService()
|
|
{
|
|
AmazonMwsCredential cred = new AmazonMwsCredential();
|
|
MarketplaceWebServiceConfig config = new MarketplaceWebServiceConfig();
|
|
|
|
MarketplaceWebService.MarketplaceWebService service = new MarketplaceWebServiceClient(
|
|
cred.accessKeyId,
|
|
cred.secretAccessKey,
|
|
cred.applicationName,
|
|
cred.applicationVersion,
|
|
config);
|
|
|
|
config.ServiceURL = cred.serviceURL;
|
|
return service;
|
|
}
|
|
}
|
|
|
|
public class AmazonMwsProduct
|
|
{
|
|
public MarketplaceWebServiceProducts.MarketplaceWebServiceProducts GetAmazonMwsServiceProduct()
|
|
{
|
|
AmazonMwsCredential cred = new AmazonMwsCredential();
|
|
MarketplaceWebServiceProductsConfig config = new MarketplaceWebServiceProductsConfig();
|
|
|
|
config.ServiceURL = cred.serviceURL;
|
|
|
|
MarketplaceWebServiceProducts.MarketplaceWebServiceProducts service = new MarketplaceWebServiceProductsClient(
|
|
cred.applicationName,
|
|
cred.applicationVersion,
|
|
cred.accessKeyId,
|
|
cred.secretAccessKey,
|
|
config);
|
|
|
|
return service;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="itemList"></param>
|
|
public List<FeesEstimateResult> WIP_GetProductEstimateFee( FeesEstimateRequestList requestList)
|
|
{
|
|
AmazonMwsCredential cred = new AmazonMwsCredential();
|
|
AmazonMwsProduct mwsProduct = new AmazonMwsProduct();
|
|
MarketplaceWebServiceProducts.MarketplaceWebServiceProducts service = mwsProduct.GetAmazonMwsServiceProduct();
|
|
|
|
// Create a request.
|
|
GetMyFeesEstimateRequest request = new GetMyFeesEstimateRequest();
|
|
request.SellerId = cred.merchantId;
|
|
request.MWSAuthToken = "example";
|
|
//FeesEstimateRequestList requestList = new FeesEstimateRequestList();
|
|
|
|
//foreach (var item in itemList)
|
|
//{
|
|
// string idType;
|
|
// if (item.IdValueIsAsin) { idType = "ASIN"; }
|
|
// else { idType = "SellerSku"; }
|
|
|
|
// requestList.FeesEstimateRequest.Add(new FeesEstimateRequest
|
|
// {
|
|
// MarketplaceId = item.marketPlaceId,
|
|
// IdType = idType,
|
|
// IdValue = item.IdValue,
|
|
// PriceToEstimateFees = new PriceToEstimateFees
|
|
// {
|
|
// ListingPrice = new MoneyType { Amount = item.listingPrice, CurrencyCode = item.currencyCode },
|
|
// //Shipping = new MoneyType { Amount = 3.5M, CurrencyCode = "GBP" },
|
|
// //Points = new Points { PointsNumber = 0 }
|
|
// },
|
|
// Identifier = "request_" + Guid.NewGuid().ToString(),
|
|
// IsAmazonFulfilled = true
|
|
// });
|
|
//}
|
|
request.FeesEstimateRequestList = requestList;
|
|
|
|
// define the list
|
|
GetMyFeesEstimateResult result = new GetMyFeesEstimateResult();
|
|
//List<GetMyFeesEstimateResult> resultList = new List<GetMyFeesEstimateResult>();
|
|
|
|
try
|
|
{
|
|
int count = 0;
|
|
do
|
|
{
|
|
GetMyFeesEstimateResponse response = service.GetMyFeesEstimate(request);
|
|
if (response.IsSetGetMyFeesEstimateResult())
|
|
{
|
|
result = response.GetMyFeesEstimateResult;
|
|
FeesEstimateResultList resultList = result.FeesEstimateResultList;
|
|
|
|
List<FeesEstimateResult> fees = resultList.FeesEstimateResult;
|
|
|
|
return fees;
|
|
}
|
|
else
|
|
{
|
|
Thread.Sleep(500);
|
|
count++;
|
|
}
|
|
} while (count < 60);
|
|
throw new Exception("Response timeout");
|
|
}
|
|
catch
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
public class AmazonReport
|
|
{
|
|
string merchantId = "A3RUYNKLWWM5KW";
|
|
string marketplaceId = "A1F83G8C2ARO7P"; // Amazon.co.uk
|
|
string accessKeyId = "AKIAJU45WSYVINEN45UA";
|
|
string secretAccessKey = "cpS3HnTYDIVxAPSxaJwCwUbeH6PGPnpij5Un5bWI";
|
|
string applicationName = "AmazonApiApp";
|
|
string applicationVersion = "0.1";
|
|
string serviceURL = "https://mws.amazonservices.co.uk";
|
|
public MarketplaceWebService.MarketplaceWebService GetMwsService()
|
|
{
|
|
MarketplaceWebServiceConfig config = new MarketplaceWebServiceConfig();
|
|
|
|
MarketplaceWebService.MarketplaceWebService service = new MarketplaceWebServiceClient(
|
|
accessKeyId,
|
|
secretAccessKey,
|
|
applicationName,
|
|
applicationVersion,
|
|
config);
|
|
|
|
config.ServiceURL = serviceURL;
|
|
return service;
|
|
}
|
|
public List<ReportInfo> GetMwsReportList(GetReportListRequest requestList)
|
|
{
|
|
MarketplaceWebService.MarketplaceWebService service = GetMwsService();
|
|
|
|
//define the list
|
|
GetReportListResult getReportListResult = new GetReportListResult();
|
|
List<ReportInfo> reportInfoList = new List<ReportInfo>();
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
GetReportListResponse responseList = service.GetReportList(requestList);
|
|
if (responseList.IsSetGetReportListResult())
|
|
{
|
|
getReportListResult = responseList.GetReportListResult;
|
|
reportInfoList = getReportListResult.ReportInfo;
|
|
}
|
|
MiscFunction.EventLogInsert("MWS 'GetReportListRequest' Successful, retrived list of " + reportInfoList.Count + " reports.");
|
|
return reportInfoList;
|
|
}
|
|
catch (MarketplaceWebServiceException ex) when (ex.ErrorCode == "RequestThrottled")
|
|
{
|
|
MiscFunction.MwsThrottleWait(73);
|
|
}
|
|
catch (MarketplaceWebServiceException ex)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"MWS 'GetReportListRequest' failed with exception: " + ex.Message,
|
|
1,
|
|
"Caught Exception: " + ex.Message +
|
|
"\r\nResponse Status Code: " + ex.StatusCode +
|
|
"\r\nError Code: " + ex.ErrorCode +
|
|
"\r\nError Type: " + ex.ErrorType +
|
|
"\r\nRequest ID: " + ex.RequestId +
|
|
"\r\nResponseHeaderMetadata: " + ex.ResponseHeaderMetadata +
|
|
"\r\nXML:\r\n" + ex.XML
|
|
);
|
|
return null;
|
|
}
|
|
} while (true);
|
|
|
|
}
|
|
public string GetMwsReportById(string reportId)
|
|
{
|
|
// retrives report by reportId, saves to disk, and returns filepath
|
|
|
|
MarketplaceWebService.MarketplaceWebService service = GetMwsService();
|
|
|
|
string filePath = MiscFunction.GetTempFilePath(reportId + ".txt");
|
|
|
|
GetReportRequest reportRequest = new GetReportRequest();
|
|
reportRequest.Merchant = merchantId;
|
|
//reportRequest.WithReportId(getReportListResult.ReportInfo[0].ReportId);
|
|
reportRequest.ReportId = reportId;
|
|
//reportRequest.WithReportId(reportID);
|
|
GetReportResponse reportResponse = new GetReportResponse();
|
|
do
|
|
{
|
|
try
|
|
{
|
|
using (reportRequest.Report = File.Open(filePath, FileMode.Create, FileAccess.ReadWrite))
|
|
{
|
|
reportResponse = service.GetReport(reportRequest);
|
|
MiscFunction.EventLogInsert("Succesfully downloaded Report '" + reportId + "'");
|
|
}
|
|
return filePath;
|
|
}
|
|
catch (MarketplaceWebServiceException e) when (e.ErrorCode == "RequestThrottled")
|
|
{
|
|
MiscFunction.MwsThrottleWait(80);
|
|
}
|
|
catch (MarketplaceWebServiceException e)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"MWS request for ReportId '" + reportId + "' failed. See extended details for MWS exception.",
|
|
1,
|
|
"Request failed with MWS exception: " + e.Message +
|
|
"\r\nCaught Exception: " + e.Message +
|
|
"\r\nResponse Status Code: " + e.StatusCode +
|
|
"\r\nError Code: " + e.ErrorCode +
|
|
"\r\nError Type: " + e.ErrorType +
|
|
"\r\nRequest ID: " + e.RequestId +
|
|
"\r\nResponseHeaderMetadata: " + e.ResponseHeaderMetadata +
|
|
"\r\nXML:\r\n" + e.XML
|
|
);
|
|
break;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"MWS request for ReportId '" + reportId + "' failed. See extended details for exception thrown.",
|
|
1,
|
|
e.ToString()
|
|
);
|
|
}
|
|
} while (true);
|
|
return "";
|
|
}
|
|
public string GetMwsReportByRequest(RequestReportRequest requestReport)
|
|
{
|
|
try
|
|
{
|
|
string targetRptType = requestReport.ReportType.ToString();
|
|
MarketplaceWebService.MarketplaceWebService service = GetMwsService();
|
|
|
|
string status;
|
|
RequestReportResponse requestResponse = new RequestReportResponse();
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
requestResponse = service.RequestReport(requestReport);
|
|
MiscFunction.ConsoleCountDown("Requested, status check in {0} seconds...", 30);
|
|
break;
|
|
}
|
|
catch (MarketplaceWebServiceException e) when (e.ErrorCode == "RequestThrottled")
|
|
{
|
|
MiscFunction.MwsThrottleWait(60);
|
|
}
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
status = requestResponse.RequestReportResult.ReportRequestInfo.ReportProcessingStatus;
|
|
break;
|
|
}
|
|
catch (MarketplaceWebServiceException e) when (e.ErrorCode == "RequestThrottled")
|
|
{
|
|
MiscFunction.MwsThrottleWait(60);
|
|
}
|
|
}
|
|
|
|
GetReportRequestListRequest requestList = new GetReportRequestListRequest();
|
|
requestList.Merchant = merchantId;
|
|
List<ReportRequestInfo> myListzz = new List<ReportRequestInfo>();
|
|
|
|
GetReportRequestListResponse requestListResponse = new GetReportRequestListResponse();
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
requestListResponse = service.GetReportRequestList(requestList);
|
|
break;
|
|
|
|
}
|
|
catch (MarketplaceWebServiceException e) when (e.ErrorCode == "RequestThrottled")
|
|
{
|
|
MiscFunction.MwsThrottleWait(60);
|
|
}
|
|
}
|
|
|
|
GetReportRequestListResult requestListResult = new GetReportRequestListResult();
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
requestListResult = requestListResponse.GetReportRequestListResult;
|
|
break;
|
|
}
|
|
catch (MarketplaceWebServiceException e) when (e.ErrorCode == "RequestThrottled")
|
|
{
|
|
MiscFunction.MwsThrottleWait(60);
|
|
}
|
|
}
|
|
|
|
//wait until status = done
|
|
myListzz = requestListResult.ReportRequestInfo;
|
|
status = myListzz[0].ReportProcessingStatus.ToString();
|
|
// Misc.EventLogInsert("Report status: " + status);
|
|
while (
|
|
status != "_CANCELLED_" &&
|
|
status != "_DONE_" &&
|
|
status != "_DONE_NO_DATA_"
|
|
)
|
|
{
|
|
try
|
|
{
|
|
MiscFunction.ConsoleCountDown("Request status '" + status + "' next check {0} seconds...", 30);
|
|
requestListResponse = service.GetReportRequestList(requestList);
|
|
requestListResult = requestListResponse.GetReportRequestListResult;
|
|
myListzz = requestListResult.ReportRequestInfo;
|
|
string newStatus = myListzz[0].ReportProcessingStatus.ToString();
|
|
if (newStatus != status)
|
|
{
|
|
status = newStatus;
|
|
//Misc.EventLogInsert("Request status: " + status);
|
|
}
|
|
}
|
|
catch (MarketplaceWebServiceException e) when (e.ErrorCode == "RequestThrottled")
|
|
{
|
|
MiscFunction.MwsThrottleWait(60);
|
|
}
|
|
}
|
|
|
|
if (status == "_CANCELLED_")
|
|
{
|
|
MiscFunction.EventLogInsert("Request result: " + status);
|
|
return "_CANCELLED_";
|
|
}
|
|
else if (status == "_DONE_NO_DATA_")
|
|
{
|
|
MiscFunction.EventLogInsert("Request result: " + status);
|
|
return "_DONE_NO_DATA_";
|
|
}
|
|
else
|
|
{
|
|
MiscFunction.EventLogInsert("Request result: " + status);
|
|
}
|
|
|
|
GetReportListRequest listRequest = new GetReportListRequest();
|
|
listRequest.Merchant = merchantId;
|
|
listRequest.ReportRequestIdList = new IdList();
|
|
listRequest.ReportRequestIdList.Id.Add(requestResponse.RequestReportResult.ReportRequestInfo.ReportRequestId);
|
|
|
|
GetReportListResponse listResponse = service.GetReportList(listRequest);
|
|
|
|
GetReportListResult getReportListResult = listResponse.GetReportListResult;
|
|
|
|
string reportId = getReportListResult.ReportInfo[0].ReportId.ToString();
|
|
|
|
return GetMwsReportById(reportId);
|
|
}
|
|
catch (MarketplaceWebServiceException e)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Request failed with MWS exception: " + e.Message,
|
|
1,
|
|
"Caught Exception: " + e.Message +
|
|
"\r\nResponse Status Code: " + e.StatusCode +
|
|
"\r\nError Code: " + e.ErrorCode +
|
|
"\r\nError Type: " + e.ErrorType +
|
|
"\r\nRequest ID: " + e.RequestId +
|
|
"\r\nResponseHeaderMetadata: " + e.ResponseHeaderMetadata +
|
|
"\r\nXML:\r\n" + e.XML
|
|
);
|
|
return "";
|
|
}
|
|
}
|
|
public List<string> GetMwsReportByPeriod(string mwsReportEnum, DateTime startTime, DateTime endTime, int maxReportCount = 12, int reportMaxPeriod = 30)
|
|
{
|
|
// method downloads reports and returns a list of filePaths
|
|
|
|
// startTime =>
|
|
// endTime =<
|
|
|
|
List<string> reportIdList = new List<string>();
|
|
DateTime now = DateTime.UtcNow;
|
|
// time checks
|
|
if (startTime.ToUniversalTime() > now.ToUniversalTime())
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"The most current date supplied from the database is a head of the current time. stoping...",
|
|
1,
|
|
MiscFunction.TraceMessage()
|
|
);
|
|
reportIdList.Clear();
|
|
return reportIdList;
|
|
}
|
|
else if (endTime.ToUniversalTime() > now.ToUniversalTime())
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Get report end time is ahead of current time, re-setting to current time",
|
|
2
|
|
);
|
|
}
|
|
|
|
int reportCount = 0;
|
|
bool stopFlag = false;
|
|
endTime = startTime.AddDays(reportMaxPeriod);
|
|
do
|
|
{
|
|
reportCount = reportCount + 1;
|
|
now = DateTime.UtcNow.AddMinutes(0);
|
|
if (endTime.ToUniversalTime() > now.ToUniversalTime())
|
|
{
|
|
endTime = now;
|
|
stopFlag = true;
|
|
}
|
|
// build the request
|
|
RequestReportRequest requestReport = new RequestReportRequest();
|
|
requestReport.Merchant = merchantId;
|
|
requestReport.ReportType = mwsReportEnum;
|
|
requestReport.StartDate = startTime.ToUniversalTime();
|
|
requestReport.EndDate = endTime.ToUniversalTime();
|
|
|
|
MiscFunction.EventLogInsert("Requesting '" + mwsReportEnum + "' '" + startTime.ToUniversalTime() + "' to '" + endTime.ToUniversalTime() + "'");
|
|
string filePath = GetMwsReportByRequest(requestReport);
|
|
|
|
if (filePath == "_DONE_NO_DATA_")
|
|
{
|
|
// do nothing, carry on with next iteration
|
|
}
|
|
else if (filePath == "_CANCELLED_")
|
|
{
|
|
/*
|
|
/ this is probably MWS higher level throttling when requesting duplicate report
|
|
/ for near real time reports waiting 30 minutes
|
|
/ for daily reports wait 4 hours
|
|
*/
|
|
return reportIdList;
|
|
}
|
|
else if (filePath.Length > 0)
|
|
{
|
|
reportIdList.Add(filePath);
|
|
}
|
|
else
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Something went wrong downloading a full list of reports over the defined period. Report downloaded up until this point (if any) will be processed.",
|
|
2
|
|
);
|
|
return reportIdList;
|
|
}
|
|
|
|
// add 30 days onto start date and loop
|
|
startTime = endTime.AddSeconds(1);
|
|
endTime = endTime.AddDays(reportMaxPeriod);
|
|
if (startTime.ToUniversalTime() > now.ToUniversalTime())
|
|
{
|
|
stopFlag = true;
|
|
}
|
|
if (reportCount == maxReportCount)
|
|
{
|
|
stopFlag = true;
|
|
}
|
|
} while (stopFlag == false);
|
|
|
|
return reportIdList;
|
|
}
|
|
public bool SetMwsReportAcknowledgement(string reportId, bool acknowledged = true)
|
|
{
|
|
MarketplaceWebService.MarketplaceWebService service = GetMwsService();
|
|
|
|
do
|
|
{
|
|
try
|
|
{
|
|
UpdateReportAcknowledgementsRequest request = new UpdateReportAcknowledgementsRequest();
|
|
request.Merchant = merchantId;
|
|
request.Acknowledged = acknowledged;
|
|
var reportIdList = new IdList();
|
|
reportIdList.Id.Add(reportId);
|
|
request.ReportIdList = reportIdList;
|
|
|
|
UpdateReportAcknowledgementsResponse response = service.UpdateReportAcknowledgements(request);
|
|
if (response.IsSetUpdateReportAcknowledgementsResult())
|
|
{
|
|
UpdateReportAcknowledgementsResult updateReportAcknowledgementsResult = response.UpdateReportAcknowledgementsResult;
|
|
List<ReportInfo> reportAckList = updateReportAcknowledgementsResult.ReportInfo;
|
|
MiscFunction.EventLogInsert("Report '" + reportAckList[0].ReportId + "' Acknowledgement set to '" + reportAckList[0].Acknowledged + "'");
|
|
}
|
|
return true;
|
|
}
|
|
catch (MarketplaceWebServiceException ex) when (ex.ErrorCode == "RequestThrottled")
|
|
{
|
|
MiscFunction.MwsThrottleWait(80);
|
|
}
|
|
catch (MarketplaceWebServiceException ex)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"MWS 'UpdateReportAcknowledgementsRequest' failed with exception: " + ex.Message,
|
|
1,
|
|
"Caught Exception: " + ex.Message +
|
|
"\r\nResponse Status Code: " + ex.StatusCode +
|
|
"\r\nError Code: " + ex.ErrorCode +
|
|
"\r\nError Type: " + ex.ErrorType +
|
|
"\r\nRequest ID: " + ex.RequestId +
|
|
"\r\nResponseHeaderMetadata: " + ex.ResponseHeaderMetadata +
|
|
"\r\nXML:\r\n" + ex.XML
|
|
);
|
|
|
|
Console.WriteLine("Caught Exception: " + ex.Message);
|
|
Console.WriteLine("Response Status Code: " + ex.StatusCode);
|
|
Console.WriteLine("Error Code: " + ex.ErrorCode);
|
|
Console.WriteLine("Error Type: " + ex.ErrorType);
|
|
Console.WriteLine("Request ID: " + ex.RequestId);
|
|
Console.WriteLine("XML: " + ex.XML);
|
|
Console.WriteLine("ResponseHeaderMetadata: " + ex.ResponseHeaderMetadata);
|
|
Console.ReadKey();
|
|
break;
|
|
}
|
|
} while (true);
|
|
return false;
|
|
}
|
|
public bool ImportReportSettlementData(string sqlConnectionString, string filePath)
|
|
{
|
|
try
|
|
{
|
|
using (TransactionScope scope = new TransactionScope())
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
filePath
|
|
);
|
|
}
|
|
else if (lineNumber == 2)
|
|
{
|
|
// check if settlement has already been imported
|
|
using (SqlCommand sqlCommand = new SqlCommand(
|
|
"SELECT COUNT(*) FROM tblImportAmazonSettlementReport WHERE [settlement-id]=@settlementId;"
|
|
, sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@settlementId", long.Parse(items[indexSettlementId]));
|
|
int recordCount = (int)sqlCommand.ExecuteScalar();
|
|
if (recordCount > 0)
|
|
{
|
|
MiscFunction.ConsoleUpdate("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 sqlCommand = new SqlCommand(
|
|
"INSERT INTO tblImportAmazonSettlementReport ( " +
|
|
"[settlement-id], [settlement-start-date], [settlement-end-date], [deposit-date], [total-amount], [currency] ) " +
|
|
"OUTPUT INSERTED.ImportAmazonSettlementReportID " +
|
|
"VALUES ( @settlementId, @settlementStartDate, @settlementEndDate, @depositDate, @settlementotalAmounttId, @currency );"
|
|
, sqlConn))
|
|
{
|
|
// add parameters
|
|
if (indexSettlementId == -1 || items[indexSettlementId].Length == 0) { sqlCommand.Parameters.AddWithValue("@settlementId", DBNull.Value); }
|
|
else
|
|
{
|
|
settlementRef = items[indexSettlementId];
|
|
sqlCommand.Parameters.AddWithValue("@settlementId", settlementRef);
|
|
}
|
|
|
|
if (indexSettlementStartDate == -1 || items[indexSettlementStartDate].Length == 0) { sqlCommand.Parameters.AddWithValue("@settlementStartDate", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@settlementStartDate", MiscFunction.ParseMwsReportDateTime(items[indexSettlementStartDate])); }
|
|
|
|
if (indexSettlementEndDate == -1 || items[indexSettlementEndDate].Length == 0) { sqlCommand.Parameters.AddWithValue("@settlementEndDate", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@settlementEndDate", MiscFunction.ParseMwsReportDateTime(items[indexSettlementEndDate])); }
|
|
|
|
if (indexDepositDate == -1 || items[indexDepositDate].Length == 0) { sqlCommand.Parameters.AddWithValue("@depositDate", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@depositDate", MiscFunction.ParseMwsReportDateTime(items[indexDepositDate])); }
|
|
|
|
if (indexTotalAmount == -1 || items[indexTotalAmount].Length == 0) { sqlCommand.Parameters.AddWithValue("@totalAmount", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@settlementotalAmounttId", settlementAmount); }
|
|
|
|
sqlCommand.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)sqlCommand.ExecuteScalar();
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//update market place name in main table, if required
|
|
if (marketPlaceUpdated == false && settlementReportId > 0 && items[indexMarketplaceName].Length > 1)
|
|
{
|
|
using (SqlCommand sqlCommand = new SqlCommand(@"
|
|
UPDATE tblImportAmazonSettlementReport
|
|
SET [marketplace-name]=@MarketplaceName
|
|
WHERE ImportAmazonSettlementReportID=@ImportAmazonSettlementReportID
|
|
", sqlConn))
|
|
{
|
|
sqlCommand.Parameters.AddWithValue("@MarketplaceName", items[indexMarketplaceName]);
|
|
sqlCommand.Parameters.AddWithValue("@ImportAmazonSettlementReportID", settlementReportId);
|
|
|
|
sqlCommand.ExecuteNonQuery();
|
|
marketPlaceUpdated = true;
|
|
}
|
|
}
|
|
|
|
//insert report items
|
|
using (SqlCommand sqlCommand = new SqlCommand(
|
|
"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 );"
|
|
, sqlConn))
|
|
{
|
|
// add parameters
|
|
sqlCommand.Parameters.AddWithValue("@ImportAmazonSettlementReportID", settlementReportId);
|
|
|
|
sqlCommand.Parameters.AddWithValue("@currency", currency);
|
|
|
|
if (indexTransactionType == -1 || items[indexTransactionType].Length == 0) { sqlCommand.Parameters.AddWithValue("@TransactionType", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@TransactionType", items[indexTransactionType]); }
|
|
|
|
if (indexOrderId == -1 || items[indexOrderId].Length == 0) { sqlCommand.Parameters.AddWithValue("@orderRef", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@orderRef", items[indexOrderId]); }
|
|
|
|
if (indexMerchantOrderId == -1 || items[indexMerchantOrderId].Length == 0) { sqlCommand.Parameters.AddWithValue("@merchantOrderRef", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@merchantOrderRef", items[indexMerchantOrderId]); }
|
|
|
|
if (indexAdjustmentId == -1 || items[indexAdjustmentId].Length == 0) { sqlCommand.Parameters.AddWithValue("@AdjustmentRef", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@AdjustmentRef", items[indexAdjustmentId]); }
|
|
|
|
if (indexShipmentId == -1 || items[indexShipmentId].Length == 0) { sqlCommand.Parameters.AddWithValue("@ShipmentRef", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@ShipmentRef", items[indexShipmentId]); }
|
|
|
|
if (indexMarketplaceName == -1 || items[indexMarketplaceName].Length == 0) { sqlCommand.Parameters.AddWithValue("@MarketplaceName", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@MarketplaceName", items[indexMarketplaceName]); }
|
|
|
|
if (indexAmountType == -1 || items[indexAmountType].Length == 0) { sqlCommand.Parameters.AddWithValue("@AmountType", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@AmountType", items[indexAmountType]); }
|
|
|
|
if (indexAmountDescription == -1 || items[indexAmountDescription].Length == 0) { sqlCommand.Parameters.AddWithValue("@AmountDescription", DBNull.Value); }
|
|
else
|
|
{
|
|
string amountDescription = items[indexAmountDescription];
|
|
if (amountDescription.Length > 100) { amountDescription = amountDescription.Substring(0, 100); }
|
|
sqlCommand.Parameters.AddWithValue("@AmountDescription", amountDescription);
|
|
}
|
|
|
|
if (indexAmount == -1 || items[indexAmount].Length == 0) { sqlCommand.Parameters.AddWithValue("@Amount", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@Amount", decimal.Parse(items[indexAmount].Replace(",", "."))); }
|
|
|
|
if (indexFulfillmentId == -1 || items[indexFulfillmentId].Length == 0) { sqlCommand.Parameters.AddWithValue("@FulfillmentRef", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@FulfillmentRef", items[indexFulfillmentId]); }
|
|
|
|
if (indexPostedDateTime == -1 || items[indexPostedDateTime].Length == 0) { sqlCommand.Parameters.AddWithValue("@PostedDateTimeUTC", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@PostedDateTimeUTC", MiscFunction.ParseMwsReportDateTime(items[indexPostedDateTime])); }
|
|
|
|
if (indexOrderItemCode == -1 || items[indexOrderItemCode].Length == 0) { sqlCommand.Parameters.AddWithValue("@OrderItemCode", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@OrderItemCode", long.Parse(items[indexOrderItemCode])); }
|
|
|
|
if (indexMerchantOrderItemId == -1 || items[indexMerchantOrderItemId].Length == 0) { sqlCommand.Parameters.AddWithValue("@MerchantOrderItemRef", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@MerchantOrderItemRef", long.Parse(items[indexMerchantOrderItemId])); }
|
|
|
|
if (indexMerchantAdjustmentItemId == -1 || items[indexMerchantAdjustmentItemId].Length == 0) { sqlCommand.Parameters.AddWithValue("@MerchantAdjustmentItemRef", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@MerchantAdjustmentItemRef", items[indexMerchantAdjustmentItemId]); }
|
|
|
|
if (indexSku == -1 || items[indexSku].Length == 0) { sqlCommand.Parameters.AddWithValue("@SkuNumber", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@SkuNumber", items[indexSku]); }
|
|
|
|
if (indexQuantityPurchased == -1 || items[indexQuantityPurchased].Length == 0) { sqlCommand.Parameters.AddWithValue("@QuantityPurchased", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@QuantityPurchased", int.Parse(items[indexQuantityPurchased])); }
|
|
|
|
if (indexPromotionId == -1 || items[indexPromotionId].Length == 0) { sqlCommand.Parameters.AddWithValue("@PromotionRef", DBNull.Value); }
|
|
else { sqlCommand.Parameters.AddWithValue("@PromotionRef", items[indexPromotionId]); }
|
|
|
|
sqlCommand.ExecuteNonQuery();
|
|
}
|
|
}
|
|
lineNumber = lineNumber + 1;
|
|
}
|
|
}
|
|
|
|
//final check - settlement amount matches sum of inserted settlement lines
|
|
using (SqlCommand sqlCommand = new SqlCommand(@"
|
|
SELECT Sum(tblImportAmazonSettlementReportLine.amount) AS SumOfAmount
|
|
FROM tblImportAmazonSettlementReportLine
|
|
WHERE ImportAmazonSettlementReportID=@ImportAmazonSettlementReportID;
|
|
", sqlConn))
|
|
{
|
|
decimal sumOfAmount = -1.12345m;
|
|
|
|
sqlCommand.Parameters.AddWithValue("@ImportAmazonSettlementReportID", settlementReportId);
|
|
sumOfAmount = (decimal)sqlCommand.ExecuteScalar();
|
|
|
|
if (sumOfAmount != settlementAmount)
|
|
{
|
|
MiscFunction.EventLogInsert("Error importing settlement id'" + settlementRef + "'. Sum of inserted settlement lines (" + sumOfAmount +
|
|
") does not match settlement amount (" + settlementAmount + ").", 1);
|
|
return false;
|
|
}
|
|
}
|
|
scope.Complete();
|
|
|
|
Console.Write("\r");
|
|
MiscFunction.EventLogInsert((lineNumber - (2 + lineSkip)) + " total settlement items inserted");
|
|
if (lineSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.ToString());
|
|
Console.ReadKey();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public bool ImportReportFbaInventoryReceipt(string sqlConnectionString, 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)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Amazon have added a new column to their 'Fba Inventory Receipt' report, you may want to check this out.",
|
|
2);
|
|
}
|
|
|
|
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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
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");
|
|
MiscFunction.EventLogInsert((lineNumber - (1 + lineErrorSkip + lineOutsideScope)) + " total report items inserted into db, " + lineOutsideScope + " item(s) outside of requested time scope where skipped.");
|
|
if (lineErrorSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running FbaInventoryReceiptReportImport, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public bool ImportReportFbaSaleShipment(string sqlConnectionString, 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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
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");
|
|
MiscFunction.EventLogInsert((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
|
|
if (lineErrorSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running FbaInventoryReceiptReportImport, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public bool ImportReportFbaReturns(string sqlConnectionString, 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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
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");
|
|
MiscFunction.EventLogInsert((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
|
|
if (lineErrorSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running FbaInventoryReceiptReportImport, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public bool ImportReportFbaAdjustment(string sqlConnectionString, 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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
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");
|
|
MiscFunction.EventLogInsert((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
|
|
if (lineErrorSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running ImportFbaAdustmentReport method, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public bool ImportReportFbaReimbursement(string sqlConnectionString, 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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
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");
|
|
MiscFunction.EventLogInsert((lineNumber - (1 + lineErrorSkip + lineDuplicateSkip)) + " total new items inserted, " + lineDuplicateSkip + " duplicates were skipped.");
|
|
if (lineErrorSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running ImportFbaReimbursementReport method, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public bool ImportReportFbaRemovalOrder(string sqlConnectionString, 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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
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");
|
|
MiscFunction.EventLogInsert("ImportFbaRemovalOrderReport() " + (lineNumber - (1 + lineErrorSkip + lineUpdate)) + " records created, " + lineUpdate + " records updated.");
|
|
if (lineErrorSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running ImportFbaRemovalOrderReport method, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
public void UpdateFbaInventoryData(string sqlConnectionString)
|
|
{
|
|
MiscFunction.EventLogInsert("Staring ImportFbaInventoryData()...");
|
|
string mwsReportEnum = "_GET_FBA_MYI_ALL_INVENTORY_DATA_";
|
|
|
|
string filePath = "";
|
|
// Uncomment to override getreport and load directly from file
|
|
//filePath = @"C:\Users\Bobbie\AppData\Local\Temp\_e2A Client\File\8539341218017503.txt";
|
|
|
|
// build the request
|
|
if (filePath == "")
|
|
{
|
|
RequestReportRequest requestReport = new RequestReportRequest();
|
|
requestReport.Merchant = merchantId;
|
|
requestReport.ReportType = mwsReportEnum;
|
|
|
|
MiscFunction.EventLogInsert("Requesting '" + mwsReportEnum + "''");
|
|
filePath = GetMwsReportByRequest(requestReport);
|
|
|
|
if (filePath == "_DONE_NO_DATA_")
|
|
{
|
|
// do nothing, carry on with next iteration
|
|
}
|
|
else if (filePath == "_CANCELLED_")
|
|
{
|
|
/*
|
|
/ this is probably MWS higher level throttling when requesting duplicate report
|
|
/ for near real time reports waiting 30 minutes
|
|
/ for daily reports wait 4 hours
|
|
*/
|
|
}
|
|
else if (filePath.Length == 0)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Something went wrong retriving report from MWS. Operation cancelled.",
|
|
2
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// import into database
|
|
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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
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");
|
|
MiscFunction.EventLogInsert(
|
|
"Operation complete. " + lineNumber + " items processes. " + (lineNumber - lineErrorSkip - lineNoStockSkip) + " total new items inserted, "
|
|
+ lineNoStockSkip + " 'No Stock' records were skipped.");
|
|
if (lineErrorSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
scope.Complete();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Something went wrong during import, check details for more.", 1, ex.ToString());
|
|
Console.WriteLine(ex.ToString());
|
|
}
|
|
}
|
|
public void UpdateFbaInventoryAgeData(string sqlConnectionString)
|
|
{
|
|
MiscFunction.EventLogInsert("Staring ImportFbaInventoryAgeReport()...");
|
|
string mwsReportEnum = "_GET_FBA_INVENTORY_AGED_DATA_";
|
|
|
|
string filePath = "";
|
|
// Uncomment to override getreport and load directly from file
|
|
//filePath = @"C:\Users\Bobbie\AppData\Local\Temp\_e2A Client\File\8539341218017503.txt";
|
|
|
|
// build the request
|
|
if (filePath == "")
|
|
{
|
|
RequestReportRequest requestReport = new RequestReportRequest();
|
|
requestReport.Merchant = merchantId;
|
|
requestReport.ReportType = mwsReportEnum;
|
|
|
|
MiscFunction.EventLogInsert("Requesting '" + mwsReportEnum + "''");
|
|
filePath = GetMwsReportByRequest(requestReport);
|
|
|
|
if (filePath == "_DONE_NO_DATA_")
|
|
{
|
|
// do nothing, carry on with next iteration
|
|
}
|
|
else if (filePath == "_CANCELLED_")
|
|
{
|
|
/*
|
|
/ this is probably MWS higher level throttling when requesting duplicate report
|
|
/ for near real time reports waiting 30 minutes
|
|
/ for daily reports wait 4 hours
|
|
*/
|
|
}
|
|
else if (filePath.Length == 0)
|
|
{
|
|
MiscFunction.EventLogInsert(
|
|
"Something went wrong retriving report from MWS. Operation cancelled.",
|
|
2
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// import into database
|
|
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;
|
|
|
|
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 removal");
|
|
|
|
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;
|
|
MiscFunction.EventLogInsert(
|
|
"Line #" + lineNumber + " skipped due to no enough element in row.",
|
|
2,
|
|
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 estimatedCostSavingsOfRemoval = items[index34];
|
|
|
|
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 removal] )
|
|
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, @estimatedCostSavingsOfRemoval );
|
|
", 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 (estimatedCostSavingsOfRemoval.Length == 0) { cmd.Parameters.AddWithValue("@estimatedCostSavingsOfRemoval", DBNull.Value); }
|
|
else { cmd.Parameters.AddWithValue("@estimatedCostSavingsOfRemoval", decimal.Parse(estimatedCostSavingsOfRemoval)); }
|
|
|
|
// execute the query
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
MiscFunction.EventLogInsert(
|
|
"Operation complete. " + lineNumber + " items processes. " + (lineNumber - lineErrorSkip - lineNoStockSkip) + " total new items inserted, "
|
|
+ lineNoStockSkip + " 'No Stock' records were skipped.");
|
|
if (lineErrorSkip > 0)
|
|
{
|
|
MiscFunction.EventLogInsert(lineErrorSkip + " total line(s) where skipped due to insufficent number of cells on row", 1);
|
|
}
|
|
}
|
|
}
|
|
scope.Complete();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Something went wrong during import, check details for more.", 1, ex.ToString());
|
|
Console.WriteLine(ex.ToString());
|
|
}
|
|
}
|
|
public void UpdateAmazonSettlementData(string sqlConnectionString)
|
|
{
|
|
string mwsReportEnum = "_GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_V2_";
|
|
|
|
MiscFunction.EventLogInsert("Requesting 'unacknowledged' '" + mwsReportEnum + "' MWS reports");
|
|
|
|
/*
|
|
/ get the list of avaiable reports
|
|
*/
|
|
|
|
TypeList reportList = new TypeList();
|
|
reportList.Type.Add(mwsReportEnum);
|
|
GetReportListRequest requestList = new GetReportListRequest();
|
|
requestList.Merchant = merchantId;
|
|
requestList.MaxCount = 100;
|
|
requestList.ReportTypeList = reportList;
|
|
bool? returnAcknowledged = false;
|
|
if (returnAcknowledged == true) { requestList.Acknowledged = true; }
|
|
else if (returnAcknowledged == false) { requestList.Acknowledged = false; }
|
|
|
|
/*
|
|
/ request, recive request, and then iterate through the list
|
|
*/
|
|
|
|
List<ReportInfo> reportInfoList = GetMwsReportList(requestList);
|
|
|
|
int reportsImported = 0;
|
|
foreach (ReportInfo reportInfo in reportInfoList)
|
|
{
|
|
//don't know what this next line does, might need it
|
|
//if (reportInfo.IsSetReportId() & reportInfo.IsSetAcknowledged())
|
|
|
|
string reportId = reportInfo.ReportId;
|
|
bool acknowledged = reportInfo.Acknowledged;
|
|
string filePath = GetMwsReportById(reportInfo.ReportId);
|
|
|
|
/*
|
|
* Pass file path to function to parse into database
|
|
*/
|
|
|
|
bool import = ImportReportSettlementData(sqlConnectionString, filePath);
|
|
|
|
// if opertion succeded, set the acknowledged property
|
|
if (import & (returnAcknowledged == false | returnAcknowledged == null))
|
|
{
|
|
SetMwsReportAcknowledgement(reportId, true);
|
|
}
|
|
if (import == true)
|
|
{
|
|
reportsImported = reportsImported + 1;
|
|
}
|
|
}
|
|
if (reportsImported > 0)
|
|
{
|
|
MiscFunction.EventLogInsert("No new '" + mwsReportEnum + "' reports available for download.");
|
|
//return true;
|
|
}
|
|
else
|
|
{
|
|
MiscFunction.EventLogInsert("Total of " + reportsImported + " new settlement reports imported");
|
|
//return false;
|
|
}
|
|
}
|
|
public void UpdateFbaInventoryReceiptData(string sqlConnectionString)
|
|
{
|
|
string mwsReportEnum = "_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_";
|
|
|
|
/*
|
|
* 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)
|
|
*/
|
|
|
|
// get the most recent date from db table
|
|
DateTime startTime;
|
|
DateTime endTime = DateTime.UtcNow;
|
|
DateTime currentTime = DateTime.UtcNow.AddMinutes(-5);
|
|
|
|
SqlConnection sqlConn;
|
|
try
|
|
{
|
|
using (sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT Max([received-date]) AS MaxDate FROM tblImportFbaInventoryReceiptReport;"
|
|
, sqlConn))
|
|
{
|
|
if (cmd.ExecuteScalar() == DBNull.Value)
|
|
{
|
|
// use first month started selling on Amazon
|
|
startTime = DateTime.Parse("2014-09-01T00:00:00Z");
|
|
// no need to specific timezone, etc, as "Z" already specifis UTC
|
|
}
|
|
else
|
|
{
|
|
startTime = ((DateTime)cmd.ExecuteScalar());
|
|
startTime = DateTime.SpecifyKind(startTime, DateTimeKind.Utc);
|
|
startTime = startTime.AddSeconds(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running FbaInventoryReceiptReportImport, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// get list of reports
|
|
List<string> reportPathList = GetMwsReportByPeriod(mwsReportEnum, startTime, endTime);
|
|
if (reportPathList.Count == 0)
|
|
{
|
|
// no report downloadeded
|
|
MiscFunction.EventLogInsert("No reports downloaded, stopping UpdateFbaInventoryReceiptData method...");
|
|
return;
|
|
}
|
|
|
|
// loop throught list of filepaths
|
|
foreach (string reportPath in reportPathList)
|
|
{
|
|
bool ackImport = ImportReportFbaInventoryReceipt(sqlConnectionString, reportPath, startTime);
|
|
if (ackImport == false)
|
|
{
|
|
MiscFunction.EventLogInsert("Problem importing report '" + mwsReportEnum + "'. stopping further report imports...",
|
|
1,
|
|
MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
public void UpdateFbaSaleShipmentData(string sqlConnectionString)
|
|
{
|
|
string mwsReportEnum = "_GET_AMAZON_FULFILLED_SHIPMENTS_DATA_";
|
|
|
|
//// Uncomment to override getreport and load directly from file
|
|
//bool ackImportTemp = FbaSaleShipmentReportImport(@"C:\Users\Bobbie\AppData\Local\Temp\_e2A Client\File\7019109828017378.txt");
|
|
//return;
|
|
|
|
/*
|
|
* flat file lines/rows are unique
|
|
* FROM MWS GUIDANCE
|
|
* https://docs.developer.amazonservices.com/en_UK/fba_guide/FBAGuide_TipsShipmentsReport.html
|
|
* Overlap report by 3 days. To disambiguate duplicate shipment reports, use the ShipmentItemId (not the OrderId or the OrderItemId)
|
|
*/
|
|
|
|
// get the most recent date from db table
|
|
DateTime startTime;
|
|
DateTime endTime = DateTime.UtcNow;
|
|
DateTime latestTime = DateTime.UtcNow.AddMinutes(-5);
|
|
|
|
SqlConnection sqlConn;
|
|
try
|
|
{
|
|
using (sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT Max([shipment-date]) AS MaxDate FROM tblImportFbaSaleShipment;"
|
|
, sqlConn))
|
|
{
|
|
if (cmd.ExecuteScalar() == DBNull.Value)
|
|
{
|
|
// use first month started selling on Amazon
|
|
startTime = DateTime.Parse("2014-09-01T00:00:00Z");
|
|
// no need to specific timezone, etc, as "Z" already specifis UTC
|
|
startTime = DateTime.Parse("2016-02-01T00:00:00Z");
|
|
// fba sale shipments for previous 18 months only
|
|
}
|
|
else
|
|
{
|
|
startTime = ((DateTime)cmd.ExecuteScalar());
|
|
startTime = DateTime.SpecifyKind(startTime, DateTimeKind.Utc);
|
|
// Amazon states in MWS guidance that shipments are added in near real time, however, in most cases,
|
|
// there will be a delay of approximately one to three hours. In some rare cases there could be a delay of up to 24 hours.
|
|
startTime = startTime.AddDays(-3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running FbaInventoryReceiptReportImport, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// get list of reports
|
|
List<string> reportPathList = GetMwsReportByPeriod(mwsReportEnum, startTime, endTime);
|
|
if (reportPathList.Count == 0)
|
|
{
|
|
// no report downloadeded
|
|
MiscFunction.EventLogInsert("No reports downloaded, stopping GetFbaReturnsReport method...");
|
|
return;
|
|
}
|
|
|
|
// loop throught list of filepaths
|
|
foreach (string reportPath in reportPathList)
|
|
{
|
|
bool ackImport = ImportReportFbaSaleShipment(sqlConnectionString, reportPath);
|
|
if (ackImport == false)
|
|
{
|
|
MiscFunction.EventLogInsert("Problem importing report '" + mwsReportEnum + "'. stopping further report imports...",
|
|
1,
|
|
MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
public void UpdateFbaReturnData(string sqlConnectionString)
|
|
{
|
|
string mwsReportEnum = "_GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA_";
|
|
|
|
//_GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA_
|
|
|
|
//// Uncomment to override getreport and load directly from file
|
|
//bool ackImportTemp = ImportFbaReturnsReport(@"C:\Users\Bobbie\AppData\Local\Temp\_e2A Client\File\7027223463017379.txt");
|
|
//return;
|
|
|
|
/*
|
|
* flat file lines/rows maybe unique
|
|
* Overlap reports by 3 days.
|
|
* To disambiguate duplicate row, I will use combination of date, orderid, fnsku, quantity, LPN#, disposition, and reason.
|
|
*/
|
|
|
|
// get the most recent date from db table
|
|
DateTime startTime;
|
|
DateTime endTime = DateTime.UtcNow;
|
|
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
|
|
startTime = DateTime.Parse("2015-08-25T00:00:00Z"); //this before first return
|
|
// no need to specific timezone, etc, as "Z" already specifis UTC
|
|
}
|
|
else
|
|
{
|
|
startTime = ((DateTime)cmd.ExecuteScalar());
|
|
startTime = DateTime.SpecifyKind(startTime, DateTimeKind.Utc);
|
|
// Amazon states in MWS guidance that content updated daily.
|
|
startTime = startTime.AddDays(-14);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running GetFbaReturnsReport, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// get list of reports
|
|
List<string> reportPathList = GetMwsReportByPeriod(mwsReportEnum, startTime, endTime);
|
|
if (reportPathList.Count == 0)
|
|
{
|
|
// no report downloadeded
|
|
MiscFunction.EventLogInsert("No reports downloaded, stopping GetFbaReturnsReport method...");
|
|
return;
|
|
}
|
|
|
|
// loop throught list of filepaths
|
|
foreach (string reportPath in reportPathList)
|
|
{
|
|
bool ackImport = ImportReportFbaReturns(sqlConnectionString, reportPath);
|
|
if (ackImport == false)
|
|
{
|
|
MiscFunction.EventLogInsert("Problem importing report '" + mwsReportEnum + "'. stopping further report imports...",
|
|
1,
|
|
MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
public void UpdateFbaAdustmentData(string sqlConnectionString)
|
|
{
|
|
string mwsReportEnum = "_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_";
|
|
|
|
//// Uncomment to override getreport and load directly from file
|
|
//bool ackImportTemp = ImportFbaAdustmentReport(@"C:\Users\Bobbie\AppData\Local\Temp\_e2A Client\File\7034366409017380.txt");
|
|
//return;
|
|
|
|
// get the most recent date from db table
|
|
DateTime startTime;
|
|
DateTime endTime = DateTime.UtcNow;
|
|
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
|
|
startTime = DateTime.Parse("2014-09-01T00:00:00Z");
|
|
// no need to specific timezone, etc, as "Z" already specifis UTC
|
|
}
|
|
else
|
|
{
|
|
startTime = ((DateTime)cmd.ExecuteScalar());
|
|
startTime = DateTime.SpecifyKind(startTime, DateTimeKind.Utc);
|
|
// Amazon states in MWS guidance that content updated daily.
|
|
startTime = startTime.AddDays(-3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running GetFbaAdustmentData, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// get list of reports
|
|
List<string> reportPathList = GetMwsReportByPeriod(mwsReportEnum, startTime, endTime);
|
|
if (reportPathList.Count == 0)
|
|
{
|
|
// no report downloadeded
|
|
MiscFunction.EventLogInsert("No reports downloaded, stopping GetFbaAdustmentData method...");
|
|
return;
|
|
}
|
|
|
|
// loop throught list of filepaths
|
|
foreach (string reportPath in reportPathList)
|
|
{
|
|
bool ackImport = ImportReportFbaAdjustment(sqlConnectionString, reportPath);
|
|
if (ackImport == false)
|
|
{
|
|
MiscFunction.EventLogInsert("Problem importing report '" + mwsReportEnum + "'. stopping further report imports...",
|
|
1,
|
|
MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
public void UpdateFbaReimbursementData(string sqlConnectionString)
|
|
{
|
|
string mwsReportEnum = "_GET_FBA_REIMBURSEMENTS_DATA_";
|
|
|
|
// Uncomment to override getreport and load directly from file
|
|
//bool ackImportTemp = ImportFbaReimbursementReport(@"C:\Users\Bobbie\AppData\Local\Temp\_e2A Client\File\7037074827017380.txt");
|
|
//return;
|
|
|
|
// get the most recent date from db table
|
|
DateTime startTime;
|
|
DateTime endTime = DateTime.UtcNow;
|
|
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
|
|
startTime = DateTime.Parse("2014-09-01T00:00:00Z");
|
|
// no need to specific timezone, etc, as "Z" already specifis UTC
|
|
}
|
|
else
|
|
{
|
|
startTime = ((DateTime)cmd.ExecuteScalar());
|
|
startTime = DateTime.SpecifyKind(startTime, DateTimeKind.Utc);
|
|
// Amazon states in MWS guidance that content updated daily.
|
|
startTime = startTime.AddDays(-3);
|
|
//startTime = DateTime.Parse("2015-05-01T00:00:00Z");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running GetFbaReimbursementData, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// get list of reports
|
|
List<string> reportPathList = GetMwsReportByPeriod(mwsReportEnum, startTime, endTime);
|
|
if (reportPathList.Count == 0)
|
|
{
|
|
// no report downloadeded
|
|
MiscFunction.EventLogInsert("No reports downloaded, stopping GetFbaReimbursementData method...");
|
|
return;
|
|
}
|
|
|
|
// loop throught list of filepaths
|
|
foreach (string reportPath in reportPathList)
|
|
{
|
|
bool ackImport = ImportReportFbaReimbursement(sqlConnectionString, reportPath);
|
|
if (ackImport == false)
|
|
{
|
|
MiscFunction.EventLogInsert("Problem importing report '" + mwsReportEnum + "'. stopping further report imports...",
|
|
1,
|
|
MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
public void UpdateFbaRemovalOrderReport(string sqlConnectionString)
|
|
{
|
|
string mwsReportEnum = "_GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA_";
|
|
|
|
// Uncomment to override getreport and load directly from file
|
|
//bool ackImportTemp = ImportFbaReimbursementReport(@"C:\Users\Bobbie\AppData\Local\Temp\_e2A Client\File\7037074827017380.txt");
|
|
//return;
|
|
|
|
// get the most recent date from db table
|
|
DateTime startTime;
|
|
DateTime endTime = DateTime.UtcNow;
|
|
SqlConnection sqlConn;
|
|
try
|
|
{
|
|
using (sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
using (SqlCommand cmd = new SqlCommand(
|
|
"SELECT Max([request-date]) AS MaxDate FROM tblImportFbaRemovalOrderReport;"
|
|
, sqlConn))
|
|
{
|
|
if (cmd.ExecuteScalar() == DBNull.Value)
|
|
{
|
|
// use first month started selling on Amazon
|
|
startTime = DateTime.Parse("2015-09-15T00:00:00Z");
|
|
// no need to specific timezone, etc, as "Z" already specifis UTC
|
|
}
|
|
else
|
|
{
|
|
startTime = ((DateTime)cmd.ExecuteScalar());
|
|
startTime = DateTime.SpecifyKind(startTime, DateTimeKind.Utc);
|
|
startTime = startTime.AddDays(-30); // yes, that's right -30 days
|
|
//startTime = DateTime.Parse("2015-05-01T00:00:00Z");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("Error running GetFbaRemovalOrderReport, no records were commited",
|
|
1,
|
|
ex.ToString() + "\r\nTraceMessage:\r\n" + MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// get list of reports
|
|
List<string> reportPathList = GetMwsReportByPeriod(mwsReportEnum, startTime, endTime, 24);
|
|
if (reportPathList.Count == 0)
|
|
{
|
|
// no report downloadeded
|
|
MiscFunction.EventLogInsert("No reports downloaded, stopping GetFbaReimbursementData method...");
|
|
return;
|
|
}
|
|
|
|
// loop throught list of filepaths
|
|
foreach (string reportPath in reportPathList)
|
|
{
|
|
bool ackImport = ImportReportFbaRemovalOrder(sqlConnectionString, reportPath);
|
|
if (ackImport == false)
|
|
{
|
|
MiscFunction.EventLogInsert("Problem importing report '" + mwsReportEnum + "'. stopping further report imports...",
|
|
1,
|
|
MiscFunction.TraceMessage()
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
public class MiscFunction
|
|
{
|
|
public static void EventLogInsert
|
|
(string detailShort = "", int eventType = 3, string detailLong = "", DateTime eventDateTime = default(DateTime), bool consolePrint = true)
|
|
{
|
|
// 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();
|
|
if (detailShort.Length == 0)
|
|
{
|
|
throw new ArgumentException("The string parameter detailShort is empty, this is a required paramenter.");
|
|
}
|
|
if (eventDateTime == default(DateTime))
|
|
{
|
|
eventDateTime = DateTime.UtcNow;
|
|
}
|
|
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);
|
|
cmd.Parameters.AddWithValue("@detailLong", detailLong);
|
|
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
ConsoleUpdate(detailShort);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ConsoleUpdate("WTF!!!! Error with error logging, jobs foooked!");
|
|
throw ex;
|
|
}
|
|
scope.Complete();
|
|
}
|
|
}
|
|
}
|
|
public static string TraceMessage(
|
|
[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
|
|
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
|
|
[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
|
|
{
|
|
string traceMessage =
|
|
"Trace:" +
|
|
"\r\n\tmember name: " + memberName +
|
|
"\r\n\tsource file path: " + sourceFilePath +
|
|
"\r\n\tsource line number: " + sourceLineNumber;
|
|
return traceMessage;
|
|
}
|
|
public static void MwsThrottleWait(int waitSeconds)
|
|
{
|
|
MiscFunction.EventLogInsert("MWS request throttled, retrying in " + waitSeconds + " seconds...");
|
|
string consoleMessage = "{0} seconds remaining...";
|
|
ConsoleCountDown(consoleMessage, waitSeconds);
|
|
}
|
|
public static void ConsoleCountDown(string consoleMessage, int waitSeconds)
|
|
{
|
|
do
|
|
{
|
|
Console.Write("\r[--------] " + consoleMessage, String.Format("{0:00}", waitSeconds));
|
|
System.Threading.Thread.Sleep(1000);
|
|
waitSeconds = waitSeconds - 1;
|
|
} while (waitSeconds > 0);
|
|
Console.Write("\r");
|
|
Console.Write(new String(' ', Console.BufferWidth -1));
|
|
Console.Write("\r");
|
|
}
|
|
public static void ConsoleUpdate(string consoleText, Boolean newLine = true)
|
|
{
|
|
if (newLine)
|
|
{
|
|
Console.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss") + "] " + consoleText);
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("\r[" + DateTime.Now.ToString("HH:mm:ss") + "] " + consoleText);
|
|
}
|
|
}
|
|
public static string GetTempFilePath(string fileName)
|
|
{
|
|
string directoryPath = Path.GetTempPath()
|
|
+ "_" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name
|
|
+ "\\File\\";
|
|
System.IO.Directory.CreateDirectory(directoryPath);
|
|
string fullPath = directoryPath + fileName;
|
|
return fullPath;
|
|
}
|
|
public static DateTime ParseMwsReportDateTime(string reportDateTime)
|
|
{
|
|
string isoDateTime =
|
|
reportDateTime.Substring(6, 4) + "-" +
|
|
reportDateTime.Substring(3, 2) + "-" +
|
|
reportDateTime.Substring(0, 2) + "T" +
|
|
reportDateTime.Substring(11, 2) + ":" +
|
|
reportDateTime.Substring(14, 2) + ":" +
|
|
reportDateTime.Substring(17, 2) + "Z";
|
|
return DateTime.Parse(isoDateTime);
|
|
}
|
|
|
|
}
|
|
public class TempFunction
|
|
{
|
|
public void UpdateSkuCost(string sqlConnectionString)
|
|
{
|
|
MiscFunction.EventLogInsert("Starting temp function UpdateSkuCost()");
|
|
int count = 0;
|
|
|
|
try
|
|
{
|
|
using (SqlConnection sqlConn = new SqlConnection(sqlConnectionString))
|
|
{
|
|
sqlConn.Open();
|
|
|
|
using (SqlCommand cmd01 = sqlConn.CreateCommand())
|
|
{
|
|
//query for list of all sku's with stock
|
|
|
|
cmd01.CommandText = @"
|
|
SELECT sku, [mfn-fulfillable-quantity], [afn-total-quantity]
|
|
FROM tblImportFbaManageInventory
|
|
WHERE ( [mfn-fulfillable-quantity] > 0 ) OR ( [afn-total-quantity] > 0 )
|
|
";
|
|
|
|
using (SqlDataReader reader01 = cmd01.ExecuteReader())
|
|
{
|
|
// retrive index of columns for faster operation
|
|
int indexOfColumn1 = reader01.GetOrdinal("sku");
|
|
int indexOfColumn2 = reader01.GetOrdinal("mfn-fulfillable-quantity");
|
|
int indexOfColumn3 = reader01.GetOrdinal("afn-total-quantity");
|
|
|
|
while (reader01.Read())
|
|
{
|
|
count = count + 1;
|
|
Console.Write("\rProcessing record #" + count);
|
|
|
|
//assign values
|
|
string skuNumber = reader01.GetString(indexOfColumn1);
|
|
|
|
int mfnTotal;
|
|
if (reader01.IsDBNull(indexOfColumn2)) { mfnTotal = 0; }
|
|
else { mfnTotal = reader01.GetInt32(indexOfColumn2); }
|
|
|
|
int afnTotal;
|
|
if (reader01.IsDBNull(indexOfColumn3)) { afnTotal = 0; }
|
|
else { afnTotal = reader01.GetInt32(indexOfColumn3); }
|
|
|
|
int total = mfnTotal + afnTotal;
|
|
|
|
//query for average unit cost
|
|
using (SqlCommand cmd02 = new SqlCommand(@"
|
|
SELECT AVG(Q.UnitCost) AS AvgCost
|
|
FROM(
|
|
SELECT TOP (@total) UnitQuantity, n, UnitCost
|
|
FROM(tblNumbers INNER JOIN tblStock ON n <= UnitQuantity) INNER JOIN tblSku ON SkuID = skuSkuID
|
|
WHERE(skuSkuNumber = @skuNumber)
|
|
ORDER BY StockID DESC
|
|
) Q
|
|
", sqlConn))
|
|
{
|
|
cmd02.Parameters.AddWithValue("@total", total);
|
|
cmd02.Parameters.AddWithValue("@skuNumber", skuNumber);
|
|
|
|
decimal AvgCost = 0;
|
|
object obj = cmd02.ExecuteScalar();
|
|
if (obj == null || obj == DBNull.Value)
|
|
{
|
|
AvgCost = 0;
|
|
}
|
|
else
|
|
{
|
|
AvgCost = Convert.ToDecimal(obj);
|
|
}
|
|
AvgCost = Math.Round(AvgCost, 2);
|
|
|
|
//Console.WriteLine(skuNumber + " " + AvgCost);
|
|
|
|
//update sku table
|
|
using (SqlCommand cmd03 = sqlConn.CreateCommand())
|
|
{
|
|
cmd03.Parameters.AddWithValue("@skuNumber", skuNumber);
|
|
cmd03.Parameters.AddWithValue("@AvgCost", AvgCost);
|
|
cmd03.Parameters.AddWithValue("@timeStamp", DateTime.UtcNow);
|
|
|
|
Console.Write(" £" + AvgCost );
|
|
|
|
cmd03.CommandText =
|
|
"UPDATE tblSku " +
|
|
"SET skuSkuAvgCost = @AvgCost, skuSkuAvgCostUpdate = @timeStamp " +
|
|
"WHERE skuSkuNumber = @skuNumber;";
|
|
cmd03.ExecuteNonQuery();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
Console.Write("\r");
|
|
MiscFunction.EventLogInsert("UpdateSkuCost() operation complete. " + count + " total SKU average cost(s) updated");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MiscFunction.EventLogInsert("UpdateSkuCost() operation exceltion. See 'details' for further information.", 1, ex.ToString());
|
|
Console.WriteLine(ex.ToString());
|
|
}
|
|
}
|
|
}
|
|
} |