mirror of
https://github.com/stokebob/bnhtrade.git
synced 2026-03-23 08:17:15 +00:00
Feature: Sync MWS Shipment with Database
Various restructuring and misc. features added. Removed reliance on ABrain Amazon MWS NuGet package, added Amazon's own C# lib
This commit is contained in:
19
src/bnhtrade.Core/Data/AmazonMWS/CredentialMws.cs
Normal file
19
src/bnhtrade.Core/Data/AmazonMWS/CredentialMws.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.AmazonMWS
|
||||
{
|
||||
public class CredentialMws
|
||||
{
|
||||
public string merchantId { get { return "A3RUYNKLWWM5KW"; } }
|
||||
public string marketPlaceId { get { return "A1F83G8C2ARO7P"; } } // Amazon.co.uk
|
||||
public string accessKeyId { get { return "AKIAJU45WSYVINEN45UA"; } }
|
||||
public string secretAccessKey { get { return "cpS3HnTYDIVxAPSxaJwCwUbeH6PGPnpij5Un5bWI"; } }
|
||||
public string applicationName { get { return "bnhtrade.Core"; } }
|
||||
public string applicationVersion { get { return "0.1"; } }
|
||||
public string serviceURL { get { return "https://mws.amazonservices.co.uk"; } }
|
||||
}
|
||||
}
|
||||
47
src/bnhtrade.Core/Data/AmazonMWS/CurrentDateTime.cs
Normal file
47
src/bnhtrade.Core/Data/AmazonMWS/CurrentDateTime.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.XPath;
|
||||
|
||||
namespace bnhtrade.Core.Data.AmazonMWS
|
||||
{
|
||||
public class CurrentDateTime
|
||||
{
|
||||
public DateTime GetUtc()
|
||||
{
|
||||
var xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load("https://mws.amazonservices.com/");
|
||||
DateTime returnTime = default(DateTime);
|
||||
|
||||
XmlNodeList elemList = xmlDoc.GetElementsByTagName("Timestamp");
|
||||
for (int i = 0; i < elemList.Count; i++)
|
||||
{
|
||||
string attrVal = elemList[i].Attributes["timestamp"].Value;
|
||||
if (!string.IsNullOrWhiteSpace(attrVal))
|
||||
{
|
||||
returnTime = DateTime.Parse(attrVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnTime == default(DateTime))
|
||||
{
|
||||
throw new Exception("Error requesting time from Amazon");
|
||||
}
|
||||
|
||||
returnTime = returnTime.ToUniversalTime();
|
||||
returnTime = returnTime.AddTicks(-(returnTime.Ticks % TimeSpan.TicksPerSecond));
|
||||
|
||||
return returnTime;
|
||||
}
|
||||
public DateTime GetLocal()
|
||||
{
|
||||
return GetUtc().ToLocalTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FBAInboundServiceMWS.Model;
|
||||
|
||||
namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
|
||||
{
|
||||
class ListInboundShipmentItems
|
||||
{
|
||||
public string AmazonShipmentId { get; private set; }
|
||||
public DateTime LastUpdatedAfter { get; private set; }
|
||||
public DateTime LastUpdatedBefore { get; private set; }
|
||||
|
||||
public bool IsSetAmazonShipmentId()
|
||||
{
|
||||
return AmazonShipmentId != null;
|
||||
}
|
||||
public bool IsSetLastUpdatedAfter()
|
||||
{
|
||||
return LastUpdatedAfter != null;
|
||||
}
|
||||
public bool IsSetLastUpdatedBefore()
|
||||
{
|
||||
return LastUpdatedBefore != null;
|
||||
}
|
||||
|
||||
public List<Model.AmazonFBAInbound.ShipmentItemInfo> GetByAmazonShipmentId(string amazonShipmentId)
|
||||
{
|
||||
// checks
|
||||
if (amazonShipmentId.Length < 9)
|
||||
{
|
||||
throw new Exception("Amazon shipment id incorrect length '" + amazonShipmentId + "'");
|
||||
}
|
||||
|
||||
var request = new ListInboundShipmentItemsRequest();
|
||||
request.ShipmentId = amazonShipmentId;
|
||||
|
||||
AmazonShipmentId = amazonShipmentId;
|
||||
|
||||
return ListInboundShipmentItemsGet(request);
|
||||
}
|
||||
|
||||
public List<Model.AmazonFBAInbound.ShipmentItemInfo> GetByDates(DateTime lastUpdatedAfter, DateTime lastUpdatedBefore)
|
||||
{
|
||||
//checks
|
||||
if (lastUpdatedAfter >= lastUpdatedBefore)
|
||||
{
|
||||
throw new Exception("Paramter LastUpdatedAfter must be greater than LastUpdatedBefore");
|
||||
}
|
||||
|
||||
var request = new ListInboundShipmentItemsRequest();
|
||||
request.LastUpdatedAfter = lastUpdatedAfter;
|
||||
request.LastUpdatedBefore = lastUpdatedBefore;
|
||||
|
||||
LastUpdatedAfter = lastUpdatedAfter;
|
||||
LastUpdatedBefore = lastUpdatedBefore;
|
||||
|
||||
return ListInboundShipmentItemsGet(request);
|
||||
}
|
||||
|
||||
private List<Model.AmazonFBAInbound.ShipmentItemInfo> ListInboundShipmentItemsGet(ListInboundShipmentItemsRequest request)
|
||||
{
|
||||
// variables
|
||||
int mwsPollFrequency = 500;
|
||||
int mwsPollTimeout = 60;
|
||||
|
||||
// add default entries, if not already set
|
||||
|
||||
if (!request.IsSetSellerId())
|
||||
{
|
||||
var cred = new AmazonMWS.CredentialMws();
|
||||
request.SellerId = cred.merchantId;
|
||||
}
|
||||
|
||||
// checks
|
||||
if ((request.IsSetLastUpdatedAfter() || request.IsSetLastUpdatedBefore()) && request.IsSetShipmentId())
|
||||
{
|
||||
throw new Exception("If ShipmentId is specified, LastUpdatedBefore and LastUpdatedAfter are ignored.");
|
||||
}
|
||||
|
||||
// get amazon service, responce and result
|
||||
var service = new AmazonMWS.Service().FbaInbound;
|
||||
//var response = new ListInboundShipmentItemsResponse();
|
||||
var result = new ListInboundShipmentItemsResult();
|
||||
|
||||
// poll mws for response
|
||||
int count = 0;
|
||||
do
|
||||
{
|
||||
var response = service.ListInboundShipmentItems(request);
|
||||
if (response.IsSetListInboundShipmentItemsResult())
|
||||
{
|
||||
result = response.ListInboundShipmentItemsResult;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(mwsPollFrequency);
|
||||
count++;
|
||||
}
|
||||
} while (count < mwsPollTimeout);
|
||||
if (count == mwsPollTimeout)
|
||||
{
|
||||
throw new Exception("Response from Amazon MWS timeout");
|
||||
}
|
||||
|
||||
// create the return list
|
||||
var returnList = new List<Model.AmazonFBAInbound.ShipmentItemInfo>();
|
||||
|
||||
// check a result was returned, return empty list on no results
|
||||
if (!result.IsSetItemData())
|
||||
{
|
||||
return returnList;
|
||||
}
|
||||
|
||||
// add data list
|
||||
InboundShipmentItemList resultList = result.ItemData;
|
||||
var infoList = new List<InboundShipmentItem>();
|
||||
infoList.AddRange(resultList.member);
|
||||
|
||||
// check for next dataset
|
||||
if (result.IsSetNextToken())
|
||||
{
|
||||
string nextToken = result.NextToken;
|
||||
do
|
||||
{
|
||||
var nextRequest = new ListInboundShipmentItemsByNextTokenRequest();
|
||||
var nextResult = new ListInboundShipmentItemsByNextTokenResult();
|
||||
nextRequest.NextToken = nextToken;
|
||||
nextRequest.SellerId = request.SellerId;
|
||||
|
||||
count = 0;
|
||||
do
|
||||
{
|
||||
var response = service.ListInboundShipmentItemsByNextToken(nextRequest);
|
||||
if (response.IsSetListInboundShipmentItemsByNextTokenResult())
|
||||
{
|
||||
nextResult = response.ListInboundShipmentItemsByNextTokenResult;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(mwsPollFrequency);
|
||||
count++;
|
||||
}
|
||||
} while (count < mwsPollTimeout);
|
||||
if (count == mwsPollTimeout)
|
||||
{
|
||||
throw new Exception("Response from Amazon MWS timeout");
|
||||
}
|
||||
|
||||
// add data to list
|
||||
InboundShipmentItemList nextResultList = nextResult.ItemData;
|
||||
infoList.AddRange(nextResultList.member);
|
||||
|
||||
if (nextResult.IsSetNextToken())
|
||||
{
|
||||
nextToken = nextResult.NextToken;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextToken = "";
|
||||
}
|
||||
|
||||
} while (nextToken.Length > 0); // next token is true
|
||||
}
|
||||
|
||||
// load data set into returnList
|
||||
foreach (var item in infoList)
|
||||
{
|
||||
var returnItem = new Model.AmazonFBAInbound.ShipmentItemInfo();
|
||||
returnItem.AmazonShipmentId = item.ShipmentId;
|
||||
returnItem.SKUNumber = item.SellerSKU;
|
||||
returnItem.AmazonFNSKU = item.FulfillmentNetworkSKU;
|
||||
if (item.IsSetQuantityShipped()) { returnItem.QuantityAllocated = (int)item.QuantityShipped; }
|
||||
else { returnItem.QuantityAllocated = 0; }
|
||||
if (item.IsSetQuantityReceived()) { returnItem.QuantityReceived = (int)item.QuantityReceived; }
|
||||
else { returnItem.QuantityReceived = 0; }
|
||||
|
||||
returnList.Add(returnItem);
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FBAInboundServiceMWS.Model;
|
||||
|
||||
namespace bnhtrade.Core.Data.AmazonMWS.FBAInbound
|
||||
{
|
||||
public class ListInboundShipments
|
||||
{
|
||||
/// <summary>
|
||||
/// List of Shipment Status' to return. Default is all status' returned.
|
||||
/// </summary>
|
||||
public List<string> ShipmentStatusList { get; set; }
|
||||
/// <summary>
|
||||
/// List of Shipment Id to return.
|
||||
/// </summary>
|
||||
public List<string> ShipmentIdList { get; set; }
|
||||
public DateTime LastUpdatedAfter { get; set; }
|
||||
public DateTime LastUpdatedBefore { get; set; }
|
||||
|
||||
public bool IsSetShipmentStatusList()
|
||||
{
|
||||
return ShipmentStatusList != null;
|
||||
}
|
||||
public bool IsSetShipmentIdList()
|
||||
{
|
||||
return ShipmentIdList != null;
|
||||
}
|
||||
public bool IsSetLastUpdatedAfter()
|
||||
{
|
||||
return LastUpdatedAfter != null;
|
||||
}
|
||||
public bool IsSetLastUpdatedBefore()
|
||||
{
|
||||
return LastUpdatedBefore != null;
|
||||
}
|
||||
|
||||
public List<Core.Model.AmazonFBAInbound.ShipmentInfo> GetShipmentInfo()
|
||||
{
|
||||
// variables
|
||||
int mwsPollFrequency = 500; // restore rate of two requests every second
|
||||
int mwsPollTimeout = 60;
|
||||
|
||||
// at least one search variable needs to be set (to make sure EVERYTHING isn't returned)
|
||||
if (!IsSetShipmentStatusList() && !IsSetShipmentIdList() && !IsSetLastUpdatedAfter() && !IsSetLastUpdatedBefore())
|
||||
{
|
||||
throw new Exception("No request variables have been set");
|
||||
}
|
||||
|
||||
// date checks
|
||||
if (IsSetLastUpdatedAfter() || IsSetLastUpdatedBefore())
|
||||
{
|
||||
if (!IsSetLastUpdatedAfter() || !IsSetLastUpdatedBefore())
|
||||
{
|
||||
throw new Exception("If LastUpdatedBefore or LastUpdatedAfter is specified then both parameters must be specified");
|
||||
}
|
||||
|
||||
// set date types
|
||||
DateTime.SpecifyKind(LastUpdatedAfter, DateTimeKind.Utc);
|
||||
DateTime.SpecifyKind(LastUpdatedBefore, DateTimeKind.Utc);
|
||||
|
||||
if (LastUpdatedBefore.ToUniversalTime() < LastUpdatedAfter.ToUniversalTime())
|
||||
{
|
||||
throw new Exception("Parameter LastUpdatedBefore must be less than LastUpdatedAfter");
|
||||
}
|
||||
}
|
||||
|
||||
// down to business, build the mws request
|
||||
var request = new ListInboundShipmentsRequest();
|
||||
|
||||
var cred = new AmazonMWS.CredentialMws();
|
||||
request.SellerId = cred.merchantId;
|
||||
|
||||
// add shipment status to request
|
||||
if (!IsSetShipmentStatusList() && !IsSetShipmentIdList())
|
||||
{
|
||||
// defaults values
|
||||
var statusList = new ShipmentStatusList();
|
||||
|
||||
statusList.member.Add("WORKING");
|
||||
statusList.member.Add("SHIPPED");
|
||||
statusList.member.Add("IN_TRANSIT");
|
||||
statusList.member.Add("DELIVERED");
|
||||
statusList.member.Add("CHECKED_IN");
|
||||
statusList.member.Add("RECEIVING");
|
||||
statusList.member.Add("CLOSED");
|
||||
statusList.member.Add("CANCELLED");
|
||||
statusList.member.Add("DELETED");
|
||||
statusList.member.Add("ERROR");
|
||||
|
||||
request.ShipmentStatusList = statusList;
|
||||
}
|
||||
else if (IsSetShipmentStatusList())
|
||||
{
|
||||
var statusList = new ShipmentStatusList();
|
||||
foreach (string item in ShipmentStatusList)
|
||||
{
|
||||
statusList.member.Add(item);
|
||||
}
|
||||
request.ShipmentStatusList = statusList;
|
||||
}
|
||||
|
||||
// add shipment Id list to request
|
||||
if (IsSetShipmentIdList())
|
||||
{
|
||||
var shipmentIdList = new ShipmentIdList();
|
||||
foreach (string item in ShipmentIdList)
|
||||
{
|
||||
shipmentIdList.member.Add(item);
|
||||
}
|
||||
request.ShipmentIdList = shipmentIdList;
|
||||
}
|
||||
|
||||
// add dates to request
|
||||
if (IsSetLastUpdatedAfter())
|
||||
{
|
||||
request.LastUpdatedAfter = LastUpdatedAfter.ToUniversalTime();
|
||||
request.LastUpdatedBefore = LastUpdatedBefore.ToUniversalTime();
|
||||
}
|
||||
|
||||
// get amazon service, responce and result
|
||||
var service = new AmazonMWS.Service().FbaInbound;
|
||||
var result = new ListInboundShipmentsResult();
|
||||
|
||||
// poll mws for response
|
||||
int count = 0;
|
||||
do
|
||||
{
|
||||
var response = service.ListInboundShipments(request);
|
||||
if (response.IsSetListInboundShipmentsResult())
|
||||
{
|
||||
result = response.ListInboundShipmentsResult;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(mwsPollFrequency);
|
||||
count++;
|
||||
}
|
||||
} while (count < mwsPollTimeout);
|
||||
if (count == mwsPollTimeout)
|
||||
{
|
||||
throw new Exception("Response from Amazon MWS timeout");
|
||||
}
|
||||
|
||||
// check a result was returned
|
||||
if (!result.IsSetShipmentData())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// add data list
|
||||
InboundShipmentList resultList = result.ShipmentData;
|
||||
var infoList = new List<InboundShipmentInfo>();
|
||||
infoList.AddRange(resultList.member);
|
||||
|
||||
// check for next dataset
|
||||
if (result.IsSetNextToken())
|
||||
{
|
||||
string nextToken = result.NextToken;
|
||||
do
|
||||
{
|
||||
var nextRequest = new ListInboundShipmentsByNextTokenRequest();
|
||||
var nextResult = new ListInboundShipmentsByNextTokenResult();
|
||||
nextRequest.NextToken = nextToken;
|
||||
nextRequest.SellerId = request.SellerId;
|
||||
|
||||
count = 0;
|
||||
do
|
||||
{
|
||||
var response = service.ListInboundShipmentsByNextToken(nextRequest);
|
||||
if (response.IsSetListInboundShipmentsByNextTokenResult())
|
||||
{
|
||||
nextResult = response.ListInboundShipmentsByNextTokenResult;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(mwsPollFrequency);
|
||||
count++;
|
||||
}
|
||||
} while (count < mwsPollTimeout);
|
||||
if (count == mwsPollTimeout)
|
||||
{
|
||||
throw new Exception("Response from Amazon MWS timeout");
|
||||
}
|
||||
|
||||
// add data to list
|
||||
InboundShipmentList nextResultList = nextResult.ShipmentData;
|
||||
infoList.AddRange(nextResultList.member);
|
||||
|
||||
if (nextResult.IsSetNextToken())
|
||||
{
|
||||
nextToken = nextResult.NextToken;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextToken = "";
|
||||
}
|
||||
} while (nextToken.Length > 0); // next token is true
|
||||
}
|
||||
|
||||
// build return value
|
||||
var returnItem = new List<Core.Model.AmazonFBAInbound.ShipmentInfo>();
|
||||
//var lastUpdated = infoList.
|
||||
foreach( InboundShipmentInfo item in infoList)
|
||||
{
|
||||
var listItem = new Core.Model.AmazonFBAInbound.ShipmentInfo();
|
||||
listItem.AmazonShipmentId = item.ShipmentId;
|
||||
listItem.DestinationFulfillmentCenterId = item.DestinationFulfillmentCenterId;
|
||||
listItem.ShipmentName = item.ShipmentName;
|
||||
listItem.ShipmentStatus = item.ShipmentStatus;
|
||||
|
||||
returnItem.Add(listItem);
|
||||
}
|
||||
|
||||
return returnItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/bnhtrade.Core/Data/AmazonMWS/Service.cs
Normal file
74
src/bnhtrade.Core/Data/AmazonMWS/Service.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
//using bnhtrade.Core.Data.AmazonMWS.FBAInbound;
|
||||
using FBAInboundServiceMWS;
|
||||
//using bnhtrade.Core.Data.AmazonMWS;
|
||||
using MarketplaceWebService;
|
||||
|
||||
namespace bnhtrade.Core.Data.AmazonMWS
|
||||
{
|
||||
public class Service : CredentialMws
|
||||
{
|
||||
private string merchantId;
|
||||
private string marketplaceId; // Amazon.co.uk
|
||||
private string accessKeyId;
|
||||
private string secretAccessKey;
|
||||
private string applicationName;
|
||||
private string applicationVersion;
|
||||
private string serviceURL;
|
||||
|
||||
// class constructor
|
||||
public Service()
|
||||
{
|
||||
var cred = new AmazonMWS.CredentialMws();
|
||||
|
||||
this.merchantId = cred.merchantId;
|
||||
this.marketplaceId = cred.marketPlaceId;
|
||||
this.accessKeyId = cred.accessKeyId;
|
||||
this.secretAccessKey = cred.secretAccessKey;
|
||||
this.applicationName = cred.applicationName;
|
||||
this.applicationVersion = cred.applicationVersion;
|
||||
this.serviceURL = cred.serviceURL;
|
||||
}
|
||||
|
||||
public MarketplaceWebService.MarketplaceWebService MarketPlaceWeb
|
||||
|
||||
{
|
||||
get
|
||||
{
|
||||
MarketplaceWebServiceConfig config = new MarketplaceWebServiceConfig();
|
||||
config.ServiceURL = serviceURL;
|
||||
|
||||
MarketplaceWebService.MarketplaceWebService service = new MarketplaceWebServiceClient(
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
applicationName,
|
||||
applicationVersion,
|
||||
config);
|
||||
|
||||
return service;
|
||||
}
|
||||
}
|
||||
|
||||
public global::FBAInboundServiceMWS.FBAInboundServiceMWS FbaInbound
|
||||
{
|
||||
get
|
||||
{
|
||||
FBAInboundServiceMWSConfig config = new FBAInboundServiceMWSConfig();
|
||||
config.ServiceURL = serviceURL;
|
||||
|
||||
global::FBAInboundServiceMWS.FBAInboundServiceMWS service = new FBAInboundServiceMWSClient(
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
applicationName,
|
||||
applicationVersion,
|
||||
config);
|
||||
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/bnhtrade.Core/Data/Database/Connection.cs
Normal file
20
src/bnhtrade.Core/Data/Database/Connection.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Database
|
||||
{
|
||||
public class Connection
|
||||
{
|
||||
protected readonly string sqlConnectionString;
|
||||
public Connection(string sqlConnectionString)
|
||||
{
|
||||
// setup sql parameters
|
||||
if (sqlConnectionString.Length == 0)
|
||||
{ throw new Exception("Zero length sql connectionstring passed"); }
|
||||
this.sqlConnectionString = sqlConnectionString;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Database.FBAInbound
|
||||
{
|
||||
public class GetShipmentHeaderInfo : Connection
|
||||
{
|
||||
private List<string> shipmentIdList;
|
||||
public GetShipmentHeaderInfo(string sqlConnectionString) : base(sqlConnectionString) { }
|
||||
/// <summary>
|
||||
/// Return active shipments only. Default is false.
|
||||
/// </summary>
|
||||
public bool ActiveShipments { get; set; } = false;
|
||||
public bool IsSetActiveShipments { get { return true; } }
|
||||
public bool IsSetShipmentIdList
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ShipmentIdList == null || !ShipmentIdList.Any()) { return false; }
|
||||
else { return true; }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Filter results by Amazon's shipment Id.
|
||||
/// </summary>
|
||||
public List<string> ShipmentIdList
|
||||
{
|
||||
get { return shipmentIdList; }
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
// clean list
|
||||
shipmentIdList = new List<string>();
|
||||
foreach (string item in value)
|
||||
{
|
||||
if (item.Length > 0)
|
||||
{
|
||||
shipmentIdList.Add(item);
|
||||
}
|
||||
}
|
||||
if (!ShipmentIdList.Any())
|
||||
{
|
||||
shipmentIdList = null;
|
||||
throw new Exception("Invalid shipment Id set");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
|
||||
/// </summary>
|
||||
/// <param name="amazonShipmentId">Amazon's inbound FBA shipment Id.</param>
|
||||
/// <returns>Primary key or -1 if match isn't found.</returns>
|
||||
public List<Model.AmazonFBAInbound.ShipmentInfo> Execute()
|
||||
{
|
||||
// build the sql string
|
||||
int countShipId = 0;
|
||||
string sqlString = @"
|
||||
SELECT
|
||||
AmazonShipmentID
|
||||
,ShipmentName
|
||||
,ShipmentId
|
||||
,CenterId
|
||||
,ShipmentStatus
|
||||
,LastUpdated
|
||||
,IsClosed
|
||||
FROM
|
||||
tblAmazonShipment
|
||||
WHERE
|
||||
1 = 1";
|
||||
if (ActiveShipments)
|
||||
{
|
||||
sqlString = sqlString + @"
|
||||
AND IsClosed = 0";
|
||||
}
|
||||
var dicShipIdByParameterString = new Dictionary<string, string>();
|
||||
if (IsSetShipmentIdList)
|
||||
{
|
||||
foreach (string item in ShipmentIdList)
|
||||
{
|
||||
countShipId = countShipId + 1;
|
||||
string parameterString = "@shipmentId" + countShipId.ToString().PadLeft(6, '0');
|
||||
dicShipIdByParameterString.Add(parameterString, item);
|
||||
if (countShipId == 1)
|
||||
{
|
||||
sqlString = sqlString + @"
|
||||
AND ( ShipmentId = " + parameterString;
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlString = sqlString + @"
|
||||
OR ShipmentId = " + parameterString;
|
||||
}
|
||||
}
|
||||
if (countShipId > 0)
|
||||
{
|
||||
sqlString = sqlString + " )";
|
||||
}
|
||||
}
|
||||
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
using (SqlCommand cmd = new SqlCommand(sqlString, conn))
|
||||
{
|
||||
// add shipId parameters
|
||||
if (ShipmentIdList.Any())
|
||||
{
|
||||
foreach (var item in dicShipIdByParameterString)
|
||||
{
|
||||
cmd.Parameters.AddWithValue(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
if (!reader.HasRows)
|
||||
{
|
||||
// no records
|
||||
return null;
|
||||
}
|
||||
|
||||
var infoList = new List<Model.AmazonFBAInbound.ShipmentInfo>();
|
||||
while (reader.Read())
|
||||
{
|
||||
var info = new Model.AmazonFBAInbound.ShipmentInfo();
|
||||
|
||||
int tablePK = reader.GetInt32(0);
|
||||
info.ShipmentName = reader.GetString(1);
|
||||
info.AmazonShipmentId = reader.GetString(2);
|
||||
info.DestinationFulfillmentCenterId = reader.GetString(3);
|
||||
info.ShipmentStatus = reader.GetString(4);
|
||||
info.LastUpdatedUtc = reader.GetDateTime(5);
|
||||
bool dbIsClosed = reader.GetBoolean(6);
|
||||
|
||||
// db consistancy check
|
||||
if (dbIsClosed != info.ShipmentIsClosed)
|
||||
{
|
||||
throw new Exception("Data inconstitancy in database: check shipment IsClosed where AmazonShipmentID=" + tablePK);
|
||||
}
|
||||
|
||||
// update cache
|
||||
infoList.Add(info);
|
||||
}
|
||||
return infoList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace bnhtrade.Core.Data.Database.FBAInbound
|
||||
{
|
||||
public class GetShipmentPrimaryKey : Connection
|
||||
{
|
||||
private bool enableCache = false;
|
||||
private Dictionary<string, int> shipmentPKByAmazonShipmentIdDic;
|
||||
private Dictionary<int, string> amazonShipmentIdByShipmentPKDic;
|
||||
public GetShipmentPrimaryKey(string sqlConnectionString) : base(sqlConnectionString) { }
|
||||
public bool CacheEnabled
|
||||
{
|
||||
get { return enableCache; }
|
||||
set
|
||||
{
|
||||
if (value && enableCache == false)
|
||||
{
|
||||
shipmentPKByAmazonShipmentIdDic = new Dictionary<string, int>();
|
||||
amazonShipmentIdByShipmentPKDic = new Dictionary<int, string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
shipmentPKByAmazonShipmentIdDic = null;
|
||||
amazonShipmentIdByShipmentPKDic = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void ClearCache()
|
||||
{
|
||||
if (CacheEnabled)
|
||||
{
|
||||
shipmentPKByAmazonShipmentIdDic.Clear();
|
||||
amazonShipmentIdByShipmentPKDic.Clear();
|
||||
}
|
||||
}
|
||||
private void DeleteCachedShipmentPK(int shipmentPrimaryKey)
|
||||
{
|
||||
if (CacheEnabled)
|
||||
{
|
||||
if (amazonShipmentIdByShipmentPKDic.ContainsKey(shipmentPrimaryKey))
|
||||
{
|
||||
string amazonShipmentId = amazonShipmentIdByShipmentPKDic[shipmentPrimaryKey];
|
||||
shipmentPKByAmazonShipmentIdDic.Remove(amazonShipmentId);
|
||||
amazonShipmentIdByShipmentPKDic.Remove(shipmentPrimaryKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Retrives table primary key 'AmazonShipmentID' for tblAmazonShipment
|
||||
/// </summary>
|
||||
/// <param name="amazonShipmentId">Amazon's inbound FBA shipment Id.</param>
|
||||
/// <param name="forceDBQuery">Forces a database query when cache is enabled.</param>
|
||||
/// <returns>Primary key or -1 if match isn't found.</returns>
|
||||
public int ByAmazonShipmentId(string amazonShipmentId, bool forceDBQuery = false)
|
||||
{
|
||||
if (amazonShipmentId.Length < 5)
|
||||
{
|
||||
throw new Exception("Incorrect Amazon shipment if supplied '" + amazonShipmentId + "'");
|
||||
}
|
||||
|
||||
// first, query class dictionary before sql call
|
||||
if (CacheEnabled
|
||||
&& forceDBQuery == false
|
||||
&& shipmentPKByAmazonShipmentIdDic.ContainsKey(amazonShipmentId))
|
||||
{
|
||||
return shipmentPKByAmazonShipmentIdDic[amazonShipmentId];
|
||||
}
|
||||
|
||||
int shipmentPK = -1;
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
SELECT AmazonShipmentID
|
||||
FROM tblAmazonShipment
|
||||
WHERE (((tblAmazonShipment.ShipmentId)=@amazonShipmentId));
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@amazonShipmentId", amazonShipmentId);
|
||||
|
||||
object obj = cmd.ExecuteScalar();
|
||||
|
||||
if (obj == null || obj == DBNull.Value)
|
||||
{
|
||||
return shipmentPK;
|
||||
}
|
||||
else
|
||||
{
|
||||
shipmentPK = (int)obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateCache(shipmentPK, amazonShipmentId);
|
||||
return shipmentPK;
|
||||
}
|
||||
private void UpdateCache(int shipmentPK, string amazonShipmentId)
|
||||
{
|
||||
if (CacheEnabled)
|
||||
{
|
||||
DeleteCachedShipmentPK(shipmentPK);
|
||||
|
||||
shipmentPKByAmazonShipmentIdDic.Add(amazonShipmentId, shipmentPK);
|
||||
amazonShipmentIdByShipmentPKDic.Add(shipmentPK, amazonShipmentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
246
src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs
Normal file
246
src/bnhtrade.Core/Data/Database/FBAInbound/SetShipmentInfo.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Transactions;
|
||||
|
||||
namespace bnhtrade.Core.Data.Database.FBAInbound
|
||||
{
|
||||
public class SetShipmentInfo : Connection
|
||||
{
|
||||
private GetShipmentPrimaryKey getPK;
|
||||
private Data.Database.SKU.GetSKUId skuIdLoopkup;
|
||||
public SetShipmentInfo(string sqlConnectionString) : base(sqlConnectionString) { }
|
||||
private GetShipmentPrimaryKey GetPK
|
||||
{
|
||||
get
|
||||
{
|
||||
if (getPK == null)
|
||||
{
|
||||
getPK = new GetShipmentPrimaryKey(sqlConnectionString);
|
||||
}
|
||||
return getPK;
|
||||
}
|
||||
set
|
||||
{
|
||||
getPK = value;
|
||||
}
|
||||
}
|
||||
private Data.Database.SKU.GetSKUId SkuIdLoopkup
|
||||
{
|
||||
get
|
||||
{
|
||||
if (skuIdLoopkup == null)
|
||||
{
|
||||
skuIdLoopkup = new SKU.GetSKUId(sqlConnectionString);
|
||||
}
|
||||
return skuIdLoopkup;
|
||||
}
|
||||
}
|
||||
public void Excecute(Model.AmazonFBAInbound.ShipmentInfo info)
|
||||
{
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
// input checks
|
||||
if (!info.IsSetAll())
|
||||
{
|
||||
throw new Exception("Insurficent ShipmentInfo parameters.");
|
||||
}
|
||||
|
||||
// get tablePK
|
||||
int shipmentPK = GetPK.ByAmazonShipmentId(info.AmazonShipmentId);
|
||||
|
||||
// add or update shipment header info
|
||||
if (shipmentPK == -1)
|
||||
{
|
||||
shipmentPK = InsertShipmentHeaderInfo(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateShipmentHeaderInfo(info);
|
||||
DeleteShipmentItems(shipmentPK);
|
||||
}
|
||||
|
||||
// insert new shipment item info
|
||||
foreach (var item in info.ShipmentItemInfoList)
|
||||
{
|
||||
int skuId = SkuIdLoopkup.BySKUNumber(item.SKUNumber);
|
||||
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
INSERT INTO tblAmazonShipmentItem (
|
||||
AmazonShipmentID
|
||||
,SkuID
|
||||
,QuantityAllocated
|
||||
,QuantityReceived
|
||||
)
|
||||
VALUES (
|
||||
@amazonShipmentID
|
||||
,@skuID
|
||||
,@quantityAllocated
|
||||
,@quantityReceived
|
||||
)
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@amazonShipmentID", shipmentPK);
|
||||
cmd.Parameters.AddWithValue("@skuID", skuId);
|
||||
cmd.Parameters.AddWithValue("@quantityAllocated", item.QuantityAllocated);
|
||||
cmd.Parameters.AddWithValue("@quantityReceived", item.QuantityReceived);
|
||||
|
||||
int effected = (int)cmd.ExecuteNonQuery();
|
||||
|
||||
if (effected == 0)
|
||||
{
|
||||
throw new Exception("Error, no tblAmazonShipment was not updated.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
public void ExcecuteByList(List<Model.AmazonFBAInbound.ShipmentInfo> infoList)
|
||||
{
|
||||
using (var scope = new TransactionScope())
|
||||
{
|
||||
foreach (var item in infoList)
|
||||
{
|
||||
Excecute(item);
|
||||
}
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteShipmentItems(int shipmentId)
|
||||
{
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
DELETE FROM
|
||||
tblAmazonShipmentItem
|
||||
WHERE
|
||||
AmazonShipmentId = @shipmentId
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@shipmentId", shipmentId);
|
||||
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int InsertShipmentHeaderInfo(Model.AmazonFBAInbound.ShipmentInfo info)
|
||||
{
|
||||
if (!info.IsSetAll())
|
||||
{
|
||||
throw new Exception("Unsuficent properties set in Shipment Header Info.");
|
||||
}
|
||||
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
if (GetPK.ByAmazonShipmentId(info.AmazonShipmentId) != -1)
|
||||
{
|
||||
throw new Exception("Shipment insert failed, shipment with same Amazon Id already exists.");
|
||||
}
|
||||
|
||||
// get next shipment Number in sequence and create shipment name
|
||||
int sequenceNumber;
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
SELECT NEXT VALUE FOR dbo.ShipmentCountSequence AS SequenceNumber
|
||||
", conn))
|
||||
{
|
||||
sequenceNumber = (int)cmd.ExecuteScalar();
|
||||
}
|
||||
// info.ShipmentName = "FBA_Shipment_" + sequenceNumber.ToString().PadLeft(4, '0') + "_" + info.DestinationFulfillmentCenterId;
|
||||
|
||||
// make the insert
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
INSERT INTO tblAmazonShipment (
|
||||
AmazonShipmentCount
|
||||
,ShipmentName
|
||||
,ShipmentId
|
||||
,CenterId
|
||||
,ShipmentStatus
|
||||
,LastUpdated
|
||||
,IsClosed
|
||||
)
|
||||
OUTPUT INSERTED.AmazonShipmentID
|
||||
VALUES (
|
||||
@amazonShipmentCount
|
||||
,@shipmentName
|
||||
,@shipmentId
|
||||
,@centerId
|
||||
,@shipmentStatus
|
||||
,@lastUpdated
|
||||
,@isClosed
|
||||
)
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@amazonShipmentCount", sequenceNumber);
|
||||
cmd.Parameters.AddWithValue("@shipmentName", info.ShipmentName);
|
||||
cmd.Parameters.AddWithValue("@shipmentId", info.AmazonShipmentId);
|
||||
cmd.Parameters.AddWithValue("@centerId", info.DestinationFulfillmentCenterId);
|
||||
cmd.Parameters.AddWithValue("@shipmentStatus", info.ShipmentStatus);
|
||||
cmd.Parameters.AddWithValue("@lastUpdated", info.LastUpdatedUtc);
|
||||
cmd.Parameters.AddWithValue("@isClosed", info.ShipmentIsClosed);
|
||||
|
||||
int tablePk = (int)cmd.ExecuteScalar();
|
||||
|
||||
// update cache and return
|
||||
return tablePk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateShipmentHeaderInfo(Model.AmazonFBAInbound.ShipmentInfo info)
|
||||
{
|
||||
int tablePK = GetPK.ByAmazonShipmentId(info.AmazonShipmentId);
|
||||
if (tablePK == -1)
|
||||
{
|
||||
throw new Exception("Shipment insert failed, shipment with same Amazon Id already exists.");
|
||||
}
|
||||
|
||||
// make the update
|
||||
using (SqlConnection conn = new SqlConnection(sqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
UPDATE tblAmazonShipment
|
||||
SET
|
||||
ShipmentName = @shipmentName
|
||||
,ShipmentStatus = @shipmentStatus
|
||||
,LastUpdated = @lastUpdated
|
||||
,IsClosed = @isClosed
|
||||
WHERE
|
||||
AmazonShipmentID = @tablePK
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@shipmentName", info.ShipmentName);
|
||||
cmd.Parameters.AddWithValue("@shipmentStatus", info.ShipmentStatus);
|
||||
cmd.Parameters.AddWithValue("@lastUpdated", info.LastUpdatedUtc);
|
||||
cmd.Parameters.AddWithValue("@isClosed", info.ShipmentIsClosed);
|
||||
cmd.Parameters.AddWithValue("@tablePK", tablePK);
|
||||
|
||||
int count = cmd.ExecuteNonQuery();
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
throw new Exception("No records updated");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs
Normal file
100
src/bnhtrade.Core/Data/Database/SKU/GetSKUId.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace bnhtrade.Core.Data.Database.SKU
|
||||
{
|
||||
public class GetSKUId
|
||||
{
|
||||
private Dictionary<string, int> SKUIdBySKUNumber { get; set; }
|
||||
private Dictionary<int, string> SKUNumberBySKUId { get; set; }
|
||||
private string SqlConnectionString { get; set; }
|
||||
public GetSKUId(string sqlConnectionString)
|
||||
{
|
||||
// setup sql parameters
|
||||
if (sqlConnectionString.Length == 0)
|
||||
{
|
||||
throw new Exception("Zero length sql connectionstring passed");
|
||||
}
|
||||
SqlConnectionString = sqlConnectionString;
|
||||
|
||||
// set paramters
|
||||
SKUIdBySKUNumber = new Dictionary<string, int>();
|
||||
SKUNumberBySKUId = new Dictionary<int, string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get SKUId by SKU number.
|
||||
/// </summary>
|
||||
/// <param name="skuNumber">SKU Number to lookup Id</param>
|
||||
/// <param name="enableLegacy">If SKUId is can not be retrived, function will attempt to lookup value by sku count.</param>
|
||||
/// <param name="forceRequery">Results are chached, option forces database requery.</param>
|
||||
/// <returns>Database SKUId or Exception if not found.</returns>
|
||||
public int BySKUNumber(string skuNumber, bool enableLegacy = false, bool forceRequery = false)
|
||||
{
|
||||
if (forceRequery == false && SKUIdBySKUNumber.ContainsKey(skuNumber))
|
||||
{
|
||||
return SKUIdBySKUNumber[skuNumber];
|
||||
}
|
||||
|
||||
int skuId = 0;
|
||||
using (SqlConnection conn = new SqlConnection(SqlConnectionString))
|
||||
{
|
||||
conn.Open();
|
||||
using (SqlCommand cmd = new SqlCommand(@"
|
||||
SELECT skuSkuID
|
||||
FROM tblSku
|
||||
WHERE skuSkuNumber=@skuNumber;
|
||||
", conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@skuNumber", skuNumber);
|
||||
|
||||
object obj = cmd.ExecuteScalar();
|
||||
if (!(obj == null) || !(obj == DBNull.Value))
|
||||
{
|
||||
skuId = Convert.ToInt32(obj);
|
||||
}
|
||||
}
|
||||
// if that didn't work, lookup buy sku count
|
||||
if (skuId == 0 && skuNumber.Length == 6 && enableLegacy == true)
|
||||
{
|
||||
int skucount;
|
||||
bool okay = int.TryParse(skuNumber, 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) || !(obj == DBNull.Value))
|
||||
{
|
||||
skuId = Convert.ToInt32(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update cache
|
||||
if (skuId > 0)
|
||||
{
|
||||
if (SKUIdBySKUNumber.ContainsKey(skuNumber))
|
||||
{ SKUIdBySKUNumber.Remove(skuNumber); }
|
||||
SKUIdBySKUNumber.Add(skuNumber, skuId);
|
||||
|
||||
if (SKUNumberBySKUId.ContainsKey(skuId))
|
||||
{ SKUNumberBySKUId.Remove(skuId); }
|
||||
SKUNumberBySKUId.Add(skuId, skuNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unable to retrive an SkuID for SKU#" + skuNumber);
|
||||
}
|
||||
|
||||
return skuId;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user