From e6545c4d35d73e059b16ddf01eacf3aa838504a9 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 23 Jul 2020 21:57:31 +0000 Subject: [PATCH] --- devdocs/specs/core-notification.txt | 6 ++-- server/AyaNova/biz/NotifyEventProcessor.cs | 12 +++---- server/AyaNova/biz/NotifyEventType.cs | 2 +- server/AyaNova/generator/CoreJobNotify.cs | 39 +++++++++++++++++----- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/devdocs/specs/core-notification.txt b/devdocs/specs/core-notification.txt index 01549870..395a638c 100644 --- a/devdocs/specs/core-notification.txt +++ b/devdocs/specs/core-notification.txt @@ -21,7 +21,7 @@ BACKEND TODO / SYSTEM FOR RAVEN IMPLEMENTATION PATH / PLAN - code as minimal a route as possible to get to working notifications end to end with minimal subset - first is test notification which is done as an implementation of the DefaultNotification Event type and is delivered to the current use running the test + first is test notification which is done as an implementation of the GeneralNotification Event type and is delivered to the current use running the test This will go through all potential problems or maybe trigger a troubleshoot route at teh server that checks all and reports back with any issues found Also needs to be localized (do the test route thing, that just makes the most sense. The test route should accept the type of notification i.e. inapp or smtp, act accordingly if it's a customer user vs regular if there is any difference) Should report to user exactly any issues found at any level preventing it from happening @@ -228,7 +228,7 @@ QuoteStatusChanged [CUSTOMER] [CONDITION: QUOTESTATUS integer] ServiceBank[Currency/Hours/Incidents]Depleted [GENERAL] NewCSR [GENERAL] NewMemo [PERSONAL] -QuickNotification DEPRECATED replaced by DefaultNotification below [PERSONAL] +QuickNotification DEPRECATED replaced by GeneralNotification below [PERSONAL] QuoteCreatedUpdated - a bit weird, which is it created or updated? :) [GENERAL] ScheduleMarkerImminent (now "reminder") [PERSONAL] ScheduleMarkerCreated (now "reminder") [PERSONAL] @@ -259,7 +259,7 @@ https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1137 QuoteStatusAge [PERSONAL (prepared by), GENERAL] [CONDITION: AGEVALUE] UnitWarranyExpiry case 1361 [GENERAL] UnitMeterReadingMultipleExceeded case 1254 [GENERAL] -DefaultNotification case 3792 used for all system and old Quick notifications [EVERYONE] +GeneralNotification 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 deprecated, use objectCRUD events for this: TagNotification case 3799 [CONDITION: tag, , ayatype global/specific] diff --git a/server/AyaNova/biz/NotifyEventProcessor.cs b/server/AyaNova/biz/NotifyEventProcessor.cs index 2712f950..a3808c2c 100644 --- a/server/AyaNova/biz/NotifyEventProcessor.cs +++ b/server/AyaNova/biz/NotifyEventProcessor.cs @@ -39,7 +39,7 @@ namespace AyaNova.Biz //This handles general notification events not requiring a decision or tied to an object that are basically just a immediate message to the user - //e.g. ops problems, DefaultNotification, NotifyHealthCheck etc + //e.g. ops problems, GeneralNotification, NotifyHealthCheck etc //optional user id to send directly to them internal static async Task AddGeneralNotifyEvent(NotifyEventType eventType, string message, Exception except = null, long userId = 0) { @@ -48,7 +48,7 @@ namespace AyaNova.Biz switch (eventType) { case NotifyEventType.BackupStatus: - case NotifyEventType.DefaultNotification: + case NotifyEventType.GeneralNotification: case NotifyEventType.NotifyHealthCheck://created by job processor itself case NotifyEventType.ServerOperationsProblem: break; @@ -56,7 +56,7 @@ namespace AyaNova.Biz throw (new System.NotSupportedException($"NotifyEventProcessor:AddGeneralNotifyEvent - Type of event {eventType} is unexpected and not supported")); } - if (eventType != NotifyEventType.DefaultNotification && userId != 0) + if (eventType != NotifyEventType.GeneralNotification && userId != 0) { throw (new System.NotSupportedException($"NotifyEventProcessor:AddGeneralNotifyEvent - event {eventType} was specified with user id {userId} which is unexpected and not supported")); } @@ -67,14 +67,14 @@ namespace AyaNova.Biz using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext) { - //Default notification goes to a specific user only + //General notification goes to a specific user only //no need to consult subscriptions - if (eventType == NotifyEventType.DefaultNotification) + if (eventType == NotifyEventType.GeneralNotification) { if (userId == 0) { //this will likely be a development error, not a production error so no need to log etc - throw new System.ArgumentException("NotifyEventProcessor:AddGeneralNotifyEvent: DefaultNotification requires a user id but none was specified"); + 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(); NotifyEvent n = new NotifyEvent() { EventType = eventType, UserId = userId, Message = message, NotifySubscriptionId = 0, Name = UserName }; diff --git a/server/AyaNova/biz/NotifyEventType.cs b/server/AyaNova/biz/NotifyEventType.cs index 0b884919..4a2d767c 100644 --- a/server/AyaNova/biz/NotifyEventType.cs +++ b/server/AyaNova/biz/NotifyEventType.cs @@ -36,7 +36,7 @@ namespace AyaNova.Biz WorkorderStatusAge = 24,//* Workorder object Created / Updated, conditional on exact status selected IdValue, Tags conditional, advance notice can be set UnitWarrantyExpiry = 25,//* Unit object created, advance notice can be used, tag conditional UnitMeterReadingMultipleExceeded = 26,//* UnitMeterReading object, Created, conditional on DecValue as the Multiple threshold, if passed then notifies - DefaultNotification = 27,//* NO OBJECT old quick notification, refers now to any direct text notification internal or user to user used for system notifications (default delivers in app but user can opt to also get email) + GeneralNotification = 27,//* NO OBJECT old quick notification, refers now to any direct text notification internal or user to user used for system notifications (default delivers in app but user can opt to also get email) ServerOperationsProblem = 28,//* NO OBJECT and serious issue with server operations requiring intervention, QuoteStatusAge = 29//* Quote object Created / Updated, conditional on exact status selected IdValue, Tags conditional, advance notice can be set diff --git a/server/AyaNova/generator/CoreJobNotify.cs b/server/AyaNova/generator/CoreJobNotify.cs index 88eef5a1..a27eb62c 100644 --- a/server/AyaNova/generator/CoreJobNotify.cs +++ b/server/AyaNova/generator/CoreJobNotify.cs @@ -200,13 +200,14 @@ namespace AyaNova.Biz private static async Task DeliverSMTP(NotifyEvent ne, AyContext ct) { - log.LogTrace($"DeliverSMTP deliving notify event: {ne}"); + log.LogTrace($"DeliverSMTP delivering notify event: {ne}"); if (string.IsNullOrWhiteSpace(ne.NotifySubscription.DeliveryAddress)) { - await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.DefaultNotification, $"Error: no email address is set in subscription to deliver email notification for this event:{ne}", null, ne.UserId); - + await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"Error: no email address is set in subscription to deliver email notification for this event:{ne}", null, ne.UserId); } + + var transid = _UserTranslationIdCache[ne.NotifySubscription.UserId]; var subject = $"AY:{GetTranslatedNotifyEventName(ne.EventType, transid)}:{ne.Name}"; @@ -216,17 +217,24 @@ namespace AyaNova.Biz var body = ""; if (ne.ObjectId != 0) { - body = OpenObjectUrlBuilder(ne.AyaType, ne.ObjectId) + "\n"; + body = OpenObjectUrlBuilder(ne.AyaType, ne.ObjectId, ne.EventType) + "\n"; } body += ne.Message; - await m.SendEmailAsync(ne.NotifySubscription.DeliveryAddress, subject, body, ServerGlobalOpsSettingsCache.Notify); - + if (!ServerGlobalOpsSettingsCache.Notify.SmtpDeliveryActive) + { + await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"Email notifications are set to OFF at server, unable to send email notification for this event:{ne}", null, ne.UserId); + log.LogInformation($"** WARNING: SMTP notification is currently set to Active=False; unable to deliver email notification, re-routed to in-app notification instead [UserId={ne.UserId}, Notify subscription={ne.NotifySubscriptionId}]. Change this setting or have users remove email delivery notifications if this is permanent **"); + } + else + { + await m.SendEmailAsync(ne.NotifySubscription.DeliveryAddress, subject, body, ServerGlobalOpsSettingsCache.Notify); + } } catch (Exception ex) { await NotifyEventProcessor.AddOpsProblemEvent("SMTP Notification failed", ex); - await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.DefaultNotification, $"Error: an error prevented delivering the following notification via email. System operator users have been notified:{ne}", null, ne.UserId); + await NotifyEventProcessor.AddGeneralNotifyEvent(NotifyEventType.GeneralNotification, $"Error: an error prevented delivering the following notification via email. System operator users have been notified:{ne}", null, ne.UserId); } finally { @@ -260,7 +268,7 @@ namespace AyaNova.Biz //Open object url //### NOTE: If this is required anywhere else, move it to a central BizUtils class in Biz folder callable from here and there - private static string OpenObjectUrlBuilder(AyaType otype, long id) + private static string OpenObjectUrlBuilder(AyaType otype, long id, NotifyEventType net) { var ServerUrl = ServerGlobalOpsSettingsCache.Notify.AyaNovaServerURL; if (string.IsNullOrWhiteSpace(ServerUrl)) @@ -269,6 +277,21 @@ namespace AyaNova.Biz return "OPS ERROR NO SERVER URL CONFIGURED"; } ServerUrl = ServerUrl.Trim().TrimEnd('/'); + + //Might not have a type or id in which case nothing directly to open + if (otype == AyaType.NoType || id == 0) + { + return ServerUrl; + } + + if (NotifyEventType.ObjectDeleted == net) + { + //goto event log for item + // path: "/history/:ayatype/:recordid/:userlog?", + return $"{ServerUrl}/history/{(int)otype}/{id}"; + } + + //default is to open the object in question directly return $"{ServerUrl}/open/{(int)otype}/{id}"; }