214 lines
10 KiB
C#
214 lines
10 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging;
|
|
using Newtonsoft.Json.Linq;
|
|
using Sockeye.Models;
|
|
using Sockeye.Util;
|
|
|
|
namespace Sockeye.Biz
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
/// Process purchases into licenses
|
|
///
|
|
/// </summary>
|
|
internal static class SockBotProcessPurchasesIntoLicenses
|
|
{
|
|
private static ILogger log = Sockeye.Util.ApplicationLogging.CreateLogger("SockBotProcessPurchasesIntoLicenses");
|
|
private static DateTime lastSweep = DateTime.MinValue;
|
|
private static TimeSpan PROCESS_V7_AGE = new TimeSpan(0, 5, 0);//Don't process a v7 order until at least 5 minutes old as it doesn't always come in at once
|
|
#if (DEBUG)
|
|
private static TimeSpan PROCESS_EVERY_INTERVAL = new TimeSpan(0, 0, 30);//every 30 seconds during development
|
|
#else
|
|
private static TimeSpan PROCESS_EVERY_INTERVAL = new TimeSpan(0, 5, 10);//every 5 minutes
|
|
#endif
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// DoSweep
|
|
//
|
|
public static async Task DoWorkAsync()
|
|
{
|
|
//This will get triggered roughly every minute, but we don't want to check that frequently
|
|
if (DateTime.UtcNow - lastSweep < PROCESS_EVERY_INTERVAL)
|
|
return;
|
|
|
|
if (ServerBootConfig.MIGRATING) return;//don't do this during migration (migration is one time only so can remove after up and running)
|
|
|
|
log.LogDebug("Process purchases into licenses starting");
|
|
await ProcessPurchasesIntoLicenses();
|
|
|
|
lastSweep = DateTime.UtcNow;
|
|
}
|
|
|
|
private static async Task ProcessPurchasesIntoLicenses()
|
|
{
|
|
using (AyContext ct = Sockeye.Util.ServiceProviderProvider.DBContext)
|
|
{
|
|
|
|
//get a list of all actionable purchases grouped by customer id
|
|
var purchaseList = (await ct.Purchase.AsNoTracking()
|
|
.Where(z => z.Processed == false
|
|
&& z.LicenseId == null
|
|
&& z.CustomerId != null
|
|
&& (z.PGroup == ProductGroup.AyaNova7 || z.PGroup == ProductGroup.RavenPerpetual || z.PGroup == ProductGroup.RavenSubscription))
|
|
.OrderByDescending(z => z.PurchaseDate)
|
|
.ToListAsync()).GroupBy(z => (long)z.CustomerId);
|
|
|
|
try
|
|
{
|
|
foreach (var purchaseGroup in purchaseList)
|
|
{
|
|
//Iterate the group and qualify it
|
|
bool isRavenPerpetual = false;
|
|
bool isRavenSubscription = false;
|
|
bool isV7 = false;
|
|
bool isLessThanV7Age = false;
|
|
var purchaseGroupCustomer = await ct.Customer.AsNoTracking().FirstAsync(z => z.Id == purchaseGroup.First().CustomerId);
|
|
|
|
foreach (var purchase in purchaseGroup)
|
|
{
|
|
|
|
if (purchase.PGroup == ProductGroup.AyaNova7)
|
|
isV7 = true;
|
|
|
|
if (purchase.PGroup == ProductGroup.RavenPerpetual)
|
|
isRavenPerpetual = true;
|
|
|
|
if (purchase.PGroup == ProductGroup.RavenSubscription)
|
|
isRavenSubscription = true;
|
|
|
|
if (DateTime.UtcNow - purchase.PurchaseDate < PROCESS_V7_AGE)
|
|
isLessThanV7Age = true; ;
|
|
}
|
|
|
|
//sanity checks should never be mixed
|
|
if ((isRavenPerpetual && isV7))
|
|
{
|
|
var err = $"SockBotProcessPurchasesIntoLicenses both raven perpetual and v7 in same customer's purchase group First record order number: {purchaseGroup.First().SalesOrderNumber}";
|
|
//serious issue requires immediate notification
|
|
await NotifyEventHelper.AddOpsProblemEvent(err);
|
|
log.LogError(err);
|
|
continue;
|
|
}
|
|
|
|
if ((isRavenSubscription && isV7))
|
|
{
|
|
var err = $"SockBotProcessPurchasesIntoLicenses both raven subscription and v7 in same customer's purchase group First record order number: {purchaseGroup.First().SalesOrderNumber}";
|
|
//serious issue requires immediate notification
|
|
await NotifyEventHelper.AddOpsProblemEvent(err);
|
|
log.LogError(err);
|
|
continue;
|
|
}
|
|
|
|
if ((isRavenPerpetual && isRavenSubscription))
|
|
{
|
|
var err = $"SockBotProcessPurchasesIntoLicenses both raven perpetual and raven subscription in same customer's purchase group First record order number: {purchaseGroup.First().SalesOrderNumber}";
|
|
//serious issue requires immediate notification
|
|
await NotifyEventHelper.AddOpsProblemEvent(err);
|
|
log.LogError(err);
|
|
continue;
|
|
}
|
|
|
|
//if v7 skip for this iteration to ensure multiple add-on's have all arrived from mycommerce
|
|
if (isV7 && isLessThanV7Age)
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//if v7 license then lookup last license for same pgroup for same customer, if none then consider it a new license fresh
|
|
//if there is one and it's not entirely expired then duplicate and fixup from purchases in this group
|
|
if (isV7)
|
|
{
|
|
|
|
//get one representative product in the group, first is fine
|
|
var firstPurchase = purchaseGroup.First();
|
|
var lastLicense = await ct.License.AsNoTracking().OrderByDescending(z => z.Id).FirstOrDefaultAsync(z => z.CustomerId == firstPurchase.CustomerId && z.PGroup == firstPurchase.PGroup);
|
|
var newLicense = new License();
|
|
newLicense.CustomerId = firstPurchase.CustomerId;
|
|
newLicense.Active = false;
|
|
newLicense.RegTo = firstPurchase.RegTo;
|
|
newLicense.FetchEmail = purchaseGroupCustomer.EmailAddress;
|
|
|
|
//is there a prior license?
|
|
if (lastLicense != null)
|
|
{
|
|
//copy all the values to the new license
|
|
newLicense.ExportToXLS = lastLicense.ExportToXLS;
|
|
newLicense.ExportToXLSExpires = lastLicense.ExportToXLSExpires;
|
|
newLicense.ImportExportCSVDuplicate=lastLicense.ImportExportCSVDuplicate;
|
|
newLicense.ImportExportCSVDuplicateExpires=lastLicense.ImportExportCSVDuplicateExpires;
|
|
newLicense.MaintenanceExpire=lastLicense.MaintenanceExpire;
|
|
newLicense.MBI=lastLicense.MBI;
|
|
newLicense.MBIExpires=lastLicense.MBIExpires;
|
|
newLicense.OLI=lastLicense.OLI;
|
|
newLicense.OLIExpires=lastLicense.OLIExpires;
|
|
newLicense.OutlookSchedule=lastLicense.OutlookSchedule;
|
|
newLicense.OutlookScheduleExpires=lastLicense.OutlookScheduleExpires;
|
|
newLicense.PTI=lastLicense.PTI;
|
|
newLicense.PTIExpires=lastLicense.PTIExpires;
|
|
newLicense.QBI=lastLicense.QBI;
|
|
newLicense.QBIExpires=lastLicense.QBIExpires;
|
|
newLicense.QBOI=lastLicense.QBOI;
|
|
newLicense.QBOIExpires=lastLicense.QBOIExpires;
|
|
newLicense.QuickNotification=lastLicense.QuickNotification;
|
|
newLicense.QuickNotificationExpires=lastLicense.QuickNotificationExpires;
|
|
newLicense.Renewal=true;
|
|
newLicense.RI=lastLicense.RI;
|
|
newLicense.RIExpires=lastLicense.RIExpires;
|
|
newLicense.Tags=lastLicense.Tags;
|
|
newLicense.Users=lastLicense.Users;
|
|
newLicense.WBI=lastLicense.WBI;
|
|
newLicense.WBIExpires=lastLicense.WBIExpires;
|
|
newLicense.Wiki=lastLicense.Wiki;
|
|
|
|
}
|
|
foreach (var purchase in purchaseGroup)
|
|
{
|
|
}
|
|
|
|
}
|
|
|
|
//IF raven license and have what is likely a recognizable dbid that ends in an = symbol then just make the new license and cancel the last one if that's necessary (NARRATOR: it wasn't, raven only ever fetches the newest)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// log.LogDebug($"Processing purchase id:{purchaseGroup[0].Id},purchasedate:{purchaseGroup.PurchaseDate}, custid:{purchaseGroup.CustomerId}");
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var err = "SockBotProcessPurchasesIntoLicenses error running job";
|
|
//serious issue requires immediate notification
|
|
await NotifyEventHelper.AddOpsProblemEvent(err, ex);
|
|
log.LogError(ex, err);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
}//eoc
|
|
|
|
|
|
}//eons
|
|
|