This commit is contained in:
2020-07-16 17:58:23 +00:00
parent 35bf96e5c0
commit 9f0944d37b
10 changed files with 50 additions and 54 deletions

View File

@@ -66,8 +66,8 @@ TODO: Translation keys needed:
NotifyDeliveryMethod NotifyDeliveryMethod
NotifyEventType NotifyEventType
NotifyDeliveryAddress NotifyDeliveryAddress
InTags tags
OutTags
todo: updating subscriptions must clear out old events and notifications if they are affected todo: updating subscriptions must clear out old events and notifications if they are affected
@@ -109,9 +109,9 @@ OBJECTS Saving an object triggers notification processing for that object:
DUPES - there can be near dupes here because user may have multiple of identical but vary in only: DUPES - there can be near dupes here because user may have multiple of identical but vary in only:
Delivery method Delivery method
advancenoticetimespan (e.g. contract expiring could be one 90 days in advance to renegotiate and then one 10 days in advance for notify service to cancel etc) advancenoticetimespan (e.g. contract expiring could be one 90 days in advance to renegotiate and then one 10 days in advance for notify service to cancel etc)
InTags - notify applies if has these tags tags - notify applies if has these tags
empty means any empty means any
OutTags - notify cancelled if has these tags s - notify cancelled if has these tags
empty means any empty means any
out trumps an in, default is safer option out trumps an in, default is safer option
@@ -186,11 +186,11 @@ MailMessageDelivery
/notifysubscription table - contains all user (and customer user) subscriptions to events and delivery method, if user wants two delivery /notifysubscription table - contains all user (and customer user) subscriptions to events and delivery method, if user wants two delivery
methods they have two entries here, no other table indicates events to be tracked, has user id methods they have two entries here, no other table indicates events to be tracked, has user id
also ayatype GLOBAL means that the subscription applies to events of any corebiz type also ayatype must be specific not GLOBAL to avoid a "sorcerers apprentice" runaway issue and many role related issues potentially
so for example a CreatedWithTag notification or UpdatedWithTag notification will work on any object with that tag if global or a specific type i.e. customer with that tag so for example a CreatedWithTag notification or UpdatedWithTag notification will work on any object with that tag if a specific type i.e. customer with that tag
Then they can control by tag as well, intags are used to filter and include (or any if no intags), outtags filter out and trump intags Then they can control by tag as well, tags are used to filter and include (or any if no tags), s filter out and trump tags
These are also used for tag type conditions These are also used for tag type conditions
(aID, userId, ayatype, aEventType, advancenoticetimespan, agevalue, idvalue, decvalue, aDeliveryMethod, deliveryaddress, attachreportid, intags, outtags, HASH) (aID, userId, ayatype, aEventType, advancenoticetimespan, agevalue, idvalue, decvalue, aDeliveryMethod, deliveryaddress, attachreportid, tags, s, HASH)
/Notifyevent table - contains all events, created by updating objects or directly in some cases and used by generator for processing as deliveries /Notifyevent table - contains all events, created by updating objects or directly in some cases and used by generator for processing as deliveries
created (timestamp used to clean out old stuck events), ayatype, objectid, eventtype, appliestouserid (single subscriber event), aEventDate, ASAVEDMESSAGE, HASH? created (timestamp used to clean out old stuck events), ayatype, objectid, eventtype, appliestouserid (single subscriber event), aEventDate, ASAVEDMESSAGE, HASH?
@@ -261,13 +261,16 @@ UnitMeterReadingMultipleExceeded case 1254 [GENERAL]
DefaultNotification case 3792 used for all system and old Quick notifications [EVERYONE] DefaultNotification case 3792 used for all system and old Quick notifications [EVERYONE]
Always present for inapp, user can add more for email if they want and filters or whatever but there is always a built in non-visible subscription to inapp for this Always present for inapp, user can add more for email if they want and filters or whatever but there is always a built in non-visible subscription to inapp for this
deprecated, use objectCUD events for this: TagNotification case 3799 [CONDITION: intag, outtag, ayatype global/specific] deprecated, use objectCUD events for this: TagNotification case 3799 [CONDITION: tag, , ayatype global/specific]
(Note: this is actually just general notification if an object is created or updated and the tagging is optional) (Note: this is actually just general notification if an object is created or updated and the tagging is optional)
CRUD Notifications: CRUD Notifications:
(note: tag filterable and also can select type specifically or global for any type) (note: tag filterable and select type specifically. Global is not a valid type for this to avoid issues)
(note: differs from tag notification above in that only applies on a CHANGE of TAGS, this is an always for this op and tags are just an optional filter) (note:
[CONDITION: intag, outtag, ayatype global/specific]
### WHAT DOES THIS MEAN?:differs from tag notification above in that only applies on a CHANGE of TAGS, this is an always for this op and tags are just an optional filter)
[CONDITION: tag, , ayatype specific]
ObjectCreated ObjectCreated
ObjectUpdated ObjectUpdated
ObjectDeleted ObjectDeleted

View File

@@ -37,12 +37,10 @@ namespace AyaNova.DataList
dlistView.Add(cm); dlistView.Add(cm);
cm = new JObject(); cm = new JObject();
cm.fld = "intags"; cm.fld = "tags";
dlistView.Add(cm); dlistView.Add(cm);
cm = new JObject();
cm.fld = "outtags";
dlistView.Add(cm);
DefaultListView = dlistView.ToString(Newtonsoft.Json.Formatting.None); DefaultListView = dlistView.ToString(Newtonsoft.Json.Formatting.None);
@@ -104,16 +102,11 @@ namespace AyaNova.DataList
FieldDefinitions.Add(new AyaDataListFieldDefinition FieldDefinitions.Add(new AyaDataListFieldDefinition
{ {
TKey = "InTags", TKey = "InTags",
FieldKey = "intags", FieldKey = "tags",
UiFieldDataType = (int)UiFieldDataType.Tags UiFieldDataType = (int)UiFieldDataType.Tags
}); });
FieldDefinitions.Add(new AyaDataListFieldDefinition
{
TKey = "OutTags",
FieldKey = "outtags",
UiFieldDataType = (int)UiFieldDataType.Tags
});
} }

View File

@@ -37,22 +37,30 @@ namespace AyaNova.Biz
await AddEvent(new NotifyEvent() { EventType = NotifyEventType.ServerOperationsProblem, Message = message }); await AddEvent(new NotifyEvent() { EventType = NotifyEventType.ServerOperationsProblem, Message = message });
} }
//Add event if there are subscribers
public static async Task AddEvent(NotifyEvent ev) public static async Task AddEvent(NotifyEvent ev, List<string> inTags = null)
{ {
log.LogTrace($"AddEvent processing: [{ev.ToString()}]"); log.LogTrace($"AddEvent processing: [{ev.ToString()}]");
try try
{ {
List<NotifySubscription> subs = new List<NotifySubscription>();
log.LogTrace("Notify set to RUNNING state and starting now");
using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext) using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext)
{ {
//iterate subs, figure out who gets this event //iterate subs, figure out who gets this event
//add to table for any that do //add to table for any that do
var subs=await ct.NotifySubscription.AsNoTracking().Where(z=>z.EventType==ev.EventType &&) if (inTags == null || inTags.Count==0)
{
//No tags
subs = await ct.NotifySubscription.AsNoTracking().Where(z => z.EventType == ev.EventType && z.AyaType == ev.AyaType).ToListAsync();
}
else
{
//In tags
}
} }
} }

View File

@@ -47,14 +47,12 @@ namespace AyaNova.Biz
return null; return null;
else else
{ {
newObject.InTags = TagBiz.NormalizeTags(newObject.InTags); newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
newObject.OutTags = TagBiz.NormalizeTags(newObject.OutTags);
await ct.NotifySubscription.AddAsync(newObject); await ct.NotifySubscription.AddAsync(newObject);
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.InTags, null); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.OutTags, null);
return newObject; return newObject;
} }
} }
@@ -80,8 +78,7 @@ namespace AyaNova.Biz
await ct.SaveChangesAsync(); await ct.SaveChangesAsync();
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct);
//await SearchIndexAsync(newObject, true); //await SearchIndexAsync(newObject, true);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.InTags, null); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.OutTags, null);
return newObject; return newObject;
} }
@@ -112,8 +109,7 @@ namespace AyaNova.Biz
NotifySubscription SnapshotOfOriginalDBObj = new NotifySubscription(); NotifySubscription SnapshotOfOriginalDBObj = new NotifySubscription();
CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj); CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
CopyObject.Copy(putObject, dbObject, "Id");//can update serial CopyObject.Copy(putObject, dbObject, "Id");//can update serial
dbObject.InTags = TagBiz.NormalizeTags(dbObject.InTags); dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
dbObject.OutTags = TagBiz.NormalizeTags(dbObject.OutTags);
ct.Entry(dbObject).OriginalValues["Concurrency"] = putObject.Concurrency; ct.Entry(dbObject).OriginalValues["Concurrency"] = putObject.Concurrency;
await ValidateAsync(dbObject); await ValidateAsync(dbObject);
@@ -131,8 +127,7 @@ namespace AyaNova.Biz
return null; return null;
} }
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.InTags, SnapshotOfOriginalDBObj.InTags); await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.OutTags, SnapshotOfOriginalDBObj.OutTags);
return dbObject; return dbObject;
} }
@@ -159,8 +154,7 @@ namespace AyaNova.Biz
//Log event //Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.EventType.ToString(), ct); await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.EventType.ToString(), ct);
// await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct); // await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.InTags); await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.OutTags);
//await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct); //await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
//TODO: DELETE RELATED RECORDS HERE //TODO: DELETE RELATED RECORDS HERE
//all good do the commit //all good do the commit

View File

@@ -15,10 +15,7 @@ namespace AyaNova.Models
public uint Concurrency { get; set; } public uint Concurrency { get; set; }
[Required] [Required]
public long UserId { get; set; } public long UserId { get; set; }
public AyaType? AyaType { get; set; }//Note: could be Global meaning any corebiz object would be included if relevant (e.g. ObjectCreated)
[Required]
public NotifyEventType EventType { get; set; }
public TimeSpan? AdvanceNotice { get; set; } //Note: I've been doing nullable wrong sort of: https://stackoverflow.com/a/29149207/8939 public TimeSpan? AdvanceNotice { get; set; } //Note: I've been doing nullable wrong sort of: https://stackoverflow.com/a/29149207/8939
public long? IdValue { get; set; } public long? IdValue { get; set; }
public decimal? DecValue { get; set; } public decimal? DecValue { get; set; }
@@ -27,13 +24,18 @@ namespace AyaNova.Models
public NotifyDeliveryMethod DeliveryMethod { get; set; } public NotifyDeliveryMethod DeliveryMethod { get; set; }
public string DeliveryAddress { get; set; } public string DeliveryAddress { get; set; }
public long? AttachReportId { get; set; } public long? AttachReportId { get; set; }
public List<string> InTags { get; set; }
public List<string> OutTags { get; set; }
//CONDITIONS - Following fields are all conditions set on whether to notify or not
public AyaType AyaType { get; set; }//Note: must be specific object, not global for any object related stuff to avoid many role issues and also potential overload
[Required]
public NotifyEventType EventType { get; set; }
public List<string> Tags { get; set; }//Tags to filter an event, object *must* have these tags to generate event related to it (AT TIME OF UPDATE)
public NotifySubscription() public NotifySubscription()
{ {
InTags = new List<string>(); Tags = new List<string>();
OutTags = new List<string>(); AyaType= AyaType.NoType;
} }
}//eoc }//eoc

View File

@@ -1857,7 +1857,6 @@
"NotifyEventType": "Benachrichtigungsereignis", "NotifyEventType": "Benachrichtigungsereignis",
"NotifyDeliveryAddress": "An Adresse liefern", "NotifyDeliveryAddress": "An Adresse liefern",
"InTags": "Filtern Sie in diesen Tags", "InTags": "Filtern Sie in diesen Tags",
"OutTags": "Filtern Sie diese Tags heraus",
"NotifyEventObjectDeleted": "Objekt gelöscht", "NotifyEventObjectDeleted": "Objekt gelöscht",
"NotifyEventObjectCreated": "Objekt erstellt", "NotifyEventObjectCreated": "Objekt erstellt",
"NotifyEventObjectModified": "Objekt geändert", "NotifyEventObjectModified": "Objekt geändert",

View File

@@ -1857,7 +1857,6 @@
"NotifyEventType": "Notification event", "NotifyEventType": "Notification event",
"NotifyDeliveryAddress": "Deliver to address", "NotifyDeliveryAddress": "Deliver to address",
"InTags": "Filter include tags", "InTags": "Filter include tags",
"OutTags": "Filter exclude tags",
"NotifyEventObjectDeleted": "Object deleted", "NotifyEventObjectDeleted": "Object deleted",
"NotifyEventObjectCreated": "Object created", "NotifyEventObjectCreated": "Object created",
"NotifyEventObjectModified": "Object changed", "NotifyEventObjectModified": "Object changed",

View File

@@ -1857,7 +1857,6 @@
"NotifyEventType": "Evento de notificación", "NotifyEventType": "Evento de notificación",
"NotifyDeliveryAddress": "Entregar a la dirección de correo electrónico", "NotifyDeliveryAddress": "Entregar a la dirección de correo electrónico",
"InTags": "Filtrar incluir etiquetas", "InTags": "Filtrar incluir etiquetas",
"OutTags": "Filtrar etiquetas excluidas",
"NotifyEventObjectDeleted": "Objeto eliminado", "NotifyEventObjectDeleted": "Objeto eliminado",
"NotifyEventObjectCreated": "Objeto creado", "NotifyEventObjectCreated": "Objeto creado",
"NotifyEventObjectModified": "Objeto cambiado", "NotifyEventObjectModified": "Objeto cambiado",

View File

@@ -1857,7 +1857,6 @@
"NotifyEventType": "Événement de notification", "NotifyEventType": "Événement de notification",
"NotifyDeliveryAddress": "Livrer à l'adresse", "NotifyDeliveryAddress": "Livrer à l'adresse",
"InTags": "Filtrer les balises inclusives", "InTags": "Filtrer les balises inclusives",
"OutTags": "Filtrer les tags exclusifs",
"NotifyEventObjectDeleted": "Objet supprimé", "NotifyEventObjectDeleted": "Objet supprimé",
"NotifyEventObjectCreated": "Objet créé", "NotifyEventObjectCreated": "Objet créé",
"NotifyEventObjectModified": "Objet changé", "NotifyEventObjectModified": "Objet changé",

View File

@@ -684,8 +684,8 @@ $BODY$;
LogUpdateMessage(log); LogUpdateMessage(log);
await ExecQueryAsync("CREATE TABLE anotifysubscription (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, " + await ExecQueryAsync("CREATE TABLE anotifysubscription (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, " +
"userid bigint not null, ayatype integer, eventtype integer not null, advancenotice interval, " + "userid bigint not null, ayatype integer not null, eventtype integer not null, advancenotice interval, " +
"idvalue bigint, decvalue decimal(19,4), agevalue interval, deliverymethod integer not null, deliveryaddress text, attachreportid bigint, intags varchar(255) ARRAY, outtags varchar(255) ARRAY)"); "idvalue bigint, decvalue decimal(19,4), agevalue interval, deliverymethod integer not null, deliveryaddress text, attachreportid bigint, tags varchar(255) ARRAY)");
await ExecQueryAsync("CREATE TABLE anotifyevent (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created timestamp not null, " + await ExecQueryAsync("CREATE TABLE anotifyevent (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created timestamp not null, " +
"ayatype integer, objectid bigint, eventtype integer not null, subscriptionid bigint not null, idvalue bigint, decvalue decimal(19,4), eventdate timestamp, deliverdate timestamp, message text)"); "ayatype integer, objectid bigint, eventtype integer not null, subscriptionid bigint not null, idvalue bigint, decvalue decimal(19,4), eventdate timestamp, deliverdate timestamp, message text)");