using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Tiku.Domain.Catalog; using Tiku.Domain.Content; using Tiku.Domain.Identity; using Tiku.Domain.Operations; using Tiku.Domain.Platform; using Tiku.Domain.QuestionBanks; using Tiku.Domain.Tenancy; namespace Tiku.Infrastructure.Persistence.Configurations; internal sealed class BannerConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("banners"); builder.ConfigureTimestamps(); builder.Property(entity => entity.LegacyId).HasMaxLength(64); builder.Property(entity => entity.Title).HasMaxLength(300); builder.Property(entity => entity.Subtitle).HasMaxLength(500); builder.Property(entity => entity.ButtonText).HasMaxLength(100); builder.Property(entity => entity.ButtonLink).HasMaxLength(2048); builder.Property(entity => entity.BackgroundColor).HasMaxLength(50); builder.Property(entity => entity.BorderColor).HasMaxLength(50); builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.RegionId, entity.IsActive, entity.SortOrder }); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.RegionId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Restrict); } } internal sealed class FaqConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("faqs"); builder.ConfigureTimestamps(); builder.Property(entity => entity.LegacyId).HasMaxLength(64); builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.RegionId, entity.IsActive, entity.SortOrder }); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.RegionId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Restrict); } } internal sealed class AnnouncementConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("announcements"); builder.ConfigureTimestamps(); builder.Property(entity => entity.LegacyId).HasMaxLength(64); builder.Property(entity => entity.Link).HasMaxLength(2048); builder.Property(entity => entity.BackgroundColor).HasMaxLength(50); builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.IsActive, entity.SortOrder }); } } internal sealed class AuditLogConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("audit_logs"); builder.Property(entity => entity.Action).HasMaxLength(200); builder.Property(entity => entity.TargetType).HasMaxLength(200); builder.Property(entity => entity.TargetId).HasMaxLength(200); builder.Property(entity => entity.Details).IsJson("{}"); builder.Property(entity => entity.IpAddress).HasMaxLength(100); builder.Property(entity => entity.UserAgent).HasMaxLength(1024); builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()"); builder.HasIndex(entity => new { entity.TenantId, entity.CreatedAt }); builder.HasIndex(entity => new { entity.TenantId, entity.TargetType, entity.TargetId, entity.CreatedAt }); builder.HasOne().WithMany().HasForeignKey(entity => entity.TenantId).OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany().HasForeignKey(entity => entity.ActorUserId).OnDelete(DeleteBehavior.SetNull); } } internal sealed class BackendPermissionConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("backend_permissions"); builder.ConfigureTimestamps(); builder.Property(entity => entity.Code).HasMaxLength(160); builder.Property(entity => entity.Name).HasMaxLength(200); builder.Property(entity => entity.Area).HasSnakeCaseEnum(); builder.Property(entity => entity.PermissionModuleCode).HasMaxLength(120); builder.Property(entity => entity.Description).HasMaxLength(1000); builder.HasIndex(entity => entity.Code).IsUnique(); builder.HasIndex(entity => new { entity.Area, entity.PermissionModuleCode, entity.SortOrder }); builder.HasOne().WithMany() .HasPrincipalKey(entity => entity.Code) .HasForeignKey(entity => entity.PermissionModuleCode) .OnDelete(DeleteBehavior.Restrict); } } internal sealed class BackendMenuConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("backend_menus"); builder.ConfigureTimestamps(); builder.Property(entity => entity.Code).HasMaxLength(160); builder.Property(entity => entity.ParentCode).HasMaxLength(160); builder.Property(entity => entity.Title).HasMaxLength(200); builder.Property(entity => entity.Area).HasSnakeCaseEnum(); builder.Property(entity => entity.Path).HasMaxLength(1024); builder.Property(entity => entity.Icon).HasMaxLength(100); builder.Property(entity => entity.PermissionCode).HasMaxLength(160); builder.HasIndex(entity => entity.Code).IsUnique(); builder.HasIndex(entity => new { entity.Area, entity.ParentCode, entity.SortOrder }); builder.HasOne().WithMany() .HasPrincipalKey(entity => entity.Code) .HasForeignKey(entity => entity.PermissionCode) .OnDelete(DeleteBehavior.SetNull); } } internal sealed class TenantBackendRoleConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("tenant_backend_roles"); builder.ConfigureTimestamps(); builder.Property(entity => entity.Code).HasMaxLength(100); builder.Property(entity => entity.Name).HasMaxLength(200); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.Description).HasMaxLength(1000); builder.Property(entity => entity.DataScope).IsJson("{}"); builder.HasIndex(entity => new { entity.TenantId, entity.Code }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.Status, entity.Code }); } } internal sealed class TenantBackendRolePermissionConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("tenant_backend_role_permissions"); builder.Property(entity => entity.PermissionCode).HasMaxLength(160); builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()"); builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id }); builder.HasIndex(entity => new { entity.TenantId, entity.RoleId, entity.PermissionCode }).IsUnique(); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.RoleId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany() .HasPrincipalKey(entity => entity.Code) .HasForeignKey(entity => entity.PermissionCode) .OnDelete(DeleteBehavior.Restrict); } } internal sealed class TenantBackendRoleMenuConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("tenant_backend_role_menus"); builder.Property(entity => entity.MenuCode).HasMaxLength(160); builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()"); builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id }); builder.HasIndex(entity => new { entity.TenantId, entity.RoleId, entity.MenuCode }).IsUnique(); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.RoleId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany() .HasPrincipalKey(entity => entity.Code) .HasForeignKey(entity => entity.MenuCode) .OnDelete(DeleteBehavior.Restrict); } } internal sealed class TenantBackendUserRoleConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("tenant_backend_user_roles"); builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()"); builder.HasAlternateKey(entity => new { entity.TenantId, entity.Id }); builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.RoleId }).IsUnique(); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.RoleId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany() .HasForeignKey(entity => entity.UserId) .OnDelete(DeleteBehavior.Cascade); } } internal sealed class PlatformBackendRoleConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("platform_backend_roles"); builder.ConfigureTimestamps(); builder.Property(entity => entity.Code).HasMaxLength(100); builder.Property(entity => entity.Name).HasMaxLength(200); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.Description).HasMaxLength(1000); builder.HasIndex(entity => entity.Code).IsUnique(); builder.HasIndex(entity => new { entity.Status, entity.Code }); } } internal sealed class PlatformBackendRolePermissionConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("platform_backend_role_permissions"); builder.Property(entity => entity.PermissionCode).HasMaxLength(160); builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()"); builder.HasIndex(entity => new { entity.RoleId, entity.PermissionCode }).IsUnique(); builder.HasOne().WithMany() .HasForeignKey(entity => entity.RoleId) .OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany() .HasPrincipalKey(entity => entity.Code) .HasForeignKey(entity => entity.PermissionCode) .OnDelete(DeleteBehavior.Restrict); } } internal sealed class PlatformBackendRoleMenuConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("platform_backend_role_menus"); builder.Property(entity => entity.MenuCode).HasMaxLength(160); builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()"); builder.HasIndex(entity => new { entity.RoleId, entity.MenuCode }).IsUnique(); builder.HasOne().WithMany() .HasForeignKey(entity => entity.RoleId) .OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany() .HasPrincipalKey(entity => entity.Code) .HasForeignKey(entity => entity.MenuCode) .OnDelete(DeleteBehavior.Restrict); } } internal sealed class PlatformBackendUserRoleConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("platform_backend_user_roles"); builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()"); builder.HasIndex(entity => new { entity.UserId, entity.RoleId }).IsUnique(); builder.HasOne().WithMany() .HasForeignKey(entity => entity.RoleId) .OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany() .HasForeignKey(entity => entity.UserId) .OnDelete(DeleteBehavior.Cascade); } } internal sealed class BackgroundJobConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("background_jobs"); builder.ConfigureTimestamps(); builder.Property(entity => entity.JobType).HasMaxLength(100); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.Payload).IsJson("{}"); builder.Property(entity => entity.LockedBy).HasMaxLength(200); builder.Property(entity => entity.LastError).HasMaxLength(4000); builder.Property(entity => entity.Result).IsJson("{}"); builder.HasIndex(entity => new { entity.TenantId, entity.Status, entity.RunAfter, entity.CreatedAt }); builder.HasIndex(entity => new { entity.TenantId, entity.JobType, entity.Status, entity.CreatedAt }); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.OutputAssetId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.SetNull); } } internal sealed class UserNotificationConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("user_notifications"); builder.ConfigureTimestamps(); builder.Property(entity => entity.NotificationType).HasMaxLength(100); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.Severity).HasSnakeCaseEnum(); builder.Property(entity => entity.Title).HasMaxLength(300); builder.Property(entity => entity.ActionLabel).HasMaxLength(100); builder.Property(entity => entity.ActionPath).HasMaxLength(2048); builder.Property(entity => entity.SourceType).HasMaxLength(100); builder.Property(entity => entity.DedupeKey).HasMaxLength(200); builder.Property(entity => entity.Metadata).IsJson("{}"); builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.NotificationType, entity.DedupeKey }) .IsUnique() .HasFilter("dedupe_key is not null"); builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.Status, entity.CreatedAt }); builder.HasIndex(entity => new { entity.TenantId, entity.SourceType, entity.SourceId }); builder.HasOne().WithMany().HasForeignKey(entity => entity.UserId).OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany().HasForeignKey(entity => entity.CreatedBy).OnDelete(DeleteBehavior.SetNull); } } internal sealed class BadgeConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("badges"); builder.ConfigureTimestamps(); builder.Property(entity => entity.LegacyId).HasMaxLength(64); builder.Property(entity => entity.Name).HasMaxLength(200); builder.Property(entity => entity.Category).HasMaxLength(100); builder.Property(entity => entity.IconUrl).HasMaxLength(2048); builder.Property(entity => entity.UnlockType).HasMaxLength(100); builder.Property(entity => entity.ConditionField).HasMaxLength(100); builder.Property(entity => entity.ConditionOperator).HasMaxLength(50); builder.Property(entity => entity.ConditionValue).HasPrecision(18, 4); builder.Property(entity => entity.ConditionExtra).IsJson("{}"); builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.Category, entity.IsActive, entity.SortOrder }); } } internal sealed class UserBadgeConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("user_badges"); builder.ConfigureTimestamps(); builder.Property(entity => entity.LegacyId).HasMaxLength(64); builder.HasIndex(entity => new { entity.TenantId, entity.LegacyId }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.BadgeId }).IsUnique(); builder.HasOne().WithMany().HasForeignKey(entity => entity.UserId).OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.BadgeId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany().HasForeignKey(entity => entity.GrantedBy).OnDelete(DeleteBehavior.SetNull); } } internal sealed class TenantContentNotificationConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("tenant_content_notifications"); builder.ConfigureTimestamps(); builder.Property(entity => entity.NotificationType).HasSnakeCaseEnum(); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.Severity).HasSnakeCaseEnum(); builder.Property(entity => entity.Title).HasMaxLength(300); builder.Property(entity => entity.ActionLabel).HasMaxLength(100); builder.Property(entity => entity.ActionPath).HasMaxLength(2048); builder.Property(entity => entity.DedupeKey).HasMaxLength(200); builder.Property(entity => entity.Metadata).IsJson("{}"); builder.HasIndex(entity => new { entity.TenantId, entity.NotificationType, entity.DedupeKey }) .IsUnique() .HasFilter("dedupe_key is not null"); builder.HasIndex(entity => new { entity.TenantId, entity.Status, entity.CreatedAt }); builder.HasIndex(entity => new { entity.TenantId, entity.AdoptionId, entity.NotificationType, entity.Status }); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.SourceQuestionBankId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Cascade); builder.HasOne().WithMany().HasForeignKey(entity => entity.CreatedBy).OnDelete(DeleteBehavior.SetNull); builder.HasOne().WithMany().HasForeignKey(entity => entity.ReadBy).OnDelete(DeleteBehavior.SetNull); } } internal sealed class TenantThemeTemplateConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureEntity("tenant_theme_templates"); builder.ConfigureTimestamps(); builder.Property(entity => entity.Code).HasMaxLength(100); builder.Property(entity => entity.Name).HasMaxLength(200); builder.Property(entity => entity.PreviewImageUrl).HasMaxLength(2048); builder.Property(entity => entity.Theme).IsJson("{}"); builder.Property(entity => entity.PublicAssets).IsJson("{}"); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.HasAlternateKey(entity => entity.Code); builder.HasIndex(entity => entity.Code).IsUnique(); builder.HasIndex(entity => new { entity.Status, entity.SortOrder, entity.Code }); } } internal sealed class TenantThemeConfigConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("tenant_theme_configs"); builder.ConfigureTimestamps(); builder.Property(entity => entity.ActiveTemplateCode).HasMaxLength(100); builder.Property(entity => entity.ActiveTheme).IsJson("{}"); builder.Property(entity => entity.ActivePublicAssets).IsJson("{}"); builder.Property(entity => entity.DraftTemplateCode).HasMaxLength(100); builder.Property(entity => entity.DraftTheme).IsJson("{}"); builder.Property(entity => entity.DraftPublicAssets).IsJson("{}"); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.HasIndex(entity => entity.TenantId).IsUnique(); builder.HasOne().WithMany() .HasForeignKey(entity => entity.ActiveTemplateCode) .HasPrincipalKey(entity => entity.Code) .OnDelete(DeleteBehavior.SetNull); builder.HasOne().WithMany() .HasForeignKey(entity => entity.DraftTemplateCode) .HasPrincipalKey(entity => entity.Code) .OnDelete(DeleteBehavior.SetNull); builder.HasOne().WithMany().HasForeignKey(entity => entity.PublishedBy).OnDelete(DeleteBehavior.SetNull); builder.HasOne().WithMany().HasForeignKey(entity => entity.DraftUpdatedBy).OnDelete(DeleteBehavior.SetNull); } }