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)
//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

View File

@@ -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;
}
}