Added ReviewImminent notification event type and backing and fronting code
This commit is contained in:
@@ -466,6 +466,7 @@ namespace AyaNova.Api.Controllers
|
|||||||
TranslationKeysToFetch.Add("NotifyEventWorkorderCreatedForCustomer");
|
TranslationKeysToFetch.Add("NotifyEventWorkorderCreatedForCustomer");
|
||||||
TranslationKeysToFetch.Add("NotifyEventPMGenerationFailed");
|
TranslationKeysToFetch.Add("NotifyEventPMGenerationFailed");
|
||||||
TranslationKeysToFetch.Add("NotifyEventPMInsufficientInventory");
|
TranslationKeysToFetch.Add("NotifyEventPMInsufficientInventory");
|
||||||
|
TranslationKeysToFetch.Add("NotifyEventReviewImminent");
|
||||||
|
|
||||||
var LT = await TranslationBiz.GetSubsetStaticAsync(TranslationKeysToFetch, translationId);
|
var LT = await TranslationBiz.GetSubsetStaticAsync(TranslationKeysToFetch, translationId);
|
||||||
|
|
||||||
@@ -482,6 +483,7 @@ namespace AyaNova.Api.Controllers
|
|||||||
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventObjectAge"], Id = (long)NotifyEventType.ObjectAge });
|
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventObjectAge"], Id = (long)NotifyEventType.ObjectAge });
|
||||||
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventPMInsufficientInventory"], Id = (long)NotifyEventType.PMInsufficientInventory });
|
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventPMInsufficientInventory"], Id = (long)NotifyEventType.PMInsufficientInventory });
|
||||||
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventReminderImminent"], Id = (long)NotifyEventType.ReminderImminent });
|
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventReminderImminent"], Id = (long)NotifyEventType.ReminderImminent });
|
||||||
|
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventReviewImminent"], Id = (long)NotifyEventType.ReviewImminent });
|
||||||
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventScheduledOnWorkorder"], Id = (long)NotifyEventType.ScheduledOnWorkorder });
|
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventScheduledOnWorkorder"], Id = (long)NotifyEventType.ScheduledOnWorkorder });
|
||||||
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventScheduledOnWorkorderImminent"], Id = (long)NotifyEventType.ScheduledOnWorkorderImminent });
|
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventScheduledOnWorkorderImminent"], Id = (long)NotifyEventType.ScheduledOnWorkorderImminent });
|
||||||
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventWorkorderCompletedStatusOverdue"], Id = (long)NotifyEventType.WorkorderCompletedStatusOverdue });
|
ReturnList.Add(new NameIdItem() { Name = LT["NotifyEventWorkorderCompletedStatusOverdue"], Id = (long)NotifyEventType.WorkorderCompletedStatusOverdue });
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ namespace AyaNova.Biz
|
|||||||
WorkorderCompleted = 30, //*Service work order is set to any status that is flagged as a "Completed" type of status. Customer & User (Note this is for users that don't want or can't pick status change to completed type)
|
WorkorderCompleted = 30, //*Service work order is set to any status that is flagged as a "Completed" type of status. Customer & User (Note this is for users that don't want or can't pick status change to completed type)
|
||||||
WorkorderCreatedForCustomer = 31, //*Service work order is created for Customer, only applies to that customer user notify sub for that customer, customer id is in conditional ID value for subscription
|
WorkorderCreatedForCustomer = 31, //*Service work order is created for Customer, only applies to that customer user notify sub for that customer, customer id is in conditional ID value for subscription
|
||||||
PMGenerationFailed = 32, //indicates there was a failure during PM generation with error
|
PMGenerationFailed = 32, //indicates there was a failure during PM generation with error
|
||||||
SendUserCredentials = 33 // Internal System use only: When user generates new credentials and sends them this is the notification type for that see UserBiz GenerateCredsAndEmailUser
|
SendUserCredentials = 33, // Internal System use only: When user generates new credentials and sends them this is the notification type for that see UserBiz GenerateCredsAndEmailUser
|
||||||
|
ReviewImminent = 34,//*Review object, Advance notice setting tag conditional
|
||||||
|
|
||||||
//POTENTIAL OTHER NOTIFICATIONS:
|
//POTENTIAL OTHER NOTIFICATIONS:
|
||||||
//WorkOrderItemLoan unit is overdue from estimate
|
//WorkOrderItemLoan unit is overdue from estimate
|
||||||
|
|||||||
@@ -501,7 +501,7 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}//warranty expiry event
|
}//Reminder imminent event
|
||||||
|
|
||||||
}//end of process notifications
|
}//end of process notifications
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -527,76 +527,126 @@ namespace AyaNova.Biz
|
|||||||
|
|
||||||
bool isNew = currentObj == null;
|
bool isNew = currentObj == null;
|
||||||
|
|
||||||
|
Review o = (Review)proposedObj;
|
||||||
|
|
||||||
//STANDARD EVENTS FOR ALL OBJECTS
|
//STANDARD EVENTS FOR ALL OBJECTS
|
||||||
await NotifyEventHelper.ProcessStandardObjectEvents(ayaEvent, proposedObj, ct);
|
await NotifyEventHelper.ProcessStandardObjectEvents(ayaEvent, proposedObj, ct);
|
||||||
|
|
||||||
//SPECIFIC EVENTS FOR THIS OBJECT
|
//SPECIFIC EVENTS FOR THIS OBJECT
|
||||||
|
#region OLD
|
||||||
|
|
||||||
//CREATED / MODIFIED
|
//OLD general notification code removed in favor of specific event for review imminent
|
||||||
|
// //CREATED / MODIFIED
|
||||||
|
// if (ayaEvent == AyaEvent.Created || ayaEvent == AyaEvent.Modified)
|
||||||
|
// {
|
||||||
|
// //OVERDUE pseudo event
|
||||||
|
// {
|
||||||
|
// //Remove prior
|
||||||
|
// await NotifyEventHelper.ClearPriorEventsForObject(ct, proposedObj.AyaType, proposedObj.Id, NotifyEventType.GeneralNotification);//assumes only general event for this object type is overdue here
|
||||||
|
|
||||||
|
// //set a deadman automatic internal notification if goes past due
|
||||||
|
// var r = (Review)proposedObj;
|
||||||
|
|
||||||
|
// //it not completed yet and not overdue already (which could indicate an import or something)
|
||||||
|
// if (r.CompletedDate == null && r.ReviewDate > DateTime.UtcNow)
|
||||||
|
// {
|
||||||
|
// //Notify user
|
||||||
|
// await NotifyEventHelper.EnsureDefaultInAppUserNotificationSubscriptionExists(r.UserId, ct);
|
||||||
|
// {
|
||||||
|
// var gensubs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.GeneralNotification && z.UserId == r.UserId).ToListAsync();
|
||||||
|
// foreach (var sub in gensubs)
|
||||||
|
// {
|
||||||
|
// var eventNameTranslated = await TranslationBiz.GetTranslationForUserStaticAsync("ReviewOverDue", r.UserId);
|
||||||
|
// NotifyEvent n = new NotifyEvent()
|
||||||
|
// {
|
||||||
|
// EventType = NotifyEventType.GeneralNotification,
|
||||||
|
// UserId = r.UserId,
|
||||||
|
// ObjectId = proposedObj.Id,
|
||||||
|
// AyaType = AyaType.Review,
|
||||||
|
// NotifySubscriptionId = sub.Id,
|
||||||
|
// Name = $"{eventNameTranslated} - {proposedObj.Name}",
|
||||||
|
// EventDate = r.ReviewDate
|
||||||
|
// };
|
||||||
|
// await ct.NotifyEvent.AddAsync(n);
|
||||||
|
// log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
|
||||||
|
// }
|
||||||
|
// if (gensubs.Count > 0)
|
||||||
|
// await ct.SaveChangesAsync();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //Notify supervisor
|
||||||
|
// if (r.UserId != r.AssignedByUserId)
|
||||||
|
// {
|
||||||
|
// await NotifyEventHelper.EnsureDefaultInAppUserNotificationSubscriptionExists(r.AssignedByUserId, ct);
|
||||||
|
// var gensubs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.GeneralNotification && z.UserId == r.AssignedByUserId).ToListAsync();
|
||||||
|
// foreach (var sub in gensubs)
|
||||||
|
// {
|
||||||
|
// var eventNameTranslated = await TranslationBiz.GetTranslationForUserStaticAsync("ReviewOverDue", r.AssignedByUserId);
|
||||||
|
// NotifyEvent n = new NotifyEvent()
|
||||||
|
// {
|
||||||
|
// EventType = NotifyEventType.GeneralNotification,
|
||||||
|
// UserId = r.AssignedByUserId,
|
||||||
|
// ObjectId = proposedObj.Id,
|
||||||
|
// AyaType = AyaType.Review,
|
||||||
|
// NotifySubscriptionId = sub.Id,
|
||||||
|
// Name = $"{eventNameTranslated} - {proposedObj.Name}",
|
||||||
|
// EventDate = r.ReviewDate
|
||||||
|
// };
|
||||||
|
// await ct.NotifyEvent.AddAsync(n);
|
||||||
|
// log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
|
||||||
|
// }
|
||||||
|
// if (gensubs.Count > 0)
|
||||||
|
// await ct.SaveChangesAsync();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }//overdue event
|
||||||
|
// }//custom events for created / modified
|
||||||
|
#endregion old
|
||||||
|
|
||||||
|
//## DELETED EVENTS
|
||||||
|
|
||||||
|
//any event added below needs to be removed, so
|
||||||
|
//just blanket remove any event for this object of eventtype that would be added below here
|
||||||
|
//do it regardless any time there's an update and then
|
||||||
|
//let this code below handle the refreshing addition that could have changes
|
||||||
|
await NotifyEventHelper.ClearPriorEventsForObject(ct, AyaType.Review, o.Id, NotifyEventType.ReviewImminent);
|
||||||
|
|
||||||
|
//## CREATED / MODIFIED EVENTS
|
||||||
if (ayaEvent == AyaEvent.Created || ayaEvent == AyaEvent.Modified)
|
if (ayaEvent == AyaEvent.Created || ayaEvent == AyaEvent.Modified)
|
||||||
{
|
{
|
||||||
//OVERDUE pseudo event
|
//# REVIEW IMMINENT
|
||||||
{
|
{
|
||||||
//Remove prior
|
//notify users (time delayed)
|
||||||
await NotifyEventHelper.ClearPriorEventsForObject(ct, proposedObj.AyaType, proposedObj.Id, NotifyEventType.GeneralNotification);//assumes only general event for this object type is overdue here
|
var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ReviewImminent).ToListAsync();
|
||||||
|
foreach (var sub in subs)
|
||||||
//set a deadman automatic internal notification if goes past due
|
|
||||||
var r = (Review)proposedObj;
|
|
||||||
|
|
||||||
//it not completed yet and not overdue already (which could indicate an import or something)
|
|
||||||
if (r.CompletedDate == null && r.ReviewDate > DateTime.UtcNow)
|
|
||||||
{
|
{
|
||||||
//Notify user
|
//not for inactive users
|
||||||
await NotifyEventHelper.EnsureDefaultInAppUserNotificationSubscriptionExists(r.UserId, ct);
|
if (!await UserBiz.UserIsActive(sub.UserId)) continue;
|
||||||
{
|
|
||||||
var gensubs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.GeneralNotification && z.UserId == r.UserId).ToListAsync();
|
|
||||||
foreach (var sub in gensubs)
|
|
||||||
{
|
|
||||||
var eventNameTranslated = await TranslationBiz.GetTranslationForUserStaticAsync("ReviewOverDue", r.UserId);
|
|
||||||
NotifyEvent n = new NotifyEvent()
|
|
||||||
{
|
|
||||||
EventType = NotifyEventType.GeneralNotification,
|
|
||||||
UserId = r.UserId,
|
|
||||||
ObjectId = proposedObj.Id,
|
|
||||||
AyaType = AyaType.Review,
|
|
||||||
NotifySubscriptionId = sub.Id,
|
|
||||||
Name = $"{eventNameTranslated} - {proposedObj.Name}",
|
|
||||||
EventDate = r.ReviewDate
|
|
||||||
};
|
|
||||||
await ct.NotifyEvent.AddAsync(n);
|
|
||||||
log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
|
|
||||||
}
|
|
||||||
if (gensubs.Count > 0)
|
|
||||||
await ct.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Notify supervisor
|
//Tag match? (will be true if no sub tags so always safe to call this)
|
||||||
if (r.UserId != r.AssignedByUserId)
|
if (NotifyEventHelper.ObjectHasAllSubscriptionTags(o.Tags, sub.Tags))
|
||||||
{
|
{
|
||||||
await NotifyEventHelper.EnsureDefaultInAppUserNotificationSubscriptionExists(r.AssignedByUserId, ct);
|
|
||||||
var gensubs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.GeneralNotification && z.UserId == r.AssignedByUserId).ToListAsync();
|
NotifyEvent n = new NotifyEvent()
|
||||||
foreach (var sub in gensubs)
|
|
||||||
{
|
{
|
||||||
var eventNameTranslated = await TranslationBiz.GetTranslationForUserStaticAsync("ReviewOverDue", r.AssignedByUserId);
|
EventType = NotifyEventType.ReviewImminent,
|
||||||
NotifyEvent n = new NotifyEvent()
|
UserId = sub.UserId,
|
||||||
{
|
AyaType = o.AyaType,
|
||||||
EventType = NotifyEventType.GeneralNotification,
|
ObjectId = o.Id,
|
||||||
UserId = r.AssignedByUserId,
|
NotifySubscriptionId = sub.Id,
|
||||||
ObjectId = proposedObj.Id,
|
Name = o.Name,
|
||||||
AyaType = AyaType.Review,
|
EventDate = o.ReviewDate
|
||||||
NotifySubscriptionId = sub.Id,
|
};
|
||||||
Name = $"{eventNameTranslated} - {proposedObj.Name}",
|
await ct.NotifyEvent.AddAsync(n);
|
||||||
EventDate = r.ReviewDate
|
log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
|
||||||
};
|
await ct.SaveChangesAsync();
|
||||||
await ct.NotifyEvent.AddAsync(n);
|
|
||||||
log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]");
|
|
||||||
}
|
|
||||||
if (gensubs.Count > 0)
|
|
||||||
await ct.SaveChangesAsync();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}//overdue event
|
|
||||||
}//custom events for created / modified
|
}//review imminent
|
||||||
|
|
||||||
|
}//end of process notifications
|
||||||
|
|
||||||
}//end of process notifications
|
}//end of process notifications
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2031,7 +2031,7 @@
|
|||||||
"NotifyEventQuoteStatusChange": "Angebotsstatus geändert",
|
"NotifyEventQuoteStatusChange": "Angebotsstatus geändert",
|
||||||
"NotifyEventQuoteStatusAge": "Angebotsstatus für den Zeitraum unverändert",
|
"NotifyEventQuoteStatusAge": "Angebotsstatus für den Zeitraum unverändert",
|
||||||
"NotifyEventServiceBankDepleted": "Service Bank erschöpft",
|
"NotifyEventServiceBankDepleted": "Service Bank erschöpft",
|
||||||
"NotifyEventReminderImminent": "Erinnerung unmittelbar bevorsteht",
|
"NotifyEventReminderImminent": "Erinnerung - unmittelbar bevorstehend",
|
||||||
"NotifyEventScheduledOnWorkorder": "Geplant auf Arbeitsauftrag",
|
"NotifyEventScheduledOnWorkorder": "Geplant auf Arbeitsauftrag",
|
||||||
"NotifyEventScheduledOnWorkorderImminent": "Arbeitsauftragsplan steht kurz bevor",
|
"NotifyEventScheduledOnWorkorderImminent": "Arbeitsauftragsplan steht kurz bevor",
|
||||||
"NotifyEventWorkorderCompletedStatusOverdue": "Arbeitsauftrag nicht rechtzeitig fertig",
|
"NotifyEventWorkorderCompletedStatusOverdue": "Arbeitsauftrag nicht rechtzeitig fertig",
|
||||||
@@ -2059,6 +2059,7 @@
|
|||||||
"NotifyEventPMStopGeneratingDateReached": "Stoppdatum für vorbeugende Wartung erreicht",
|
"NotifyEventPMStopGeneratingDateReached": "Stoppdatum für vorbeugende Wartung erreicht",
|
||||||
"NotifyEventPMGenerationFailed": "Vorbeugende Wartung Generatorausfall",
|
"NotifyEventPMGenerationFailed": "Vorbeugende Wartung Generatorausfall",
|
||||||
"NotifyEventPMInsufficientInventory": "Vorbeugende Wartung unzureichender Lagerbestand",
|
"NotifyEventPMInsufficientInventory": "Vorbeugende Wartung unzureichender Lagerbestand",
|
||||||
|
"NotifyEventReviewImminent": "Überprüfung - unmittelbar bevorstehend",
|
||||||
"Duration": "Dauer",
|
"Duration": "Dauer",
|
||||||
"Notifications": "Benachrichtigungen",
|
"Notifications": "Benachrichtigungen",
|
||||||
"NotifyMailSecurityNone": "Keiner",
|
"NotifyMailSecurityNone": "Keiner",
|
||||||
|
|||||||
@@ -2031,7 +2031,7 @@
|
|||||||
"NotifyEventQuoteStatusChange": "Quote status changed",
|
"NotifyEventQuoteStatusChange": "Quote status changed",
|
||||||
"NotifyEventQuoteStatusAge": "Quote status age",
|
"NotifyEventQuoteStatusAge": "Quote status age",
|
||||||
"NotifyEventServiceBankDepleted": "Service bank empty",
|
"NotifyEventServiceBankDepleted": "Service bank empty",
|
||||||
"NotifyEventReminderImminent": "Reminder imminent",
|
"NotifyEventReminderImminent": "Reminder - imminent",
|
||||||
"NotifyEventScheduledOnWorkorder": "Scheduled on work order",
|
"NotifyEventScheduledOnWorkorder": "Scheduled on work order",
|
||||||
"NotifyEventScheduledOnWorkorderImminent": "Work order scheduled service imminent",
|
"NotifyEventScheduledOnWorkorderImminent": "Work order scheduled service imminent",
|
||||||
"NotifyEventWorkorderCompletedStatusOverdue": "Work order not completed on time",
|
"NotifyEventWorkorderCompletedStatusOverdue": "Work order not completed on time",
|
||||||
@@ -2059,6 +2059,7 @@
|
|||||||
"NotifyEventPMStopGeneratingDateReached": "Preventive maintenance stop date",
|
"NotifyEventPMStopGeneratingDateReached": "Preventive maintenance stop date",
|
||||||
"NotifyEventPMGenerationFailed": "Preventive maintenance generation failure",
|
"NotifyEventPMGenerationFailed": "Preventive maintenance generation failure",
|
||||||
"NotifyEventPMInsufficientInventory": "Preventive maintenance insufficient inventory",
|
"NotifyEventPMInsufficientInventory": "Preventive maintenance insufficient inventory",
|
||||||
|
"NotifyEventReviewImminent": "Review - imminent",
|
||||||
"Duration": "Duration",
|
"Duration": "Duration",
|
||||||
"Notifications": "Notifications",
|
"Notifications": "Notifications",
|
||||||
"NotifyMailSecurityNone": "None",
|
"NotifyMailSecurityNone": "None",
|
||||||
|
|||||||
@@ -2059,6 +2059,7 @@
|
|||||||
"NotifyEventPMStopGeneratingDateReached": "Se alcanzó la fecha de 'detención' del mantenimiento preventivo",
|
"NotifyEventPMStopGeneratingDateReached": "Se alcanzó la fecha de 'detención' del mantenimiento preventivo",
|
||||||
"NotifyEventPMGenerationFailed": "Fallo de generación de mantenimiento preventivo",
|
"NotifyEventPMGenerationFailed": "Fallo de generación de mantenimiento preventivo",
|
||||||
"NotifyEventPMInsufficientInventory": "Inventario insuficiente de mantenimiento preventivo",
|
"NotifyEventPMInsufficientInventory": "Inventario insuficiente de mantenimiento preventivo",
|
||||||
|
"NotifyEventReviewImminent": "Revisión - inminente",
|
||||||
"Duration": "Duración",
|
"Duration": "Duración",
|
||||||
"Notifications": "Notificaciones",
|
"Notifications": "Notificaciones",
|
||||||
"NotifyMailSecurityNone": "Ninguna",
|
"NotifyMailSecurityNone": "Ninguna",
|
||||||
|
|||||||
@@ -2031,7 +2031,7 @@
|
|||||||
"NotifyEventQuoteStatusChange": "Statut du devis modifié",
|
"NotifyEventQuoteStatusChange": "Statut du devis modifié",
|
||||||
"NotifyEventQuoteStatusAge": "Statut du devis inchangé pour la période de temps",
|
"NotifyEventQuoteStatusAge": "Statut du devis inchangé pour la période de temps",
|
||||||
"NotifyEventServiceBankDepleted": "Banque de services épuisée",
|
"NotifyEventServiceBankDepleted": "Banque de services épuisée",
|
||||||
"NotifyEventReminderImminent": "Rappel imminent",
|
"NotifyEventReminderImminent": "Rappel - imminent",
|
||||||
"NotifyEventScheduledOnWorkorder": "Planifié sur ordre de travail",
|
"NotifyEventScheduledOnWorkorder": "Planifié sur ordre de travail",
|
||||||
"NotifyEventScheduledOnWorkorderImminent": "Service planifié d'un ordre de travail imminent",
|
"NotifyEventScheduledOnWorkorderImminent": "Service planifié d'un ordre de travail imminent",
|
||||||
"NotifyEventWorkorderCompletedStatusOverdue": "Ordre de travail non terminé à temps",
|
"NotifyEventWorkorderCompletedStatusOverdue": "Ordre de travail non terminé à temps",
|
||||||
@@ -2059,6 +2059,7 @@
|
|||||||
"NotifyEventPMStopGeneratingDateReached": "Date d'arrêt de la maintenance préventive atteinte",
|
"NotifyEventPMStopGeneratingDateReached": "Date d'arrêt de la maintenance préventive atteinte",
|
||||||
"NotifyEventPMGenerationFailed": "Défaillance du système de maintenance préventive",
|
"NotifyEventPMGenerationFailed": "Défaillance du système de maintenance préventive",
|
||||||
"NotifyEventPMInsufficientInventory": "Maintenance préventive inventaire insuffisant",
|
"NotifyEventPMInsufficientInventory": "Maintenance préventive inventaire insuffisant",
|
||||||
|
"NotifyEventReviewImminent": "Révision - imminente",
|
||||||
"Duration": "Durée",
|
"Duration": "Durée",
|
||||||
"Notifications": "Notifications",
|
"Notifications": "Notifications",
|
||||||
"NotifyMailSecurityNone": "Aucun",
|
"NotifyMailSecurityNone": "Aucun",
|
||||||
|
|||||||
Reference in New Issue
Block a user