This commit is contained in:
@@ -352,7 +352,8 @@ namespace Sockeye.Biz
|
||||
#if (DEBUG)
|
||||
//Test dev stuff
|
||||
#warning DEV TEST ORDER PROCESSING REMOVE THIS WHEN DONE
|
||||
await SockBotProcessVendorNotifications.ParseVendorNotificationData(vn, ct, log);
|
||||
if (!string.IsNullOrWhiteSpace(vn.VendorData))
|
||||
await SockBotProcessVendorNotifications.ParseVendorNotificationData(vn, ct, log);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -793,7 +794,7 @@ namespace Sockeye.Biz
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
}//eoc
|
||||
|
||||
@@ -51,7 +51,6 @@ namespace Sockeye.Biz
|
||||
|
||||
//get a list of all actionable vendor notifications
|
||||
var vnList = await ct.VendorNotification
|
||||
.AsNoTracking()
|
||||
.Where(z => z.Processed == null)
|
||||
.OrderBy(z => z.Id)
|
||||
.ToListAsync();
|
||||
@@ -60,8 +59,7 @@ namespace Sockeye.Biz
|
||||
{
|
||||
foreach (var vn in vnList)
|
||||
{
|
||||
var biz = PurchaseBiz.GetBiz(ct);
|
||||
var p = new Purchase();
|
||||
|
||||
|
||||
log.LogDebug($"Processing vendor notification {vn.Id}-{vn.Created}");
|
||||
|
||||
@@ -73,15 +71,9 @@ namespace Sockeye.Biz
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Parse json vendordata
|
||||
await ParseVendorNotificationData(vn, ct, log);
|
||||
|
||||
//save changes
|
||||
p.Processed = true;
|
||||
await biz.PutAsync(p);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -97,14 +89,17 @@ namespace Sockeye.Biz
|
||||
|
||||
|
||||
|
||||
internal static async Task ParseVendorNotificationData(VendorNotification vn, AyContext ct, ILogger log)
|
||||
internal static async Task<bool> ParseVendorNotificationData(VendorNotification vn, AyContext ct, ILogger log)
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(vn.VendorData)) return;
|
||||
|
||||
try
|
||||
{
|
||||
var jData = JObject.Parse(vn.VendorData);
|
||||
//It's a test purchase, no need to process it any further...or is there??
|
||||
if (jData["order_notification"]["purchase"]["is_test"].Value<bool>() == true)
|
||||
{
|
||||
vn.Processed = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
//fundamentally validate the object is a purchase notification
|
||||
if (jData["order_notification"]["purchase"]["purchase_id"] == null)
|
||||
@@ -113,7 +108,11 @@ namespace Sockeye.Biz
|
||||
throw new System.FormatException($"Vendor data unexpected format:{vn.VendorData}");
|
||||
}
|
||||
|
||||
//CUSTOMER create or locate
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
#region CUSTOMER MAKE OR LOCATED
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
var jCustomerName = jData["order_notification"]["purchase"]["customer_data"]["reg_name"].Value<string>() ?? throw new System.FormatException($"Vendor data empty reg_name:{vn.VendorData}");
|
||||
var jCustomerEmail = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["email"].Value<string>() ?? throw new System.FormatException($"Vendor data empty email:{vn.VendorData}");
|
||||
var jCustomerAccountNumber = jData["order_notification"]["purchase"]["customer_data"]["shopper_id"].Value<string>();//appears to be mycommerce customer id number hopefully static between orders
|
||||
@@ -122,17 +121,17 @@ namespace Sockeye.Biz
|
||||
|
||||
//attempt to match to existing customer
|
||||
//account number is most ideal match, name second but could be multiple in sockeye from rockfish sites so name will start the same, finally email if nothing else
|
||||
Customer c = await ct.Customer.FirstOrDefaultAsync(z => z.AccountNumber == jCustomerAccountNumber) ?? await ct.Customer.FirstOrDefaultAsync(z => z.Name.StartsWith(jCustomerName)) ?? await ct.Customer.FirstOrDefaultAsync(z => z.EmailAddress == jCustomerEmail);
|
||||
if (c == null)
|
||||
Customer customer = await ct.Customer.FirstOrDefaultAsync(z => z.AccountNumber == jCustomerAccountNumber) ?? await ct.Customer.FirstOrDefaultAsync(z => z.Name.StartsWith(jCustomerName)) ?? await ct.Customer.FirstOrDefaultAsync(z => z.EmailAddress == jCustomerEmail);
|
||||
if (customer == null)
|
||||
{
|
||||
//New customer
|
||||
c = new Customer();
|
||||
c.Name = jCustomerName;
|
||||
c.EmailAddress = jCustomerEmail;
|
||||
c.AccountNumber = jCustomerAccountNumber;
|
||||
UpdateCustomerFromVendorData(jData, c);
|
||||
c = await customerBiz.CreateAsync(c);
|
||||
if (c == null)
|
||||
customer = new Customer();
|
||||
customer.Name = jCustomerName;
|
||||
customer.EmailAddress = jCustomerEmail;
|
||||
customer.AccountNumber = jCustomerAccountNumber;
|
||||
UpdateCustomerFromVendorData(jData, customer);
|
||||
customer = await customerBiz.CreateAsync(customer);
|
||||
if (customer == null)
|
||||
throw new System.ApplicationException($"Error creating new Customer: {customerBiz.GetErrorsAsString()} vendor data :{vn.VendorData}");
|
||||
}
|
||||
else
|
||||
@@ -143,47 +142,90 @@ namespace Sockeye.Biz
|
||||
//email differs, this can happen and is ok
|
||||
//account number differs if was empty then it's ok. If it wasn't empty and it differs this is a potential problem:
|
||||
//
|
||||
if (c.EmailAddress != jCustomerEmail)
|
||||
if (customer.EmailAddress != jCustomerEmail)
|
||||
{
|
||||
c.EmailAddress = jCustomerEmail;//assume it was empty or has been recently updated
|
||||
customer.EmailAddress = jCustomerEmail;//assume it was empty or has been recently updated
|
||||
}
|
||||
|
||||
if (c.AccountNumber != jCustomerAccountNumber)
|
||||
|
||||
if (customer.AccountNumber != jCustomerAccountNumber)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(c.AccountNumber))
|
||||
c.AccountNumber=jCustomerAccountNumber;//this is ok, there wasn't an account number before so we're just adding it
|
||||
else{
|
||||
if (string.IsNullOrWhiteSpace(customer.AccountNumber))
|
||||
customer.AccountNumber = jCustomerAccountNumber;//this is ok, there wasn't an account number before so we're just adding it
|
||||
else
|
||||
{
|
||||
// this is problematic, it matched but for some reason the account numbers differ, there's no safe way to process this so alert and bail
|
||||
throw new System.ApplicationException($"Not processed due to error updating existing Customer: {c.Name} Account numbers differ, expected: {c.AccountNumber} vendor data:{vn.VendorData}");
|
||||
}
|
||||
throw new System.ApplicationException($"Not processed due to error updating existing Customer: {customer.Name} Account numbers differ, expected: {customer.AccountNumber} vendor data:{vn.VendorData}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//refresh
|
||||
UpdateCustomerFromVendorData(jData, c);
|
||||
c = await customerBiz.PutAsync(c);
|
||||
if (c == null)
|
||||
UpdateCustomerFromVendorData(jData, customer);
|
||||
customer = await customerBiz.PutAsync(customer);
|
||||
if (customer == null)
|
||||
throw new System.ApplicationException($"Error updating existing Customer: {customerBiz.GetErrorsAsString()} vendor data :{vn.VendorData}");
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
#endregion customer make or locate
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
#region MAKE PURCHASE RECORD
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var salesOrderNumber = jData["order_notification"]["purchase"]["purchase_id"].Value<string>();
|
||||
|
||||
if (await ct.Purchase.AnyAsync(z => z.SalesOrderNumber == salesOrderNumber))
|
||||
throw new System.ApplicationException($"Sales order already exists: {salesOrderNumber} will not be processed");
|
||||
|
||||
//ok, turn this into a fully realized Purchase record
|
||||
//iterate purchase items array
|
||||
var jaPurchaseList = (JArray)jData["order_notification"]["purchase"]["purchase_item"];
|
||||
|
||||
//Product group
|
||||
p.PGroup = ProductBiz.ProductGroupFromProductCode(p.OurCode);
|
||||
foreach (JObject jPurchase in jaPurchaseList)
|
||||
{
|
||||
Purchase p = new Purchase();
|
||||
p.CustomerId = customer.Id;
|
||||
p.VendorId = vn.VendorId;
|
||||
p.Notes = vn.VendorData;//redundantly keep it
|
||||
p.SalesOrderNumber = salesOrderNumber;
|
||||
p.Currency = jPurchase["currency"].Value<string>();
|
||||
var pId = jPurchase["product_id"].Value<string>();
|
||||
var product = await ct.Product.AsNoTracking().FirstOrDefaultAsync(z => z.VendorCode == pId) ?? throw new System.ArgumentOutOfRangeException($"Vendor product code:{pId} was not found in Sockeye Products, record not processed");
|
||||
p.ProductId = product.Id;
|
||||
p.PGroup = product.PGroup;
|
||||
p.
|
||||
|
||||
if (p.ProductId == 0)
|
||||
|
||||
switch (p.PGroup)
|
||||
{
|
||||
case ProductGroup.Misc:
|
||||
//not a licensed product, probably misc custom or some fee or etc
|
||||
p.Processed = true;//flag no further processing is required
|
||||
break;
|
||||
case ProductGroup.AyaNova7:
|
||||
|
||||
break;
|
||||
case ProductGroup.RavenPerpetual:
|
||||
|
||||
break;
|
||||
case ProductGroup.RavenSubscription:
|
||||
|
||||
break;
|
||||
default://not set or unrecognized
|
||||
throw new System.NotSupportedException($"Product group {p.PGroup} not recognized or supported for processing into purchase");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
#endregion make purchase record
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var err = $"ParseVendorNotificationData: Purchase record {vn.Id}-{vn.Created} triggered exception, see log";
|
||||
await NotifyEventHelper.AddOpsProblemEvent(err);//notify, this is serious
|
||||
log.LogError(ex, err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user