This commit is contained in:
2023-01-01 02:07:51 +00:00
parent fdad40d6bd
commit 7366dd48d6
7 changed files with 158 additions and 19 deletions

View File

@@ -246,6 +246,7 @@ namespace Sockeye.Biz
p.Active = true;//not entirely true but we can always deactivate there aren't many products
p.VendorId = 1;
p.OurCode = p.VendorCode = jPurchase["productCode"].Value<string>();
p.Group = ProductGroupFromProductCode(p.OurCode);
if (p.VendorCode == "301028468")//subscription yearly
{
@@ -270,7 +271,7 @@ namespace Sockeye.Biz
var s = new Purchase();
s.VendorId = 1;
s.ProductId = p.Id;
s.Group = p.Group;
s.CustomerId = CurrentCustomerId;
s.CancelDate = DateUtil.EpochToDateNullIsNull(jPurchase["cancelDate"].Value<long?>());
s.CouponCode = jPurchase["couponCode"].Value<string>();
@@ -340,7 +341,7 @@ namespace Sockeye.Biz
p.VendorData += ",\n";
p.VendorData += jVendorNotificationItem["data"].Value<string>();
await ct.SaveChangesAsync();
}
}
}// all vendor notifications loop
}
@@ -541,7 +542,7 @@ namespace Sockeye.Biz
var jKey = JObject.Parse(keyNoWS);
l.LicenseExpire = DateTime.MaxValue.ToUniversalTime();
l.MaintenanceExpire = jKey["AyaNovaLicenseKey"]["Expires"].Value<DateTime>().ToUniversalTime();
l.Group = ProductGroup.AyaNova7;
l.FetchCode = jLicense["code"].Value<string>();
l.Tags.Add("v7");
}
@@ -559,7 +560,7 @@ namespace Sockeye.Biz
var jKey = JObject.Parse(keyNoWS);
l.LicenseExpire = DateTime.MaxValue.ToUniversalTime();
l.MaintenanceExpire = jKey["AyaNovaLiteLicenseKey"]["Expires"].Value<DateTime>().ToUniversalTime();
l.Group = ProductGroup.AyaNova7;
l.FetchCode = jLicense["code"].Value<string>();
l.Tags.Add("v7");
l.Tags.Add("lite");
@@ -590,6 +591,10 @@ namespace Sockeye.Biz
var jKey = JObject.Parse(keyNoWS);
l.DbId = jKey["Key"]["DBID"].Value<string>();
l.LicenseExpire = jKey["Key"]["LicenseExpiration"].Value<DateTime>().ToUniversalTime();
if (jKey["Key"]["Perpetual"].Value<bool>())
l.Group = ProductGroup.RavenPerpetual;
else
l.Group = ProductGroup.RavenSubscription;
l.MaintenanceExpire = jKey["Key"]["MaintenanceExpiration"].Value<DateTime>().ToUniversalTime();
l.Tags.Add("raven");
}
@@ -678,6 +683,70 @@ namespace Sockeye.Biz
//await Task.CompletedTask;
}
private static ProductGroup ProductGroupFromProductCode(string productCode)
{
switch (productCode)
{
case "300740321"://wbi
case "300740317"://up to 5
case "300740314"://RI
case "300740328"://Quick notification
case "300784766"://QBOI
case "300740315"://Single
case "300740323"://QBI
case "300740318"://Up to 10
case "300740327"://Export to XLS
case "300740329"://ImportExport CSV duplicate
case "300740319"://Up to 20
case "300740322"://MBI
case "300740324"://PTI
case "300740325"://OLI
case "300807973"://Up to 15
case "300740326"://Outlook Schedule Export
case "300740316"://AyaNova LITE
case "999"://Up to 999
return ProductGroup.AyaNova7;
case "300093112"://Key administration
case "301010670"://Custom 733918243
case "300151145"://Custom 539230073
return ProductGroup.Misc;
case "301028317"://AyaNova perpetual single user license includes one year maintenance plan
return ProductGroup.RavenPerpetual;
case "301028468"://AyaNova subscription one user YEARLY
case "301028467"://AyaNova subscription one user MONTHLY
return ProductGroup.RavenSubscription;
default:
throw new Exception($"Uknown product code {productCode}");
}
}
/*
"id" "name" "active" "vendorid" "licenseinterval" "maintinterval" "vendorcode" "ourcode" "wiki" "tags"
1 "WBI" true 1 "00:00:00" "365 days" "300740321" "300740321" "{}"
2 "Up to 5" true 1 "00:00:00" "365 days" "300740317" "300740317" "{}"
3 "RI" true 1 "00:00:00" "365 days" "300740314" "300740314" "{}"
4 "Quick Notification" true 1 "00:00:00" "365 days" "300740328" "300740328" "{}"
5 "QBOI" true 1 "00:00:00" "365 days" "300784766" "300784766" "{}"
6 "Single" true 1 "00:00:00" "365 days" "300740315" "300740315" "{}"
7 "QBI" true 1 "00:00:00" "365 days" "300740323" "300740323" "{}"
8 "Up to 10" true 1 "00:00:00" "365 days" "300740318" "300740318" "{}"
9 "Export to XLS" true 1 "00:00:00" "365 days" "300740327" "300740327" "{}"
10 "Importexport.csv duplicate" true 1 "00:00:00" "365 days" "300740329" "300740329" "{}"
11 "Up to 20" true 1 "00:00:00" "365 days" "300740319" "300740319" "{}"
12 "MBI" true 1 "00:00:00" "365 days" "300740322" "300740322" "{}"
13 "Key Administration" true 1 "00:00:00" "365 days" "300093112" "300093112" "{}"
14 "PTI " true 1 "00:00:00" "365 days" "300740324" "300740324" "{}"
15 "OLI" true 1 "00:00:00" "365 days" "300740325" "300740325" "{}"
16 "Up to 15" true 1 "00:00:00" "365 days" "300807973" "300807973" "{}"
17 "Outlook Schedule Export" true 1 "00:00:00" "365 days" "300740326" "300740326" "{}"
18 "AyaNova Lite" true 1 "00:00:00" "365 days" "300740316" "300740316" "{}"
19 "Up to 999" true 1 "00:00:00" "365 days" "999" "999" "{}"
20 "AyaNova perpetual single user license includes one year maintenance plan" true 1 "00:00:00" "365 days" "301028317" "301028317" "{}"
21 "Custom 733918243" true 1 "00:00:00" "365 days" "301010670" "301010670" "{}"
22 "AyaNova subscription one user monthly" true 1 "31 days" "31 days" "301028467" "301028467" "{}"
23 "Custom 539230073" true 1 "00:00:00" "365 days" "300151145" "300151145" "{}"
24 "AyaNova subscription one user yearly" true 1 "365 days" "365 days" "301028468" "301028468" "{}"
*/
/////////////////////////////////////////////////////////////////////
}//eoc

View File

@@ -0,0 +1,11 @@
namespace Sockeye.Biz
{
public enum ProductGroup
{
Misc = 0,
AyaNova7 = 1,
RavenPerpetual = 2,
RavenSubscription = 3
}
}//eons

View File

@@ -19,12 +19,14 @@ namespace Sockeye.Models
public long? CustomerId { get; set; }
[NotMapped]
public string CustomerViz { get; set; }
[Required]
public ProductGroup Group {get;set;}
public string RegTo { get; set; }
public string Key { get; set; }
public string FetchCode { get; set; }
public string FetchEmail { get; set; }
public string FetchCode { get; set; }//v7 uses
public string FetchEmail { get; set; }//v7 uses
public DateTime? FetchedOn { get; set; }
public string DbId { get; set; }
public string DbId { get; set; }//v8 uses
public DateTime LicenseExpire { get; set; }
public DateTime MaintenanceExpire { get; set; }

View File

@@ -15,6 +15,8 @@ namespace Sockeye.Models
[Required]
public string Name { get; set; }
public bool Active { get; set; }
[Required]
public ProductGroup Group {get;set;}
public long VendorId { get; set; }
public TimeSpan LicenseInterval { get; set; }
public TimeSpan MaintInterval { get; set; }

View File

@@ -10,8 +10,7 @@ namespace Sockeye.Models
public class Purchase : ICoreBizObjectModel
{
public long Id { get; set; }
public uint Concurrency { get; set; }
[Required]
public uint Concurrency { get; set; }
public long CustomerId { get; set; }
[NotMapped]
public string CustomerViz { get; set; }
@@ -21,6 +20,8 @@ namespace Sockeye.Models
public string VendorViz { get; set; }
[Required]
public long ProductId { get; set; }
[Required]
public ProductGroup Group {get;set;}
[NotMapped]
public string ProductViz { get; set; }
public string SalesOrderNumber { get; set; }

View File

@@ -874,7 +874,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
LogUpdateMessage(log);
await ExecQueryAsync("CREATE TABLE alicense (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created TIMESTAMPTZ NOT NULL, "
+ "customerid BIGINT REFERENCES acustomer(id), regto TEXT NOT NULL, key TEXT NOT NULL, fetchcode TEXT, fetchemail TEXT, "
+ "customerid BIGINT REFERENCES acustomer(id), group INTEGER NOT NULL DEFAULT 0, regto TEXT NOT NULL, key TEXT NOT NULL, fetchcode TEXT, fetchemail TEXT, "
+ "fetchedon TIMESTAMPTZ, dbid TEXT, licenseexpire TIMESTAMPTZ, maintenanceexpire TIMESTAMPTZ NOT NULL, "
+ "wiki TEXT, tags VARCHAR(255) ARRAY )");
@@ -892,12 +892,12 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync("CREATE TABLE aproduct (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL DEFAULT true, "
+ "vendorid BIGINT NOT NULL REFERENCES avendor(id), licenseinterval INTERVAL, maintinterval INTERVAL, vendorcode TEXT NOT NULL UNIQUE, ourcode TEXT NOT NULL UNIQUE, "
+ "vendorid BIGINT NOT NULL REFERENCES avendor(id), group INTEGER NOT NULL DEFAULT 0, licenseinterval INTERVAL, maintinterval INTERVAL, vendorcode TEXT NOT NULL UNIQUE, ourcode TEXT NOT NULL UNIQUE, "
+ "wiki TEXT, tags VARCHAR(255) ARRAY )");
await ExecQueryAsync("CREATE TABLE apurchase (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, customerid BIGINT NOT NULL REFERENCES acustomer(id) ON DELETE CASCADE, "
+ "vendorid BIGINT NOT NULL REFERENCES avendor(id), productid BIGINT NOT NULL REFERENCES aproduct(id), salesordernumber TEXT NOT NULL, "
await ExecQueryAsync("CREATE TABLE apurchase (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, customerid BIGINT REFERENCES acustomer(id) ON DELETE CASCADE, "
+ "vendorid BIGINT NOT NULL REFERENCES avendor(id), productid BIGINT NOT NULL REFERENCES aproduct(id), group INTEGER NOT NULL DEFAULT 0, salesordernumber TEXT NOT NULL, "
+ "purchasedate TIMESTAMPTZ NOT NULL, expiredate TIMESTAMPTZ, canceldate TIMESTAMPTZ, couponcode text, notes text, "
+ "renewnoticesent BOOL NOT NULL DEFAULT false, quantity INTEGER NOT NULL DEFAULT 1, "
+ "vendordata TEXT, processeddate TIMESTAMPTZ, "
@@ -1104,6 +1104,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductMaintInterval', 'Maintenance period' FROM atranslation t where t.baselanguage = 'en'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductVendorCode', 'Vendor code' FROM atranslation t where t.baselanguage = 'en'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductOurCode', 'Our code' FROM atranslation t where t.baselanguage = 'en'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductGroup', 'Product group' FROM atranslation t where t.baselanguage = 'en'");
//spanish translations
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'Product', 'Product' FROM atranslation t where t.baselanguage = 'es'");
@@ -1113,6 +1114,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductMaintInterval', 'Maintenance period' FROM atranslation t where t.baselanguage = 'es'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductVendorCode', 'Vendor code' FROM atranslation t where t.baselanguage = 'es'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductOurCode', 'Our code' FROM atranslation t where t.baselanguage = 'es'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductGroup', 'Product group' FROM atranslation t where t.baselanguage = 'es'");
//french translations
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'Product', 'Product' FROM atranslation t where t.baselanguage = 'fr'");
@@ -1122,6 +1124,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductMaintInterval', 'Maintenance period' FROM atranslation t where t.baselanguage = 'fr'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductVendorCode', 'Vendor code' FROM atranslation t where t.baselanguage = 'fr'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductOurCode', 'Our code' FROM atranslation t where t.baselanguage = 'fr'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductGroup', 'Product group' FROM atranslation t where t.baselanguage = 'fr'");
//german translations
@@ -1132,6 +1135,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductMaintInterval', 'Maintenance period' FROM atranslation t where t.baselanguage = 'de'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductVendorCode', 'Vendor code' FROM atranslation t where t.baselanguage = 'de'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductOurCode', 'Our code' FROM atranslation t where t.baselanguage = 'de'");
await ExecQueryAsync("INSERT INTO atranslationitem(translationid,key,display) SELECT t.id, 'ProductGroup', 'Product group' FROM atranslation t where t.baselanguage = 'de'");
#endregion product

View File

@@ -1,18 +1,62 @@
client - open / edit all the things
import all vendor data packets from shareit into purchases
PURCHASE drives new licensing ui
To automate as much as possible need following:
- Purchase Customer id nullable as may not be able to match to an existing customer
- processed date important as shows what is not processed yet if empty
- product category for purchase automatically attributed, i.e. v7, raven perpet, raven sub, misc
License edit / entry form
- Pick license key type different fields appear
NEED TO ADD KEYTYPE ENUM TO LICENSE OBJECT
this will future proof and make UI and handling easier
Keytypes: AyaNova 7, RAVEN Perpetual, RAVEN Subscription
- generates key at server on save depending on what is new or changed I guess or needs to be edited after the fact?
- Generate v7 license from entered ad-hoc data, i.e. it should be from the license edit form and take the entries and make a key on save
- Generate v7 license for customer from all active purchases
NEED TO ADD PRODUCT CATEGORY FOR AUTO LICENSE GENERATION?
V7, RAVEN, MISC (not license keyed)
this way, can automatically create key for v7 from all purchases that have not yet expired for a customer
- Generate v8 license from entered data, ''
- Opening license existing in edit form should re-populate the controls even for v7 so that they can be changed, saved, edited etc
- Once it's fetched it's read-only but can duplicate!!!!!
- direct open a case by case number like workorder
(id's differ so it isn't easy to just open a case in the url)
- all the rockfish functionality for generating new licenses ad-hoc but with a server route doing the work so can be automated
NOTE: v7 licensing will be hard to automate fully as it's a fucked up system
RAVEN is much easier to automate with only one key per db
So I'm thinking make v7 renewals and purchases as easy and semiautomatic as possible, perhaps it fills in and suggest the whole thing but requires me
to press a button to actually do it, whereas raven can ultimately just process automatically, particularly subscription monthly important!!
AUTOMATION ROUTES REQUIRED
Both v7 and v8 point to "rockfish.ayanova.com" so maybe nginx can redirect?
forgot about that, was hoping for ability to parallel and keep rockfish going... hmmm...
AyaNova 7 license fetch URL
"https://rockfish.ayanova.com/fetch/" + sFetchCode + "/" + sEmail;
rockfish FetchController.cs
RAVEN trial request URL
POST to
$"{LICENSE_SERVER_URL_ROCKFISH}rvr";
RAVEN license fetch url
POST to
$"{LicenseServer}/rvf"
License server url is one of:
new roles and bizroles set appropo
Developer - rw cases
Support - read cases, read sales and customer data?
Sales - licenses
LICENSE_SERVER_URL_ROCKFISH = "http://localhost:3001/";//dev testing
LICENSE_SERVER_URL_ROCKFISH = "https://rockfish.ayanova.com/";//1st default production primary
LICENSE_SERVER_URL_IO = "https://io.ayanova.com/";//2nd production
LICENSE_SERVER_URL_EUROPA = "https://europa.ayanova.com/";//3rd production
LICENSE_SERVER_URL_CALLISTO = "https://callisto.ayanova.com/";//4th production
DTR
@@ -22,3 +66,9 @@ automatic jobs to create purchase record from vendor data
send license emails based on event etc, really gets into the new stuff here
Need ui that shows money required for paying future for yearly subs so at a glance know what money need in bank each month
Also, sidebar, check if can pay d.o. in advance, or do I want that??
new roles and bizroles set appropo
Developer - rw cases
Support - read cases, read sales and customer data?
Sales - licenses