This commit is contained in:
2023-01-23 18:46:40 +00:00
parent 114ac25292
commit 176f31c591
2 changed files with 83 additions and 40 deletions

View File

@@ -352,7 +352,8 @@ namespace Sockeye.Biz
#if (DEBUG) #if (DEBUG)
//Test dev stuff //Test dev stuff
#warning DEV TEST ORDER PROCESSING REMOVE THIS WHEN DONE #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 #endif

View File

@@ -51,7 +51,6 @@ namespace Sockeye.Biz
//get a list of all actionable vendor notifications //get a list of all actionable vendor notifications
var vnList = await ct.VendorNotification var vnList = await ct.VendorNotification
.AsNoTracking()
.Where(z => z.Processed == null) .Where(z => z.Processed == null)
.OrderBy(z => z.Id) .OrderBy(z => z.Id)
.ToListAsync(); .ToListAsync();
@@ -60,8 +59,7 @@ namespace Sockeye.Biz
{ {
foreach (var vn in vnList) foreach (var vn in vnList)
{ {
var biz = PurchaseBiz.GetBiz(ct);
var p = new Purchase();
log.LogDebug($"Processing vendor notification {vn.Id}-{vn.Created}"); log.LogDebug($"Processing vendor notification {vn.Id}-{vn.Created}");
@@ -73,15 +71,9 @@ namespace Sockeye.Biz
continue; continue;
} }
//Parse json vendordata //Parse json vendordata
await ParseVendorNotificationData(vn, ct, log); await ParseVendorNotificationData(vn, ct, log);
//save changes
p.Processed = true;
await biz.PutAsync(p);
} }
} }
catch (Exception ex) 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 try
{ {
var jData = JObject.Parse(vn.VendorData); 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 //fundamentally validate the object is a purchase notification
if (jData["order_notification"]["purchase"]["purchase_id"] == null) 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}"); 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 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 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 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 //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 //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); 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 (c == null) if (customer == null)
{ {
//New customer //New customer
c = new Customer(); customer = new Customer();
c.Name = jCustomerName; customer.Name = jCustomerName;
c.EmailAddress = jCustomerEmail; customer.EmailAddress = jCustomerEmail;
c.AccountNumber = jCustomerAccountNumber; customer.AccountNumber = jCustomerAccountNumber;
UpdateCustomerFromVendorData(jData, c); UpdateCustomerFromVendorData(jData, customer);
c = await customerBiz.CreateAsync(c); customer = await customerBiz.CreateAsync(customer);
if (c == null) if (customer == null)
throw new System.ApplicationException($"Error creating new Customer: {customerBiz.GetErrorsAsString()} vendor data :{vn.VendorData}"); throw new System.ApplicationException($"Error creating new Customer: {customerBiz.GetErrorsAsString()} vendor data :{vn.VendorData}");
} }
else else
@@ -143,47 +142,90 @@ namespace Sockeye.Biz
//email differs, this can happen and is ok //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: //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)) if (string.IsNullOrWhiteSpace(customer.AccountNumber))
c.AccountNumber=jCustomerAccountNumber;//this is ok, there wasn't an account number before so we're just adding it customer.AccountNumber = jCustomerAccountNumber;//this is ok, there wasn't an account number before so we're just adding it
else{ 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 // 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 //refresh
UpdateCustomerFromVendorData(jData, c); UpdateCustomerFromVendorData(jData, customer);
c = await customerBiz.PutAsync(c); customer = await customerBiz.PutAsync(customer);
if (c == null) if (customer == null)
throw new System.ApplicationException($"Error updating existing Customer: {customerBiz.GetErrorsAsString()} vendor data :{vn.VendorData}"); 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>(); var salesOrderNumber = jData["order_notification"]["purchase"]["purchase_id"].Value<string>();
if (await ct.Purchase.AnyAsync(z => z.SalesOrderNumber == salesOrderNumber)) if (await ct.Purchase.AnyAsync(z => z.SalesOrderNumber == salesOrderNumber))
throw new System.ApplicationException($"Sales order already exists: {salesOrderNumber} will not be processed"); 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 foreach (JObject jPurchase in jaPurchaseList)
p.PGroup = ProductBiz.ProductGroupFromProductCode(p.OurCode); {
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) catch (Exception ex)
{ {
var err = $"ParseVendorNotificationData: Purchase record {vn.Id}-{vn.Created} triggered exception, see log"; var err = $"ParseVendorNotificationData: Purchase record {vn.Id}-{vn.Created} triggered exception, see log";
await NotifyEventHelper.AddOpsProblemEvent(err);//notify, this is serious await NotifyEventHelper.AddOpsProblemEvent(err);//notify, this is serious
log.LogError(ex, err); log.LogError(ex, err);
return false;
} }
} }