diff --git a/.vscode/launch.json b/.vscode/launch.json
index d0cceaa8..d1ace0ad 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -40,9 +40,9 @@
"env": {
// "ASPNETCORE_ENVIRONMENT": "Development",
"AYANOVA_JWT_SECRET": "1111111MyRandom32CharacterSecret",
- "AYANOVA_LOG_LEVEL": "Info",
- //"AYANOVA_LOG_LEVEL": "Debug",
- // // "AYANOVA_LOG_LEVEL": "Trace",
+ //"AYANOVA_LOG_LEVEL": "Info",
+ "AYANOVA_LOG_LEVEL": "Debug",
+ //"AYANOVA_LOG_LEVEL": "Trace",
"AYANOVA_DEFAULT_TRANSLATION": "en",
"AYANOVA_DB_CONNECTION": "Server=localhost;Username=postgres;Password=raven;Database=AyaNova;CommandTimeout=120;",
"AYANOVA_DATA_PATH": "c:\\temp\\ravendata",
diff --git a/server/AyaNova/biz/JobsBiz.cs b/server/AyaNova/biz/JobsBiz.cs
index f3a763a1..9836a739 100644
--- a/server/AyaNova/biz/JobsBiz.cs
+++ b/server/AyaNova/biz/JobsBiz.cs
@@ -204,19 +204,14 @@ namespace AyaNova.Biz
if (!KeepOnWorking()) return;
log.LogTrace("Processing level 2 internal jobs");
- // #if (DEBUG)
- // log.LogInformation("Processing semi-critical internal jobs (backup, pm, notification etc)");
- // #endif
-
//BACKUP
await CoreJobBackup.DoWorkAsync();
if (!KeepOnWorking()) return;
//NOTIFICATIONS
- TaskUtil.Forget(Task.Run(() => CoreJobNotify.DoWorkAsync()));//must fire and forget as it will call a report render job. In fact probably all of these can be fire and forget
- // await CoreJobNotify.DoWorkAsync();
-
+ await CoreJobNotify.DoWorkAsync();
if (!KeepOnWorking()) return;
+
await CoreNotificationSweeper.DoWorkAsync();
if (!KeepOnWorking()) return;
@@ -241,6 +236,8 @@ namespace AyaNova.Biz
await CoreJobReportRenderEngineProcessCleanup.DoWork();
if (!KeepOnWorking()) return;
+ //CUSTOMER NOTIFICATIONS
+ TaskUtil.Forget(Task.Run(() => CoreJobCustomerNotify.DoWorkAsync()));//must fire and forget as it will call a report render job. In fact probably all of these can be fire and forget
log.LogTrace("Processing exclusive dynamic jobs");
diff --git a/server/AyaNova/biz/QuoteBiz.cs b/server/AyaNova/biz/QuoteBiz.cs
index f1e74e09..9cd1e955 100644
--- a/server/AyaNova/biz/QuoteBiz.cs
+++ b/server/AyaNova/biz/QuoteBiz.cs
@@ -1301,7 +1301,7 @@ namespace AyaNova.Biz
AyaType = AyaType.Quote,
ObjectId = oProposed.QuoteId,
CustomerNotifySubscriptionId = sub.Id,
- Name = $"{QuoteInfo.Serial.ToString()} - {qos.Name}",
+ Name = QuoteInfo.Serial.ToString(),
Subject="TEST SUBJECT",
Message="TEST MESSAGE"//TODO: template processing here
};
diff --git a/server/AyaNova/generator/CoreJobCustomerNotify.cs b/server/AyaNova/generator/CoreJobCustomerNotify.cs
new file mode 100644
index 00000000..c3ee535f
--- /dev/null
+++ b/server/AyaNova/generator/CoreJobCustomerNotify.cs
@@ -0,0 +1,250 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using AyaNova.Models;
+using AyaNova.Util;
+using Newtonsoft.Json.Linq;
+
+namespace AyaNova.Biz
+{
+
+ ///
+ /// Notification processor
+ /// turn notifyEvent records into inappnotification records for in app viewing and / or deliver smtp notifications seperately
+ ///
+ ///
+ internal static class CoreJobCustomerNotify
+ {
+ private static bool NotifyIsRunning = false;
+ private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobCustomerNotify");
+ private static DateTime lastRun = DateTime.MinValue;
+
+#if (DEBUG)
+ private static TimeSpan RUN_EVERY_INTERVAL = new TimeSpan(0, 0, 21);//no more frequently than once every 20 seconds
+#else
+ private static TimeSpan RUN_EVERY_INTERVAL = new TimeSpan(0, 1, 1);//no more frequently than once every 1 minute
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // DoSweep
+ //
+ public static async Task DoWorkAsync()
+ {
+ log.LogTrace("Checking if CustomerNotify should run");
+ if (NotifyIsRunning)
+ {
+ log.LogTrace("CustomerNotify is running already exiting this cycle");
+ return;
+ }
+ //This will get triggered roughly every minute, but we don't want to deliver that frequently
+ if (DateTime.UtcNow - lastRun < RUN_EVERY_INTERVAL)
+ {
+ log.LogTrace($"CustomerNotify ran less than {RUN_EVERY_INTERVAL} ago, exiting this cycle");
+ return;
+ }
+ try
+ {
+ NotifyIsRunning = true;
+ log.LogDebug("CustomerNotify set to RUNNING state and starting now");
+
+ using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext)
+ {
+ var customerevents = await ct.CustomerNotifyEvent.AsNoTracking().ToListAsync();
+ log.LogDebug($"Found {customerevents.Count} CustomerNotifyEvents to examine for potential delivery");
+
+ //iterate and deliver
+ foreach (var customernotifyevent in customerevents)
+ {
+ //no notifications for inactive users, just delete it as if it was delivered
+ var CustInfo = await ct.Customer.AsNoTracking().Where(x => x.Id == customernotifyevent.CustomerId).Select(x => new { x.Name, x.Active, x.Tags, x.EmailAddress }).FirstOrDefaultAsync();
+
+
+ if (!CustInfo.Active)
+ {
+ log.LogDebug($"Inactive Customer {CustInfo.Name}, removing notify rather than delivering it: {customernotifyevent}");
+ ct.CustomerNotifyEvent.Remove(customernotifyevent);
+ await ct.SaveChangesAsync();
+ continue;
+ }
+
+ if (string.IsNullOrWhiteSpace(CustInfo.EmailAddress))
+ {
+ log.LogDebug($"Customer {CustInfo.Name} has no email address, removing notify rather than delivering it: {customernotifyevent}");
+ ct.CustomerNotifyEvent.Remove(customernotifyevent);
+ await ct.SaveChangesAsync();
+ continue;
+ }
+
+ //Get subscription for delivery
+ var Subscription = await ct.CustomerNotifySubscription.AsNoTracking().FirstOrDefaultAsync(x => x.Id == customernotifyevent.CustomerNotifySubscriptionId);
+
+ //NOTE: There is no need to separate out future delivery and immediate delivery because
+ // All events have an event date, it's either immediate upon creation or it's future
+ // but not all events have an age value including ones with future event dates,
+ // and the default agevalue and advancenotice are both zero regardless so the block below works for either future or immediate deliveries
+
+ var deliverAfter = customernotifyevent.EventDate + Subscription.AgeValue - Subscription.AdvanceNotice;
+ if (deliverAfter < DateTime.UtcNow)
+ {
+ //Do the delivery, it's kosher
+ await DeliverCustomerNotificationSMTP(customernotifyevent, Subscription, CustInfo.EmailAddress, ct);
+ }
+ }
+ }
+
+ }
+ catch (Exception ex)
+ {
+ log.LogError(ex, $"Error processing customer notification event");
+ }
+ finally
+ {
+ log.LogDebug("CustomerNotify is done setting to not running state and tagging lastRun timestamp");
+ lastRun = DateTime.UtcNow;
+ NotifyIsRunning = false;
+
+ }
+
+ }
+
+
+ //===
+ private static async Task DeliverCustomerNotificationSMTP(CustomerNotifyEvent ne, CustomerNotifySubscription subscription, string deliveryAddress, AyContext ct)
+ {
+
+ var DeliveryLogItem = new NotifyDeliveryLog()
+ {
+ Processed = DateTime.UtcNow,
+ ObjectId = ne.ObjectId,
+ NotifySubscriptionId = ne.CustomerNotifySubscriptionId,
+ Fail = false
+ };
+
+ try
+ {
+ log.LogDebug($"DeliverCustomerNotificationSMTP delivering notify event: {ne}");
+ if (string.IsNullOrWhiteSpace(deliveryAddress))
+ {
+ DeliveryLogItem.Fail = true;
+ DeliveryLogItem.Error = $"No email address provided for smtp delivery; event: {ne}";
+ }
+ else
+ {
+ IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
+ if (!ServerGlobalOpsSettingsCache.Notify.SmtpDeliveryActive)
+ {
+ await NotifyEventHelper.AddOpsProblemEvent($"Email notifications are set to OFF at server, unable to send Customer email notification for this event:{ne}");
+ log.LogInformation($"** WARNING: SMTP notification is currently set to Active=False; unable to deliver Customer email notification, [CustomerId={ne.CustomerId}, Customer Notify subscription={ne.CustomerNotifySubscriptionId}]. Change this setting or remove all Customer notifications if this is permanent **");
+ DeliveryLogItem.Fail = true;
+ DeliveryLogItem.Error = $"Email notifications are set to OFF at server, unable to send Customer email notification for this event: {ne}";
+ }
+ else
+ {
+ //generate report if applicable
+
+ if (subscription.LinkReportId != null)
+ {
+ long subTranslationId = (long)subscription.TranslationId;
+
+ ReportBiz biz = new ReportBiz(ct, 1, subTranslationId, AuthorizationRoles.BizAdmin);
+ //example with workorder report
+ //{"AType":34,"selectedRowIds":[355],"ReportId":9,"ClientMeta":{"UserName":"AyaNova SuperUser","Authorization":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNjQ2NzgyNTc4IiwiaXNzIjoiYXlhbm92YS5jb20iLCJpZCI6IjEifQ.ad7Acq54JCRGitDWKDJFFnqKkidbdaKaFmj-RA_RG5E","DownloadToken":"NdoU8ca3LG4L39Tj2oi3UReeeM7FLevTgbgopTPhGbA","TimeZoneName":"America/Los_Angeles","LanguageName":"en-US","Hour12":true,"CurrencyName":"USD","DefaultLocale":"en","PDFDate":"3/3/22","PDFTime":"3:38 PM"}}
+
+ var reportRequest = new DataListReportRequest();
+
+ reportRequest.AType = ne.AyaType;
+ reportRequest.ReportId = (long)subscription.LinkReportId;
+ reportRequest.SelectedRowIds = new long[] { ne.ObjectId };
+ var jwt = Api.Controllers.AuthController.GenRpt(subTranslationId);
+
+ //this could be adjusted by culture if we allow user to set a culture but that's getting a bit into the weeds, likely the server default is fine
+ var pdfDate = new DateTime().ToShortDateString();
+ var pdfTime = new DateTime().ToShortTimeString();
+ var h12 = subscription.Hour12 ? "true" : "false";
+ reportRequest.ClientMeta = JToken.Parse($"{{'UserName':'-','Authorization':'Bearer {jwt}','TimeZoneName':'{subscription.TimeZoneOverride}','LanguageName':'{subscription.LanguageOverride}','Hour12':{h12},'CurrencyName':'{subscription.CurrencyName}','DefaultLocale':'en','PDFDate':'{pdfDate}','PDFTime':'{pdfTime}'}}");
+ //get port number
+ var match = System.Text.RegularExpressions.Regex.Match(ServerBootConfig.AYANOVA_USE_URLS, "[0-9]+");
+ var API_URL = $"http://127.0.0.1:{match.Value}/api/{AyaNovaVersion.CurrentApiVersion}/";
+ var jobid = await biz.RequestRenderReport(reportRequest, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT), API_URL, "CUSTOMER NOTIFICATION - NO USER");
+ if (jobid == null)
+ {
+ throw new ApplicationException($"Report render job id is null failed to start");
+ }
+ else
+ {
+ bool done = false;
+ DateTime bailAfter = DateTime.Now.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT);
+ while (!done && DateTime.Now < bailAfter)
+ {
+ var status = await JobsBiz.GetJobStatusAsync((Guid)jobid);
+ switch (status)
+ {
+ case JobStatus.Completed:
+ {
+ done = true;
+ //get job logs and parse file name from it
+ JobOperationsBiz jobopsbiz = new JobOperationsBiz(ct, 1, AuthorizationRoles.BizAdmin);
+ List log = await jobopsbiz.GetJobLogListAsync((Guid)jobid);
+ var lastLog = log[log.Count - 1];
+ var lastLogJ = JObject.Parse(lastLog.StatusText);
+ var path = (string)lastLogJ["reportfilename"];
+ var FilePath = FileUtil.GetFullPathForTemporaryFile(path);
+ var FileName = FileUtil.StringToSafeFileName(await TranslationBiz.GetTranslationStaticAsync(ne.AyaType.ToString(), subTranslationId, ct) + $"-{ne.Name}.pdf").ToLowerInvariant();
+ await m.SendEmailAsync(deliveryAddress, ne.Subject, ne.Message, ServerGlobalOpsSettingsCache.Notify, FilePath, FileName);
+ break;
+ }
+ case JobStatus.Failed:
+ case JobStatus.Absent:
+ throw new ApplicationException($"REPORT RENDER JOB {jobid} started but failed");
+
+ }
+
+ }
+ if (!done)
+ throw new TimeoutException("JOB FAILED DUE TO REPORT RENDER TIMEOUT");
+ }
+ }
+ else
+ await m.SendEmailAsync(deliveryAddress, ne.Subject, ne.Message, ServerGlobalOpsSettingsCache.Notify);
+
+ }
+
+ }
+ }
+ catch (Exception ex)
+ {
+ await NotifyEventHelper.AddOpsProblemEvent("SMTP Customer Notification failed", ex);
+ DeliveryLogItem.Fail = true;
+ DeliveryLogItem.Error = $"SMTP Notification failed to deliver for this Customer notify event: {ne}, message: {ex.Message}";
+ log.LogDebug(ex, $"DeliverSMTP Failure delivering Customer notify event: {ne}");
+ }
+ finally
+ {
+ //remove event no matter what
+ ct.CustomerNotifyEvent.Remove(ne);
+
+ //add delivery log item
+ await ct.NotifyDeliveryLog.AddAsync(DeliveryLogItem);
+ await ct.SaveChangesAsync();
+ }
+ }
+ //===
+
+
+
+
+
+
+
+
+
+ /////////////////////////////////////////////////////////////////////
+
+ }//eoc
+
+
+}//eons
+
diff --git a/server/AyaNova/generator/CoreJobNotify.cs b/server/AyaNova/generator/CoreJobNotify.cs
index 5a7e1cc2..3daf2d93 100644
--- a/server/AyaNova/generator/CoreJobNotify.cs
+++ b/server/AyaNova/generator/CoreJobNotify.cs
@@ -6,7 +6,6 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
using AyaNova.Util;
-using Newtonsoft.Json.Linq;
namespace AyaNova.Biz
{
@@ -67,7 +66,7 @@ namespace AyaNova.Biz
}
}
- #region User notification subscription events
+
using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext)
{
var events = await ct.NotifyEvent.AsNoTracking().ToListAsync();
@@ -137,55 +136,6 @@ namespace AyaNova.Biz
}
}
}
- #endregion user notification events
-
-
- #region Customer 'proxy' notification subscription events
- using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext)
- {
- var customerevents = await ct.CustomerNotifyEvent.AsNoTracking().ToListAsync();
- log.LogDebug($"Found {customerevents.Count} CustomerNotifyEvents to examine for potential delivery");
-
- //iterate and deliver
- foreach (var customernotifyevent in customerevents)
- {
- //no notifications for inactive users, just delete it as if it was delivered
- var CustInfo = await ct.Customer.AsNoTracking().Where(x => x.Id == customernotifyevent.CustomerId).Select(x => new { x.Name, x.Active, x.Tags, x.EmailAddress }).FirstOrDefaultAsync();
-
-
- if (!CustInfo.Active)
- {
- log.LogDebug($"Inactive Customer {CustInfo.Name}, removing notify rather than delivering it: {customernotifyevent}");
- ct.CustomerNotifyEvent.Remove(customernotifyevent);
- await ct.SaveChangesAsync();
- continue;
- }
-
- if (string.IsNullOrWhiteSpace(CustInfo.EmailAddress))
- {
- log.LogDebug($"Customer {CustInfo.Name} has no email address, removing notify rather than delivering it: {customernotifyevent}");
- ct.CustomerNotifyEvent.Remove(customernotifyevent);
- await ct.SaveChangesAsync();
- continue;
- }
-
- //Get subscription for delivery
- var Subscription = await ct.CustomerNotifySubscription.AsNoTracking().FirstOrDefaultAsync(x => x.Id == customernotifyevent.CustomerNotifySubscriptionId);
-
- //NOTE: There is no need to separate out future delivery and immediate delivery because
- // All events have an event date, it's either immediate upon creation or it's future
- // but not all events have an age value including ones with future event dates,
- // and the default agevalue and advancenotice are both zero regardless so the block below works for either future or immediate deliveries
-
- var deliverAfter = customernotifyevent.EventDate + Subscription.AgeValue - Subscription.AdvanceNotice;
- if (deliverAfter < DateTime.UtcNow)
- {
- //Do the delivery, it's kosher
- await DeliverCustomerNotificationSMTP(customernotifyevent, Subscription, CustInfo.EmailAddress, ct);
- }
- }
- }
- #endregion customer notification events
}
catch (Exception ex)
@@ -380,208 +330,14 @@ namespace AyaNova.Biz
}
-
-
- //===
- private static async Task DeliverCustomerNotificationSMTP(CustomerNotifyEvent ne, CustomerNotifySubscription subscription, string deliveryAddress, AyContext ct)
- {
-
- var DeliveryLogItem = new NotifyDeliveryLog()
- {
- Processed = DateTime.UtcNow,
- ObjectId = ne.ObjectId,
- NotifySubscriptionId = ne.CustomerNotifySubscriptionId,
- Fail = false
- };
-
- try
- {
- log.LogDebug($"DeliverCustomerNotificationSMTP delivering notify event: {ne}");
- if (string.IsNullOrWhiteSpace(deliveryAddress))
- {
- DeliveryLogItem.Fail = true;
- DeliveryLogItem.Error = $"No email address provided for smtp delivery; event: {ne}";
- }
- else
- {
- IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
- if (!ServerGlobalOpsSettingsCache.Notify.SmtpDeliveryActive)
- {
- await NotifyEventHelper.AddOpsProblemEvent($"Email notifications are set to OFF at server, unable to send Customer email notification for this event:{ne}");
- log.LogInformation($"** WARNING: SMTP notification is currently set to Active=False; unable to deliver Customer email notification, [CustomerId={ne.CustomerId}, Customer Notify subscription={ne.CustomerNotifySubscriptionId}]. Change this setting or remove all Customer notifications if this is permanent **");
- DeliveryLogItem.Fail = true;
- DeliveryLogItem.Error = $"Email notifications are set to OFF at server, unable to send Customer email notification for this event: {ne}";
- }
- else
- {
- //generate report if applicable
-
- if (subscription.LinkReportId != null)
- {
- long subTranslationId = (long)subscription.TranslationId;
-
- ReportBiz biz = new ReportBiz(ct, 1, subTranslationId, AuthorizationRoles.BizAdmin);
- //example with workorder report
- //{"AType":34,"selectedRowIds":[355],"ReportId":9,"ClientMeta":{"UserName":"AyaNova SuperUser","Authorization":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNjQ2NzgyNTc4IiwiaXNzIjoiYXlhbm92YS5jb20iLCJpZCI6IjEifQ.ad7Acq54JCRGitDWKDJFFnqKkidbdaKaFmj-RA_RG5E","DownloadToken":"NdoU8ca3LG4L39Tj2oi3UReeeM7FLevTgbgopTPhGbA","TimeZoneName":"America/Los_Angeles","LanguageName":"en-US","Hour12":true,"CurrencyName":"USD","DefaultLocale":"en","PDFDate":"3/3/22","PDFTime":"3:38 PM"}}
-
- var reportRequest = new DataListReportRequest();
-
- reportRequest.AType = ne.AyaType;
- reportRequest.ReportId = (long)subscription.LinkReportId;
- reportRequest.SelectedRowIds = new long[] { ne.ObjectId };
- var jwt = Api.Controllers.AuthController.GenRpt(subTranslationId);
-
- //this could be adjusted by culture if we allow user to set a culture but that's getting a bit into the weeds, likely the server default is fine
- var pdfDate = new DateTime().ToShortDateString();
- var pdfTime = new DateTime().ToShortTimeString();
- var h12 = subscription.Hour12 ? "true" : "false";
- reportRequest.ClientMeta = JToken.Parse($"{{'UserName':'-','Authorization':'Bearer {jwt}','TimeZoneName':'{subscription.TimeZoneOverride}','LanguageName':'{subscription.LanguageOverride}','Hour12':{h12},'CurrencyName':'{subscription.CurrencyName}','DefaultLocale':'en','PDFDate':'{pdfDate}','PDFTime':'{pdfTime}'}}");
- //get port number
- var match = System.Text.RegularExpressions.Regex.Match(ServerBootConfig.AYANOVA_USE_URLS, "[0-9]+");
- var API_URL = $"http://127.0.0.1:{match.Value}/api/{AyaNovaVersion.CurrentApiVersion}/";
- var jobid = await biz.RequestRenderReport(reportRequest, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT), API_URL, "CUSTOMER NOTIFICATION - NO USER");
- if (jobid == null)
- {
- throw new ApplicationException($"Report render job id is null failed to start");
- }
- else
- {
- bool done = false;
- DateTime bailAfter = DateTime.Now.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT);
- while (!done && DateTime.Now < bailAfter)
- {
- var status = await JobsBiz.GetJobStatusAsync((Guid)jobid);
- switch (status)
- {
- case JobStatus.Completed:
- {
- done = true;
- //get job logs and parse file name from it
- JobOperationsBiz jobopsbiz = new JobOperationsBiz(ct, 1, AuthorizationRoles.BizAdmin);
- List log = await jobopsbiz.GetJobLogListAsync((Guid)jobid);
- var lastLog = log[log.Count - 1];
- var lastLogJ = JObject.Parse(lastLog.StatusText);
- var path = (string)lastLogJ["reportfilename"];
- var FilePath = FileUtil.GetFullPathForTemporaryFile(path);
- await m.SendEmailAsync(deliveryAddress, ne.Subject, ne.Message, ServerGlobalOpsSettingsCache.Notify, FilePath);
- break;
- }
- case JobStatus.Failed:
- case JobStatus.Absent:
- throw new ApplicationException($"REPORT RENDER JOB {jobid} started but failed");
-
- }
-
- }
- if (!done)
- throw new TimeoutException("JOB FAILED DUE TO REPORT RENDER TIMEOUT");
- }
- }
- else
- await m.SendEmailAsync(deliveryAddress, ne.Subject, ne.Message, ServerGlobalOpsSettingsCache.Notify);
-
- }
-
- }
- }
- catch (Exception ex)
- {
- await NotifyEventHelper.AddOpsProblemEvent("SMTP Customer Notification failed", ex);
- DeliveryLogItem.Fail = true;
- DeliveryLogItem.Error = $"SMTP Notification failed to deliver for this Customer notify event: {ne}, message: {ex.Message}";
- log.LogDebug(ex, $"DeliverSMTP Failure delivering Customer notify event: {ne}");
- }
- finally
- {
- //remove event no matter what
- ct.CustomerNotifyEvent.Remove(ne);
-
- //add delivery log item
- await ct.NotifyDeliveryLog.AddAsync(DeliveryLogItem);
- await ct.SaveChangesAsync();
- }
- }
- //===
-
-
//Called from ops notification settings to test smtp setup by delivering to address of choosing
public static async Task TestSMTPDelivery(string toAddress)
{
- //DO TEST DELIVERY HERE USING EXACT SAME SETTINGS AS FOR DeliverSMTP above
- //todo: abstract out email sending to it's own class maybe or whatever method I choose supports the best
- //https://jasonwatmore.com/post/2020/07/15/aspnet-core-3-send-emails-via-smtp-with-mailkit
- //https://medium.com/@ffimnsr/sending-email-using-mailkit-in-asp-net-core-web-api-71b946380442
-
IMailer m = AyaNova.Util.ServiceProviderProvider.Mailer;
try
{
-#if (DEBUG)
- //generate a workorder report here get the path and send it with the message
- using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext)
- {
- long overrideLanguageId = 2;
-
- ReportBiz biz = new ReportBiz(ct, 1, overrideLanguageId, AuthorizationRoles.BizAdmin);
- //example with workorder report
- //{"AType":34,"selectedRowIds":[355],"ReportId":9,"ClientMeta":{"UserName":"AyaNova SuperUser","Authorization":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNjQ2NzgyNTc4IiwiaXNzIjoiYXlhbm92YS5jb20iLCJpZCI6IjEifQ.ad7Acq54JCRGitDWKDJFFnqKkidbdaKaFmj-RA_RG5E","DownloadToken":"NdoU8ca3LG4L39Tj2oi3UReeeM7FLevTgbgopTPhGbA","TimeZoneName":"America/Los_Angeles","LanguageName":"en-US","Hour12":true,"CurrencyName":"USD","DefaultLocale":"en","PDFDate":"3/3/22","PDFTime":"3:38 PM"}}
-
- var reportRequest = new DataListReportRequest();
- reportRequest.AType = AyaType.WorkOrder;
- reportRequest.ReportId = 9;
- reportRequest.SelectedRowIds = new long[] { 1 };
- var jwt = Api.Controllers.AuthController.GenRpt(overrideLanguageId);
-
- //this could be adjusted by culture if we allow user to set a culture but that's getting a bit into the weeds, likely the server default is fine
- var pdfDate = new DateTime().ToShortDateString();
- var pdfTime = new DateTime().ToShortTimeString();
-
- reportRequest.ClientMeta = JToken.Parse($"{{'UserName':'-','Authorization':'Bearer {jwt}','TimeZoneName':'America/Los_Angeles','LanguageName':'en-US','Hour12':true,'CurrencyName':'USD','DefaultLocale':'en','PDFDate':'{pdfDate}','PDFTime':'{pdfTime}'}}");
- //get port number
- var match = System.Text.RegularExpressions.Regex.Match(ServerBootConfig.AYANOVA_USE_URLS, "[0-9]+");
- var API_URL = $"http://127.0.0.1:{match.Value}/api/{AyaNovaVersion.CurrentApiVersion}/";
- var jobid = await biz.RequestRenderReport(reportRequest, DateTime.UtcNow.AddMinutes(ServerBootConfig.AYANOVA_REPORT_RENDERING_TIMEOUT), API_URL, "AUTOMATED NO USER");
- if (jobid == null)
- {
- return "JOB FAILED";
- }
- else
- {
- bool done = false;
- //todo: need a timeout here that sets done as failed due to timeout
- while (!done)
- {
- var status = await JobsBiz.GetJobStatusAsync((Guid)jobid);
- switch (status)
- {
- case JobStatus.Completed:
- {
- //get job logs and parse file name from it
- JobOperationsBiz jobopsbiz = new JobOperationsBiz(ct, 1, AuthorizationRoles.BizAdmin);
- List log = await jobopsbiz.GetJobLogListAsync((Guid)jobid);
- var lastLog = log[log.Count - 1];
- var lastLogJ = JObject.Parse(lastLog.StatusText);
- var path = (string)lastLogJ["reportfilename"];
- var FilePath = FileUtil.GetFullPathForTemporaryFile(path);
- await m.SendEmailAsync(toAddress, "DEBUG Test from Notification system", "This is a DEBUG test to confirm notification system is working", ServerGlobalOpsSettingsCache.Notify, FilePath);
- return "ok";
- }
- case JobStatus.Failed:
- return $"JOB {jobid} started but failed";
- }
- if (status == JobStatus.Failed)
- {
- return $"JOB {jobid} started but failed";
- }
- }
- return "JOB FAILED DUE TO TIMEOUT";
- }
- }
-
-#else
await m.SendEmailAsync(toAddress, "Test from Notification system", "This is a test to confirm notification system is working", ServerGlobalOpsSettingsCache.Notify);
return "ok";
-#endif
-
}
catch (Exception ex)
{
@@ -593,7 +349,6 @@ 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 aType, long id, NotifyEventType net)
{
var ServerUrl = ServerGlobalOpsSettingsCache.Notify.AyaNovaServerURL;
@@ -629,21 +384,6 @@ namespace AyaNova.Biz
}
- // //Used to directly open a report at client
- // private static string OpenReportUrlBuilder(long objectId, long reportId)
- // {
- // //CLIENT EXPECTS: open report links to have a query string [CLIENTAPPURL]/viewreport/[objectid]/[reportid]
- // var ServerUrl = ServerGlobalOpsSettingsCache.Notify.AyaNovaServerURL;
- // if (string.IsNullOrWhiteSpace(ServerUrl))
- // {
- // NotifyEventHelper.AddOpsProblemEvent("Notification system: The OPS Notification setting is empty for AyaNova Server URL. This prevents Notification system from linking events to openable objects.").Wait();
- // return "OPS ERROR NO SERVER URL CONFIGURED";
- // }
- // ServerUrl = ServerUrl.Trim().TrimEnd('/');
- // return $"{ServerUrl}/viewreport/{objectId}/{reportId}";
- // }
-
-
//url to open subscription for editing
private static string OpenSubscriptionUrlBuilder(long id)