From 73f8dbc3dc40771e40dabf43c3c432d8c6215d8d Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Mon, 7 Mar 2022 20:08:45 +0000 Subject: [PATCH] --- .../docs/customer-notify-subscriptions.md | 6 +- .../CustomerNotifySubscriptionController.cs | 2 +- .../DataListSqlFilterCriteriaBuilder.cs | 6 +- server/AyaNova/biz/QuoteBiz.cs | 41 +++++++++++++- server/AyaNova/kpi/CSROpenList.cs | 2 +- server/AyaNova/kpi/WorkOrderByStatusList.cs | 4 +- .../kpi/WorkOrderCompletedOnTimePct.cs | 2 +- server/AyaNova/kpi/WorkOrderCreatedCount.cs | 4 +- ...rkOrderItemLaborQuantityEveryoneSummary.cs | 6 +- .../kpi/WorkOrderItemLaborQuantitySummary.cs | 4 +- server/AyaNova/kpi/WorkOrderOverdueAllList.cs | 4 +- .../kpi/WorkOrderOverduePersonalList.cs | 4 +- server/AyaNova/kpi/WorkOrderStatusCount.cs | 2 +- server/AyaNova/kpi/WorkOrderStatusPct.cs | 2 +- .../kpi/WorkOrderUnscheduledOpenList.cs | 4 +- server/AyaNova/models/AyContext.cs | 1 + server/AyaNova/models/CustomerNotifyEvent.cs | 56 +++++++++++++++++++ server/AyaNova/util/AySchema.cs | 3 + 18 files changed, 125 insertions(+), 28 deletions(-) create mode 100644 server/AyaNova/models/CustomerNotifyEvent.cs diff --git a/docs/8.0/ayanova/docs/customer-notify-subscriptions.md b/docs/8.0/ayanova/docs/customer-notify-subscriptions.md index 6a9d977c..874067bc 100644 --- a/docs/8.0/ayanova/docs/customer-notify-subscriptions.md +++ b/docs/8.0/ayanova/docs/customer-notify-subscriptions.md @@ -68,11 +68,9 @@ Only Customers who are set to Active and have an email address set will be notif ### Duplicate or overlapping notifications -You can set up multiple subscriptions for the same event to allow for alternative languages and other settings. Because of this, it is possible to set a combination of settings that results in the same customer being notified more than once of the same event. +You can set up multiple subscriptions for the same event to allow for alternative languages and other settings. Because of this, it is possible to set a combination of settings that could result in the same customer being notified more than once of the same event. -For example if you have two notifications set up for the same event but with different language or time zone settings but choose tags in each subscription that end up matching the same Customer, that customer will receive two notifications. - -Use distinct and specific Customer notification tags to ensure that the appropriate notification event goes to the correct Customers without overlap. For example "workorder-completed-spanish", "workorder-completed-english" or whatever makes sense for your business but clearly separates the Customers into the appropriate groups for notification. +To prevent redundant excess notifications, AyaNova will only send *one* notification per event to the same Customer. If two notification subscriptions for the same event would apply to the same Customer, the subscription created first (lowest id number) will "win" and be the one used to make the delivery. ### Email address diff --git a/server/AyaNova/Controllers/CustomerNotifySubscriptionController.cs b/server/AyaNova/Controllers/CustomerNotifySubscriptionController.cs index 0fa07306..6e0774a3 100644 --- a/server/AyaNova/Controllers/CustomerNotifySubscriptionController.cs +++ b/server/AyaNova/Controllers/CustomerNotifySubscriptionController.cs @@ -143,7 +143,7 @@ namespace AyaNova.Api.Controllers if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); - string custTagsWhere = DataList.DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("acustomer.tags", customerTags, false); + string custTagsWhere = DataList.DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("acustomer.tags", customerTags, false); List ret = new List(); diff --git a/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs b/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs index acd5e481..a08b557d 100644 --- a/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs +++ b/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs @@ -1146,11 +1146,11 @@ namespace AyaNova.DataList //////////////////////////////////////////////////////////////////////// - // /// - /// Translate KPI tag filter to PostgreSQL friendly SQL criteria + /// Translate tag filter to PostgreSQL friendly SQL criteria /// - public static string KPITagFilterToSqlCriteria(string SqlColumnNameToFilter, List sValue, bool bAny) + /// + public static string TagFilterToSqlCriteriaHelper(string SqlColumnNameToFilter, List sValue, bool bAny) { if(sValue.Count==0) return string.Empty; //if it's an OR (any) query then need to build individual terms, if it's not then it's just an all or AND query and can pass through as is diff --git a/server/AyaNova/biz/QuoteBiz.cs b/server/AyaNova/biz/QuoteBiz.cs index 51be5ebd..4f56f2ee 100644 --- a/server/AyaNova/biz/QuoteBiz.cs +++ b/server/AyaNova/biz/QuoteBiz.cs @@ -1249,6 +1249,7 @@ namespace AyaNova.Biz { //# STATUS CHANGE (create new status) { + //PERSONAL SUBSCCRIPTION //Conditions: must match specific status id value and also tags below //delivery is immediate so no need to remove old ones of this kind var subs = await ct.NotifySubscription.AsNoTracking().Where(z => z.EventType == NotifyEventType.QuoteStatusChange && z.IdValue == oProposed.QuoteStatusId).ToListAsync(); @@ -1276,6 +1277,44 @@ namespace AyaNova.Biz } }//quote status change event + { + //PROXY CUSTOMER NOTIFICATION SUBSCRIPTION HANDLING + //can this customer even be delivered to? + var custInfo = await ct.Customer.AsNoTracking().Where(x => x.Id == QuoteInfo.CustomerId).Select(x => new { x.Active, x.Tags, x.EmailAddress }).FirstOrDefaultAsync(); + if (custInfo != null && custInfo.Active && !string.IsNullOrWhiteSpace(custInfo.EmailAddress)) + { + //Conditions: must match specific status id value and also tags below + //delivery is immediate so no need to remove old ones of this kind + //note order by id ascending so that only the oldest notification "wins" as per docs in case of overlap to same customer + var subs = await ct.CustomerNotifySubscription.AsNoTracking().Where(z => z.EventType == NotifyEventType.QuoteStatusChange && z.IdValue == oProposed.QuoteStatusId).OrderBy(z=>z.Id).ToListAsync(); + + foreach (var sub in subs) + { + //Object tags must match and Customer tags must match + if (NotifyEventHelper.ObjectHasAllSubscriptionTags(QuoteInfo.Tags, sub.Tags) && NotifyEventHelper.ObjectHasAllSubscriptionTags(custInfo.Tags, sub.CustomerTags)) + { + + + + + NotifyEvent n = new NotifyEvent() + { + EventType = NotifyEventType.QuoteStatusChange, + UserId = sub.UserId, + AyaType = AyaType.Quote, + ObjectId = oProposed.QuoteId, + NotifySubscriptionId = sub.Id, + Name = $"{QuoteInfo.Serial.ToString()} - {qos.Name}" + }; + await ct.NotifyEvent.AddAsync(n); + log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]"); + await ct.SaveChangesAsync(); + break;//we have a match no need to process any further subs for this event + } + } + } + }//quote status change event + //# STATUS AGE { //QuoteStatusAge = 29,//* Quote STATUS unchanged for set time (stuck in state), conditional on: Duration (how long stuck), exact status selected IdValue, Tags. Advance notice can NOT be set @@ -4172,7 +4211,7 @@ namespace AyaNova.Biz return; } - if (!isNew && UserIsRestrictedType) + if (!isNew && UserIsRestrictedType) { //Existing record so just make sure they haven't changed the not changeable fields from the db version //* Tasks: view and edit existing tasks, set completion type and date only, no add or remove or changing other fields diff --git a/server/AyaNova/kpi/CSROpenList.cs b/server/AyaNova/kpi/CSROpenList.cs index 89bf29f7..82da9a20 100644 --- a/server/AyaNova/kpi/CSROpenList.cs +++ b/server/AyaNova/kpi/CSROpenList.cs @@ -29,7 +29,7 @@ AuthorizationRoles.TechRestricted; { var custtags = options.Criteria["custtags"].ToObject>(); bool custtagsany = options.Criteria["custtagsany"].ToObject(); - string custTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("acustomer.tags", custtags, custtagsany); ; + string custTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("acustomer.tags", custtags, custtagsany); ; _dataQuery = @$"SELECT row_to_json(t) as res from ( SELECT ACUSTOMERSERVICEREQUEST.DATEREQUESTED, diff --git a/server/AyaNova/kpi/WorkOrderByStatusList.cs b/server/AyaNova/kpi/WorkOrderByStatusList.cs index 9be2d3f5..168cdb44 100644 --- a/server/AyaNova/kpi/WorkOrderByStatusList.cs +++ b/server/AyaNova/kpi/WorkOrderByStatusList.cs @@ -62,8 +62,8 @@ namespace AyaNova.KPI bool wotagsany = options.Criteria["wotagsany"].ToObject(); var woitemtags = options.Criteria["woitemtags"].ToObject>(); bool woitemtagsany = options.Criteria["woitemtagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); - string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorderitem.tags", woitemtags, woitemtagsany); ; + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); + string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorderitem.tags", woitemtags, woitemtagsany); ; _dataQuery = @$"SELECT row_to_json(t) as res from ( SELECT distinct(AWORKORDER.ID), AWORKORDER.SERIAL, diff --git a/server/AyaNova/kpi/WorkOrderCompletedOnTimePct.cs b/server/AyaNova/kpi/WorkOrderCompletedOnTimePct.cs index d6bc5fb4..87276db8 100644 --- a/server/AyaNova/kpi/WorkOrderCompletedOnTimePct.cs +++ b/server/AyaNova/kpi/WorkOrderCompletedOnTimePct.cs @@ -45,7 +45,7 @@ AuthorizationRoles.Accounting; var dateWhere = DataListSqlFilterCriteriaBuilder.DataFilterToColumnCriteria("aworkorder.createddate", UiFieldDataType.DateTime, "no-operator", timeSpan, options.ClientTimeStamp); var wotags = options.Criteria["wotags"].ToObject>(); bool wotagsany = options.Criteria["wotagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); diff --git a/server/AyaNova/kpi/WorkOrderCreatedCount.cs b/server/AyaNova/kpi/WorkOrderCreatedCount.cs index 1eaa7e44..a67b81b3 100644 --- a/server/AyaNova/kpi/WorkOrderCreatedCount.cs +++ b/server/AyaNova/kpi/WorkOrderCreatedCount.cs @@ -47,8 +47,8 @@ AuthorizationRoles.Accounting; bool wotagsany = options.Criteria["wotagsany"].ToObject(); var woitemtags = options.Criteria["woitemtags"].ToObject>(); bool woitemtagsany = options.Criteria["woitemtagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); - string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorderitem.tags", woitemtags, woitemtagsany); ; + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); + string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorderitem.tags", woitemtags, woitemtagsany); ; _dataQuery = @$"SELECT row_to_json(t) as res from ( SELECT COUNT(AWORKORDER.ID) Y, diff --git a/server/AyaNova/kpi/WorkOrderItemLaborQuantityEveryoneSummary.cs b/server/AyaNova/kpi/WorkOrderItemLaborQuantityEveryoneSummary.cs index c0aa5b7f..1912f43c 100644 --- a/server/AyaNova/kpi/WorkOrderItemLaborQuantityEveryoneSummary.cs +++ b/server/AyaNova/kpi/WorkOrderItemLaborQuantityEveryoneSummary.cs @@ -50,9 +50,9 @@ AuthorizationRoles.Accounting; bool wotagsany = options.Criteria["wotagsany"].ToObject(); var woitemtags = options.Criteria["woitemtags"].ToObject>(); bool woitemtagsany = options.Criteria["woitemtagsany"].ToObject(); - string techTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("auser.tags", techtags, techtagsany); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); - string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorderitem.tags", woitemtags, woitemtagsany); ; + string techTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("auser.tags", techtags, techtagsany); + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); + string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorderitem.tags", woitemtags, woitemtagsany); ; diff --git a/server/AyaNova/kpi/WorkOrderItemLaborQuantitySummary.cs b/server/AyaNova/kpi/WorkOrderItemLaborQuantitySummary.cs index a1981e3c..f54f2d9f 100644 --- a/server/AyaNova/kpi/WorkOrderItemLaborQuantitySummary.cs +++ b/server/AyaNova/kpi/WorkOrderItemLaborQuantitySummary.cs @@ -40,8 +40,8 @@ namespace AyaNova.KPI bool wotagsany = options.Criteria["wotagsany"].ToObject(); var woitemtags = options.Criteria["woitemtags"].ToObject>(); bool woitemtagsany = options.Criteria["woitemtagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); - string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorderitem.tags", woitemtags, woitemtagsany); ; + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); + string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorderitem.tags", woitemtags, woitemtagsany); ; _dataQuery = @$"SELECT row_to_json(t) as res from ( select SUM(AWORKORDERITEMLABOR.serviceratequantity) y, date_trunc('{interval}',AWORKORDERITEMLABOR.servicestopdate) x diff --git a/server/AyaNova/kpi/WorkOrderOverdueAllList.cs b/server/AyaNova/kpi/WorkOrderOverdueAllList.cs index 700de86c..73a55953 100644 --- a/server/AyaNova/kpi/WorkOrderOverdueAllList.cs +++ b/server/AyaNova/kpi/WorkOrderOverdueAllList.cs @@ -30,8 +30,8 @@ namespace AyaNova.KPI bool wotagsany = options.Criteria["wotagsany"].ToObject(); var woitemtags = options.Criteria["woitemtags"].ToObject>(); bool woitemtagsany = options.Criteria["woitemtagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); - string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorderitem.tags", woitemtags, woitemtagsany); ; + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); + string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorderitem.tags", woitemtags, woitemtagsany); ; _dataQuery = @$"SELECT row_to_json(t) as res from ( SELECT distinct(AWORKORDER.ID), diff --git a/server/AyaNova/kpi/WorkOrderOverduePersonalList.cs b/server/AyaNova/kpi/WorkOrderOverduePersonalList.cs index 4eb1ba91..c748f5ad 100644 --- a/server/AyaNova/kpi/WorkOrderOverduePersonalList.cs +++ b/server/AyaNova/kpi/WorkOrderOverduePersonalList.cs @@ -25,8 +25,8 @@ namespace AyaNova.KPI bool wotagsany = options.Criteria["wotagsany"].ToObject(); var woitemtags = options.Criteria["woitemtags"].ToObject>(); bool woitemtagsany = options.Criteria["woitemtagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); - string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorderitem.tags", woitemtags, woitemtagsany); ; + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); + string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorderitem.tags", woitemtags, woitemtagsany); ; _dataQuery = @$"SELECT row_to_json(t) as res from ( SELECT distinct(AWORKORDER.ID), diff --git a/server/AyaNova/kpi/WorkOrderStatusCount.cs b/server/AyaNova/kpi/WorkOrderStatusCount.cs index db35752f..dd2dfc81 100644 --- a/server/AyaNova/kpi/WorkOrderStatusCount.cs +++ b/server/AyaNova/kpi/WorkOrderStatusCount.cs @@ -45,7 +45,7 @@ namespace AyaNova.KPI var dateWhere = DataListSqlFilterCriteriaBuilder.DataFilterToColumnCriteria("aworkorder.createddate", UiFieldDataType.DateTime, "no-operator", timeSpan, options.ClientTimeStamp); var wotags = options.Criteria["wotags"].ToObject>(); bool wotagsany = options.Criteria["wotagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); _dataQuery = @$"SELECT row_to_json(t) as res from ( SELECT COUNT(AWORKORDER.ID) Y,DATE_TRUNC('{interval}', AWORKORDER.createddate) X, aworkorder.laststatusid Z diff --git a/server/AyaNova/kpi/WorkOrderStatusPct.cs b/server/AyaNova/kpi/WorkOrderStatusPct.cs index 6ddbb449..ee30ab2c 100644 --- a/server/AyaNova/kpi/WorkOrderStatusPct.cs +++ b/server/AyaNova/kpi/WorkOrderStatusPct.cs @@ -45,7 +45,7 @@ namespace AyaNova.KPI var dateWhere = DataListSqlFilterCriteriaBuilder.DataFilterToColumnCriteria("aworkorder.createddate", UiFieldDataType.DateTime, "no-operator", timeSpan, options.ClientTimeStamp); var wotags = options.Criteria["wotags"].ToObject>(); bool wotagsany = options.Criteria["wotagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); _dataQuery = @$"SELECT row_to_json(t) as res from ( WITH SUBQ AS diff --git a/server/AyaNova/kpi/WorkOrderUnscheduledOpenList.cs b/server/AyaNova/kpi/WorkOrderUnscheduledOpenList.cs index 397b4b7b..6d168db4 100644 --- a/server/AyaNova/kpi/WorkOrderUnscheduledOpenList.cs +++ b/server/AyaNova/kpi/WorkOrderUnscheduledOpenList.cs @@ -45,8 +45,8 @@ AuthorizationRoles.TechRestricted; bool wotagsany = options.Criteria["wotagsany"].ToObject(); var woitemtags = options.Criteria["woitemtags"].ToObject>(); bool woitemtagsany = options.Criteria["woitemtagsany"].ToObject(); - string woTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorder.tags", wotags, wotagsany); - string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.KPITagFilterToSqlCriteria("aworkorderitem.tags", woitemtags, woitemtagsany); ; + string woTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorder.tags", wotags, wotagsany); + string woItemTagsWhere = DataListSqlFilterCriteriaBuilder.TagFilterToSqlCriteriaHelper("aworkorderitem.tags", woitemtags, woitemtagsany); ; diff --git a/server/AyaNova/models/AyContext.cs b/server/AyaNova/models/AyContext.cs index ab1c1504..72503dc6 100644 --- a/server/AyaNova/models/AyContext.cs +++ b/server/AyaNova/models/AyContext.cs @@ -128,6 +128,7 @@ namespace AyaNova.Models public virtual DbSet ViewScheduleWorkOrder { get; set; } public virtual DbSet CustomerNotifySubscription { get; set; } + public virtual DbSet CustomerNotifyEvent { get; set; } diff --git a/server/AyaNova/models/CustomerNotifyEvent.cs b/server/AyaNova/models/CustomerNotifyEvent.cs new file mode 100644 index 00000000..743cfc68 --- /dev/null +++ b/server/AyaNova/models/CustomerNotifyEvent.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using AyaNova.Biz; +using System.ComponentModel.DataAnnotations; +using Newtonsoft.Json; + +namespace AyaNova.Models +{ + //Customer notification event + public class CustomerNotifyEvent + { + public long Id { get; set; } + public uint Concurrency { get; set; } + + [Required] + public DateTime Created { get; set; } + public AyaType AyaType { get; set; } + public long ObjectId { get; set; } + [Required] + public string Name { get; set; }//object name or closest equivalent for display + [Required] + public NotifyEventType EventType { get; set; } + [Required] + public long CustomerId { get; set; } + [Required] + public long CustomerNotifySubscriptionId { get; set; }//source subscription that triggered this event to be created + + 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; } + public string Message { get; set; } + + + public CustomerNotifyEvent() + { + Created = EventDate = DateTime.UtcNow; + // IdValue = 0; + DecValue = 0; + AyaType = AyaType.NoType; + ObjectId = 0; + Name = string.Empty; + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.None); + } + + //linked entity + // public NotifySubscription NotifySubscription { get; set; } + // public User User { get; set; } + + }//eoc + +}//eons diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs index cba2c4ee..41b7bfd5 100644 --- a/server/AyaNova/util/AySchema.cs +++ b/server/AyaNova/util/AySchema.cs @@ -1213,6 +1213,9 @@ $BODY$ LANGUAGE PLPGSQL STABLE"); + "idvalue BIGINT NOT NULL, decvalue DECIMAL(38,18) NOT NULL, agevalue INTERVAL NOT NULL, " + "linkreportid BIGINT, template TEXT NOT NULL, tags VARCHAR(255) ARRAY)"); + await ExecQueryAsync("CREATE TABLE acustomernotifyevent (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created TIMESTAMPTZ NOT NULL, " + + "ayatype INTEGER NOT NULL, objectid BIGINT NOT NULL, name TEXT NOT NULL, eventtype INTEGER NOT NULL, customernotifysubscriptionid BIGINT NOT NULL REFERENCES acustomernotifysubscription(id) ON DELETE CASCADE, " + + "customerid BIGINT NOT NULL REFERENCES acustomer (id) ON DELETE CASCADE, eventdate TIMESTAMPTZ NOT NULL, decvalue DECIMAL(38,18) NULL, message TEXT)");