239 lines
12 KiB
C#
239 lines
12 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
|
using Tiku.Domain.Content;
|
|
using Tiku.Domain.Learning;
|
|
|
|
namespace Tiku.Infrastructure.Persistence.Configurations;
|
|
|
|
internal sealed class ContentReleaseConfiguration : IEntityTypeConfiguration<ContentRelease>
|
|
{
|
|
public void Configure(EntityTypeBuilder<ContentRelease> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("content_releases");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(entity => entity.Name).HasMaxLength(300);
|
|
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
|
|
builder.Property(entity => entity.CompilerVersion).HasMaxLength(100);
|
|
builder.Property(entity => entity.SourceFingerprint).HasMaxLength(64);
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.CurriculumVersionId, entity.ReleaseNo }).IsUnique();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.BusinessLineId, entity.Status, entity.PublishedAt });
|
|
builder.HasOne<BusinessLine>().WithMany().HasForeignKey(entity => entity.BusinessLineId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<CurriculumVersion>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.CurriculumVersionId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class AudienceSegmentConfiguration : IEntityTypeConfiguration<AudienceSegment>
|
|
{
|
|
public void Configure(EntityTypeBuilder<AudienceSegment> builder)
|
|
{
|
|
builder.ConfigureTenantOwned("audience_segments");
|
|
builder.Property(entity => entity.RuleHash).HasMaxLength(64);
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.ContentReleaseId, entity.RuleHash }).IsUnique();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.ContentReleaseId, entity.SegmentOrdinal }).IsUnique();
|
|
builder.HasOne<ContentRelease>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.ContentReleaseId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
}
|
|
}
|
|
|
|
internal sealed class AudienceSegmentMemberConfiguration : IEntityTypeConfiguration<AudienceSegmentMember>
|
|
{
|
|
public void Configure(EntityTypeBuilder<AudienceSegmentMember> builder)
|
|
{
|
|
builder.ConfigureTenantOwned("audience_segment_members");
|
|
builder.HasIndex(entity => new
|
|
{
|
|
entity.TenantId,
|
|
entity.ContentReleaseId,
|
|
entity.AudienceSegmentId,
|
|
entity.ExamTargetProfileVersionId
|
|
}).IsUnique();
|
|
builder.HasIndex(entity => new
|
|
{
|
|
entity.TenantId,
|
|
entity.ContentReleaseId,
|
|
entity.ExamTargetProfileVersionId,
|
|
entity.AudienceSegmentId
|
|
});
|
|
builder.HasOne<AudienceSegment>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.AudienceSegmentId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<ExamTargetProfileVersion>().WithMany()
|
|
.HasForeignKey(entity => entity.ExamTargetProfileVersionId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class ContentReleaseQuestionConfiguration : IEntityTypeConfiguration<ContentReleaseQuestion>
|
|
{
|
|
public void Configure(EntityTypeBuilder<ContentReleaseQuestion> builder)
|
|
{
|
|
builder.ConfigureTenantOwned("content_release_questions");
|
|
builder.Property(entity => entity.QuestionType).HasMaxLength(50);
|
|
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
|
|
builder.HasIndex(entity => new
|
|
{
|
|
entity.TenantId,
|
|
entity.ContentReleaseId,
|
|
entity.AudienceSegmentId,
|
|
entity.CurriculumNodeId,
|
|
entity.Ordinal
|
|
}).IsUnique();
|
|
builder.HasIndex(entity => new
|
|
{
|
|
entity.TenantId,
|
|
entity.ContentReleaseId,
|
|
entity.AudienceSegmentId,
|
|
entity.CurriculumNodeId,
|
|
entity.Status,
|
|
entity.Difficulty,
|
|
entity.QuestionType,
|
|
entity.Ordinal
|
|
}).HasDatabaseName("ix_content_release_question_candidates");
|
|
builder.HasOne<ContentRelease>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.ContentReleaseId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<AudienceSegment>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.AudienceSegmentId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<QuestionPlacement>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.QuestionPlacementId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<QuestionRevision>().WithMany()
|
|
.HasForeignKey(entity => new
|
|
{
|
|
TenantId = entity.QuestionAssetOwnerTenantId,
|
|
entity.QuestionAssetId,
|
|
Id = entity.QuestionRevisionId
|
|
})
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.QuestionAssetId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<AssessmentPolicyVersion>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.AssessmentPolicyVersionId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class CollectionReleaseConfiguration : IEntityTypeConfiguration<CollectionRelease>
|
|
{
|
|
public void Configure(EntityTypeBuilder<CollectionRelease> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("collection_releases");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(entity => entity.Name).HasMaxLength(300);
|
|
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.SourceCollectionId, entity.VersionNo }).IsUnique();
|
|
builder.HasOne<ContentRelease>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.ContentReleaseId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class CollectionReleaseQuestionConfiguration : IEntityTypeConfiguration<CollectionReleaseQuestion>
|
|
{
|
|
public void Configure(EntityTypeBuilder<CollectionReleaseQuestion> builder)
|
|
{
|
|
builder.ConfigureTenantOwned("collection_release_questions");
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.CollectionReleaseId, entity.SortOrder })
|
|
.HasDatabaseName("ux_collection_release_question_order")
|
|
.IsUnique();
|
|
builder.HasIndex(entity => new
|
|
{
|
|
entity.TenantId,
|
|
entity.CollectionReleaseId,
|
|
entity.ContentReleaseQuestionId
|
|
}).HasDatabaseName("ux_collection_release_question_item").IsUnique();
|
|
builder.HasOne<CollectionRelease>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.CollectionReleaseId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<ContentReleaseQuestion>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.ContentReleaseQuestionId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class BlueprintReleaseConfiguration : IEntityTypeConfiguration<BlueprintRelease>
|
|
{
|
|
public void Configure(EntityTypeBuilder<BlueprintRelease> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("blueprint_releases");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(entity => entity.Name).HasMaxLength(300);
|
|
builder.Property(entity => entity.AssemblyRules).IsJson("{}");
|
|
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.SourceBlueprintId, entity.VersionNo }).IsUnique();
|
|
builder.HasOne<ContentRelease>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.ContentReleaseId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<CollectionRelease>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.CollectionReleaseId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<ExamPaperSpecificationVersion>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.ExamPaperSpecificationVersionId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformContentPackageVersionConfiguration :
|
|
IEntityTypeConfiguration<PlatformContentPackageVersion>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformContentPackageVersion> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("platform_content_package_versions");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(entity => entity.PackageCode).HasMaxLength(100);
|
|
builder.Property(entity => entity.ContentHash).HasMaxLength(64);
|
|
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.PackageCode, entity.VersionNo }).IsUnique();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.ContentHash }).IsUnique();
|
|
builder.HasOne<ContentRelease>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.ContentReleaseId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformContentPackageCellProjectionConfiguration :
|
|
IEntityTypeConfiguration<PlatformContentPackageCellProjection>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformContentPackageCellProjection> builder)
|
|
{
|
|
builder.ConfigureEntity("platform_content_package_cell_projections");
|
|
builder.Property(entity => entity.PackageCode).HasMaxLength(100);
|
|
builder.Property(entity => entity.CellId).HasMaxLength(100);
|
|
builder.Property(entity => entity.ContentHash).HasMaxLength(64);
|
|
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
|
|
builder.Property(entity => entity.LastError).HasMaxLength(2000);
|
|
builder.HasIndex(entity => new { entity.PackageOwnerTenantId, entity.PackageCode, entity.CellId })
|
|
.HasDatabaseName("ux_platform_package_cell_cursor").IsUnique();
|
|
builder.HasIndex(entity => new { entity.PlatformContentPackageVersionId, entity.CellId })
|
|
.HasDatabaseName("ix_platform_package_cell_version");
|
|
builder.HasIndex(entity => new { entity.PackageOwnerTenantId, entity.PlatformContentPackageVersionId })
|
|
.HasDatabaseName("ix_platform_package_cell_owner_version");
|
|
builder.HasOne<PlatformContentPackageVersion>().WithMany()
|
|
.HasForeignKey(entity => new
|
|
{
|
|
TenantId = entity.PackageOwnerTenantId,
|
|
Id = entity.PlatformContentPackageVersionId
|
|
})
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
}
|
|
}
|