This commit is contained in:
@@ -77,6 +77,8 @@ namespace AyaNova.Biz
|
|||||||
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ObjectCreated && z.AyaType == newObject.AyaType).ToListAsync();
|
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ObjectCreated && z.AyaType == newObject.AyaType).ToListAsync();
|
||||||
foreach (var sub in subs)
|
foreach (var sub in subs)
|
||||||
{
|
{
|
||||||
|
//not for inactive users
|
||||||
|
if (!await UserBiz.UserIsActive(sub.UserId)) continue;
|
||||||
if (TagsMatch(newObject.Tags, sub.Tags))
|
if (TagsMatch(newObject.Tags, sub.Tags))
|
||||||
{
|
{
|
||||||
NotifyEvent n = new NotifyEvent()
|
NotifyEvent n = new NotifyEvent()
|
||||||
@@ -101,6 +103,8 @@ namespace AyaNova.Biz
|
|||||||
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ObjectAge && z.AyaType == newObject.AyaType).ToListAsync();
|
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ObjectAge && z.AyaType == newObject.AyaType).ToListAsync();
|
||||||
foreach (var sub in subs)
|
foreach (var sub in subs)
|
||||||
{
|
{
|
||||||
|
//not for inactive users
|
||||||
|
if (!await UserBiz.UserIsActive(sub.UserId)) continue;
|
||||||
if (TagsMatch(newObject.Tags, sub.Tags))
|
if (TagsMatch(newObject.Tags, sub.Tags))
|
||||||
{
|
{
|
||||||
//Note: age is set by advance notice which is consulted by CoreJobNotify in it's run so the deliver date is not required here only the reference EventDate to check for deliver
|
//Note: age is set by advance notice which is consulted by CoreJobNotify in it's run so the deliver date is not required here only the reference EventDate to check for deliver
|
||||||
@@ -137,6 +141,8 @@ namespace AyaNova.Biz
|
|||||||
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ObjectModified && z.AyaType == newObject.AyaType).ToListAsync();
|
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ObjectModified && z.AyaType == newObject.AyaType).ToListAsync();
|
||||||
foreach (var sub in subs)
|
foreach (var sub in subs)
|
||||||
{
|
{
|
||||||
|
//not for inactive users
|
||||||
|
if (!await UserBiz.UserIsActive(sub.UserId)) continue;
|
||||||
if (TagsMatch(newObject.Tags, sub.Tags))
|
if (TagsMatch(newObject.Tags, sub.Tags))
|
||||||
{
|
{
|
||||||
NotifyEvent n = new NotifyEvent()
|
NotifyEvent n = new NotifyEvent()
|
||||||
@@ -174,6 +180,8 @@ namespace AyaNova.Biz
|
|||||||
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ObjectDeleted && z.AyaType == bizObject.AyaType).ToListAsync();
|
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ObjectDeleted && z.AyaType == bizObject.AyaType).ToListAsync();
|
||||||
foreach (var sub in subs)
|
foreach (var sub in subs)
|
||||||
{
|
{
|
||||||
|
//not for inactive users
|
||||||
|
if (!await UserBiz.UserIsActive(sub.UserId)) continue;
|
||||||
if (TagsMatch(bizObject.Tags, sub.Tags))
|
if (TagsMatch(bizObject.Tags, sub.Tags))
|
||||||
{
|
{
|
||||||
//TODO: On deliver should point to history event log record or take from there and insert into delivery message?
|
//TODO: On deliver should point to history event log record or take from there and insert into delivery message?
|
||||||
@@ -265,6 +273,7 @@ namespace AyaNova.Biz
|
|||||||
|
|
||||||
internal static async Task AddGeneralNotifyEvent(NotifyEventType eventType, string message, string name, Exception except = null, long userId = 0)
|
internal static async Task AddGeneralNotifyEvent(NotifyEventType eventType, string message, string name, Exception except = null, long userId = 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
//This handles general notification events not requiring a decision or tied to an object that are basically just a immediate message to the user
|
//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, GeneralNotification, NotifyHealthCheck etc
|
//e.g. ops problems, GeneralNotification, NotifyHealthCheck etc
|
||||||
//optional user id to send directly to them
|
//optional user id to send directly to them
|
||||||
@@ -301,6 +310,8 @@ namespace AyaNova.Biz
|
|||||||
//this will likely be a development error, not a production error so no need to log etc
|
//this will likely be a development error, not a production error so no need to log etc
|
||||||
throw new System.ArgumentException("NotifyEventProcessor:AddGeneralNotifyEvent: GeneralNotification requires a user id but none was specified");
|
throw new System.ArgumentException("NotifyEventProcessor:AddGeneralNotifyEvent: GeneralNotification requires a user id but none was specified");
|
||||||
}
|
}
|
||||||
|
//not for inactive users
|
||||||
|
if (!await UserBiz.UserIsActive(userId)) return;
|
||||||
|
|
||||||
var UserName = await ct.User.AsNoTracking().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();
|
||||||
|
|
||||||
@@ -328,6 +339,8 @@ namespace AyaNova.Biz
|
|||||||
|
|
||||||
foreach (var sub in subs)
|
foreach (var sub in subs)
|
||||||
{
|
{
|
||||||
|
//not for inactive users
|
||||||
|
if (!await UserBiz.UserIsActive(sub.UserId)) continue;
|
||||||
//note flag ~SERVER~ means to client to substitute "Server" translation key text instead
|
//note flag ~SERVER~ means to client to substitute "Server" translation key text instead
|
||||||
NotifyEvent n = new NotifyEvent() { EventType = eventType, UserId = sub.UserId, Message = message, NotifySubscriptionId = sub.Id, Name = "~SERVER~" };
|
NotifyEvent n = new NotifyEvent() { EventType = eventType, UserId = sub.UserId, Message = message, NotifySubscriptionId = sub.Id, Name = "~SERVER~" };
|
||||||
await ct.NotifyEvent.AddAsync(n);
|
await ct.NotifyEvent.AddAsync(n);
|
||||||
|
|||||||
@@ -44,6 +44,16 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check for active status of user
|
||||||
|
//used by notification processing and others
|
||||||
|
internal static async Task<bool> UserIsActive(long userId)
|
||||||
|
{
|
||||||
|
using (AyContext ct = ServiceProviderProvider.DBContext)
|
||||||
|
{
|
||||||
|
return await ct.User.AsNoTracking().Where(z => z.Id == userId).Select(z => z.Active).FirstAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Called by license processor when use downgrades to lesser amount of techs
|
//Called by license processor when use downgrades to lesser amount of techs
|
||||||
internal static async Task DeActivateExcessiveTechs(long KeepThisManyActiveTechs, ILogger _log)
|
internal static async Task DeActivateExcessiveTechs(long KeepThisManyActiveTechs, ILogger _log)
|
||||||
{
|
{
|
||||||
@@ -492,6 +502,7 @@ namespace AyaNova.Biz
|
|||||||
//USEROPTIONS
|
//USEROPTIONS
|
||||||
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from auseroptions where userid = {dbObject.Id}");
|
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from auseroptions where userid = {dbObject.Id}");
|
||||||
//NOTIFY SUBSCRIPTIONS
|
//NOTIFY SUBSCRIPTIONS
|
||||||
|
//Note: will cascade delete notifyevent, and notification automatically
|
||||||
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from anotifysubscription where userid = {dbObject.Id}");
|
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from anotifysubscription where userid = {dbObject.Id}");
|
||||||
//personal datalistview
|
//personal datalistview
|
||||||
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from adatalistview where public = {false} and userid = {dbObject.Id}");
|
await ct.Database.ExecuteSqlInterpolatedAsync($"delete from adatalistview where public = {false} and userid = {dbObject.Id}");
|
||||||
@@ -942,7 +953,7 @@ namespace AyaNova.Biz
|
|||||||
//iterate subs and remove any user shouldn't have
|
//iterate subs and remove any user shouldn't have
|
||||||
var userSubs = await ct.NotifySubscription.Where(z => z.UserId == proposedObj.Id).ToListAsync();
|
var userSubs = await ct.NotifySubscription.Where(z => z.UserId == proposedObj.Id).ToListAsync();
|
||||||
foreach (var sub in userSubs)
|
foreach (var sub in userSubs)
|
||||||
{
|
{
|
||||||
if (sub.AyaType != AyaType.NoType)
|
if (sub.AyaType != AyaType.NoType)
|
||||||
{
|
{
|
||||||
//check if user has rights to it or not still
|
//check if user has rights to it or not still
|
||||||
|
|||||||
@@ -108,12 +108,12 @@ namespace AyaNova.Biz
|
|||||||
|
|
||||||
//All items have an event date, for non time delayed events it's just the moment it was created
|
//All items have an event date, for non time delayed events it's just the moment it was created
|
||||||
//which will predate this moment now if it's pre-existing
|
//which will predate this moment now if it's pre-existing
|
||||||
var events = await ct.NotifyEvent.Include(z => z.NotifySubscription).ToListAsync();
|
var events = await ct.NotifyEvent.Include(z => z.User).Include(z => z.NotifySubscription).AsNoTracking().ToListAsync();
|
||||||
log.LogTrace($"Found {events.Count} NotifyEvents to examine for potential delivery");
|
log.LogTrace($"Found {events.Count} NotifyEvents to examine for potential delivery");
|
||||||
|
|
||||||
//cache translations
|
//cache translations
|
||||||
//Get all subscription unique userId's that aren't inapp deliveries
|
//Get all subscription unique userId's that aren't inapp deliveries
|
||||||
var usersNeedingTranslations = events.Where(z => z.NotifySubscription.DeliveryMethod != NotifyDeliveryMethod.App).Select(z => z.NotifySubscription.UserId).ToList().Distinct();
|
var usersNeedingTranslations = events.Where(z => z.NotifySubscription.DeliveryMethod != NotifyDeliveryMethod.App && z.User.Active).Select(z => z.NotifySubscription.UserId).ToList().Distinct();
|
||||||
foreach (long userid in usersNeedingTranslations)
|
foreach (long userid in usersNeedingTranslations)
|
||||||
{
|
{
|
||||||
long transId = (await ct.UserOptions.SingleAsync(z => z.UserId == userid)).TranslationId;
|
long transId = (await ct.UserOptions.SingleAsync(z => z.UserId == userid)).TranslationId;
|
||||||
@@ -126,6 +126,14 @@ namespace AyaNova.Biz
|
|||||||
//iterate and deliver
|
//iterate and deliver
|
||||||
foreach (var notifyevent in events)
|
foreach (var notifyevent in events)
|
||||||
{
|
{
|
||||||
|
//no notifications for inactive users, just delete it as if it was delivered
|
||||||
|
if (!notifyevent.User.Active)
|
||||||
|
{
|
||||||
|
log.LogTrace($"Inactive user {notifyevent.User.Name}, removing notify rather than delivering it: {notifyevent}");
|
||||||
|
ct.NotifyEvent.Remove(notifyevent);
|
||||||
|
await ct.SaveChangesAsync();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
//TIME DELAYED AGED EVENT?
|
//TIME DELAYED AGED EVENT?
|
||||||
//when to time delay deliver formula:If sub.agevalue!= timespan.zero then deliver on =
|
//when to time delay deliver formula:If sub.agevalue!= timespan.zero then deliver on =
|
||||||
//NotifyEvent "EventDate"+NotifySubscription.AgeValue timespan - NotifySubscription AdvanceNotice timespan > utcNow
|
//NotifyEvent "EventDate"+NotifySubscription.AgeValue timespan - NotifySubscription AdvanceNotice timespan > utcNow
|
||||||
@@ -150,7 +158,7 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
//COULD BE TIME DELAYED BUT WITHOUT AGE, i.e. EventDate takes precedence?
|
//COULD BE TIME DELAYED BUT WITHOUT AGE, i.e. EventDate takes precedence?
|
||||||
|
|
||||||
//NORMAL IMMEDIATE DELIVERY EVENT
|
//NORMAL IMMEDIATE DELIVERY EVENT
|
||||||
@@ -249,15 +257,15 @@ namespace AyaNova.Biz
|
|||||||
|
|
||||||
if (ne.ObjectId != 0 || ne.EventType == NotifyEventType.BackupStatus)
|
if (ne.ObjectId != 0 || ne.EventType == NotifyEventType.BackupStatus)
|
||||||
{
|
{
|
||||||
body = OpenObjectUrlBuilder(ne.AyaType, ne.ObjectId, ne.EventType) + "\n";
|
body = OpenObjectUrlBuilder(ne.AyaType, ne.ObjectId, ne.EventType) + "\n";
|
||||||
}
|
}
|
||||||
body += ne.Message;
|
body += ne.Message;
|
||||||
|
|
||||||
//Add link to subscription
|
//Add link to subscription
|
||||||
//http://localhost:8080/open/51/1 //add subscription link, notifysub is object type 51
|
//http://localhost:8080/open/51/1 //add subscription link, notifysub is object type 51
|
||||||
if (!body.EndsWith('\n'))
|
if (!body.EndsWith('\n'))
|
||||||
body += "\n";
|
body += "\n";
|
||||||
|
|
||||||
body += $"-----\n({SubscriptionTypeName}: {OpenSubscriptionUrlBuilder(ne.NotifySubscriptionId)} )\n";
|
body += $"-----\n({SubscriptionTypeName}: {OpenSubscriptionUrlBuilder(ne.NotifySubscriptionId)} )\n";
|
||||||
|
|
||||||
if (!ServerGlobalOpsSettingsCache.Notify.SmtpDeliveryActive)
|
if (!ServerGlobalOpsSettingsCache.Notify.SmtpDeliveryActive)
|
||||||
@@ -369,7 +377,7 @@ namespace AyaNova.Biz
|
|||||||
return "OPS ERROR NO SERVER URL CONFIGURED";
|
return "OPS ERROR NO SERVER URL CONFIGURED";
|
||||||
}
|
}
|
||||||
ServerUrl = ServerUrl.Trim().TrimEnd('/');
|
ServerUrl = ServerUrl.Trim().TrimEnd('/');
|
||||||
|
|
||||||
//default is to open the object in question directly
|
//default is to open the object in question directly
|
||||||
return $"{ServerUrl}/open/{(int)AyaType.NotifySubscription}/{id}";
|
return $"{ServerUrl}/open/{(int)AyaType.NotifySubscription}/{id}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,13 @@ namespace AyaNova.Models
|
|||||||
public string CustomFields { get; set; }
|
public string CustomFields { get; set; }
|
||||||
public List<string> Tags { get; set; }
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
todo: Consider adding latitude / longitude to wo, quote, pm objects
|
||||||
|
can copy over from the unit or customer or set themselves
|
||||||
|
and can always hide
|
||||||
|
means wo could be scheduled for ad-hoc locations and serviced that way, i.e. a truck parked on the side of the highway etc
|
||||||
|
*/
|
||||||
//dependents
|
//dependents
|
||||||
public List<PMItem> PMItems { get; set; }
|
public List<PMItem> PMItems { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,13 @@ namespace AyaNova.Models
|
|||||||
public string CustomFields { get; set; }
|
public string CustomFields { get; set; }
|
||||||
public List<string> Tags { get; set; }
|
public List<string> Tags { get; set; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
todo: Consider adding latitude / longitude to wo, quote, pm objects
|
||||||
|
can copy over from the unit or customer or set themselves
|
||||||
|
and can always hide
|
||||||
|
means wo could be scheduled for ad-hoc locations and serviced that way, i.e. a truck parked on the side of the highway etc
|
||||||
|
*/
|
||||||
//dependents
|
//dependents
|
||||||
public List<QuoteItem> QuoteItems { get; set; }
|
public List<QuoteItem> QuoteItems { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,13 @@ namespace AyaNova.Models
|
|||||||
public AyaType AyaType { get => AyaType.WorkOrder; }
|
public AyaType AyaType { get => AyaType.WorkOrder; }
|
||||||
|
|
||||||
}//eoc
|
}//eoc
|
||||||
|
/*
|
||||||
|
|
||||||
|
todo: Consider adding latitude / longitude to wo, quote, pm objects
|
||||||
|
can copy over from the unit or customer or set themselves
|
||||||
|
and can always hide
|
||||||
|
means wo could be scheduled for ad-hoc locations and serviced that way, i.e. a truck parked on the side of the highway etc
|
||||||
|
*/
|
||||||
public class WorkOrder : ICoreBizObjectModel
|
public class WorkOrder : ICoreBizObjectModel
|
||||||
{
|
{
|
||||||
public WorkOrder()
|
public WorkOrder()
|
||||||
|
|||||||
Reference in New Issue
Block a user