diff --git a/.vscode/launch.json b/.vscode/launch.json index b77f3b95..fcc80a75 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -53,7 +53,7 @@ "AYANOVA_FOLDER_USER_FILES": "c:\\temp\\RavenTestData\\userfiles", "AYANOVA_FOLDER_BACKUP_FILES": "c:\\temp\\RavenTestData\\backupfiles", "AYANOVA_FOLDER_TEMPORARY_SERVER_FILES": "c:\\temp\\RavenTestData\\tempfiles", - "AYANOVA_SERVER_TEST_MODE": "false", + "AYANOVA_SERVER_TEST_MODE": "true", "AYANOVA_SERVER_TEST_MODE_SEEDLEVEL": "small", "AYANOVA_SERVER_TEST_MODE_TZ_OFFSET": "-7", "AYANOVA_BACKUP_PG_DUMP_PATH": "C:\\data\\code\\postgres_13\\bin\\" diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index cbd3b5c8..659a1668 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -582,10 +582,8 @@ namespace AyaNova.Biz // line totals, if in future need more can return a Record object instead with split out // taxes, net etc etc) // - private async Task WorkorderTotalAsync(long workOrderId, AyContext ct) + private async Task WorkorderGrandTotalAsync(long workOrderId, AyContext ct) { - - var wo = await ct.WorkOrder.AsNoTracking().AsSplitQuery() .Include(w => w.Items.OrderBy(item => item.Sequence)) .ThenInclude(wi => wi.Expenses) @@ -600,7 +598,6 @@ namespace AyaNova.Biz .Include(w => w.Items) .ThenInclude(wi => wi.OutsideServices) .SingleOrDefaultAsync(z => z.Id == workOrderId); - if (wo == null) return 0m; decimal GrandTotal = 0m; @@ -1435,7 +1432,7 @@ namespace AyaNova.Biz //that are active then proceed to fetch billed woitem children and total workorder and send notification if necessary bool haveTotal = false; - decimal total = 0m; + decimal GrandTotal = 0m; //look for potential subscribers var subs = await ct.NotifySubscription.AsNoTracking().Where(z => z.EventType == NotifyEventType.WorkorderTotalExceedsThreshold).ToListAsync(); @@ -1451,24 +1448,37 @@ namespace AyaNova.Biz //get the total because we have at least one subscriber and matching tags if (haveTotal == false) { - long WorkOrderId = 0; - if (ayaType == AyaType.WorkOrder) - WorkOrderId = id; - else - WorkOrderId = await GetWorkOrderIdFromRelativeAsync(ayaType, id, ct); + GrandTotal = await WorkorderGrandTotalAsync(oProposed.WorkOrderId, ct); - //clear out any existing ones as they may have *just* been set from a save and we don't want a workorder save of a bunch of items to trigger 10,000 notifications + //Note: not a time delayed notification, however user could be flipping states quickly triggering multiple notifications that are in queue temporarily + //so this will prevent that //Always clear any old ones for this object as they are all irrelevant the moment changed: - await NotifyEventHelper.ClearPriorEventsForObject(ct, AyaType.WorkOrder, WorkOrderId, NotifyEventType.WorkorderTotalExceedsThreshold); + await NotifyEventHelper.ClearPriorEventsForObject(ct, AyaType.WorkOrder, oProposed.WorkOrderId, NotifyEventType.WorkorderTotalExceedsThreshold); - //total workorder + //Ok, we're here because there is a subscriber who is active and tags match so only check left is total against decvalue + if (sub.DecValue < GrandTotal) + { + //notification is a go + NotifyEvent n = new NotifyEvent() + { + EventType = NotifyEventType.WorkorderTotalExceedsThreshold, + UserId = sub.UserId, + AyaType = AyaType.WorkOrder, + ObjectId = oProposed.WorkOrderId, + NotifySubscriptionId = sub.Id, + Name = $"{WorkorderInfo.Serial.ToString()} - {wos.Name}", + DecValue = GrandTotal + }; + await ct.NotifyEvent.AddAsync(n); + log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]"); + await ct.SaveChangesAsync(); + + } } - } - } - }//The Andy notification + }//"The Andy" for Dynamic Dental corp. notification diff --git a/server/AyaNova/models/NotifyEvent.cs b/server/AyaNova/models/NotifyEvent.cs index 5449a835..62f75227 100644 --- a/server/AyaNova/models/NotifyEvent.cs +++ b/server/AyaNova/models/NotifyEvent.cs @@ -31,16 +31,8 @@ namespace AyaNova.Models public long UserId { get; set; } [Required] public long NotifySubscriptionId { get; set; }//source subscription that triggered this event to be created - - //Not sure why these were put here, I'm commenting them out for now - //they seem to just be an artifact possibly of making this model from the subscription model? (copy paste) - //read the specs again and they aren't mentioned and I don't see any reference anywhere in actual delivery notification nor front end etc - //only for the subscription itself - //KEEP THIS UNTIL DONE THEN REMOVE IN FUTURE IF IT WASN"T NEEDED - // [Required] - // public long IdValue { get; set; } - // [Required] - // public decimal DecValue { get; set; } + + public decimal DecValue { get; set; } //date of the event actually occuring, e.g. WarrantyExpiry date. Compared with subscription to determine if deliverable or not public DateTime EventDate { get; set; } @@ -51,7 +43,7 @@ namespace AyaNova.Models { Created = EventDate = DateTime.UtcNow; // IdValue = 0; - // DecValue = 0; + DecValue = 0; AyaType = AyaType.NoType; ObjectId = 0; Name = string.Empty; diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index 566b781c..3f3b5627 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -938,10 +938,8 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); await ExecQueryAsync("CREATE TABLE anotifyevent (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created TIMESTAMP NOT NULL, " + "ayatype INTEGER NOT NULL, objectid BIGINT NOT NULL, name TEXT NOT NULL, eventtype INTEGER NOT NULL, notifysubscriptionid BIGINT NOT NULL REFERENCES anotifysubscription(id) ON DELETE CASCADE, " - + "userid BIGINT NOT NULL REFERENCES auser (id), eventdate TIMESTAMP NOT NULL, message TEXT)"); - //these fields were in here but seem to not be required so commented out for now, see notifyevent model for deets but - //basically remove this comment once certain don't need these fields (close to release or after) - //idvalue BIGINT NOT NULL, decvalue DECIMAL(38,18) NOT NULL, + + "userid BIGINT NOT NULL REFERENCES auser (id), eventdate TIMESTAMP NOT NULL, decvalue DECIMAL(38,18) NULL, message TEXT)"); + await ExecQueryAsync("CREATE TABLE anotification (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, userid BIGINT NOT NULL REFERENCES auser (id), " + "created TIMESTAMP NOT NULL, ayatype INTEGER NOT NULL, objectid BIGINT NOT NULL, name TEXT NOT NULL, agevalue INTERVAL, eventtype INTEGER NOT NULL, "