This commit is contained in:
2023-01-23 01:45:03 +00:00
parent ec6ec2701e
commit 040d8ca836
2 changed files with 62 additions and 50 deletions

View File

@@ -195,7 +195,10 @@ namespace Sockeye.Biz
{ {
var CustomerName = jCustomer["name"].Value<string>(); var CustomerName = jCustomer["name"].Value<string>();
if (multiSite) if (multiSite)
{
CustomerName += " - " + jSite["name"].Value<string>(); CustomerName += " - " + jSite["name"].Value<string>();
log.LogInformation($"RFImport MULTISITE CUSTOMER: {CustomerName}");
}
long CurrentCustomerId = 0; long CurrentCustomerId = 0;
//Create customer if we don't have one already //Create customer if we don't have one already
@@ -222,9 +225,12 @@ namespace Sockeye.Biz
if (jSite["hosted"].Value<bool>() == true) if (jSite["hosted"].Value<bool>() == true)
c.Tags.Add("hosted"); c.Tags.Add("hosted");
var adminEmail = jCustomer["adminEmail"].Value<string>(); //In rockfish there were support emails that were people allowed to be contacting us on behalf of the customer
if (!string.IsNullOrWhiteSpace(adminEmail)) var supportEmail = jCustomer["supportEmail"].Value<string>();
c.Notes += "\nAdmin Email: " + adminEmail; if (!string.IsNullOrWhiteSpace(supportEmail))
c.Notes += "\nSupport Emails: " + supportEmail;
//in Rockfish the admin email is the main license related contact and technically the only person responsible to contact us
//usually the same as the purchase email
c.EmailAddress = jCustomer["adminEmail"].Value<string>(); c.EmailAddress = jCustomer["adminEmail"].Value<string>();
CustomerBiz biz = CustomerBiz.GetBiz(ct); CustomerBiz biz = CustomerBiz.GetBiz(ct);
var NewObject = await biz.CreateAsync(c); var NewObject = await biz.CreateAsync(c);

View File

@@ -13,11 +13,11 @@ namespace Sockeye.Biz
/// <summary> /// <summary>
/// Process purchases that are from vendor notification /// Process vendor notifications
/// Turn vendordata into fully filled out purchase /// Turn vendordata into fully filled out purchase
/// attempt to match to existing customer or create one if necessary /// attempt to match to existing customer or create one if necessary
/// ///
/// A Separate job will make licenses /// A Separate job will make licenses from the new purchases where feasible
/// ///
/// </summary> /// </summary>
internal static class SockBotProcessVendorNotifications internal static class SockBotProcessVendorNotifications
@@ -39,9 +39,6 @@ namespace Sockeye.Biz
log.LogDebug("Process vendor notifications starting"); log.LogDebug("Process vendor notifications starting");
await ProcessVendorNotificationDataIntoPurchases(); await ProcessVendorNotificationDataIntoPurchases();
// log.LogDebug("Process licenses from purchases starting");
// await ProcessPurchasesIntoLicenses();
lastSweep = DateTime.UtcNow; lastSweep = DateTime.UtcNow;
} }
@@ -53,58 +50,43 @@ namespace Sockeye.Biz
{ {
//get a list of all actionable vendor notifications //get a list of all actionable vendor notifications
var ProcessablePurchaseIdList = await ct.Purchase var vnList = await ct.VendorNotification
.AsNoTracking() .AsNoTracking()
.Where(z => z.Processed == false .Where(z => z.Processed == null)
&& z.ProductId == null)
.OrderBy(z => z.Id) .OrderBy(z => z.Id)
.Select(z => z.Id)
.ToListAsync(); .ToListAsync();
try try
{ {
foreach (long purchaseId in ProcessablePurchaseIdList) foreach (var vn in vnList)
{ {
var biz = PurchaseBiz.GetBiz(ct); var biz = PurchaseBiz.GetBiz(ct);
var p = await biz.GetAsync(purchaseId, false); var p = new Purchase();
if (p == null)
log.LogDebug($"Processing vendor notification {vn.Id}-{vn.Created}");
if (string.IsNullOrWhiteSpace(vn.VendorData))
{ {
//this is a serious issue log and server ops it var err = $"VendorNotification record {vn.Id}-{vn.Created} has no vendor data";
var err = $"SockBotProcessPurchases error running job, purchase record id {purchaseId} could not be fetched {biz.GetErrorsAsString}"; await NotifyEventHelper.AddOpsProblemEvent("SockBotProcessVendorNotifications: " + err);
await NotifyEventHelper.AddOpsProblemEvent(err);
log.LogError(err); log.LogError(err);
continue;
} }
else
{
log.LogDebug($"Processing purchase {p.Id}-{p.PurchaseDate}");
if (string.IsNullOrWhiteSpace(p.VendorData))
{
var err = $"Purchase record with ID {purchaseId} has no vendor data for sales order {p.SalesOrderNumber}";
await NotifyEventHelper.AddOpsProblemEvent("SockBotProcessPurchases: " + err);
log.LogError(err);
continue;
}
//Parse json vendordata
//Existing customer or create new one? //Parse json vendordata
//here maybe need to match by vendor provided customer ID?? await ParseVendorNotificationData(vn, ct, log);
//sometimes a user will make a new account for a new purchase but intend it as an addon to v7
//for v8 it should be straightforward, however if pricing chagnes and new product needs to be purchased they may create a new record
//same dbid for v8 should do the trick
//save changes
p.Processed = true;
await biz.PutAsync(p);
//save changes
p.Processed = true;
await biz.PutAsync(p);
}
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
var err = "SockBotProcessPurchases error running job"; var err = "SockBotProcessVendorNotifications error running job";
//serious issue requires immediate notification //serious issue requires immediate notification
await NotifyEventHelper.AddOpsProblemEvent(err, ex); await NotifyEventHelper.AddOpsProblemEvent(err, ex);
log.LogError(ex, err); log.LogError(ex, err);
@@ -134,26 +116,50 @@ namespace Sockeye.Biz
//CUSTOMER create or locate //CUSTOMER create or locate
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 customerBiz = CustomerBiz.GetBiz(ct); var customerBiz = CustomerBiz.GetBiz(ct);
Customer c = await ct.Customer.FirstOrDefaultAsync(z => z.Name == jCustomerName) ?? await ct.Customer.FirstOrDefaultAsync(z => z.EmailAddress == jCustomerEmail); //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) if (c == null)
{ {
//New customer //New customer
c = new Customer(); c = new Customer();
c.Name = jCustomerName; c.Name = jCustomerName;
UpdateCustomerFromVendorData(jData, jCustomerEmail, c); c.EmailAddress = jCustomerEmail;
c.AccountNumber = jCustomerAccountNumber;
UpdateCustomerFromVendorData(jData, c);
c = await customerBiz.CreateAsync(c); c = await customerBiz.CreateAsync(c);
if (c == null) if (c == 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
{ {
//existing customer, refresh it //existing customer
UpdateCustomerFromVendorData(jData, jCustomerEmail, c); //here there could be several potential issues:
//name differs because it was a separate site in rockfish, it's not cool to change the name
//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)
{
c.EmailAddress = jCustomerEmail;//assume it was empty or has been recently updated
}
if (c.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{
// 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}");
}
}
//refresh
UpdateCustomerFromVendorData(jData, c);
c = await customerBiz.PutAsync(c); c = await customerBiz.PutAsync(c);
if (c == null) if (c == 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}");
@@ -170,21 +176,20 @@ namespace Sockeye.Biz
} }
catch (Exception ex) catch (Exception ex)
{ {
var err = $"ParseVendorNotificationData: Purchase record {vn.Id}-{vn.PurchaseDate} 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);
} }
} }
private static void UpdateCustomerFromVendorData(JObject jData, string jCustomerEmail, Customer c) private static void UpdateCustomerFromVendorData(JObject jData, Customer c)
{ {
c.EmailAddress = jCustomerEmail;
c.Active = true;//if they just made a purchase they are active even if they weren't before c.Active = true;//if they just made a purchase they are active even if they weren't before
c.DoNotContact = false;//if they just made a purchase they are contactable even if they weren't before c.DoNotContact = false;//if they just made a purchase they are contactable even if they weren't before
c.AccountNumber = jData["order_notification"]["purchase"]["customer_data"]["shopper_id"].Value<string>();//appears to be mycommerce customer id number hopefully static between orders
c.Address = c.PostAddress = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["street1"].Value<string>(); c.Address = c.PostAddress = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["street1"].Value<string>();
c.City = c.PostCity = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["city"].Value<string>(); c.City = c.PostCity = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["city"].Value<string>();
c.Region = c.PostRegion = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["state"].Value<string>(); c.Region = c.PostRegion = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["state"].Value<string>();
@@ -201,6 +206,7 @@ namespace Sockeye.Biz
c.Notes += "\n"; c.Notes += "\n";
c.Notes += $"Purchase contact:{firstName} {lastName}, language: {language}\n"; c.Notes += $"Purchase contact:{firstName} {lastName}, language: {language}\n";
} }
} }