This commit is contained in:
2020-12-22 19:46:46 +00:00
parent 290b39be15
commit 18df3ab55e
4 changed files with 134 additions and 92 deletions

View File

@@ -33,6 +33,7 @@ namespace AyaNova.DataList
cm = new JObject();
cm.fld = "ReviewName";
dlistView.Add(cm);
cm = new JObject();
cm.fld = "Object";
dlistView.Add(cm);

View File

@@ -28,7 +28,7 @@ namespace AyaNova.Biz
if (ex != null)
{
//actually, if there is an exception it's already logged anyway so don't re-log it here, just makes dupes
// log.LogError(ex, $"Ops problem notification: \"{message}\"");
// log.LogError(ex, $"Ops problem notification: \"{message}\"");
message += $"\nException error: {ExceptionUtil.ExtractAllExceptionMessages(ex)}";
}
else
@@ -77,16 +77,10 @@ namespace AyaNova.Biz
throw new System.ArgumentException("NotifyEventProcessor:AddGeneralNotifyEvent: GeneralNotification requires a user id but none was specified");
}
var UserName = await ct.User.Where(z => z.Id == userId).Select(z => z.Name).FirstOrDefaultAsync();
var UserName = await ct.User.AsNoTracking().Where(z => z.Id == userId).Select(z => z.Name).FirstOrDefaultAsync();
//if they don't have a regular inapp subscription create one now
var defaultsub = await ct.NotifySubscription.FirstOrDefaultAsync(z => z.EventType == NotifyEventType.GeneralNotification && z.UserId == userId && z.DeliveryMethod == NotifyDeliveryMethod.App);
if (defaultsub == null)
{
defaultsub = new NotifySubscription() { UserId = userId, EventType = NotifyEventType.GeneralNotification, DeliveryMethod = NotifyDeliveryMethod.App };
await ct.NotifySubscription.AddAsync(defaultsub);
await ct.SaveChangesAsync();
}
NotifySubscription defaultsub = await EnsureDefaultInAppUserNotificationSubscriptionExists(userId, ct);
if (string.IsNullOrWhiteSpace(name))
{
@@ -125,6 +119,29 @@ namespace AyaNova.Biz
}//eom
private static async Task<NotifySubscription> EnsureDefaultInAppUserNotificationSubscriptionExists(long userId, AyContext ct)
{
var defaultsub = await ct.NotifySubscription.FirstOrDefaultAsync(z => z.EventType == NotifyEventType.GeneralNotification && z.UserId == userId && z.DeliveryMethod == NotifyDeliveryMethod.App);
if (defaultsub == null)
{
//NOTE: agevalue and advanced notice settings here will ensure that direct in app notifications with a future delivery date set in their
//notifyevent.eventdate will deliver on that date and not immediately to support all the things that are direct built in notifications
//such as for an overdue Review which doesn't have or need it's own notifyeventtype and subscription independently
defaultsub = new NotifySubscription()
{
UserId = userId,
EventType = NotifyEventType.GeneralNotification,
DeliveryMethod = NotifyDeliveryMethod.App,
AgeValue = new TimeSpan(0, 0, 1),
AdvanceNotice = new TimeSpan(0, 0, 1)
};
await ct.NotifySubscription.AddAsync(defaultsub);
await ct.SaveChangesAsync();
}
return defaultsub;
}
@@ -160,6 +177,56 @@ namespace AyaNova.Biz
// generally being created notifications are further down below
switch (newObject.AyaType)
{
case AyaType.Review:
{
//set a deadman automatic internal notification if goes past due
var r = (Review)newObject;
var userNotifySub = await EnsureDefaultInAppUserNotificationSubscriptionExists(r.UserId, ct);
NotifySubscription supervisorNotifySub = null;
if (r.UserId != r.AssignedByUserId)
{
supervisorNotifySub = await EnsureDefaultInAppUserNotificationSubscriptionExists(r.AssignedByUserId, ct);
}
//it not completed yet and not overdue already (which could indicate an import or something)
if (r.CompletedDate == null && r.DueDate > DateTime.UtcNow)
{
{
NotifyEvent n = new NotifyEvent()
{
EventType = NotifyEventType.GeneralNotification,
UserId = r.UserId,
ObjectId = newObject.Id,
AyaType = AyaType.Review,
NotifySubscriptionId = userNotifySub.Id,
Name = "LT:ReviewOverDue - " + newObject.Name,
EventDate = r.DueDate.AddMinutes(1)
};
await ct.NotifyEvent.AddAsync(n);
log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
}
if (supervisorNotifySub != null)
{
NotifyEvent n = new NotifyEvent()
{
EventType = NotifyEventType.GeneralNotification,
UserId = r.AssignedByUserId,
ObjectId = newObject.Id,
AyaType = AyaType.Review,
NotifySubscriptionId = supervisorNotifySub.Id,
Name = "LT:ReviewOverDue - " + newObject.Name,
EventDate = r.DueDate.AddMinutes(1)
};
await ct.NotifyEvent.AddAsync(n);
log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
}
}
}
break;
//AyaTypes with their own special notification related events
case AyaType.WorkOrder:
{
@@ -292,6 +359,56 @@ namespace AyaNova.Biz
//
switch (newObject.AyaType)
{
case AyaType.Review:
{
//set a deadman automatic internal notification if goes past due
var r = (Review)newObject;
var userNotifySub = await EnsureDefaultInAppUserNotificationSubscriptionExists(r.UserId, ct);
NotifySubscription supervisorNotifySub = null;
if (r.UserId != r.AssignedByUserId)
{
supervisorNotifySub = await EnsureDefaultInAppUserNotificationSubscriptionExists(r.AssignedByUserId, ct);
}
//it not completed yet and not overdue already (which could indicate an import or something)
if (r.CompletedDate == null && r.DueDate > DateTime.UtcNow)
{
{
NotifyEvent n = new NotifyEvent()
{
EventType = NotifyEventType.GeneralNotification,
UserId = r.UserId,
ObjectId = newObject.Id,
AyaType = AyaType.Review,
NotifySubscriptionId = userNotifySub.Id,
Name = "LT:ReviewOverDue - " + newObject.Name,
EventDate = r.DueDate.AddMinutes(1)
};
await ct.NotifyEvent.AddAsync(n);
log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
}
if (supervisorNotifySub != null)
{
NotifyEvent n = new NotifyEvent()
{
EventType = NotifyEventType.GeneralNotification,
UserId = r.AssignedByUserId,
ObjectId = newObject.Id,
AyaType = AyaType.Review,
NotifySubscriptionId = supervisorNotifySub.Id,
Name = "LT:ReviewOverDue - " + newObject.Name,
EventDate = r.DueDate.AddMinutes(1)
};
await ct.NotifyEvent.AddAsync(n);
log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
}
}
}
break;
//AyaTypes with their own special notification related events
case AyaType.WorkOrder:
{
@@ -514,89 +631,6 @@ namespace AyaNova.Biz
//################### FIRST ATTEMPT STUFF
// //find all the Notification subscription subs that are relevant
// //this first query ensures that the equality matching conditions of AyaType and EventType and idValue are matched leaving only more complex matches to rectify below
// var subs = await ct.NotifySubscription.AsNoTracking().Where(z => z.EventType == ev.EventType && z.AyaType == ev.AyaType && z.IdValue == ev.IdValue).ToListAsync();
// foreach (var sub in subs)
// {
// //CONDITION CHECK Tags condition
// if (sub.Tags.Count > 0)
// {
// if (!HasTags)
// continue;//not a match, this sub needs tags and we don't have any
// //bool existsCheck = list1.All(x => list2.Any(y => x.SupplierId == y.SupplierId));
// //would tell you if all of list1's items are in list2.
// if (!sub.Tags.All(z => inTags.Any(x => x == z)))
// continue;
// }
// //CONDITION CHECK Decimal value, so far only for "The Andy" so the only condition is that the event value be greater than or equal to subscription setting
// if (ev.EventType == NotifyEventType.WorkorderTotalExceedsThreshold && ev.DecValue < sub.DecValue)
// continue;
// //Here ready for delivery
// //HANDLE RELATED INDIRECT EVENTS AND CLEANUP
// //some event types create related events here automatically (e.g. WorkorderStatusChange in turn will trigger workorderstatusage if subbed here)
// //Deleting an object or changing status etc will affect other events in turn so clean up for them here
// switch (ev.EventType)
// {
// case NotifyEventType.ObjectDeleted:
// {
// //object is deleted so remove any other events pending for it
// //current working concept is there is no reason to keep any event related to a freshly deleted object
// var deleteEventList = await ct.NotifyEvent.Where(z => z.ObjectId == ev.ObjectId && z.AyaType == ev.AyaType).ToListAsync();
// ct.NotifyEvent.RemoveRange(deleteEventList);
// await ct.SaveChangesAsync();
// }
// break;
// case NotifyEventType.WorkorderStatusChange:
// {
// //Workorder status changed so remove any other prior workorderstatuschanged events and
// //remove any prior workorderstatusAge events for this object id
// var deleteEventList = await ct.NotifyEvent.Where(z => z.ObjectId == ev.ObjectId && z.AyaType == ev.AyaType && ev.EventType == NotifyEventType.WorkorderStatusChange).ToListAsync();
// ct.NotifyEvent.RemoveRange(deleteEventList);
// await ct.SaveChangesAsync();
// }
// break;
// case NotifyEventType.WorkorderStatusAge://delete any workorder status age ones because there is potentially a new status invalidating the old status
// case NotifyEventType.QuoteStatusAge:
// //Delete any existing ones
// var StaleAgedEvents = await ct.NotifyEvent.Where(z => z.EventType == ev.EventType && z.ObjectId == ev.ObjectId && z.AyaType == ev.AyaType).ToListAsync();
// break;
// }
// //AgeValue refresh?
// //Age based ones need to replace any prior existing age based ones made for the same object as they are the only ones that can sit in the queue for any length of time
// //and become invalidated (i.e. deadman type deliveries that sb removed if no longer applicable e.g. WorkorderStatusAge)
// switch (ev.EventType)
// {
// case NotifyEventType.ObjectAge://this is set on creation so it will never change unless the object is deleted
// case NotifyEventType.WorkorderStatusAge://delete any workorder status age ones because there is potentially a new status invalidating the old status
// case NotifyEventType.QuoteStatusAge:
// //Delete any existing ones
// var StaleAgedEvents = await ct.NotifyEvent.Where(z => z.EventType == ev.EventType && z.ObjectId == ev.ObjectId && z.AyaType == ev.AyaType).ToListAsync();
// break;
// }
// //Here we know the sub matches the event and passes all the conditions so set the deliver date if necessary and save the NotifyEvent here
// //todo: create message here (delivery thing?)
// //todo: Attach report here or is that a delivery thing (delivery thing)
// }
private static bool TagsMatch(List<string> objectTags, List<string> subTags)
{
//no subscription tags? Then it always will match

View File

@@ -44,6 +44,7 @@ namespace AyaNova.Biz
WorkorderFinishedFollowUp = 32, //* Service workorder closed status follow up again after this many TIMESPAN
SendUserCredentials = 33 // Internal System use only: When user generates new credentials and sends them this is the notification type for that see UserBiz GenerateCredsAndEmailUser
//NEW ITEMS REQUIRE translation KEYS
}

View File

@@ -130,6 +130,9 @@ namespace AyaNova.Biz
//when to time delay deliver formula:If sub.agevalue!= timespan.zero then deliver on =
//NotifyEvent "EventDate"+NotifySubscription.AgeValue timespan - NotifySubscription AdvanceNotice timespan > utcNow
//Is it time delayed?
//(NOTE: some direct notifications in app e.g. overdue review will have a future date set as a deadman switch to deliver after unless completed before then
//their EventDate will be that future date, however regular in app notifications will go through here too but their evendate will be the moment they are created so should still
//deliver immediately-ish)
if (notifyevent.NotifySubscription.AgeValue != TimeSpan.Zero)
{
var deliverAfter = notifyevent.EventDate + notifyevent.NotifySubscription.AgeValue - notifyevent.NotifySubscription.AdvanceNotice;
@@ -147,6 +150,9 @@ namespace AyaNova.Biz
}
else
{
//COULD BE TIME DELAYED BUT WITHOUT AGE, i.e. EventDate takes precedence?
//NORMAL IMMEDIATE DELIVERY EVENT
if (notifyevent.NotifySubscription.DeliveryMethod == NotifyDeliveryMethod.App)
{