Manuel Notification eklendi
This commit is contained in:
parent
969b048946
commit
722decd040
30 changed files with 1772 additions and 55 deletions
|
|
@ -1213,6 +1213,8 @@ Kök menü `App.Administration`. Bu menünün tabloları `Adm_T_*` — yani **ki
|
||||||
| **Licence** | `App.Licence` · `/admin/form/App.Licence` | `AbpTenants` + `V_Sas_H_OrderItem_ByTenantId` | **`ListFormType = Form`** (listesiz, tek kayıtlık ekran) + alt kalem listesi. "Tek kayıtlık kart ekran" isteğinin karşılığı budur. |
|
| **Licence** | `App.Licence` · `/admin/form/App.Licence` | `AbpTenants` + `V_Sas_H_OrderItem_ByTenantId` | **`ListFormType = Form`** (listesiz, tek kayıtlık ekran) + alt kalem listesi. "Tek kayıtlık kart ekran" isteğinin karşılığı budur. |
|
||||||
| **Dev Request** | `App.DevRequest` | `Sas_H_DevRequest` | Kiracı tarafındaki talep ekranı (Saas'taki listenin kullanıcı yüzü). |
|
| **Dev Request** | `App.DevRequest` | `Sas_H_DevRequest` | Kiracı tarafındaki talep ekranı (Saas'taki listenin kullanıcı yüzü). |
|
||||||
| **Agenda** | `App.Agenda` | `Adm_T_Agenda` | **Takvim (Scheduler) düzeninin** referansı: `StartDate`, `EndDate`, `AllDay`, `RecurrenceRule`, `RecurrenceException`. Tekrarlayan randevu isteği kod gerektirmez. |
|
| **Agenda** | `App.Agenda` | `Adm_T_Agenda` | **Takvim (Scheduler) düzeninin** referansı: `StartDate`, `EndDate`, `AllDay`, `RecurrenceRule`, `RecurrenceException`. Tekrarlayan randevu isteği kod gerektirmez. |
|
||||||
|
| **Bildirimler › Manuel Bildirim** | `App.ManualNotification` | `Adm_T_NotificationManual` | Seçilen kullanıcılara seçilen kanallardan elle bildirim gönderimi; kayıt gönderimin günlüğüdür, gönderim `INotificationManager` üzerinden "Manuel" tipiyle yapılır. Ayrıntı: `README.md` §13.5.1. |
|
||||||
|
| **Bildirimler › Bildirim Şablonları** | `App.Notifications.NotificationTemplates` | `Adm_T_NotificationTemplate` | Manuel gönderimde seçilen mesaj şablonları (kanal, konu, gövde, yer tutucular); şablon seçilince konu ve gövde forma kopyalanır. Örnek satırlar seed ile gelir. |
|
||||||
| **Settings** | `App.Setting` · `/admin/settings` | — | `SettingDefinition` kayıtlarından üretilen ayar ekranı; değerler burada girilir. |
|
| **Settings** | `App.Setting` · `/admin/settings` | — | `SettingDefinition` kayıtlarından üretilen ayar ekranı; değerler burada girilir. |
|
||||||
| **Intranet › Announcement (+Like/Comment)** | `App.Intranet.Announcement` | `Adm_T_Announcement` · `Adm_T_AnnouncementLike` · `Adm_T_AnnouncementComment` | Duyuru + beğeni + yorum: **ana kayıt / alt etkileşim** kalıbının hazır örneği. |
|
| **Intranet › Announcement (+Like/Comment)** | `App.Intranet.Announcement` | `Adm_T_Announcement` · `Adm_T_AnnouncementLike` · `Adm_T_AnnouncementComment` | Duyuru + beğeni + yorum: **ana kayıt / alt etkileşim** kalıbının hazır örneği. |
|
||||||
| **Intranet › Survey (+Question/Option/Response/Answer)** | `App.Intranet.Survey` | `Adm_T_Survey` · `Adm_T_SurveyQuestion` · `Adm_T_SurveyQuestionOption` · `Adm_T_SurveyResponse` · `Adm_T_SurveyAnswer` | Anket motoru; soru–seçenek–yanıt zinciri **iki seviyeli alt form** ihtiyacının referansıdır. |
|
| **Intranet › Survey (+Question/Option/Response/Answer)** | `App.Intranet.Survey` | `Adm_T_Survey` · `Adm_T_SurveyQuestion` · `Adm_T_SurveyQuestionOption` · `Adm_T_SurveyResponse` · `Adm_T_SurveyAnswer` | Anket motoru; soru–seçenek–yanıt zinciri **iki seviyeli alt form** ihtiyacının referansıdır. |
|
||||||
|
|
|
||||||
40
README.md
40
README.md
|
|
@ -1196,6 +1196,46 @@ Tercih ekranı (`/admin/profile/notification-settings`) satırlarını bildirim
|
||||||
üzerinden eşler; tip adı yalnızca gösterimdir. `NotificationType.Description` alanı aynı ekranda
|
üzerinden eşler; tip adı yalnızca gösterimdir. `NotificationType.Description` alanı aynı ekranda
|
||||||
ipucu olarak görünür ve Bildirim Türleri ekranından yazılır.
|
ipucu olarak görünür ve Bildirim Türleri ekranından yazılır.
|
||||||
|
|
||||||
|
### 13.5.1. Manuel gönderim (Administration › Bildirimler)
|
||||||
|
|
||||||
|
İki ekran Administration menüsünde `App.Administration.Notifications` grubunda durur:
|
||||||
|
**Manuel Bildirim** ve **Bildirim Şablonları**. Grup Agenda'nın üstündedir; Saas › Notifications
|
||||||
|
altında bildirim **tipi/kuralı/kaydı** ekranları kalır.
|
||||||
|
|
||||||
|
Kural yazmadan, seçilen kullanıcılara seçilen kanallardan bildirim göndermek için
|
||||||
|
`App.ManualNotification` ekranı kullanılır (`Adm_T_NotificationManual`). Kayıt gönderimin kendisi
|
||||||
|
değil **günlüğüdür**: ekleme anında yazma işi `list-form-dynamic-api/notification-manual-insert`
|
||||||
|
ucuna gider (`InsertServiceAddress`), uç kaydı yazar ve gönderimi
|
||||||
|
`INotificationManager.SendManualNotificationAsync` üzerinden yapar — yani Bildirim Kuralları
|
||||||
|
ekranındaki elle gönderimle **aynı yol**, tek fark alıcı kümesinin kurallardan değil ekrandan
|
||||||
|
gelmesi. Güncelleme kapalıdır, silme kaydı kaldırır.
|
||||||
|
|
||||||
|
| Kural | Nerede |
|
||||||
|
| --- | --- |
|
||||||
|
| Bildirim tipi her zaman `Manuel` | `NotificationConsts.ManualTypeName`; tip kaydı `App.Notifications.NotificationTypes.json` |
|
||||||
|
| `Notification.NotificationRuleId` NOT NULL olduğu için tipin **çapa kuralına** bağlanır (`RecipientType = Custom`, `IsActive = false`) | `App.Notifications.NotificationRules.json`; kural pasif olduğu için kural motoru ve profil tercih ekranında görünmez |
|
||||||
|
| Kullanıcı tercihi okunmaz (zorunlu bildirim gibi davranır) | `NotificationManager.SendManualNotificationAsync` |
|
||||||
|
| Alıcı listesi kiracı filtresinden geçer | Kullanıcı sorgusu ABP kiracı filtresiyle çalışır; istekteki kimlikler değiştirilse bile başka kiracıya gönderilemez |
|
||||||
|
| İlgili kanalda adresi olmayan alıcı atlanır | `SkippedCount` + `ResultNote` (kanal bazlı gerekçe) |
|
||||||
|
| Kanaldan çıkış yine `NotificationWorker` | `UiActivity` oluşurken iletilmiş sayılır, tarayıcı kanallarını istemci işaretler (§13.3) |
|
||||||
|
|
||||||
|
**Şablonlar** (`Administration › Bildirimler › Bildirim Şablonları`,
|
||||||
|
`App.Notifications.NotificationTemplates`,
|
||||||
|
`Adm_T_NotificationTemplate`) mesaj metnini taşır: `Code`, `Name`, `Channel` (boş = tüm kanallar),
|
||||||
|
`Subject`, `Body`, `IsActive`. Örnek şablonlar seed ile gelir
|
||||||
|
(`data/App.Notifications.NotificationTemplates.json`; ekran `SeedFilePath` ile bu dosyaya
|
||||||
|
aynalanır). Gönderimde şablon seçilirse ekranda **boş bırakılan** konu ve gövde şablondan
|
||||||
|
tamamlanır; ekranda yazılan metin şablonu ezer.
|
||||||
|
|
||||||
|
Gövdedeki yer tutucular alıcı bazında çözülür (`NotificationMessageTokens`): `{AdSoyad}`,
|
||||||
|
`{KullaniciAdi}`, `{Eposta}`, `{Tarih}`, `{Saat}`, `{Kiraci}`. Bildirim kaydının `Message` kolonu
|
||||||
|
2048 karakterdir; yer tutucular çözülünce metin bu sınırda kırpılır.
|
||||||
|
|
||||||
|
**Mail konu satırı:** bildirim kaydı `Subject` kolonu taşır (`Sas_H_Notification`, 256).
|
||||||
|
`NotificationWorker` konuyu bu kolondan alır; kolon boşsa bildirim tipinin adına düşer
|
||||||
|
(`Platform Bildirim: {tip}`). Kural motorundan gelen bildirimlerde kolon boş kalır, manuel
|
||||||
|
gönderimde ekrandan ya da şablondan gelir — yani konu artık gövdeye gömülmez.
|
||||||
|
|
||||||
### 13.6. Göndericiler (`Sozsoft.Sender`)
|
### 13.6. Göndericiler (`Sozsoft.Sender`)
|
||||||
|
|
||||||
| Kanal | Sağlayıcı |
|
| Kanal | Sağlayıcı |
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,12 @@
|
||||||
public static class NotificationConsts
|
public static class NotificationConsts
|
||||||
{
|
{
|
||||||
public const string AppName = "Notifications";
|
public const string AppName = "Notifications";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Elle yapilan gonderimlerin bildirim tipi. Kural motorundan gecmeyen her bildirim bu tiple
|
||||||
|
/// yazilir; tip kaydi seed ile gelir (<c>App.Notifications.NotificationTypes.json</c>).
|
||||||
|
/// </summary>
|
||||||
|
public const string ManualTypeName = "Manuel";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NotificationRecipientTypes
|
public static class NotificationRecipientTypes
|
||||||
|
|
@ -14,3 +20,16 @@ public static class NotificationRecipientTypes
|
||||||
public const string Custom = "Custom";
|
public const string Custom = "Custom";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manuel gonderimde mesaj icinde cozulen yer tutucular. Sablon metni bu anahtarlari tasir,
|
||||||
|
/// gonderim aninda her alici icin ayri ayri degistirilir.
|
||||||
|
/// </summary>
|
||||||
|
public static class NotificationMessageTokens
|
||||||
|
{
|
||||||
|
public const string FullName = "{AdSoyad}";
|
||||||
|
public const string UserName = "{KullaniciAdi}";
|
||||||
|
public const string Email = "{Eposta}";
|
||||||
|
public const string Date = "{Tarih}";
|
||||||
|
public const string Time = "{Saat}";
|
||||||
|
public const string Tenant = "{Kiraci}";
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,13 @@ public class Notification : FullAuditedEntity<Guid>
|
||||||
public Guid? UserId { get; set; }
|
public Guid? UserId { get; set; }
|
||||||
public required string Message { get; set; }
|
public required string Message { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mail kanalinin konu satiri. Bos ise <c>NotificationWorker</c> konuyu bildirim tipinin
|
||||||
|
/// adindan uretir; kural motorundan gecen bildirimlerde bos kalir, manuel gonderimde
|
||||||
|
/// ekrandan ya da sablondan gelir.
|
||||||
|
/// </summary>
|
||||||
|
public string? Subject { get; set; }
|
||||||
|
|
||||||
public bool IsSent { get; set; }
|
public bool IsSent { get; set; }
|
||||||
public bool IsRead { get; set; }
|
public bool IsRead { get; set; }
|
||||||
public DateTime? ReadTime { get; set; }
|
public DateTime? ReadTime { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,12 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Sozsoft.Notifications.Entities;
|
using Sozsoft.Notifications.Entities;
|
||||||
using Sozsoft.Notifications.Enums;
|
using Sozsoft.Notifications.Enums;
|
||||||
|
using Volo.Abp;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
using Volo.Abp.Domain.Repositories;
|
using Volo.Abp.Domain.Repositories;
|
||||||
using Volo.Abp.Identity;
|
using Volo.Abp.Identity;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
|
using Volo.Abp.Timing;
|
||||||
|
|
||||||
namespace Sozsoft.Notifications.Domain;
|
namespace Sozsoft.Notifications.Domain;
|
||||||
|
|
||||||
|
|
@ -18,6 +21,36 @@ public interface INotificationManager : ITransientDependency
|
||||||
/// kaydi uretir. Kayitlarin kanaldan cikisi <c>NotificationWorker</c>'a aittir.
|
/// kaydi uretir. Kayitlarin kanaldan cikisi <c>NotificationWorker</c>'a aittir.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task SendNotificationAsync(Guid NotificationTypeId, string NotificationMessage);
|
Task SendNotificationAsync(Guid NotificationTypeId, string NotificationMessage);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alici kumesi kurallardan degil ekrandan gelen gonderim: secilen her kullanici icin secilen
|
||||||
|
/// her kanalda bir bildirim kaydi uretir. Kanaldan cikis yine <c>NotificationWorker</c>'a
|
||||||
|
/// aittir; kullanici tercihi dikkate alinmaz, cunku gonderim zaten bilincli bir aksiyondur.
|
||||||
|
/// </summary>
|
||||||
|
Task<ManualNotificationResult> SendManualNotificationAsync(ManualNotificationRequest request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Manuel gonderim istegi; alicilar ve kanallar cagirandan gelir.</summary>
|
||||||
|
public class ManualNotificationRequest
|
||||||
|
{
|
||||||
|
public Guid NotificationTypeId { get; set; }
|
||||||
|
public IReadOnlyCollection<Guid> UserIds { get; set; } = [];
|
||||||
|
public IReadOnlyCollection<string> Channels { get; set; } = [];
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>Mail konu satiri; bos ise konu bildirim tipinin adindan uretilir.</summary>
|
||||||
|
public string Subject { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manuel gonderimin sonucu. Atlananlar kanal kanal raporlanir: bir alicinin o kanalda adresi
|
||||||
|
/// (e-posta, telefon, chat id) yoksa bildirim uretilemez ve bunun cozumu kullanici kaydindadir.
|
||||||
|
/// </summary>
|
||||||
|
public class ManualNotificationResult
|
||||||
|
{
|
||||||
|
public int SentCount { get; set; }
|
||||||
|
public Dictionary<string, int> SkippedByChannel { get; set; } = [];
|
||||||
|
public int SkippedCount => SkippedByChannel.Values.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NotificationManager : INotificationManager
|
public class NotificationManager : INotificationManager
|
||||||
|
|
@ -29,6 +62,8 @@ public class NotificationManager : INotificationManager
|
||||||
private readonly INotificationIdentifierProvider notificationIdentifierProvider;
|
private readonly INotificationIdentifierProvider notificationIdentifierProvider;
|
||||||
private readonly IOrganizationUnitRepository repositoryOrganizationUnit;
|
private readonly IOrganizationUnitRepository repositoryOrganizationUnit;
|
||||||
private readonly INotificationRealtimeNotifier realtimeNotifier;
|
private readonly INotificationRealtimeNotifier realtimeNotifier;
|
||||||
|
private readonly ICurrentTenant currentTenant;
|
||||||
|
private readonly IClock clock;
|
||||||
|
|
||||||
public NotificationManager(
|
public NotificationManager(
|
||||||
IReadOnlyRepository<NotificationRule> repository,
|
IReadOnlyRepository<NotificationRule> repository,
|
||||||
|
|
@ -37,7 +72,9 @@ public class NotificationManager : INotificationManager
|
||||||
IRepository<Notification, Guid> repositoryNotification,
|
IRepository<Notification, Guid> repositoryNotification,
|
||||||
INotificationIdentifierProvider notificationIdentifierProvider,
|
INotificationIdentifierProvider notificationIdentifierProvider,
|
||||||
IOrganizationUnitRepository repositoryOrganizationUnit,
|
IOrganizationUnitRepository repositoryOrganizationUnit,
|
||||||
INotificationRealtimeNotifier realtimeNotifier
|
INotificationRealtimeNotifier realtimeNotifier,
|
||||||
|
ICurrentTenant currentTenant,
|
||||||
|
IClock clock
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
|
|
@ -47,6 +84,8 @@ public class NotificationManager : INotificationManager
|
||||||
this.notificationIdentifierProvider = notificationIdentifierProvider;
|
this.notificationIdentifierProvider = notificationIdentifierProvider;
|
||||||
this.repositoryOrganizationUnit = repositoryOrganizationUnit;
|
this.repositoryOrganizationUnit = repositoryOrganizationUnit;
|
||||||
this.realtimeNotifier = realtimeNotifier;
|
this.realtimeNotifier = realtimeNotifier;
|
||||||
|
this.currentTenant = currentTenant;
|
||||||
|
this.clock = clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendNotificationAsync(Guid NotificationTypeId, string NotificationMessage)
|
public async Task SendNotificationAsync(Guid NotificationTypeId, string NotificationMessage)
|
||||||
|
|
@ -121,16 +160,119 @@ public class NotificationManager : INotificationManager
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await SaveAndAnnounceAsync(notifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alicilari kurallar yerine cagiranin verdigi gonderim. Kullanici tercihi okunmaz: manuel
|
||||||
|
/// gonderim zorunlu bildirim (<c>IsFixed</c>) gibi davranir, aksi halde yonetici bilincli
|
||||||
|
/// yaptigi gonderimin kime gitmedigini hic ogrenemezdi.
|
||||||
|
/// </summary>
|
||||||
|
public async Task<ManualNotificationResult> SendManualNotificationAsync(ManualNotificationRequest request)
|
||||||
|
{
|
||||||
|
var result = new ManualNotificationResult();
|
||||||
|
|
||||||
|
var channels = (request.Channels ?? [])
|
||||||
|
.Where(channel => !channel.IsNullOrWhiteSpace())
|
||||||
|
.Select(channel => channel.Trim())
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
var userIds = (request.UserIds ?? []).Distinct().ToList();
|
||||||
|
|
||||||
|
if (channels.Count == 0 || userIds.Count == 0 || request.Message.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sas_H_Notification.NotificationRuleId NOT NULL'dur. Manuel gonderim kural motorundan
|
||||||
|
// gecmedigi icin tipin capa kuralina baglanir; kural pasiftir, alici kumesini o belirlemez.
|
||||||
|
var anchorRule = await repository.FirstOrDefaultAsync(rule =>
|
||||||
|
rule.NotificationTypeId == request.NotificationTypeId
|
||||||
|
&& rule.RecipientType == NotificationRecipientTypes.Custom)
|
||||||
|
?? await repository.FirstOrDefaultAsync(rule => rule.NotificationTypeId == request.NotificationTypeId)
|
||||||
|
?? throw new BusinessException("Notifications:ManualAnchorRuleNotFound")
|
||||||
|
.WithData("NotificationTypeId", request.NotificationTypeId);
|
||||||
|
|
||||||
|
// Kullanici sorgusu ABP kiraci filtresinden gecer; istekteki kimlikler degistirilse bile
|
||||||
|
// baska bir kiracinin kullanicisina bildirim uretilemez.
|
||||||
|
var queryUsers = await repositoryUser.GetQueryableAsync();
|
||||||
|
var users = await queryUsers
|
||||||
|
.Where(user => userIds.Contains(user.Id) && user.IsActive)
|
||||||
|
.Select(user => new ManualRecipient(user.Id, user.UserName, user.Name, user.Surname, user.Email))
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var notifications = new List<Notification>();
|
||||||
|
foreach (var channel in channels)
|
||||||
|
{
|
||||||
|
foreach (var user in users)
|
||||||
|
{
|
||||||
|
var identifier = await notificationIdentifierProvider.GetIdentifier(user.Id, channel);
|
||||||
|
if (identifier.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
result.SkippedByChannel[channel] = result.SkippedByChannel.GetOrDefault(channel) + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifications.Add(new Notification
|
||||||
|
{
|
||||||
|
NotificationTypeId = request.NotificationTypeId,
|
||||||
|
NotificationRuleId = anchorRule.Id,
|
||||||
|
NotificationChannel = channel,
|
||||||
|
Identifier = identifier!,
|
||||||
|
UserId = user.Id,
|
||||||
|
Message = ResolveTokens(request.Message, user),
|
||||||
|
Subject = request.Subject,
|
||||||
|
IsSent = IsDeliveredOnCreate(channel),
|
||||||
|
IsRead = false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.SentCount = notifications.Count;
|
||||||
|
await SaveAndAnnounceAsync(notifications);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Mesajdaki yer tutucular alici bazinda cozulur; her alici kendi metnini alir.</summary>
|
||||||
|
private string ResolveTokens(string message, ManualRecipient recipient)
|
||||||
|
{
|
||||||
|
var now = clock.Now;
|
||||||
|
var resolved = message
|
||||||
|
.Replace(NotificationMessageTokens.FullName, $"{recipient.Name} {recipient.Surname}".Trim())
|
||||||
|
.Replace(NotificationMessageTokens.UserName, recipient.UserName ?? string.Empty)
|
||||||
|
.Replace(NotificationMessageTokens.Email, recipient.Email ?? string.Empty)
|
||||||
|
.Replace(NotificationMessageTokens.Date, now.ToShortDateString())
|
||||||
|
.Replace(NotificationMessageTokens.Time, now.ToShortTimeString())
|
||||||
|
.Replace(NotificationMessageTokens.Tenant, currentTenant.Name ?? string.Empty);
|
||||||
|
|
||||||
|
// Yer tutucular cozulunce metin uzayabilir; kayit kolonu 2048 karakterdir.
|
||||||
|
return resolved.Length > 2048 ? resolved[..2048] : resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Kayitlari yazar ve acik istemcilere duyurur. Duyuru kayit yazildiktan sonra yapilir;
|
||||||
|
/// istemci duyuruyu alip listesini okudugunda kaydi mutlaka gormeli. Duyuru gitmezse
|
||||||
|
/// istemcideki yedek yoklama ayni kaydi getirir.
|
||||||
|
/// </summary>
|
||||||
|
private async Task SaveAndAnnounceAsync(List<Notification> notifications)
|
||||||
|
{
|
||||||
|
if (notifications.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await repositoryNotification.InsertManyAsync(notifications, autoSave: true);
|
await repositoryNotification.InsertManyAsync(notifications, autoSave: true);
|
||||||
|
|
||||||
// Duyuru kayit yazildiktan sonra yapilir; istemci duyuruyu alip listesini okudugunda
|
|
||||||
// kaydi mutlaka gormeli. Duyuru gitmezse yedek yoklama ayni kaydi getirir.
|
|
||||||
await realtimeNotifier.NotifyAsync(
|
await realtimeNotifier.NotifyAsync(
|
||||||
[.. notifications
|
[.. notifications
|
||||||
.Where(notification => notification.UserId.HasValue)
|
.Where(notification => notification.UserId.HasValue)
|
||||||
.Select(notification => new NotificationDelivery(notification.UserId!.Value, notification.NotificationChannel))]);
|
.Select(notification => new NotificationDelivery(notification.UserId!.Value, notification.NotificationChannel))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Yer tutucularin cozulmesi icin gereken alici bilgisi.</summary>
|
||||||
|
private sealed record ManualRecipient(Guid Id, string UserName, string Name, string Surname, string Email);
|
||||||
|
|
||||||
/// <summary>Kuralin hedefledigi kullanicilar; <c>Custom</c> alici bu yoldan gecmez.</summary>
|
/// <summary>Kuralin hedefledigi kullanicilar; <c>Custom</c> alici bu yoldan gecmez.</summary>
|
||||||
private async Task<List<Guid>> ResolveRecipientUserIdsAsync(NotificationRule notificationRule, IQueryable<IdentityUser> queryUsers)
|
private async Task<List<Guid>> ResolveRecipientUserIdsAsync(NotificationRule notificationRule, IQueryable<IdentityUser> queryUsers)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ public static class NotificationDbContextModelCreatingExtensions
|
||||||
b.Property(x => x.NotificationChannel).IsRequired().HasMaxLength(64);
|
b.Property(x => x.NotificationChannel).IsRequired().HasMaxLength(64);
|
||||||
b.Property(x => x.Identifier).IsRequired().HasMaxLength(256);
|
b.Property(x => x.Identifier).IsRequired().HasMaxLength(256);
|
||||||
b.Property(x => x.Message).IsRequired().HasMaxLength(2048);
|
b.Property(x => x.Message).IsRequired().HasMaxLength(2048);
|
||||||
|
b.Property(x => x.Subject).HasMaxLength(256);
|
||||||
|
|
||||||
b.HasOne(x => x.NotificationType)
|
b.HasOne(x => x.NotificationType)
|
||||||
.WithMany(x => x.Notifications)
|
.WithMany(x => x.Notifications)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Sozsoft.Platform.ListForms.DynamicApi;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manuel bildirim gonderim ekraninin kayit girdisi. <see cref="Channels"/> ve
|
||||||
|
/// <see cref="UserIds"/> ekranda <c>dxTagBox</c> ile secilir; tipli DTO yolunda
|
||||||
|
/// <c>QueryHelper</c> devreye girmedigi icin dizi/metin donusumu converter ile yapilir.
|
||||||
|
/// </summary>
|
||||||
|
public class CreateNotificationManualInput
|
||||||
|
{
|
||||||
|
public string NotificationTemplateId { get; set; }
|
||||||
|
|
||||||
|
[JsonConverter(typeof(MultiValueStringJsonConverter))]
|
||||||
|
public string Channels { get; set; }
|
||||||
|
|
||||||
|
[JsonConverter(typeof(MultiValueStringJsonConverter))]
|
||||||
|
public string UserIds { get; set; }
|
||||||
|
|
||||||
|
public string Subject { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -13,4 +13,5 @@ public interface IListFormDynamicApiAppService
|
||||||
Task PostTenantUpdateAsync(DynamicApiBaseInput<CreateUpdateTenantInput> input);
|
Task PostTenantUpdateAsync(DynamicApiBaseInput<CreateUpdateTenantInput> input);
|
||||||
Task PostTenantDeleteAsync(DynamicApiBaseInput<string> input);
|
Task PostTenantDeleteAsync(DynamicApiBaseInput<string> input);
|
||||||
Task<Guid> PostCreateTenantFromOrderAsync(DynamicApiBaseInput<CreateTenantFromOrderInput> input);
|
Task<Guid> PostCreateTenantFromOrderAsync(DynamicApiBaseInput<CreateTenantFromOrderInput> input);
|
||||||
|
Task<Guid> PostNotificationManualInsertAsync(DynamicApiBaseInput<CreateNotificationManualInput> input);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,38 @@ public static class LookupQueryValues
|
||||||
$"FROM \"AbpRoles\"" +
|
$"FROM \"AbpRoles\"" +
|
||||||
$"ORDER BY \"Name\"";
|
$"ORDER BY \"Name\"";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manuel bildirim alicilari: yalnizca oturumun kiracisindaki aktif kullanicilar. Kiraci
|
||||||
|
/// filtresi '@TENANTID' ile kurulur, host baglaminda "IS NULL" olarak cozulur.
|
||||||
|
/// </summary>
|
||||||
|
public static string TenantUserValues =
|
||||||
|
$"SELECT " +
|
||||||
|
$"\"Id\" AS \"Key\", " +
|
||||||
|
$"CONCAT(\"Name\", ' ', \"Surname\", ' (', \"UserName\", ')') AS \"Name\" " +
|
||||||
|
$"FROM \"AbpUsers\" " +
|
||||||
|
$"WHERE " +
|
||||||
|
$"\"IsDeleted\" = 'false' " +
|
||||||
|
$"AND \"IsActive\" = 'true' " +
|
||||||
|
$"AND \"TenantId\" = '@TENANTID' " +
|
||||||
|
$"ORDER BY \"Name\";";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manuel gonderimde secilebilen aktif sablonlar. Konu ve govde de secilir: ekrandaki
|
||||||
|
/// <c>copy</c> kurali sablon secilince bu kolonlari forma tasir (EditorScript).
|
||||||
|
/// </summary>
|
||||||
|
public static string NotificationTemplateValues =
|
||||||
|
$"SELECT " +
|
||||||
|
$"\"Id\" AS \"Key\", " +
|
||||||
|
$"\"Name\" AS \"Name\", " +
|
||||||
|
$"\"Subject\", " +
|
||||||
|
$"\"Body\" " +
|
||||||
|
$"FROM \"{FullNameTable(TableNameEnum.NotificationTemplate)}\" " +
|
||||||
|
$"WHERE " +
|
||||||
|
$"\"IsDeleted\" = 'false' " +
|
||||||
|
$"AND \"IsActive\" = 'true' " +
|
||||||
|
$"AND \"TenantId\" = '@TENANTID' " +
|
||||||
|
$"ORDER BY \"Name\";";
|
||||||
|
|
||||||
public static string UserValues =
|
public static string UserValues =
|
||||||
$"SELECT " +
|
$"SELECT " +
|
||||||
$"\"Id\" AS \"Key\", " +
|
$"\"Id\" AS \"Key\", " +
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Sozsoft.Notifications.Domain;
|
||||||
using Sozsoft.Platform.BlobStoring;
|
using Sozsoft.Platform.BlobStoring;
|
||||||
using Sozsoft.Platform.Entities;
|
using Sozsoft.Platform.Entities;
|
||||||
using Sozsoft.Platform.Extensions;
|
using Sozsoft.Platform.Extensions;
|
||||||
|
|
@ -36,6 +38,10 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
private readonly IOptions<IdentityOptions> identityOptions;
|
private readonly IOptions<IdentityOptions> identityOptions;
|
||||||
private readonly IRepository<Order, Guid> orderRepository;
|
private readonly IRepository<Order, Guid> orderRepository;
|
||||||
private readonly IListFormSeedDataSynchronizer seedDataSynchronizer;
|
private readonly IListFormSeedDataSynchronizer seedDataSynchronizer;
|
||||||
|
private readonly IRepository<NotificationManual, Guid> notificationManualRepository;
|
||||||
|
private readonly IRepository<NotificationTemplate, Guid> notificationTemplateRepository;
|
||||||
|
private readonly IReadOnlyRepository<Sozsoft.Notifications.Entities.NotificationType> notificationTypeRepository;
|
||||||
|
private readonly INotificationManager notificationManager;
|
||||||
|
|
||||||
public ListFormDynamicApiAppService(
|
public ListFormDynamicApiAppService(
|
||||||
ITenantRepository tenantRepository,
|
ITenantRepository tenantRepository,
|
||||||
|
|
@ -46,7 +52,11 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
IOptions<IdentityOptions> identityOptions,
|
IOptions<IdentityOptions> identityOptions,
|
||||||
IRepository<Order, Guid> orderRepository,
|
IRepository<Order, Guid> orderRepository,
|
||||||
IListFormSeedDataSynchronizer seedDataSynchronizer)
|
IListFormSeedDataSynchronizer seedDataSynchronizer,
|
||||||
|
IRepository<NotificationManual, Guid> notificationManualRepository,
|
||||||
|
IRepository<NotificationTemplate, Guid> notificationTemplateRepository,
|
||||||
|
IReadOnlyRepository<Sozsoft.Notifications.Entities.NotificationType> notificationTypeRepository,
|
||||||
|
INotificationManager notificationManager)
|
||||||
{
|
{
|
||||||
this.tenantRepository = tenantRepository;
|
this.tenantRepository = tenantRepository;
|
||||||
this.tenantManager = tenantManager;
|
this.tenantManager = tenantManager;
|
||||||
|
|
@ -57,6 +67,10 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
this.identityOptions = identityOptions;
|
this.identityOptions = identityOptions;
|
||||||
this.orderRepository = orderRepository;
|
this.orderRepository = orderRepository;
|
||||||
this.seedDataSynchronizer = seedDataSynchronizer;
|
this.seedDataSynchronizer = seedDataSynchronizer;
|
||||||
|
this.notificationManualRepository = notificationManualRepository;
|
||||||
|
this.notificationTemplateRepository = notificationTemplateRepository;
|
||||||
|
this.notificationTypeRepository = notificationTypeRepository;
|
||||||
|
this.notificationManager = notificationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Guid ParseGuid(string value)
|
private static Guid ParseGuid(string value)
|
||||||
|
|
@ -382,5 +396,88 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
|
|
||||||
await seedDataSynchronizer.RemoveRowsAsync(input.ListFormCode, input.Keys);
|
await seedDataSynchronizer.RemoveRowsAsync(input.ListFormCode, input.Keys);
|
||||||
}
|
}
|
||||||
}
|
/// <summary>
|
||||||
|
/// Manuel bildirim gonderimi. Kayit olusur olusmaz gonderim yapilir: kayit gonderimin kendisi
|
||||||
|
/// degil gunlugudur. Gonderim yolu Bildirim Kurallari ekranindaki elle gonderimle aynidir
|
||||||
|
/// (<c>INotificationManager</c>); tek fark alici kumesinin kurallardan degil ekrandan gelmesi.
|
||||||
|
/// </summary>
|
||||||
|
[Authorize(PlatformConsts.AppCodes.ManualNotifications.Create)]
|
||||||
|
public async Task<Guid> PostNotificationManualInsertAsync(DynamicApiBaseInput<CreateNotificationManualInput> input)
|
||||||
|
{
|
||||||
|
var data = input.Data ?? throw new UserFriendlyException(L["App.Platform.Error"]);
|
||||||
|
|
||||||
|
if (data.Channels.IsNullOrWhiteSpace() || data.UserIds.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new UserFriendlyException(L["App.ManualNotification.RecipientAndChannelRequired"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var templateId = ParseGuid(data.NotificationTemplateId);
|
||||||
|
var subject = data.Subject;
|
||||||
|
var message = data.Message;
|
||||||
|
|
||||||
|
// Sablon secildiginde ekranda bos birakilan konu ve govde sablondan tamamlanir; ekranda
|
||||||
|
// yazilan metin sablonu ezer, cunku gonderen son sozu soyler.
|
||||||
|
if (templateId != Guid.Empty)
|
||||||
|
{
|
||||||
|
var template = await notificationTemplateRepository.GetAsync(templateId);
|
||||||
|
subject = subject.IsNullOrWhiteSpace() ? template.Subject : subject;
|
||||||
|
message = message.IsNullOrWhiteSpace() ? template.Body : message;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new UserFriendlyException(L["App.ManualNotification.MessageRequired"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var manualType = await notificationTypeRepository.FirstOrDefaultAsync(type => type.Name == NotificationConsts.ManualTypeName)
|
||||||
|
?? throw new UserFriendlyException(L["App.ManualNotification.TypeNotFound"]);
|
||||||
|
|
||||||
|
var record = await notificationManualRepository.InsertAsync(
|
||||||
|
new NotificationManual
|
||||||
|
{
|
||||||
|
TenantId = CurrentTenant.Id,
|
||||||
|
NotificationTemplateId = templateId == Guid.Empty ? null : templateId,
|
||||||
|
Channels = data.Channels,
|
||||||
|
UserIds = data.UserIds,
|
||||||
|
Subject = subject,
|
||||||
|
Message = message,
|
||||||
|
},
|
||||||
|
autoSave: true);
|
||||||
|
|
||||||
|
var result = await notificationManager.SendManualNotificationAsync(new ManualNotificationRequest
|
||||||
|
{
|
||||||
|
NotificationTypeId = manualType.Id,
|
||||||
|
Channels = SplitMultiValue(data.Channels),
|
||||||
|
UserIds = [.. SplitMultiValue(data.UserIds).Select(ParseGuid).Where(id => id != Guid.Empty)],
|
||||||
|
Message = message,
|
||||||
|
Subject = subject,
|
||||||
|
});
|
||||||
|
|
||||||
|
record.SentTime = Clock.Now;
|
||||||
|
record.SentCount = result.SentCount;
|
||||||
|
record.SkippedCount = result.SkippedCount;
|
||||||
|
record.ResultNote = BuildSkippedNote(result);
|
||||||
|
await notificationManualRepository.UpdateAsync(record, autoSave: true);
|
||||||
|
|
||||||
|
return record.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> SplitMultiValue(string value)
|
||||||
|
{
|
||||||
|
return [.. (value ?? string.Empty)
|
||||||
|
.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Atlananlarin kanal bazli gerekcesi. Adresi olmayan alici gonderimi durdurmaz; gonderen
|
||||||
|
/// kimin alamadigini kayitta gorur, cozum kullanici kaydindadir.
|
||||||
|
/// </summary>
|
||||||
|
private string BuildSkippedNote(ManualNotificationResult result)
|
||||||
|
{
|
||||||
|
return result.SkippedCount == 0
|
||||||
|
? null
|
||||||
|
: string.Join(" | ", result.SkippedByChannel
|
||||||
|
.Where(item => item.Value > 0)
|
||||||
|
.Select(item => L["App.ManualNotification.SkippedChannel", item.Key, item.Value].Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28769,6 +28769,132 @@
|
||||||
"key": "App.Mcp.Error.RegistrationLimitReached",
|
"key": "App.Mcp.Error.RegistrationLimitReached",
|
||||||
"en": "The limit of {0} dynamically registered MCP clients has been reached. Remove unused clients from the OpenIddict applications.",
|
"en": "The limit of {0} dynamically registered MCP clients has been reached. Remove unused clients from the OpenIddict applications.",
|
||||||
"tr": "Dinamik kayıtlı MCP istemcisi tavanına ({0}) ulaşıldı. Kullanılmayan istemcileri OpenIddict uygulamalarından silin."
|
"tr": "Dinamik kayıtlı MCP istemcisi tavanına ({0}) ulaşıldı. Kullanılmayan istemcileri OpenIddict uygulamalarından silin."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.ManualNotification.RecipientAndChannelRequired",
|
||||||
|
"en": "Select at least one recipient and one channel.",
|
||||||
|
"tr": "En az bir alıcı ve bir kanal seçin."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.ManualNotification.MessageRequired",
|
||||||
|
"en": "The message is empty: type a body or choose a template that has one.",
|
||||||
|
"tr": "Mesaj boş: bir gövde yazın ya da gövdesi olan bir şablon seçin."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.ManualNotification.TypeNotFound",
|
||||||
|
"en": "The \"Manuel\" notification type was not found; run the seed data.",
|
||||||
|
"tr": "\"Manuel\" bildirim tipi bulunamadı; seed verisini çalıştırın."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.ManualNotification.SkippedChannel",
|
||||||
|
"en": "{0}: {1} recipient(s) have no address",
|
||||||
|
"tr": "{0}: {1} alıcının adresi yok"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.ManualNotification",
|
||||||
|
"en": "Manual Notification",
|
||||||
|
"tr": "Manuel Bildirim"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.ManualNotification.Description",
|
||||||
|
"en": "Sends a notification to the selected users over the selected channels; every send is queued with the \"Manuel\" notification type.",
|
||||||
|
"tr": "Seçilen kullanıcılara seçilen kanallardan bildirim gönderir; her gönderim \"Manuel\" bildirim tipiyle kuyruğa yazılır."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Notifications.NotificationTemplates",
|
||||||
|
"en": "Notification Templates",
|
||||||
|
"tr": "Bildirim Şablonları"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Notifications.NotificationTemplates.Description",
|
||||||
|
"en": "Reusable message templates for manual notifications. Placeholders resolved per recipient: {AdSoyad}, {KullaniciAdi}, {Eposta}, {Tarih}, {Saat}, {Kiraci}.",
|
||||||
|
"tr": "Manuel bildirim gönderiminde kullanılan mesaj şablonları. Alıcı bazında çözülen yer tutucular: {AdSoyad}, {KullaniciAdi}, {Eposta}, {Tarih}, {Saat}, {Kiraci}."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.Body",
|
||||||
|
"en": "Body",
|
||||||
|
"tr": "Gövde"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.Channels",
|
||||||
|
"en": "Channels",
|
||||||
|
"tr": "Kanallar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.UserIds",
|
||||||
|
"en": "Recipients",
|
||||||
|
"tr": "Alıcılar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.NotificationTemplateId",
|
||||||
|
"en": "Template",
|
||||||
|
"tr": "Şablon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.SentTime",
|
||||||
|
"en": "Sent Time",
|
||||||
|
"tr": "Gönderim Zamanı"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.SentCount",
|
||||||
|
"en": "Sent",
|
||||||
|
"tr": "Gönderilen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.SkippedCount",
|
||||||
|
"en": "Skipped",
|
||||||
|
"tr": "Atlanan"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.ResultNote",
|
||||||
|
"en": "Result",
|
||||||
|
"tr": "Sonuç"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Administration.Notifications",
|
||||||
|
"en": "Notifications",
|
||||||
|
"tr": "Bildirimler"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.Event",
|
||||||
|
"en": "Event",
|
||||||
|
"tr": "Olay"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.QuestionId",
|
||||||
|
"en": "Question",
|
||||||
|
"tr": "Soru"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.ResponseId",
|
||||||
|
"en": "Response",
|
||||||
|
"tr": "Yanıt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Listform.ListformField.OrderId",
|
||||||
|
"en": "Order",
|
||||||
|
"tr": "Sipariş"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6874,6 +6874,487 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Notification Template
|
||||||
|
listFormName = AppCodes.Notifications.NotificationTemplates;
|
||||||
|
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))
|
||||||
|
{
|
||||||
|
var listForm = await _listFormRepository.InsertAsync(
|
||||||
|
new ListForm
|
||||||
|
{
|
||||||
|
ListFormType = ListFormTypeEnum.List,
|
||||||
|
PageSize = 10,
|
||||||
|
ExportJson = DefaultExportJson,
|
||||||
|
IsSubForm = false,
|
||||||
|
ShowNote = false,
|
||||||
|
LayoutJson = DefaultLayoutJson(),
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
ListFormCode = listFormName,
|
||||||
|
Name = listFormName,
|
||||||
|
Title = listFormName,
|
||||||
|
DataSourceCode = SeedConsts.DataSources.DefaultCode,
|
||||||
|
IsTenant = true,
|
||||||
|
IsBranch = false,
|
||||||
|
IsOrganizationUnit = false,
|
||||||
|
Description = $"{listFormName}.Description",
|
||||||
|
SelectCommandType = SelectCommandTypeEnum.Table,
|
||||||
|
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.NotificationTemplate)),
|
||||||
|
KeyFieldName = "Id",
|
||||||
|
KeyFieldDbSourceType = DbType.Guid,
|
||||||
|
SeedFilePath = SeedPathResolver.GetDataFilePath(listFormName),
|
||||||
|
SeedSyncInsert = true,
|
||||||
|
SeedSyncUpdate = true,
|
||||||
|
SeedSyncDelete = true,
|
||||||
|
DefaultFilter = DefaultFilterJson,
|
||||||
|
SortMode = GridOptions.SortModeSingle,
|
||||||
|
FilterRowJson = DefaultFilterRowJson(),
|
||||||
|
HeaderFilterJson = DefaultHeaderFilterJson(),
|
||||||
|
SearchPanelJson = DefaultSearchPanelJson(),
|
||||||
|
GroupPanelJson = DefaultGroupPanelJson(),
|
||||||
|
SelectionJson = DefaultSelectionSingleJson,
|
||||||
|
ColumnOptionJson = DefaultColumnOptionJson(),
|
||||||
|
PermissionJson = DefaultPermissionJson(listFormName),
|
||||||
|
DeleteCommand = DefaultDeleteCommand(nameof(TableNameEnum.NotificationTemplate)),
|
||||||
|
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
|
||||||
|
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
||||||
|
PagerOptionJson = DefaultPagerOptionJson,
|
||||||
|
EditingOptionJson = DefaultEditingOptionJson(listFormName, 700, 620, true, true, true, true, false),
|
||||||
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
||||||
|
{
|
||||||
|
new() { Order = 1, ColCount = 2, ColSpan = 2, ItemType = "group" },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
#region Notification Template Fields
|
||||||
|
await _listFormFieldRepository.InsertManyAsync([
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.Guid,
|
||||||
|
FieldName = "Id",
|
||||||
|
CaptionName = "App.Listform.ListformField.Id",
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 1,
|
||||||
|
Visible = false,
|
||||||
|
IsActive = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Code",
|
||||||
|
CaptionName = "App.Listform.ListformField.Code",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 1,
|
||||||
|
EditorType2 = EditorTypes.dxTextBox,
|
||||||
|
EditorOptions = EditorOptions.ShowClearButton().MaxLength(64),
|
||||||
|
ColSpan = 1,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 2,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Name",
|
||||||
|
CaptionName = "App.Listform.ListformField.Name",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 2,
|
||||||
|
EditorType2 = EditorTypes.dxTextBox,
|
||||||
|
EditorOptions = EditorOptions.ShowClearButton().MaxLength(128),
|
||||||
|
ColSpan = 1,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 3,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Channel",
|
||||||
|
CaptionName = "App.Listform.ListformField.Channel",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 3,
|
||||||
|
EditorType2 = EditorTypes.dxSelectBox,
|
||||||
|
EditorOptions = EditorOptions.ShowClearButton(),
|
||||||
|
ColSpan = 1,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 4,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
// Kanal bos birakilabilir: sablon o zaman butun kanallarda secilebilir.
|
||||||
|
LookupJson = NotificationChannelLookupJson(),
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.Boolean,
|
||||||
|
FieldName = "IsActive",
|
||||||
|
CaptionName = "App.Listform.ListformField.IsActive",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 4,
|
||||||
|
EditorType2 = EditorTypes.dxCheckBox,
|
||||||
|
ColSpan = 1,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 5,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Subject",
|
||||||
|
CaptionName = "App.Listform.ListformField.Subject",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 5,
|
||||||
|
EditorType2 = EditorTypes.dxTextBox,
|
||||||
|
EditorOptions = EditorOptions.ShowClearButton().MaxLength(256),
|
||||||
|
ColSpan = 2,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 6,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Body",
|
||||||
|
CaptionName = "App.Listform.ListformField.Body",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 6,
|
||||||
|
EditorType2 = EditorTypes.dxTextArea,
|
||||||
|
EditorOptions = EditorOptions.Multiline(220).MaxLength(2048),
|
||||||
|
ColSpan = 2,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 7,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Manual Notification
|
||||||
|
listFormName = AppCodes.ManualNotification;
|
||||||
|
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))
|
||||||
|
{
|
||||||
|
var listForm = await _listFormRepository.InsertAsync(
|
||||||
|
new ListForm
|
||||||
|
{
|
||||||
|
ListFormType = ListFormTypeEnum.List,
|
||||||
|
PageSize = 10,
|
||||||
|
ExportJson = DefaultExportJson,
|
||||||
|
IsSubForm = false,
|
||||||
|
ShowNote = false,
|
||||||
|
LayoutJson = DefaultLayoutJson(),
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
ListFormCode = listFormName,
|
||||||
|
Name = listFormName,
|
||||||
|
Title = listFormName,
|
||||||
|
DataSourceCode = SeedConsts.DataSources.DefaultCode,
|
||||||
|
IsTenant = true,
|
||||||
|
IsBranch = false,
|
||||||
|
IsOrganizationUnit = false,
|
||||||
|
Description = $"{listFormName}.Description",
|
||||||
|
SelectCommandType = SelectCommandTypeEnum.Table,
|
||||||
|
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.NotificationManual)),
|
||||||
|
KeyFieldName = "Id",
|
||||||
|
KeyFieldDbSourceType = DbType.Guid,
|
||||||
|
DefaultFilter = DefaultFilterJson,
|
||||||
|
SortMode = GridOptions.SortModeSingle,
|
||||||
|
FilterRowJson = DefaultFilterRowJson(),
|
||||||
|
HeaderFilterJson = DefaultHeaderFilterJson(),
|
||||||
|
SearchPanelJson = DefaultSearchPanelJson(),
|
||||||
|
GroupPanelJson = DefaultGroupPanelJson(),
|
||||||
|
SelectionJson = DefaultSelectionSingleJson,
|
||||||
|
ColumnOptionJson = DefaultColumnOptionJson(),
|
||||||
|
PermissionJson = DefaultPermissionJson(listFormName),
|
||||||
|
DeleteCommand = DefaultDeleteCommand(nameof(TableNameEnum.NotificationManual)),
|
||||||
|
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
|
||||||
|
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
||||||
|
// Kayit olusur olusmaz gonderim yapilmasi gerektigi icin yazma isi tipli uca
|
||||||
|
// devredilir: uc hem kaydi yazar hem NotificationManager ile bildirimleri
|
||||||
|
// uretir. Guncelleme kapali, cunku kayit gonderimin gunlugudur.
|
||||||
|
InsertServiceAddress = "list-form-dynamic-api/notification-manual-insert",
|
||||||
|
PagerOptionJson = DefaultPagerOptionJson,
|
||||||
|
EditingOptionJson = DefaultEditingOptionJson(listFormName, 760, 680, true, true, false, true, false),
|
||||||
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
||||||
|
{
|
||||||
|
new() { Order = 1, ColCount = 2, ColSpan = 2, ItemType = "group" },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
#region Manual Notification Fields
|
||||||
|
await _listFormFieldRepository.InsertManyAsync([
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.Guid,
|
||||||
|
FieldName = "Id",
|
||||||
|
CaptionName = "App.Listform.ListformField.Id",
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 1,
|
||||||
|
Visible = false,
|
||||||
|
IsActive = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.DateTime,
|
||||||
|
FieldName = "CreationTime",
|
||||||
|
CaptionName = "App.Listform.ListformField.CreationTime",
|
||||||
|
EditorType2 = EditorTypes.dxDateBox,
|
||||||
|
EditorOptions = EditorOptions.DateTime(),
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 2,
|
||||||
|
SortIndex = 0,
|
||||||
|
SortDirection = GridColumnOptions.SortOrderDesc,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.Guid,
|
||||||
|
FieldName = "NotificationTemplateId",
|
||||||
|
CaptionName = "App.Listform.ListformField.NotificationTemplateId",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 1,
|
||||||
|
EditorType2 = EditorTypes.dxSelectBox,
|
||||||
|
EditorOptions = EditorOptions.ShowClearButton().Flag("searchEnabled", true),
|
||||||
|
ColSpan = 2,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 3,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
// Sablon zorunlu degil: konu ve govde elle de yazilabilir. Sablon
|
||||||
|
// secildiginde konu ve govde secili lookup kaydindan forma tasinir; script
|
||||||
|
// sablon alanina baglidir, cunku bir alanin scripti yalnizca o alan
|
||||||
|
// degistiginde calisir.
|
||||||
|
EditorScript = EditorScript.Build(
|
||||||
|
EditorScript.Copy("Subject", "Subject").OnChange(),
|
||||||
|
EditorScript.Copy("Body", "Message").OnChange()),
|
||||||
|
LookupJson = JsonSerializer.Serialize(new LookupDto {
|
||||||
|
DataSourceType = UiLookupDataSourceTypeEnum.Query,
|
||||||
|
DisplayExpr = "Name",
|
||||||
|
ValueExpr = "Key",
|
||||||
|
LookupQuery = LookupQueryValues.NotificationTemplateValues,
|
||||||
|
}),
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Channels",
|
||||||
|
CaptionName = "App.Listform.ListformField.Channels",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 2,
|
||||||
|
EditorType2 = EditorTypes.dxTagBox,
|
||||||
|
EditorOptions = EditorOptions.New()
|
||||||
|
.Flag("showSelectionControls", true)
|
||||||
|
.Flag("searchEnabled", true)
|
||||||
|
.Flag("multiline", true)
|
||||||
|
.Text("applyValueMode", "useButtons"),
|
||||||
|
ColSpan = 2,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 4,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
LookupJson = NotificationChannelLookupJson(),
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "UserIds",
|
||||||
|
CaptionName = "App.Listform.ListformField.UserIds",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 3,
|
||||||
|
EditorType2 = EditorTypes.dxTagBox,
|
||||||
|
EditorOptions = EditorOptions.New()
|
||||||
|
.Flag("showSelectionControls", true)
|
||||||
|
.Flag("searchEnabled", true)
|
||||||
|
.Flag("multiline", true)
|
||||||
|
.Text("applyValueMode", "useButtons")
|
||||||
|
.Number("maxDisplayedTags", 6),
|
||||||
|
ColSpan = 2,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 5,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
LookupJson = JsonSerializer.Serialize(new LookupDto {
|
||||||
|
DataSourceType = UiLookupDataSourceTypeEnum.Query,
|
||||||
|
DisplayExpr = "Name",
|
||||||
|
ValueExpr = "Key",
|
||||||
|
LookupQuery = LookupQueryValues.TenantUserValues,
|
||||||
|
}),
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Subject",
|
||||||
|
CaptionName = "App.Listform.ListformField.Subject",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 4,
|
||||||
|
EditorType2 = EditorTypes.dxTextBox,
|
||||||
|
EditorOptions = EditorOptions.ShowClearButton().MaxLength(256),
|
||||||
|
ColSpan = 2,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 6,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Message",
|
||||||
|
CaptionName = "App.Listform.ListformField.Message",
|
||||||
|
EditGroupOrderNo = 1,
|
||||||
|
EditOrderNo = 5,
|
||||||
|
EditorType2 = EditorTypes.dxTextArea,
|
||||||
|
EditorOptions = EditorOptions.Multiline(220).MaxLength(2048),
|
||||||
|
ColSpan = 2,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 7,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.DateTime,
|
||||||
|
FieldName = "SentTime",
|
||||||
|
CaptionName = "App.Listform.ListformField.SentTime",
|
||||||
|
EditorType2 = EditorTypes.dxDateBox,
|
||||||
|
EditorOptions = EditorOptions.DateTime(),
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 8,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.Int32,
|
||||||
|
FieldName = "SentCount",
|
||||||
|
CaptionName = "App.Listform.ListformField.SentCount",
|
||||||
|
EditorType2 = EditorTypes.dxNumberBox,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 9,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.Int32,
|
||||||
|
FieldName = "SkippedCount",
|
||||||
|
CaptionName = "App.Listform.ListformField.SkippedCount",
|
||||||
|
EditorType2 = EditorTypes.dxNumberBox,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 10,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "ResultNote",
|
||||||
|
CaptionName = "App.Listform.ListformField.ResultNote",
|
||||||
|
EditorType2 = EditorTypes.dxTextBox,
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 11,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Agenda
|
#region Agenda
|
||||||
listFormName = AppCodes.Agenda;
|
listFormName = AppCodes.Agenda;
|
||||||
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))
|
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,29 @@ public static class ListFormSeeder_DefaultJsons
|
||||||
});
|
});
|
||||||
|
|
||||||
public static readonly string DefaultFilterJson = "\"IsDeleted\" = 'false'";
|
public static readonly string DefaultFilterJson = "\"IsDeleted\" = 'false'";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bildirim kanallarinin sabit listesi. Bildirim ekranlarinin hepsi ayni kumeyi gosterir;
|
||||||
|
/// kanal eklendiginde tek yerde eklenir (<c>NotificationChannels</c> ile ayni sira).
|
||||||
|
/// </summary>
|
||||||
|
public static string NotificationChannelLookupJson() => JsonSerializer.Serialize(new LookupDto
|
||||||
|
{
|
||||||
|
DataSourceType = UiLookupDataSourceTypeEnum.StaticData,
|
||||||
|
DisplayExpr = "name",
|
||||||
|
ValueExpr = "key",
|
||||||
|
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[]
|
||||||
|
{
|
||||||
|
new() { Key = "Sms", Name = "App.Sender.Sms" },
|
||||||
|
new() { Key = "Mail", Name = "App.StaticLookup.Mail" },
|
||||||
|
new() { Key = "Rocket", Name = "App.StaticLookup.Rocket" },
|
||||||
|
new() { Key = "Desktop", Name = "App.StaticLookup.Desktop" },
|
||||||
|
new() { Key = "UiActivity", Name = "App.StaticLookup.UiActivity" },
|
||||||
|
new() { Key = "UiToast", Name = "App.StaticLookup.UiToast" },
|
||||||
|
new() { Key = "WhatsApp", Name = "App.Sender.WhatsApp" },
|
||||||
|
new() { Key = "Telegram", Name = "App.Sender.Telegram" },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
public static string EncodeHtmlJson(bool value) => JsonSerializer.Serialize(new { encodeHtml = value });
|
public static string EncodeHtmlJson(bool value) => JsonSerializer.Serialize(new { encodeHtml = value });
|
||||||
public static string DefaultFilterRowJson(bool visible = true) => JsonSerializer.Serialize(new GridFilterRowDto { Visible = visible });
|
public static string DefaultFilterRowJson(bool visible = true) => JsonSerializer.Serialize(new GridFilterRowDto { Visible = visible });
|
||||||
public static string DefaultHeaderFilterJson(bool visible = true) => JsonSerializer.Serialize(new { Visible = visible });
|
public static string DefaultHeaderFilterJson(bool visible = true) => JsonSerializer.Serialize(new { Visible = visible });
|
||||||
|
|
|
||||||
|
|
@ -5469,22 +5469,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
||||||
|
|
||||||
AllowSearch = true,
|
AllowSearch = true,
|
||||||
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
LookupJson = JsonSerializer.Serialize(new LookupDto
|
LookupJson = NotificationChannelLookupJson(),
|
||||||
{
|
|
||||||
DataSourceType = UiLookupDataSourceTypeEnum.StaticData,
|
|
||||||
DisplayExpr = "name",
|
|
||||||
ValueExpr = "key",
|
|
||||||
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
|
|
||||||
new () { Key="Sms", Name="App.Sender.Sms" },
|
|
||||||
new () { Key="Mail", Name="App.StaticLookup.Mail" },
|
|
||||||
new () { Key="WhatsApp", Name="App.Sender.WhatsApp" },
|
|
||||||
new () { Key="Telegram", Name="App.Sender.Telegram" },
|
|
||||||
new () { Key="Rocket", Name="App.StaticLookup.Rocket" },
|
|
||||||
new () { Key="UiActivity", Name="App.StaticLookup.UiActivity" },
|
|
||||||
new () { Key="UiToast", Name="App.StaticLookup.UiToast" },
|
|
||||||
new () { Key="Desktop", Name="App.StaticLookup.Desktop" },
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
PivotSettingsJson = DefaultPivotSettingsJson
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
|
@ -5687,22 +5672,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
|
|
||||||
AllowSearch = true,
|
AllowSearch = true,
|
||||||
LookupJson = JsonSerializer.Serialize(new LookupDto
|
LookupJson = NotificationChannelLookupJson(),
|
||||||
{
|
|
||||||
DataSourceType = UiLookupDataSourceTypeEnum.StaticData,
|
|
||||||
DisplayExpr = "name",
|
|
||||||
ValueExpr = "key",
|
|
||||||
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
|
|
||||||
new () { Key="Sms", Name="App.Sender.Sms" },
|
|
||||||
new () { Key="Mail", Name="App.StaticLookup.Mail" },
|
|
||||||
new () { Key="Rocket", Name="App.StaticLookup.Rocket" },
|
|
||||||
new () { Key="Desktop", Name="App.StaticLookup.Desktop" },
|
|
||||||
new () { Key="UiActivity", Name="App.StaticLookup.UiActivity" },
|
|
||||||
new () { Key="UiToast", Name="App.StaticLookup.UiToast" },
|
|
||||||
new () { Key="WhatsApp", Name="App.Sender.WhatsApp" },
|
|
||||||
new () { Key="Telegram", Name="App.Sender.Telegram" },
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
PivotSettingsJson = DefaultPivotSettingsJson
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
|
@ -5757,6 +5727,23 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
||||||
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
PivotSettingsJson = DefaultPivotSettingsJson
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
},
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Subject",
|
||||||
|
CaptionName = "App.Listform.ListformField.Subject",
|
||||||
|
Width = 0,
|
||||||
|
ListOrderNo = 2,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
|
||||||
|
AllowSearch = true,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
new() {
|
new() {
|
||||||
ListFormCode = listForm.ListFormCode,
|
ListFormCode = listForm.ListFormCode,
|
||||||
CultureName = LanguageCodes.En,
|
CultureName = LanguageCodes.En,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ public enum TableNameEnum
|
||||||
Notification,
|
Notification,
|
||||||
NotificationRule,
|
NotificationRule,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
|
NotificationTemplate,
|
||||||
|
NotificationManual,
|
||||||
BackgroundWorker,
|
BackgroundWorker,
|
||||||
BackgroundWorker_MailQueue,
|
BackgroundWorker_MailQueue,
|
||||||
BackgroundWorker_MailQueueEvents,
|
BackgroundWorker_MailQueueEvents,
|
||||||
|
|
|
||||||
|
|
@ -456,6 +456,19 @@ public static class PlatformConsts
|
||||||
public const string NotificationTypes = Default + ".NotificationTypes";
|
public const string NotificationTypes = Default + ".NotificationTypes";
|
||||||
public const string NotificationRules = Default + ".NotificationRules";
|
public const string NotificationRules = Default + ".NotificationRules";
|
||||||
public const string Notification = Default + ".Notification";
|
public const string Notification = Default + ".Notification";
|
||||||
|
public const string NotificationTemplates = Default + ".NotificationTemplates";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Elle bildirim gonderim ekrani (Administration menusu). <see cref="ManualNotification"/>
|
||||||
|
/// ekrani gorme yetkisidir; gonderimin kendisi <see cref="ManualNotifications.Create"/>
|
||||||
|
/// ister, cunku kayit olusturmak gonderim demektir.
|
||||||
|
/// </summary>
|
||||||
|
public const string ManualNotification = Prefix.App + ".ManualNotification";
|
||||||
|
|
||||||
|
public static class ManualNotifications
|
||||||
|
{
|
||||||
|
public const string Create = ManualNotification + ".Create";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BackgroundWorkers
|
public static class BackgroundWorkers
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,8 @@ public static class TableNameResolver
|
||||||
{ nameof(TableNameEnum.VideoroomChat), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
{ nameof(TableNameEnum.VideoroomChat), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
||||||
{ nameof(TableNameEnum.Sequence), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
{ nameof(TableNameEnum.Sequence), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
||||||
{ nameof(TableNameEnum.Agenda), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
{ nameof(TableNameEnum.Agenda), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
||||||
|
{ nameof(TableNameEnum.NotificationTemplate), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
||||||
|
{ nameof(TableNameEnum.NotificationManual), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
||||||
|
|
||||||
// 🔹 INTRANET TABLOLARI
|
// 🔹 INTRANET TABLOLARI
|
||||||
{ nameof(TableNameEnum.IntranetWidget), (TablePrefix.TenantByName, MenuPrefix.Sas) },
|
{ nameof(TableNameEnum.IntranetWidget), (TablePrefix.TenantByName, MenuPrefix.Sas) },
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,8 @@ public class NotificationWorker : BackgroundWorkerBase
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Konu satirinda bildirim tipinin adi gecer; navigasyon yuklenmezse konu bos kalirdi.
|
// Konu kaydin kendisinden gelir; yoksa bildirim tipinin adina duselir, bu yuzden
|
||||||
|
// navigasyon yuklenir (includeDetails) - yuklenmezse konu bos kalirdi.
|
||||||
await SendChannelAsync(
|
await SendChannelAsync(
|
||||||
NotificationChannels.Mail,
|
NotificationChannels.Mail,
|
||||||
async notification => (await ErpEmailSender.SendEmailAsync(
|
async notification => (await ErpEmailSender.SendEmailAsync(
|
||||||
|
|
@ -124,7 +125,9 @@ public class NotificationWorker : BackgroundWorkerBase
|
||||||
new KeyValuePair<string, string>(senderName ?? senderEmail!, senderEmail!),
|
new KeyValuePair<string, string>(senderName ?? senderEmail!, senderEmail!),
|
||||||
new { },
|
new { },
|
||||||
notification.Message,
|
notification.Message,
|
||||||
$"Platform Bildirim: {notification.NotificationType?.Name}")).Success,
|
notification.Subject.IsNullOrWhiteSpace()
|
||||||
|
? $"Platform Bildirim: {notification.NotificationType?.Name}"
|
||||||
|
: notification.Subject)).Success,
|
||||||
cancellationToken,
|
cancellationToken,
|
||||||
includeDetails: true);
|
includeDetails: true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,7 @@ public static class SeedConsts
|
||||||
public const string NotificationTypes = Default + ".NotificationTypes";
|
public const string NotificationTypes = Default + ".NotificationTypes";
|
||||||
public const string NotificationRules = Default + ".NotificationRules";
|
public const string NotificationRules = Default + ".NotificationRules";
|
||||||
public const string Notification = Default + ".Notification";
|
public const string Notification = Default + ".Notification";
|
||||||
|
public const string NotificationTemplates = Default + ".NotificationTemplates";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BackgroundWorkers
|
public static class BackgroundWorkers
|
||||||
|
|
@ -498,6 +499,7 @@ public static class SeedConsts
|
||||||
public const string DevRequest = Prefix.App + ".DevRequest";
|
public const string DevRequest = Prefix.App + ".DevRequest";
|
||||||
public const string DevRequests = Prefix.App + ".DevRequests";
|
public const string DevRequests = Prefix.App + ".DevRequests";
|
||||||
public const string Agenda = Prefix.App + ".Agenda";
|
public const string Agenda = Prefix.App + ".Agenda";
|
||||||
|
public const string ManualNotification = Prefix.App + ".ManualNotification";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DataSources
|
public static class DataSources
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
|
|
||||||
|
namespace Sozsoft.Platform.Entities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Elle yapilan bildirim gonderiminin kaydi. Kayit olusur olusmaz ekranin
|
||||||
|
/// <c>InsertAfterCommand</c> kancasi <c>Adm_T_NotificationManual_Dispatch</c> prosedurunu cagirir;
|
||||||
|
/// prosedur alici x kanal acilimini <c>Sas_H_Notification</c> kuyruguna "Manuel" bildirim tipiyle
|
||||||
|
/// yazar ve sonuc sayaclarini bu kayda geri isler. Kayit gonderimin kendisi degil, gunlugudur.
|
||||||
|
/// </summary>
|
||||||
|
public class NotificationManual : FullAuditedEntity<Guid>, IMultiTenant
|
||||||
|
{
|
||||||
|
public Guid? TenantId { get; set; }
|
||||||
|
|
||||||
|
public Guid? NotificationTemplateId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Secilen kanallar; cok degerli alan sozlesmesine gore <c>|</c> ile saklanir.</summary>
|
||||||
|
public string Channels { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Secilen kullanici kimlikleri; <c>|</c> ile saklanir.</summary>
|
||||||
|
public string UserIds { get; set; }
|
||||||
|
|
||||||
|
public string Subject { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
public DateTime? SentTime { get; set; }
|
||||||
|
public int SentCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Ilgili kanalda adresi (e-posta, telefon, chat id) olmadigi icin atlanan alici sayisi.</summary>
|
||||||
|
public int SkippedCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Atlananlarin kanal bazli gerekcesi; bos ise herkese gonderildi.</summary>
|
||||||
|
public string ResultNote { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
|
|
||||||
|
namespace Sozsoft.Platform.Entities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Manuel bildirim gonderiminde secilebilen mesaj sablonu. Govde, gonderim aninda alici bazli
|
||||||
|
/// yer tutucularla (<c>{AdSoyad}</c>, <c>{KullaniciAdi}</c>, <c>{Eposta}</c>, <c>{Tarih}</c>,
|
||||||
|
/// <c>{Saat}</c>, <c>{Kiraci}</c>) cozulur.
|
||||||
|
/// </summary>
|
||||||
|
public class NotificationTemplate : FullAuditedEntity<Guid>, IMultiTenant
|
||||||
|
{
|
||||||
|
public Guid? TenantId { get; set; }
|
||||||
|
|
||||||
|
public string Code { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Sablonun hangi kanal icin oldugu; bos ise tum kanallarda kullanilabilir.</summary>
|
||||||
|
public string Channel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mail konusu. Gonderimde bildirim kaydinin <c>Subject</c> kolonuna yazilir; bos ise
|
||||||
|
/// <c>NotificationWorker</c> konuyu bildirim tipinin adindan uretir.
|
||||||
|
/// </summary>
|
||||||
|
public string Subject { get; set; }
|
||||||
|
|
||||||
|
public string Body { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -102,6 +102,8 @@ public class PlatformDbContext :
|
||||||
public DbSet<SkillType> SkillTypes { get; set; }
|
public DbSet<SkillType> SkillTypes { get; set; }
|
||||||
public DbSet<DevRequest> DevRequests { get; set; }
|
public DbSet<DevRequest> DevRequests { get; set; }
|
||||||
public DbSet<Agenda> Agendas { get; set; }
|
public DbSet<Agenda> Agendas { get; set; }
|
||||||
|
public DbSet<NotificationManual> NotificationManuals { get; set; }
|
||||||
|
public DbSet<NotificationTemplate> NotificationTemplates { get; set; }
|
||||||
|
|
||||||
// Dynamic Services
|
// Dynamic Services
|
||||||
public DbSet<Skill> Skills { get; set; }
|
public DbSet<Skill> Skills { get; set; }
|
||||||
|
|
@ -1593,6 +1595,42 @@ public class PlatformDbContext :
|
||||||
b.Property(e => e.RecurrenceException).HasColumnType("nvarchar(max)");
|
b.Property(e => e.RecurrenceException).HasColumnType("nvarchar(max)");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Entity<NotificationTemplate>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.NotificationTemplate)), Prefix.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.Property(e => e.Code).HasMaxLength(64).IsRequired();
|
||||||
|
b.Property(e => e.Name).HasMaxLength(128).IsRequired();
|
||||||
|
b.Property(e => e.Channel).HasMaxLength(64);
|
||||||
|
b.Property(e => e.Subject).HasMaxLength(256);
|
||||||
|
|
||||||
|
// Govde, bildirim kaydinin Message kolonuyla ayni sinirdadir; daha uzun bir sablon
|
||||||
|
// gonderimde kirpilirdi.
|
||||||
|
b.Property(e => e.Body).HasMaxLength(2048).IsRequired();
|
||||||
|
b.Property(e => e.IsActive).HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.HasIndex(e => new { e.TenantId, e.Code })
|
||||||
|
.IsUnique()
|
||||||
|
.HasFilter("[IsDeleted] = 0");
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Entity<NotificationManual>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.NotificationManual)), Prefix.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.Property(e => e.Channels).HasMaxLength(256).IsRequired();
|
||||||
|
b.Property(e => e.UserIds).HasColumnType("nvarchar(max)").IsRequired();
|
||||||
|
b.Property(e => e.Subject).HasMaxLength(256);
|
||||||
|
b.Property(e => e.Message).HasMaxLength(2048);
|
||||||
|
b.Property(e => e.SentCount).HasDefaultValue(0);
|
||||||
|
b.Property(e => e.SkippedCount).HasDefaultValue(0);
|
||||||
|
b.Property(e => e.ResultNote).HasMaxLength(1024);
|
||||||
|
|
||||||
|
b.HasIndex(e => new { e.TenantId, e.CreationTime });
|
||||||
|
});
|
||||||
|
|
||||||
ConfigureProviderSpecificModel(builder);
|
ConfigureProviderSpecificModel(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
||||||
namespace Sozsoft.Platform.Migrations
|
namespace Sozsoft.Platform.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PlatformDbContext))]
|
[DbContext(typeof(PlatformDbContext))]
|
||||||
[Migration("20260920201729_Initial")]
|
[Migration("20260921060400_Initial")]
|
||||||
partial class Initial
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -577,6 +577,10 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.Property<DateTime?>("ReadTime")
|
b.Property<DateTime?>("ReadTime")
|
||||||
.HasColumnType("datetime2");
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
b.Property<Guid?>("UserId")
|
b.Property<Guid?>("UserId")
|
||||||
.HasColumnType("uniqueidentifier");
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
|
@ -4303,6 +4307,165 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.ToTable("Adm_T_Note", (string)null);
|
b.ToTable("Adm_T_Note", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sozsoft.Platform.Entities.NotificationManual", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("Channels")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("nvarchar(2048)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("NotificationTemplateId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("ResultNote")
|
||||||
|
.HasMaxLength(1024)
|
||||||
|
.HasColumnType("nvarchar(1024)");
|
||||||
|
|
||||||
|
b.Property<int>("SentCount")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<DateTime?>("SentTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("SkippedCount")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.Property<string>("UserIds")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("TenantId", "CreationTime");
|
||||||
|
|
||||||
|
b.ToTable("Adm_T_NotificationManual", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sozsoft.Platform.Entities.NotificationTemplate", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("nvarchar(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("Channel")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
|
b.Property<string>("Code")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("TenantId", "Code")
|
||||||
|
.IsUnique()
|
||||||
|
.HasFilter("[IsDeleted] = 0");
|
||||||
|
|
||||||
|
b.ToTable("Adm_T_NotificationTemplate", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.Platform.Entities.Order", b =>
|
modelBuilder.Entity("Sozsoft.Platform.Entities.Order", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -677,6 +677,59 @@ namespace Sozsoft.Platform.Migrations
|
||||||
table.PrimaryKey("PK_Adm_T_Note", x => x.Id);
|
table.PrimaryKey("PK_Adm_T_Note", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Adm_T_NotificationManual",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
NotificationTemplateId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
Channels = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
||||||
|
UserIds = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
Subject = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||||
|
Message = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: true),
|
||||||
|
SentTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
SentCount = table.Column<int>(type: "int", nullable: false, defaultValue: 0),
|
||||||
|
SkippedCount = table.Column<int>(type: "int", nullable: false, defaultValue: 0),
|
||||||
|
ResultNote = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Adm_T_NotificationManual", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Adm_T_NotificationTemplate",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
Code = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
|
||||||
|
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
||||||
|
Channel = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||||
|
Subject = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||||
|
Body = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: false),
|
||||||
|
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Adm_T_NotificationTemplate", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Adm_T_ReportCategory",
|
name: "Adm_T_ReportCategory",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -3412,6 +3465,7 @@ namespace Sozsoft.Platform.Migrations
|
||||||
Identifier = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
Identifier = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
||||||
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
Message = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: false),
|
Message = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: false),
|
||||||
|
Subject = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||||
IsSent = table.Column<bool>(type: "bit", nullable: false),
|
IsSent = table.Column<bool>(type: "bit", nullable: false),
|
||||||
IsRead = table.Column<bool>(type: "bit", nullable: false),
|
IsRead = table.Column<bool>(type: "bit", nullable: false),
|
||||||
ReadTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
ReadTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
|
@ -3827,6 +3881,18 @@ namespace Sozsoft.Platform.Migrations
|
||||||
table: "Adm_T_MessengerConversationMessage",
|
table: "Adm_T_MessengerConversationMessage",
|
||||||
columns: new[] { "TenantId", "ConversationId", "SentAt" });
|
columns: new[] { "TenantId", "ConversationId", "SentAt" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Adm_T_NotificationManual_TenantId_CreationTime",
|
||||||
|
table: "Adm_T_NotificationManual",
|
||||||
|
columns: new[] { "TenantId", "CreationTime" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Adm_T_NotificationTemplate_TenantId_Code",
|
||||||
|
table: "Adm_T_NotificationTemplate",
|
||||||
|
columns: new[] { "TenantId", "Code" },
|
||||||
|
unique: true,
|
||||||
|
filter: "[IsDeleted] = 0");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Adm_T_ReportCategory_TenantId_Name",
|
name: "IX_Adm_T_ReportCategory_TenantId_Name",
|
||||||
table: "Adm_T_ReportCategory",
|
table: "Adm_T_ReportCategory",
|
||||||
|
|
@ -4444,6 +4510,12 @@ namespace Sozsoft.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Adm_T_Note");
|
name: "Adm_T_Note");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Adm_T_NotificationManual");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Adm_T_NotificationTemplate");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Adm_T_ReportTemplate");
|
name: "Adm_T_ReportTemplate");
|
||||||
|
|
||||||
|
|
@ -574,6 +574,10 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.Property<DateTime?>("ReadTime")
|
b.Property<DateTime?>("ReadTime")
|
||||||
.HasColumnType("datetime2");
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
b.Property<Guid?>("UserId")
|
b.Property<Guid?>("UserId")
|
||||||
.HasColumnType("uniqueidentifier");
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
|
@ -4300,6 +4304,165 @@ namespace Sozsoft.Platform.Migrations
|
||||||
b.ToTable("Adm_T_Note", (string)null);
|
b.ToTable("Adm_T_Note", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sozsoft.Platform.Entities.NotificationManual", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("Channels")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("nvarchar(2048)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("NotificationTemplateId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("ResultNote")
|
||||||
|
.HasMaxLength(1024)
|
||||||
|
.HasColumnType("nvarchar(1024)");
|
||||||
|
|
||||||
|
b.Property<int>("SentCount")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<DateTime?>("SentTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("SkippedCount")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.Property<string>("UserIds")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("TenantId", "CreationTime");
|
||||||
|
|
||||||
|
b.ToTable("Adm_T_NotificationManual", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sozsoft.Platform.Entities.NotificationTemplate", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("nvarchar(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("Channel")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
|
b.Property<string>("Code")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("TenantId", "Code")
|
||||||
|
.IsUnique()
|
||||||
|
.HasFilter("[IsDeleted] = 0");
|
||||||
|
|
||||||
|
b.ToTable("Adm_T_NotificationTemplate", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Sozsoft.Platform.Entities.Order", b =>
|
modelBuilder.Entity("Sozsoft.Platform.Entities.Order", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
|
||||||
|
|
@ -3604,12 +3604,132 @@
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"Modules": "Sas|Adm"
|
"Modules": "Sas|Adm"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.Administration.Notifications",
|
||||||
|
"ParentName": null,
|
||||||
|
"DisplayName": "App.Administration.Notifications",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.ManualNotification",
|
||||||
|
"ParentName": "App.Administration.Notifications",
|
||||||
|
"DisplayName": "App.ManualNotification",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.ManualNotification.Create",
|
||||||
|
"ParentName": "App.ManualNotification",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.ManualNotification.Update",
|
||||||
|
"ParentName": "App.ManualNotification",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.ManualNotification.Delete",
|
||||||
|
"ParentName": "App.ManualNotification",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.ManualNotification.Export",
|
||||||
|
"ParentName": "App.ManualNotification",
|
||||||
|
"DisplayName": "Export",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.Notifications.NotificationTemplates",
|
||||||
|
"ParentName": "App.Administration.Notifications",
|
||||||
|
"DisplayName": "App.Notifications.NotificationTemplates",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.Notifications.NotificationTemplates.Create",
|
||||||
|
"ParentName": "App.Notifications.NotificationTemplates",
|
||||||
|
"DisplayName": "App.Platform.Create",
|
||||||
|
"Order": 1,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.Notifications.NotificationTemplates.Delete",
|
||||||
|
"ParentName": "App.Notifications.NotificationTemplates",
|
||||||
|
"DisplayName": "App.Platform.Delete",
|
||||||
|
"Order": 2,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.Notifications.NotificationTemplates.Export",
|
||||||
|
"ParentName": "App.Notifications.NotificationTemplates",
|
||||||
|
"DisplayName": "Export",
|
||||||
|
"Order": 3,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.Notifications.NotificationTemplates.Import",
|
||||||
|
"ParentName": "App.Notifications.NotificationTemplates",
|
||||||
|
"DisplayName": "Import",
|
||||||
|
"Order": 4,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Administration",
|
||||||
|
"Name": "App.Notifications.NotificationTemplates.Update",
|
||||||
|
"ParentName": "App.Notifications.NotificationTemplates",
|
||||||
|
"DisplayName": "App.Platform.Update",
|
||||||
|
"Order": 5,
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"Modules": "Sas|Adm"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Administration",
|
"GroupName": "App.Administration",
|
||||||
"Name": "App.Agenda",
|
"Name": "App.Agenda",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "App.Agenda",
|
"DisplayName": "App.Agenda",
|
||||||
"Order": 5,
|
"Order": 6,
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"Modules": "Sas|Adm"
|
"Modules": "Sas|Adm"
|
||||||
|
|
@ -3669,7 +3789,7 @@
|
||||||
"Name": "App.Setting",
|
"Name": "App.Setting",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "App.Setting",
|
"DisplayName": "App.Setting",
|
||||||
"Order": 6,
|
"Order": 7,
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"Modules": "Sas|Adm"
|
"Modules": "Sas|Adm"
|
||||||
|
|
@ -3919,7 +4039,7 @@
|
||||||
"Name": "App.Intranet",
|
"Name": "App.Intranet",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "App.Intranet",
|
"DisplayName": "App.Intranet",
|
||||||
"Order": 7,
|
"Order": 8,
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"Modules": "Sas|Adm"
|
"Modules": "Sas|Adm"
|
||||||
|
|
@ -5149,7 +5269,7 @@
|
||||||
"Name": "App.Platform.Restrictions",
|
"Name": "App.Platform.Restrictions",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "App.Platform.Restrictions",
|
"DisplayName": "App.Platform.Restrictions",
|
||||||
"Order": 8,
|
"Order": 9,
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"Modules": "Sas|Adm"
|
"Modules": "Sas|Adm"
|
||||||
|
|
@ -5279,7 +5399,7 @@
|
||||||
"Name": "Abp.Identity",
|
"Name": "Abp.Identity",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "Abp.Identity",
|
"DisplayName": "Abp.Identity",
|
||||||
"Order": 9,
|
"Order": 10,
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 2,
|
"MultiTenancySide": 2,
|
||||||
"Modules": "Sas|Adm"
|
"Modules": "Sas|Adm"
|
||||||
|
|
@ -5879,7 +5999,7 @@
|
||||||
"Name": "App.Videoroom",
|
"Name": "App.Videoroom",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "App.Videoroom",
|
"DisplayName": "App.Videoroom",
|
||||||
"Order": 10,
|
"Order": 11,
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"Modules": "Sas|Adm"
|
"Modules": "Sas|Adm"
|
||||||
|
|
@ -5909,7 +6029,7 @@
|
||||||
"Name": "App.ForumManagement.Publish",
|
"Name": "App.ForumManagement.Publish",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "App.ForumManagement.Publish",
|
"DisplayName": "App.ForumManagement.Publish",
|
||||||
"Order": 11,
|
"Order": 12,
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"Modules": "Sas|Adm"
|
"Modules": "Sas|Adm"
|
||||||
|
|
|
||||||
|
|
@ -775,11 +775,44 @@
|
||||||
"IsDisabled": false,
|
"IsDisabled": false,
|
||||||
"ModuleId": "Adm"
|
"ModuleId": "Adm"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Administration",
|
||||||
|
"Code": "App.Administration.Notifications",
|
||||||
|
"DisplayName": "App.Administration.Notifications",
|
||||||
|
"Order": 4,
|
||||||
|
"Url": null,
|
||||||
|
"Icon": "FcWorkflow",
|
||||||
|
"RequiredPermissionName": null,
|
||||||
|
"IsDisabled": false,
|
||||||
|
"ModuleId": "Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Administration.Notifications",
|
||||||
|
"Code": "App.Notifications.NotificationTemplates",
|
||||||
|
"DisplayName": "App.Notifications.NotificationTemplates",
|
||||||
|
"Order": 1,
|
||||||
|
"Url": "/admin/list/App.Notifications.NotificationTemplates",
|
||||||
|
"Icon": "FcDocument",
|
||||||
|
"RequiredPermissionName": "App.Notifications.NotificationTemplates",
|
||||||
|
"IsDisabled": false,
|
||||||
|
"ModuleId": "Adm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Administration.Notifications",
|
||||||
|
"Code": "App.ManualNotification",
|
||||||
|
"DisplayName": "App.ManualNotification",
|
||||||
|
"Order": 2,
|
||||||
|
"Url": "/admin/list/App.ManualNotification",
|
||||||
|
"Icon": "FcSms",
|
||||||
|
"RequiredPermissionName": "App.ManualNotification",
|
||||||
|
"IsDisabled": false,
|
||||||
|
"ModuleId": "Adm"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Agenda",
|
"Code": "App.Agenda",
|
||||||
"DisplayName": "App.Agenda",
|
"DisplayName": "App.Agenda",
|
||||||
"Order": 4,
|
"Order": 5,
|
||||||
"Url": "/admin/list/App.Agenda",
|
"Url": "/admin/list/App.Agenda",
|
||||||
"Icon": "FcPlanner",
|
"Icon": "FcPlanner",
|
||||||
"RequiredPermissionName": "App.Agenda",
|
"RequiredPermissionName": "App.Agenda",
|
||||||
|
|
@ -790,7 +823,7 @@
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Setting",
|
"Code": "App.Setting",
|
||||||
"DisplayName": "App.Setting",
|
"DisplayName": "App.Setting",
|
||||||
"Order": 5,
|
"Order": 6,
|
||||||
"Url": "/admin/settings",
|
"Url": "/admin/settings",
|
||||||
"Icon": "FcSettings",
|
"Icon": "FcSettings",
|
||||||
"RequiredPermissionName": "App.Setting",
|
"RequiredPermissionName": "App.Setting",
|
||||||
|
|
@ -801,7 +834,7 @@
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Administration.Intranet",
|
"Code": "App.Administration.Intranet",
|
||||||
"DisplayName": "App.Intranet",
|
"DisplayName": "App.Intranet",
|
||||||
"Order": 6,
|
"Order": 7,
|
||||||
"Url": null,
|
"Url": null,
|
||||||
"Icon": "FcConferenceCall",
|
"Icon": "FcConferenceCall",
|
||||||
"RequiredPermissionName": null,
|
"RequiredPermissionName": null,
|
||||||
|
|
@ -900,7 +933,7 @@
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Administration.Restrictions",
|
"Code": "App.Administration.Restrictions",
|
||||||
"DisplayName": "App.Platform.Restrictions",
|
"DisplayName": "App.Platform.Restrictions",
|
||||||
"Order": 7,
|
"Order": 8,
|
||||||
"Url": null,
|
"Url": null,
|
||||||
"Icon": "FaLock",
|
"Icon": "FaLock",
|
||||||
"RequiredPermissionName": null,
|
"RequiredPermissionName": null,
|
||||||
|
|
@ -933,7 +966,7 @@
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "Abp.Identity",
|
"Code": "Abp.Identity",
|
||||||
"DisplayName": "Abp.Identity",
|
"DisplayName": "Abp.Identity",
|
||||||
"Order": 8,
|
"Order": 9,
|
||||||
"Url": null,
|
"Url": null,
|
||||||
"Icon": "FcConferenceCall",
|
"Icon": "FcConferenceCall",
|
||||||
"RequiredPermissionName": null,
|
"RequiredPermissionName": null,
|
||||||
|
|
@ -1032,7 +1065,7 @@
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Reports.Management",
|
"Code": "App.Reports.Management",
|
||||||
"DisplayName": "App.Reports.Management",
|
"DisplayName": "App.Reports.Management",
|
||||||
"Order": 9,
|
"Order": 10,
|
||||||
"Url": null,
|
"Url": null,
|
||||||
"Icon": "FcDocument",
|
"Icon": "FcDocument",
|
||||||
"RequiredPermissionName": null,
|
"RequiredPermissionName": null,
|
||||||
|
|
@ -1065,7 +1098,7 @@
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Videoroom",
|
"Code": "App.Videoroom",
|
||||||
"DisplayName": "App.Videoroom",
|
"DisplayName": "App.Videoroom",
|
||||||
"Order": 10,
|
"Order": 11,
|
||||||
"Url": "/admin/videoroom/dashboard",
|
"Url": "/admin/videoroom/dashboard",
|
||||||
"Icon": "FcVideoCall",
|
"Icon": "FcVideoCall",
|
||||||
"RequiredPermissionName": "App.Videoroom",
|
"RequiredPermissionName": "App.Videoroom",
|
||||||
|
|
@ -1076,7 +1109,7 @@
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Forum",
|
"Code": "App.Forum",
|
||||||
"DisplayName": "App.Forum",
|
"DisplayName": "App.Forum",
|
||||||
"Order": 11,
|
"Order": 12,
|
||||||
"Url": "/admin/forum",
|
"Url": "/admin/forum",
|
||||||
"Icon": "FcLink",
|
"Icon": "FcLink",
|
||||||
"RequiredPermissionName": "App.ForumManagement.Publish",
|
"RequiredPermissionName": "App.ForumManagement.Publish",
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,16 @@
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"IsFixed": false,
|
"IsFixed": false,
|
||||||
"IsCustomized": false
|
"IsCustomized": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "7d2e5a90-1c84-5b37-9e62-8a4f0d3b6c22",
|
||||||
|
"NotificationTypeId": "3f6c8b41-9d27-5a63-8f1e-4b0a9c6d2e11",
|
||||||
|
"RecipientType": "Custom",
|
||||||
|
"RecipientId": null,
|
||||||
|
"Channel": "UiActivity",
|
||||||
|
"IsActive": false,
|
||||||
|
"IsFixed": false,
|
||||||
|
"IsCustomized": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"ListFormCode": "App.Notifications.NotificationTemplates",
|
||||||
|
"KeyFieldName": "Id",
|
||||||
|
"GeneratedAt": "2026-09-20T21:00:00Z",
|
||||||
|
"Order": 3,
|
||||||
|
"Rows": [
|
||||||
|
{
|
||||||
|
"Id": "b1f9a0d2-6c41-5f8e-9a37-2d5c7e1b4a01",
|
||||||
|
"Code": "GENEL-DUYURU",
|
||||||
|
"Name": "Genel Duyuru",
|
||||||
|
"Channel": null,
|
||||||
|
"Subject": "Duyuru",
|
||||||
|
"Body": "Sayın {AdSoyad},\n\n{Kiraci} yönetimi tarafından bir duyuru paylaşıldı. Ayrıntılar için uygulamadaki duyurular ekranını inceleyin.\n\n{Tarih} {Saat}",
|
||||||
|
"IsActive": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "b1f9a0d2-6c41-5f8e-9a37-2d5c7e1b4a02",
|
||||||
|
"Code": "BAKIM-BILDIRIMI",
|
||||||
|
"Name": "Planlı Bakım Bildirimi",
|
||||||
|
"Channel": "Mail",
|
||||||
|
"Subject": "Planlı bakım çalışması",
|
||||||
|
"Body": "Sayın {AdSoyad},\n\n{Tarih} {Saat} itibarıyla planlı bakım çalışması başlayacaktır. Çalışma süresince uygulamaya erişim kesintili olabilir.\n\nİyi çalışmalar.",
|
||||||
|
"IsActive": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "b1f9a0d2-6c41-5f8e-9a37-2d5c7e1b4a03",
|
||||||
|
"Code": "SMS-KISA-BILGI",
|
||||||
|
"Name": "Kısa Bilgi (SMS)",
|
||||||
|
"Channel": "Sms",
|
||||||
|
"Subject": null,
|
||||||
|
"Body": "{AdSoyad}: {Kiraci} uygulamasinda sizi bekleyen bir islem var. {Tarih} {Saat}",
|
||||||
|
"IsActive": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "b1f9a0d2-6c41-5f8e-9a37-2d5c7e1b4a04",
|
||||||
|
"Code": "TOPLANTI-HATIRLATMA",
|
||||||
|
"Name": "Toplantı Hatırlatma",
|
||||||
|
"Channel": null,
|
||||||
|
"Subject": "Toplantı hatırlatması",
|
||||||
|
"Body": "Sayın {AdSoyad},\n\n{Tarih} günü {Saat} saatindeki toplantıyı hatırlatırız. Katılamayacaksanız organizatöre bilgi verin.",
|
||||||
|
"IsActive": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,11 @@
|
||||||
"Id": "78a4b82b-de80-5826-bf9b-e49a2436cd43",
|
"Id": "78a4b82b-de80-5826-bf9b-e49a2436cd43",
|
||||||
"Name": "YeniKullanici",
|
"Name": "YeniKullanici",
|
||||||
"Description": "Sisteme yeni bir kullanıcı eklendiğinde tetiklenir. Yönetici ekibin yetki ve rol atamasını yapması için haberdar olmasını sağlar."
|
"Description": "Sisteme yeni bir kullanıcı eklendiğinde tetiklenir. Yönetici ekibin yetki ve rol atamasını yapması için haberdar olmasını sağlar."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "3f6c8b41-9d27-5a63-8f1e-4b0a9c6d2e11",
|
||||||
|
"Name": "Manuel",
|
||||||
|
"Description": "Manuel Bildirim ekranindan elle yapilan gonderimlerin tipi. Kural motorundan gecmez: alicilar ve kanallar ekranda secilir, her gonderim bu tiple kuyruga yazilir."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue