NotificationType, Seeder ve List

This commit is contained in:
Sedat ÖZTÜRK 2026-05-11 12:37:52 +03:00
parent 96b78bd4b9
commit 8feab2184a
31 changed files with 530 additions and 166 deletions

View file

@ -1,9 +1,11 @@
namespace Sozsoft.Notifications.NotificationRules;
using System;
namespace Sozsoft.Notifications.NotificationRules;
public class CreateUpdateNotificationRuleDto
{
public string Channel { get; set; }
public string NotificationType { get; set; }
public Guid NotificationTypeId { get; set; }
public bool IsActive { get; set; }
}

View file

@ -12,11 +12,10 @@ public interface INotificationRuleAppService : ICrudAppService<
PagedAndSortedResultRequestDto,
CreateUpdateNotificationRuleDto>
{
string[] GetNotificationTypes();
Task<string[]> GetNotificationTypes();
Task<string[]> GetMyNotificationTypesAsync();
Task<List<NotificationRuleDto>> GetMyNotificationRules();
Task PostMyNotificationRule(CreateUpdateNotificationRuleDto Input);
Task DeleteMyNotificationRules(string NotificationType);
Task DeleteMyNotificationRules(Guid NotificationTypeId);
}

View file

@ -5,7 +5,7 @@ namespace Sozsoft.Notifications.NotificationRules;
public class NotificationRuleDto : FullAuditedEntityDto<Guid>
{
public string? NotificationType { get; set; }
public Guid? NotificationTypeId { get; set; }
public string? RecipientType { get; set; }
public string? RecipientId { get; set; } //UserId, RoleId, OrganizationUnitId
public string? Channel { get; set; }

View file

@ -0,0 +1,10 @@
using System;
using Volo.Abp.Application.Dtos;
namespace Sozsoft.Notifications.NotificationRules;
public class NotificationTypeDto : FullAuditedEntityDto<Guid>
{
public string Name { get; set; }
}

View file

@ -57,10 +57,10 @@ public class NotificationAppService : ReadOnlyAppService<
public async Task CreateNotificationByNotificationRuleIdAsync(NotificationRequestDto input)
{
var notificationRule = await repositoryRule.GetAsync(input.Id);
var notificationRule = await repositoryRule.GetAsync(input.Id, true);
if (notificationRule != null)
{
await notificationManager.SendNotificationAsync(notificationRule.NotificationType, input.Message);
await notificationManager.SendNotificationAsync(notificationRule.NotificationTypeId, input.Message);
}
}

View file

@ -8,6 +8,7 @@ public class NotificationApplicationAutoMapperProfile : Profile
{
public NotificationApplicationAutoMapperProfile()
{
CreateMap<NotificationType, NotificationTypeDto>();
CreateMap<NotificationRule, NotificationRuleDto>();
CreateMap<Notification, NotificationDto>()
.ForMember(d => d.CreatorFullname, o => o.Ignore())

View file

@ -4,7 +4,6 @@ using System.Linq;
using System.Threading.Tasks;
using Sozsoft.Notifications.Domain;
using Sozsoft.Notifications.Entities;
using Sozsoft.Notifications.Enums;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Application.Dtos;
@ -23,25 +22,30 @@ public class NotificationRuleAppService : CrudAppService<
CreateUpdateNotificationRuleDto>,
INotificationRuleAppService
{
private readonly IRepository<NotificationType, Guid> repositoryType;
private readonly IOrganizationUnitRepository repositoryOrganizationUnit;
private readonly IdentityUserManager userManager;
private readonly IIdentityUserRepository repositoryUser;
private readonly IOrganizationUnitRepository repositoryOrganizationUnit;
public NotificationRuleAppService(
IRepository<NotificationType, Guid> repositoryType,
IRepository<NotificationRule, Guid> repository,
IdentityUserManager userManager,
IIdentityUserRepository repositoryUser,
IOrganizationUnitRepository repositoryOrganizationUnit
) : base(repository)
{
this.repositoryType = repositoryType;
this.userManager = userManager;
this.repositoryUser = repositoryUser;
this.repositoryOrganizationUnit = repositoryOrganizationUnit;
}
public string[] GetNotificationTypes()
public async Task<string[]> GetNotificationTypes()
{
return NotificationTypes.GetAll();
var types = await repositoryType.GetListAsync();
return types.Select(a => a.Name).ToArray();
}
private void GetAllParentCodes(string code, List<string>? codes)
@ -83,7 +87,8 @@ public class NotificationRuleAppService : CrudAppService<
public async Task<string[]> GetMyNotificationTypesAsync()
{
var query = await CreateFilteredQueryAsync(new PagedAndSortedResultRequestDto());
return await query.Select(a => a.NotificationType).Distinct().ToArrayAsync();
return await query.Select(a => a.NotificationType.Name).Distinct().ToArrayAsync();
}
public async Task<List<NotificationRuleDto>> GetMyNotificationRules()
@ -91,7 +96,7 @@ public class NotificationRuleAppService : CrudAppService<
var query = await CreateFilteredQueryAsync(new PagedAndSortedResultRequestDto());
var all = await query.ToListAsync();
var list = all
.GroupBy(a => new { a.NotificationType, a.Channel })
.GroupBy(a => new { a.NotificationTypeId, a.Channel })
.Select(a =>
{
var item = a.FirstOrDefault(a => a.IsFixed)
@ -101,7 +106,7 @@ public class NotificationRuleAppService : CrudAppService<
return new NotificationRuleDto
{
Id = item.Id,
NotificationType = a.Key.NotificationType,
NotificationTypeId = a.Key.NotificationTypeId,
Channel = a.Key.Channel,
IsActive = item.IsActive,
IsFixed = item.IsFixed,
@ -121,13 +126,13 @@ public class NotificationRuleAppService : CrudAppService<
a.RecipientId == CurrentUser.UserName &&
a.IsCustomized &&
a.Channel == Input.Channel &&
a.NotificationType == Input.NotificationType);
a.NotificationTypeId == Input.NotificationTypeId);
if (item is null)
{
// insert
item = new NotificationRule
{
NotificationType = Input.NotificationType,
NotificationTypeId = Input.NotificationTypeId,
RecipientType = NotificationRecipientTypes.User,
RecipientId = CurrentUser.UserName,
Channel = Input.Channel,
@ -144,51 +149,16 @@ public class NotificationRuleAppService : CrudAppService<
}
}
public async Task DeleteMyNotificationRules(string NotificationType)
public async Task DeleteMyNotificationRules(Guid NotificationTypeId)
{
var query = await CreateFilteredQueryAsync(new PagedAndSortedResultRequestDto());
var items = await query.Where(a =>
a.RecipientType == NotificationRecipientTypes.User &&
a.RecipientId == CurrentUser.UserName &&
a.IsCustomized &&
a.NotificationType == NotificationType)
a.NotificationTypeId == NotificationTypeId)
.ToListAsync();
await Repository.DeleteManyAsync(items);
}
}
/*
var defaultRules = await query.Where(a => !a.IsCustomized && a.IsActive)
.GroupBy(a => new { a.NotificationType, a.Channel })
.Select(a => new NotificationRuleDto
{
Id = a.FirstOrDefault(a => a.UserId != null)?.Id ?? a.First().Id,
NotificationType = a.Key.NotificationType,
Channel = a.Key.Channel,
IsActive = a.First().IsActive,
IsFixed = a.First().IsFixed,
IsCustomized = a.First().IsCustomized,
})
.ToListAsync();
var customizedRules = await query.Where(a => a.IsCustomized)
.Select(a => new NotificationRuleDto
{
Id = a.Id,
NotificationType = a.NotificationType,
Channel = a.Channel,
IsActive = a.IsActive,
IsFixed = a.IsFixed,
IsCustomized = a.IsCustomized
})
.ToListAsync();
//defaultRules.IsFixed
//customizedRules - defaultRules.IsFixed
//!defaultRules.IsFixed - customizedRules
var list = new List<NotificationRuleDto>();
list.AddRange(defaultRules.Where(a => a.IsFixed).ToList());
list.AddRange(customizedRules.Where(a => !list.Any(b => b.NotificationType == a.NotificationType && b.Channel == a.Channel)).ToList());
list.AddRange(defaultRules.Where(a => !a.IsFixed && !list.Any(b => b.NotificationType == a.NotificationType && b.Channel == a.Channel)).ToList());
*/

View file

@ -9,6 +9,6 @@ public static class NotificationChannels
public const string UiActivity = "UiActivity";
public const string UiToast = "UiToast";
public const string WhatsApp = "WhatsApp";
public const string Telegram = "Telegram";
// public const string Telegram = "Telegram";
}

View file

@ -1,16 +0,0 @@
using Volo.Abp.Reflection;
namespace Sozsoft.Notifications.Enums;
public static class NotificationTypes
{
// public const string SiparisPasla = "SiparisPasla";
// public const string YeniSiparis = "YeniSiparis";
// public const string YeniKullanici = "YeniKullanici";
public static string[] GetAll()
{
return ReflectionHelper.GetPublicConstantsRecursively(typeof(NotificationTypes));
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Domain.Entities.Auditing;
namespace Sozsoft.Notifications.Entities;
@ -7,7 +8,8 @@ public class Notification : FullAuditedEntity<Guid>
{
public Guid NotificationRuleId { get; set; }
public required string NotificationChannel { get; set; }
public required string NotificationType { get; set; }
public required Guid NotificationTypeId { get; set; }
public virtual NotificationType NotificationType { get; set; }
// Bildirim tipine göre bildirimi alacak olan hedef bilgisini içerir
public required string Identifier { get; set; } //UserId, Email, PhoneNumber..

View file

@ -6,7 +6,9 @@ namespace Sozsoft.Notifications.Entities;
public class NotificationRule : FullAuditedEntity<Guid>
{
public required string NotificationType { get; set; }
public required Guid NotificationTypeId { get; set; }
public NotificationType NotificationType { get; set; }
/// <summary>
/// Alıcı Tipi: User, Role, Organization, All, Custom
/// User ise RecipientId UserId olacak

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Domain.Entities.Auditing;
namespace Sozsoft.Notifications.Entities;
public class NotificationType : FullAuditedEntity<Guid>
{
public required string Name { get; set; }
public virtual ICollection<NotificationRule> NotificationRules { get; set; } = [];
public ICollection<Notification> Notifications { get; set; } = [];
}

View file

@ -40,7 +40,7 @@ public class NotificationIdentifierProvider : INotificationIdentifierProvider
NotificationChannels.UiActivity => user.Id.ToString(),
NotificationChannels.UiToast => user.Id.ToString(),
NotificationChannels.WhatsApp => user.PhoneNumber,
NotificationChannels.Telegram => user.PhoneNumber,
// NotificationChannels.Telegram => user.PhoneNumber,
_ => null,
};

View file

@ -13,12 +13,13 @@ namespace Sozsoft.Notifications.Domain;
public interface INotificationManager : ITransientDependency
{
Task SendNotificationAsync(string NotificationType, string NotificationMessage);
Task SendNotificationAsync(Guid NotificationTypeId, string NotificationMessage);
Task SendNotificationAsync(string NotificationType, string NotificationChannel, string NotificationMessage, string Identifier, Guid? UserId = null);
}
public class NotificationManager : INotificationManager
{
private readonly IReadOnlyRepository<NotificationType> repositoryType;
private readonly IReadOnlyRepository<NotificationRule> repository;
private readonly IReadOnlyRepository<IdentityUser> repositoryUser;
private readonly IReadOnlyRepository<IdentityRole> repositoryRole;
@ -28,6 +29,7 @@ public class NotificationManager : INotificationManager
private readonly ICurrentUser currentUser;
public NotificationManager(
IReadOnlyRepository<NotificationType> repositoryType,
IReadOnlyRepository<NotificationRule> repository,
IReadOnlyRepository<IdentityUser> repositoryUser,
IReadOnlyRepository<IdentityRole> repositoryRole,
@ -37,6 +39,7 @@ public class NotificationManager : INotificationManager
ICurrentUser currentUser
)
{
this.repositoryType = repositoryType;
this.repository = repository;
this.repositoryUser = repositoryUser;
this.repositoryRole = repositoryRole;
@ -46,9 +49,9 @@ public class NotificationManager : INotificationManager
this.currentUser = currentUser;
}
public async Task SendNotificationAsync(string NotificationType, string NotificationMessage)
public async Task SendNotificationAsync(Guid NotificationTypeId, string NotificationMessage)
{
var list = await repository.GetListAsync(a => a.NotificationType == NotificationType);
var list = await repository.GetListAsync(a => a.NotificationTypeId == NotificationTypeId);
var notificationRules = list
.GroupBy(a => new { a.NotificationType, a.Channel })
.Select(a =>
@ -110,11 +113,12 @@ public class NotificationManager : INotificationManager
var notifications = new List<Notification>();
//Eğer "Custom" seçildiyse girilen RecipientId dinamik olabilir. Telefon Numarası, Email vs.
if (notificationRule.RecipientType == NotificationRecipientTypes.Custom) {
if (notificationRule.RecipientType == NotificationRecipientTypes.Custom)
{
var notification = new Notification
{
NotificationTypeId = notificationRule.NotificationTypeId,
NotificationRuleId = notificationRule.Id,
NotificationType = NotificationType,
NotificationChannel = notificationRule.Channel,
Identifier = notificationRule.RecipientId!,
UserId = currentUser.Id,
@ -124,7 +128,8 @@ public class NotificationManager : INotificationManager
};
notifications.Add(notification);
}
else {
else
{
if (userIds.IsNullOrEmpty())
{
continue;
@ -142,8 +147,8 @@ public class NotificationManager : INotificationManager
var notification = new Notification
{
NotificationTypeId = notificationRule.NotificationTypeId,
NotificationRuleId = notificationRule.Id,
NotificationType = NotificationType,
NotificationChannel = notificationRule.Channel,
Identifier = identifier,
UserId = userId,
@ -154,7 +159,7 @@ public class NotificationManager : INotificationManager
notifications.Add(notification);
}
}
await repositoryNotification.InsertManyAsync(notifications);
}
}
@ -163,7 +168,7 @@ public class NotificationManager : INotificationManager
/// <summary>
/// Belirtilen Ident
/// </summary>
/// <param name="NotificationType"></param>
/// <param name="NotificationTypeId"></param>
/// <param name="NotificationMessage"></param>
/// <param name="Identifier"></param>
/// <param name="UserId"></param>
@ -187,9 +192,12 @@ public class NotificationManager : INotificationManager
}
}
var notificationType = await repositoryType.FirstOrDefaultAsync(a => a.Name == NotificationType)
?? throw new Exception($"NotificationType '{NotificationType}' not found.");
await repositoryNotification.InsertAsync(new Notification
{
NotificationType = NotificationType,
NotificationTypeId = notificationType.Id,
NotificationChannel = NotificationChannel,
Identifier = Identifier,
UserId = UserId,

View file

@ -12,6 +12,7 @@ public class NotificationDbContext : AbpDbContext<NotificationDbContext>, INotif
/* Add DbSet for each Aggregate Root here. Example:
* public DbSet<Question> Questions { get; set; }
*/
public DbSet<NotificationType> NotificationTypes { get; set; }
public DbSet<NotificationRule> NotificationRules { get; set; }
public DbSet<Notification> Notifications { get; set; }

View file

@ -1,6 +1,7 @@
using Sozsoft.Notifications.Domain;
using Sozsoft.Notifications.Entities;

using Microsoft.EntityFrameworkCore;
using Sozsoft.Notifications.Domain;
using Sozsoft.Notifications.Entities;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
@ -13,21 +14,29 @@ public static class NotificationDbContextModelCreatingExtensions
{
Check.NotNull(builder, nameof(builder));
builder.Entity<NotificationType>(b =>
{
b.ToTable(TablePrefix.ByName(nameof(NotificationType)), Prefix.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
});
builder.Entity<NotificationRule>(b =>
{
b.ToTable(TablePrefix.ByName(nameof(NotificationRule)), Prefix.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.NotificationType).IsRequired().HasMaxLength(128);
b.Property(x => x.NotificationTypeId).IsRequired();
b.Property(x => x.RecipientType).IsRequired().HasMaxLength(64);
b.Property(x => x.RecipientId).HasMaxLength(256);
b.Property(x => x.Channel).IsRequired().HasMaxLength(64);
// 1:N ilişki NotificationRule -> Notifications
b.HasMany(x => x.Notifications)
.WithOne(x => x.NotificationRule)
.HasForeignKey(x => x.NotificationRuleId)
.OnDelete(DeleteBehavior.Cascade);
b.HasOne(x => x.NotificationType)
.WithMany(x => x.NotificationRules)
.HasForeignKey(x => x.NotificationTypeId)
.OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<Notification>(b =>
@ -35,10 +44,17 @@ public static class NotificationDbContextModelCreatingExtensions
b.ToTable(TablePrefix.ByName(nameof(Notification)), Prefix.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.NotificationTypeId).IsRequired();
b.Property(x => x.NotificationRuleId).IsRequired();
b.Property(x => x.NotificationChannel).IsRequired().HasMaxLength(64);
b.Property(x => x.NotificationType).IsRequired().HasMaxLength(128);
b.Property(x => x.Identifier).IsRequired().HasMaxLength(256);
b.Property(x => x.Message).IsRequired().HasMaxLength(2048);
b.HasOne(x => x.NotificationType)
.WithMany(x => x.Notifications)
.HasForeignKey(x => x.NotificationTypeId)
.OnDelete(DeleteBehavior.Restrict);
});
}
}

View file

@ -26,6 +26,6 @@ public class LookupDto
/// Not: FieldName alaninin veritabani turu int+ turunde ise {key:1:, name:"nn"} seklide olmali
/// FieldName alaninin veritabani turu string+ turunde ise {key:"1", name:"nn"} seklide olmali
/// </summary>
public string LookupQuery { get; set; }
public string LookupQuery { get; set; } //"GET;notification-rule/notification-types;{};a;a;null",
}

View file

@ -1023,6 +1023,7 @@
"order": 66
}
],
"NotificationTypes": [],
"NotificationRules": [
{
"notificationType": "YeniSiparis",
@ -1074,7 +1075,7 @@
"isActive": true,
"dataSourceCode": "Default",
"beforeSp": "Adm_T_DatabaseBackupAll",
"afterSp": "Adm_T_DatabaseBackupDeleteAll"
"afterSp": "Adm_T_DatabaseBackupFilesDeleteAll"
}
],
"ContactTitles": [

View file

@ -1758,6 +1758,12 @@
"en": "Notifications",
"tr": "Bildirimler"
},
{
"resourceName": "Platform",
"key": "App.Notifications.NotificationTypes",
"en": "Notification Types",
"tr": "Bildirim Türleri"
},
{
"resourceName": "Platform",
"key": "App.Notifications.NotificationRules",
@ -15142,7 +15148,7 @@
},
{
"resourceName": "Platform",
"key": "App.Listform.ListformField.NotificationType",
"key": "App.Listform.ListformField.NotificationTypeId",
"en": "Notification Type",
"tr": "Bildirim Türü"
},

View file

@ -4186,6 +4186,96 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
}
#endregion
#region Notification Type
listFormName = AppCodes.Notifications.NotificationTypes;
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 = true,
LayoutJson = DefaultLayoutJson(),
CultureName = LanguageCodes.En,
ListFormCode = listFormName,
Name = listFormName,
Title = listFormName,
DataSourceCode = SeedConsts.DataSources.DefaultCode,
IsTenant = false,
IsBranch = false,
IsOrganizationUnit = false,
Description = listFormName,
SelectCommandType = SelectCommandTypeEnum.Table,
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.NotificationType)),
KeyFieldName = "Id",
KeyFieldDbSourceType = DbType.Guid,
DefaultFilter = DefaultFilterJson,
SortMode = GridOptions.SortModeSingle,
FilterRowJson = DefaultFilterRowJson,
HeaderFilterJson = DefaultHeaderFilterJson,
SearchPanelJson = DefaultSearchPanelJson,
GroupPanelJson = JsonSerializer.Serialize(new { Visible = false }),
SelectionJson = DefaultSelectionSingleJson,
ColumnOptionJson = DefaultColumnOptionJson(),
PermissionJson = DefaultPermissionJson(listFormName),
DeleteCommand = DefaultDeleteCommand(nameof(TableNameEnum.NotificationType)),
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
PagerOptionJson = DefaultPagerOptionJson,
EditingOptionJson = DefaultEditingOptionJson(listFormName, 400, 200, true, true, true, true, false),
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
{
new() {
Order = 1, ColCount = 1, ColSpan = 1, ItemType = "group", Items =
[
new EditingFormItemDto { Order = 1, ColSpan = 1, DataField = "Name", IsRequired = true, EditorType2 = EditorTypes.dxTextBox }
]
}
}),
});
#region Notification Type 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),
},
new()
{
ListFormCode = listForm.ListFormCode,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "Name",
CaptionName = "App.Listform.ListformField.Name",
Width = 0,
ListOrderNo = 2,
Visible = true,
IsActive = true,
AllowSearch = true,
ValidationRuleJson = DefaultValidationRuleRequiredJson,
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
}
]);
#endregion
}
#endregion
#region Notification Rule
listFormName = AppCodes.Notifications.NotificationRules;
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))
@ -4224,10 +4314,10 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
DeleteCommand = $"UPDATE \"{FullNameTable(TableNameEnum.NotificationRule)}\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\"=@Id",
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
PagerOptionJson = DefaultPagerOptionJson,
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 500, true, true, true, true, false),
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 550, true, true, true, true, false),
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>() {
new() { Order=1, ColCount=1, ColSpan=1, ItemType="group", Items=[
new EditingFormItemDto { Order = 1, DataField = "NotificationType", ColSpan = 1, IsRequired = true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order = 1, DataField = "NotificationTypeId", ColSpan = 1, IsRequired = true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order = 2, DataField = "RecipientType", ColSpan = 1, IsRequired = true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order = 3, DataField = "Channel", ColSpan = 1, IsRequired = true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton },
new EditingFormItemDto { Order = 4, DataField = "RecipientId", ColSpan = 1, EditorType2=EditorTypes.dxTextBox },
@ -4276,21 +4366,22 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
new() {
ListFormCode = listForm.ListFormCode,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "NotificationType",
CaptionName = "App.Listform.ListformField.NotificationType",
SourceDbType = DbType.Guid,
FieldName = "NotificationTypeId",
CaptionName = "App.Listform.ListformField.NotificationTypeId",
Width = 0,
ListOrderNo = 2,
Visible = true,
IsActive = true,
AllowSearch = true,
LookupJson = JsonSerializer.Serialize(new LookupDto {
DataSourceType = UiLookupDataSourceTypeEnum.WebService,
DisplayExpr = "Name",
ValueExpr = "Key",
LookupQuery = "GET;notification-rule/notification-types;{};a;a;null",
}),
LookupJson = LookupQueryValues.DefaultLookupQueryJson(nameof(TableNameEnum.NotificationType), "Id", "Name"),
// LookupJson = JsonSerializer.Serialize(new LookupDto {
// DataSourceType = UiLookupDataSourceTypeEnum.WebService,
// DisplayExpr = "Name",
// ValueExpr = "Key",
// LookupQuery = "GET;notification-rule/notification-types;{};a;a;null",
// }),
ValidationRuleJson = DefaultValidationRuleRequiredJson,
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
@ -4465,7 +4556,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
DeleteCommand = $"UPDATE \"{FullNameTable(TableNameEnum.Notification)}\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\"=@Id",
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
PagerOptionJson = DefaultPagerOptionJson,
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 500, true, true, true, true, false),
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 500, false, false, false, false, false, false),
}
);
@ -4482,7 +4573,6 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
ListOrderNo = 1,
Visible = false,
IsActive = true,
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
PivotSettingsJson = DefaultPivotSettingsJson
@ -4513,7 +4603,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
new () { Key="UiActivity",Name="UiActivity" },
new () { Key="UiToast",Name="UiToast" },
new () { Key="WhatsApp",Name="WhatsApp" },
new () { Key="Telegram",Name="Telegram" },
// new () { Key="Telegram",Name="Telegram" },
}),
}),
ColumnCustomizationJson = DefaultColumnCustomizationJson,
@ -4523,21 +4613,22 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
new() {
ListFormCode = listForm.ListFormCode,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "NotificationType",
CaptionName = "App.Listform.ListformField.NotificationType",
SourceDbType = DbType.Guid,
FieldName = "NotificationTypeId",
CaptionName = "App.Listform.ListformField.NotificationTypeId",
Width = 0,
ListOrderNo = 4,
Visible = true,
IsActive = true,
AllowSearch = true,
LookupJson = JsonSerializer.Serialize(new LookupDto {
DataSourceType = UiLookupDataSourceTypeEnum.WebService,
DisplayExpr = "Name",
ValueExpr = "Key",
LookupQuery = "GET;notification-rule/notification-types;{};a;a;null",
}),
LookupJson = LookupQueryValues.DefaultLookupQueryJson(nameof(TableNameEnum.NotificationType), "Id", "Name"),
// LookupJson = JsonSerializer.Serialize(new LookupDto {
// DataSourceType = UiLookupDataSourceTypeEnum.WebService,
// DisplayExpr = "Name",
// ValueExpr = "Key",
// LookupQuery = "GET;notification-rule/notification-types;{};a;a;null",
// }),
ValidationRuleJson = DefaultValidationRuleRequiredJson,
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(listForm.Name),

View file

@ -702,11 +702,21 @@
"RequiredPermissionName": null,
"IsDisabled": false
},
{
"ParentCode": "App.Notifications",
"Code": "App.Notifications.NotificationTypes",
"DisplayName": "App.Notifications.NotificationTypes",
"Order": 1,
"Url": "/admin/list/App.Notifications.NotificationTypes",
"Icon": "FcComboChart",
"RequiredPermissionName": "App.Notifications.NotificationTypes",
"IsDisabled": false
},
{
"ParentCode": "App.Notifications",
"Code": "App.Notifications.NotificationRules",
"DisplayName": "App.Notifications.NotificationRules",
"Order": 1,
"Order": 2,
"Url": "/admin/list/App.Notifications.NotificationRules",
"Icon": "FcLibrary",
"RequiredPermissionName": "App.Notifications.NotificationRules",
@ -716,7 +726,7 @@
"ParentCode": "App.Notifications",
"Code": "App.Notifications.Notification",
"DisplayName": "App.Notifications.Notification",
"Order": 2,
"Order": 3,
"Url": "/admin/list/App.Notifications.Notification",
"Icon": "FcBrokenLink",
"RequiredPermissionName": "App.Notifications.Notification",

View file

@ -1198,6 +1198,62 @@
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Notifications.NotificationTypes",
"ParentName": null,
"DisplayName": "App.Notifications.NotificationTypes",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Notifications.NotificationTypes.Create",
"ParentName": "App.Notifications.NotificationTypes",
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Notifications.NotificationTypes.Delete",
"ParentName": "App.Notifications.NotificationTypes",
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Notifications.NotificationTypes.Export",
"ParentName": "App.Notifications.NotificationTypes",
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Notifications.NotificationTypes.Import",
"ParentName": "App.Notifications.NotificationTypes",
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Notifications.NotificationTypes.Update",
"ParentName": "App.Notifications.NotificationTypes",
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Notifications.NotificationRules",

View file

@ -1,4 +1,4 @@
CREATE OR ALTER PROCEDURE [dbo].[Adm_T_DatabaseBackupDeleteAll]
CREATE OR ALTER PROCEDURE [dbo].[Adm_T_DatabaseBackupFilesDeleteAll]
AS
BEGIN
SET NOCOUNT ON;

View file

@ -8,6 +8,7 @@ public enum TableNameEnum
SettingDefinition,
Notification,
NotificationRule,
NotificationType,
BackgroundWorker,
BackgroundWorker_MailQueue,
BackgroundWorker_MailQueueEvents,

View file

@ -418,6 +418,7 @@ public static class PlatformConsts
{
public const string Default = Prefix.App + ".Notifications";
public const string NotificationTypes = Default + ".NotificationTypes";
public const string NotificationRules = Default + ".NotificationRules";
public const string Notification = Default + ".Notification";
}

View file

@ -40,6 +40,7 @@ public static class TableNameResolver
{ nameof(TableNameEnum.ListFormImportExecute), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.Notification), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.NotificationRule), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.NotificationType), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.BackgroundWorker), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.BackgroundWorker_MailQueue), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.BackgroundWorker_MailQueueEvents), (TablePrefix.PlatformByName, MenuPrefix.Saas) },

View file

@ -59,7 +59,7 @@ public class PlatformBackgroundWorker : PlatformDomainService, IPlatformBackgrou
{
using var uow = LazyServiceProvider.LazyGetRequiredService<IUnitOfWorkManager>().Begin(requiresNew: true, isTransactional: false);
var Worker = await Repository.GetAsync(a => a.Id == WorkerId);
var Worker = await Repository.FirstOrDefaultAsync(a => a.Id == WorkerId);
var LogPrefix = $"{Clock.Now:s}_{Worker.Name}: {{0}}";
var DistributedLockName = Worker.Name;

View file

@ -399,6 +399,7 @@ public static class SeedConsts
{
public const string Default = Prefix.App + ".Notifications";
public const string NotificationTypes = Default + ".NotificationTypes";
public const string NotificationRules = Default + ".NotificationRules";
public const string Notification = Default + ".Notification";
}

View file

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Sozsoft.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
[Migration("20260508144450_Initial")]
[Migration("20260511093511_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -397,10 +397,8 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("NotificationRuleId")
.HasColumnType("uniqueidentifier");
b.Property<string>("NotificationType")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid>("NotificationTypeId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("ReadTime")
.HasColumnType("datetime2");
@ -412,6 +410,8 @@ namespace Sozsoft.Platform.Migrations
b.HasIndex("NotificationRuleId");
b.HasIndex("NotificationTypeId");
b.ToTable("Sas_H_Notification", (string)null);
});
@ -465,10 +465,8 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("NotificationType")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid>("NotificationTypeId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RecipientId")
.HasMaxLength(256)
@ -481,9 +479,57 @@ namespace Sozsoft.Platform.Migrations
b.HasKey("Id");
b.HasIndex("NotificationTypeId");
b.ToTable("Sas_H_NotificationRule", (string)null);
});
modelBuilder.Entity("Sozsoft.Notifications.Entities.NotificationType", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
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>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.HasKey("Id");
b.ToTable("Sas_H_NotificationType", (string)null);
});
modelBuilder.Entity("Sozsoft.Platform.Entities.About", b =>
{
b.Property<Guid>("Id")
@ -7711,7 +7757,26 @@ namespace Sozsoft.Platform.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Sozsoft.Notifications.Entities.NotificationType", "NotificationType")
.WithMany("Notifications")
.HasForeignKey("NotificationTypeId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("NotificationRule");
b.Navigation("NotificationType");
});
modelBuilder.Entity("Sozsoft.Notifications.Entities.NotificationRule", b =>
{
b.HasOne("Sozsoft.Notifications.Entities.NotificationType", "NotificationType")
.WithMany("NotificationRules")
.HasForeignKey("NotificationTypeId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("NotificationType");
});
modelBuilder.Entity("Sozsoft.Platform.Entities.BlogPost", b =>
@ -8236,6 +8301,13 @@ namespace Sozsoft.Platform.Migrations
b.Navigation("Notifications");
});
modelBuilder.Entity("Sozsoft.Notifications.Entities.NotificationType", b =>
{
b.Navigation("NotificationRules");
b.Navigation("Notifications");
});
modelBuilder.Entity("Sozsoft.Platform.Entities.BlogCategory", b =>
{
b.Navigation("Posts");

View file

@ -1414,17 +1414,11 @@ namespace Sozsoft.Platform.Migrations
});
migrationBuilder.CreateTable(
name: "Sas_H_NotificationRule",
name: "Sas_H_NotificationType",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
NotificationType = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
RecipientType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
RecipientId = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Channel = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
IsFixed = table.Column<bool>(type: "bit", nullable: false),
IsCustomized = table.Column<bool>(type: "bit", nullable: false),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
@ -1435,7 +1429,7 @@ namespace Sozsoft.Platform.Migrations
},
constraints: table =>
{
table.PrimaryKey("PK_Sas_H_NotificationRule", x => x.Id);
table.PrimaryKey("PK_Sas_H_NotificationType", x => x.Id);
});
migrationBuilder.CreateTable(
@ -2611,19 +2605,17 @@ namespace Sozsoft.Platform.Migrations
});
migrationBuilder.CreateTable(
name: "Sas_H_Notification",
name: "Sas_H_NotificationRule",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
NotificationRuleId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
NotificationChannel = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NotificationType = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Identifier = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Message = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: false),
IsSent = table.Column<bool>(type: "bit", nullable: false),
IsRead = table.Column<bool>(type: "bit", nullable: false),
ReadTime = table.Column<DateTime>(type: "datetime2", nullable: true),
NotificationTypeId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
RecipientType = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
RecipientId = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Channel = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
IsFixed = table.Column<bool>(type: "bit", nullable: false),
IsCustomized = table.Column<bool>(type: "bit", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
@ -2634,13 +2626,13 @@ namespace Sozsoft.Platform.Migrations
},
constraints: table =>
{
table.PrimaryKey("PK_Sas_H_Notification", x => x.Id);
table.PrimaryKey("PK_Sas_H_NotificationRule", x => x.Id);
table.ForeignKey(
name: "FK_Sas_H_Notification_Sas_H_NotificationRule_NotificationRuleId",
column: x => x.NotificationRuleId,
principalTable: "Sas_H_NotificationRule",
name: "FK_Sas_H_NotificationRule_Sas_H_NotificationType_NotificationTypeId",
column: x => x.NotificationTypeId,
principalTable: "Sas_H_NotificationType",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
@ -3109,6 +3101,45 @@ namespace Sozsoft.Platform.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Sas_H_Notification",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
NotificationRuleId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
NotificationChannel = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
NotificationTypeId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Identifier = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Message = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: false),
IsSent = table.Column<bool>(type: "bit", nullable: false),
IsRead = table.Column<bool>(type: "bit", nullable: false),
ReadTime = table.Column<DateTime>(type: "datetime2", 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_Sas_H_Notification", x => x.Id);
table.ForeignKey(
name: "FK_Sas_H_Notification_Sas_H_NotificationRule_NotificationRuleId",
column: x => x.NotificationRuleId,
principalTable: "Sas_H_NotificationRule",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Sas_H_Notification_Sas_H_NotificationType_NotificationTypeId",
column: x => x.NotificationTypeId,
principalTable: "Sas_H_NotificationType",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "Sas_T_ForumPost",
columns: table => new
@ -3685,6 +3716,16 @@ namespace Sozsoft.Platform.Migrations
table: "Sas_H_Notification",
column: "NotificationRuleId");
migrationBuilder.CreateIndex(
name: "IX_Sas_H_Notification_NotificationTypeId",
table: "Sas_H_Notification",
column: "NotificationTypeId");
migrationBuilder.CreateIndex(
name: "IX_Sas_H_NotificationRule_NotificationTypeId",
table: "Sas_H_NotificationRule",
column: "NotificationTypeId");
migrationBuilder.CreateIndex(
name: "IX_Sas_H_OrderItem_OrderId",
table: "Sas_H_OrderItem",
@ -4089,6 +4130,9 @@ namespace Sozsoft.Platform.Migrations
migrationBuilder.DropTable(
name: "Sas_H_ListForm");
migrationBuilder.DropTable(
name: "Sas_H_NotificationType");
migrationBuilder.DropTable(
name: "Sas_T_ForumCategory");

View file

@ -394,10 +394,8 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("NotificationRuleId")
.HasColumnType("uniqueidentifier");
b.Property<string>("NotificationType")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid>("NotificationTypeId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("ReadTime")
.HasColumnType("datetime2");
@ -409,6 +407,8 @@ namespace Sozsoft.Platform.Migrations
b.HasIndex("NotificationRuleId");
b.HasIndex("NotificationTypeId");
b.ToTable("Sas_H_Notification", (string)null);
});
@ -462,10 +462,8 @@ namespace Sozsoft.Platform.Migrations
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("NotificationType")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<Guid>("NotificationTypeId")
.HasColumnType("uniqueidentifier");
b.Property<string>("RecipientId")
.HasMaxLength(256)
@ -478,9 +476,57 @@ namespace Sozsoft.Platform.Migrations
b.HasKey("Id");
b.HasIndex("NotificationTypeId");
b.ToTable("Sas_H_NotificationRule", (string)null);
});
modelBuilder.Entity("Sozsoft.Notifications.Entities.NotificationType", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
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>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.HasKey("Id");
b.ToTable("Sas_H_NotificationType", (string)null);
});
modelBuilder.Entity("Sozsoft.Platform.Entities.About", b =>
{
b.Property<Guid>("Id")
@ -7708,7 +7754,26 @@ namespace Sozsoft.Platform.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Sozsoft.Notifications.Entities.NotificationType", "NotificationType")
.WithMany("Notifications")
.HasForeignKey("NotificationTypeId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("NotificationRule");
b.Navigation("NotificationType");
});
modelBuilder.Entity("Sozsoft.Notifications.Entities.NotificationRule", b =>
{
b.HasOne("Sozsoft.Notifications.Entities.NotificationType", "NotificationType")
.WithMany("NotificationRules")
.HasForeignKey("NotificationTypeId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("NotificationType");
});
modelBuilder.Entity("Sozsoft.Platform.Entities.BlogPost", b =>
@ -8233,6 +8298,13 @@ namespace Sozsoft.Platform.Migrations
b.Navigation("Notifications");
});
modelBuilder.Entity("Sozsoft.Notifications.Entities.NotificationType", b =>
{
b.Navigation("NotificationRules");
b.Navigation("Notifications");
});
modelBuilder.Entity("Sozsoft.Platform.Entities.BlogCategory", b =>
{
b.Navigation("Posts");