160 lines
8.1 KiB
C#
160 lines
8.1 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
|
using Tiku.Domain.Content;
|
|
|
|
namespace Tiku.Infrastructure.Persistence.Configurations;
|
|
|
|
internal sealed class QuestionAssetConfiguration : IEntityTypeConfiguration<QuestionAsset>
|
|
{
|
|
public void Configure(EntityTypeBuilder<QuestionAsset> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("question_assets");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(entity => entity.DeliveryFingerprint).HasMaxLength(64);
|
|
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.DeliveryFingerprint }).IsUnique();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.FamilyId });
|
|
builder.HasOne<QuestionFamily>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.FamilyId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<QuestionRevision>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, QuestionAssetId = entity.Id, Id = entity.CurrentRevisionId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.QuestionAssetId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class QuestionRevisionConfiguration : IEntityTypeConfiguration<QuestionRevision>
|
|
{
|
|
public void Configure(EntityTypeBuilder<QuestionRevision> builder)
|
|
{
|
|
builder.ConfigureTenantOwned("question_revisions");
|
|
builder.HasAlternateKey(entity => new { entity.TenantId, entity.QuestionAssetId, entity.Id });
|
|
builder.Property(entity => entity.QuestionType).HasMaxLength(50);
|
|
builder.Property(entity => entity.TypeLabel).HasMaxLength(100);
|
|
builder.Property(entity => entity.NormalizedContent).HasColumnType("text");
|
|
builder.Property(entity => entity.Options).IsJson("[]");
|
|
builder.Property(entity => entity.CorrectOptionIndices).IsJson("[]");
|
|
builder.Property(entity => entity.SubQuestions).IsJson("[]");
|
|
builder.Property(entity => entity.CodeLang).HasMaxLength(50);
|
|
builder.Property(entity => entity.DeliveryFingerprint).HasMaxLength(64);
|
|
builder.Property(entity => entity.CreatedAt).HasDefaultValueSql("now()");
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.QuestionAssetId, entity.RevisionNo }).IsUnique();
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.DeliveryFingerprint });
|
|
builder.HasIndex(entity => entity.NormalizedContent).HasMethod("gin")
|
|
.HasOperators("gin_trgm_ops")
|
|
.HasDatabaseName("ix_question_revisions_content_trgm");
|
|
builder.HasOne<QuestionAsset>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.QuestionAssetId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
}
|
|
}
|
|
|
|
internal sealed class QuestionFamilyConfiguration : IEntityTypeConfiguration<QuestionFamily>
|
|
{
|
|
public void Configure(EntityTypeBuilder<QuestionFamily> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("question_families");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(entity => entity.Name).HasMaxLength(300);
|
|
builder.Property(entity => entity.Description).HasMaxLength(2000);
|
|
}
|
|
}
|
|
|
|
internal sealed class QuestionPlacementConfiguration : IEntityTypeConfiguration<QuestionPlacement>
|
|
{
|
|
public void Configure(EntityTypeBuilder<QuestionPlacement> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("question_placements");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(entity => entity.Status).HasSnakeCaseEnum();
|
|
builder.HasIndex(entity => new
|
|
{
|
|
entity.TenantId,
|
|
entity.QuestionAssetOwnerTenantId,
|
|
entity.QuestionAssetId,
|
|
entity.CurriculumVersionId,
|
|
entity.CurriculumNodeId,
|
|
entity.AssessmentPolicyVersionId
|
|
}).IsUnique();
|
|
builder.HasOne<QuestionAsset>().WithMany()
|
|
.HasForeignKey(entity => new { TenantId = entity.QuestionAssetOwnerTenantId, Id = entity.QuestionAssetId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.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);
|
|
builder.HasOne<CurriculumNode>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.CurriculumNodeId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, 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);
|
|
builder.ToTable(table => table.HasCheckConstraint(
|
|
"ck_question_placements_valid_period", "valid_to is null or valid_from is null or valid_to > valid_from"));
|
|
}
|
|
}
|
|
|
|
internal sealed class QuestionPlacementConceptConfiguration : IEntityTypeConfiguration<QuestionPlacementConcept>
|
|
{
|
|
public void Configure(EntityTypeBuilder<QuestionPlacementConcept> builder)
|
|
{
|
|
builder.ConfigureTenantOwned("question_placement_concepts");
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.PlacementId, entity.KnowledgeConceptId }).IsUnique();
|
|
builder.HasOne<QuestionPlacement>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.PlacementId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<KnowledgeConcept>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.KnowledgeConceptId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class QuestionPlacementRuleGroupConfiguration : IEntityTypeConfiguration<QuestionPlacementRuleGroup>
|
|
{
|
|
public void Configure(EntityTypeBuilder<QuestionPlacementRuleGroup> builder)
|
|
{
|
|
builder.ConfigureTenantOwned("question_placement_rule_groups");
|
|
builder.HasIndex(entity => new { entity.TenantId, entity.PlacementId, entity.GroupOrder }).IsUnique();
|
|
builder.HasOne<QuestionPlacement>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.PlacementId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
}
|
|
}
|
|
|
|
internal sealed class QuestionPlacementRuleConditionConfiguration :
|
|
IEntityTypeConfiguration<QuestionPlacementRuleCondition>
|
|
{
|
|
public void Configure(EntityTypeBuilder<QuestionPlacementRuleCondition> builder)
|
|
{
|
|
builder.ConfigureTenantOwned("question_placement_rule_conditions");
|
|
builder.Property(entity => entity.Operator).HasSnakeCaseEnum();
|
|
builder.HasIndex(entity => new
|
|
{
|
|
entity.TenantId,
|
|
entity.RuleGroupId,
|
|
entity.TargetDimensionDefinitionId,
|
|
entity.TargetNodeId,
|
|
entity.Operator
|
|
}).IsUnique();
|
|
builder.HasOne<QuestionPlacementRuleGroup>().WithMany()
|
|
.HasForeignKey(entity => new { entity.TenantId, Id = entity.RuleGroupId })
|
|
.HasPrincipalKey(entity => new { entity.TenantId, entity.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<TargetDimensionDefinition>().WithMany()
|
|
.HasForeignKey(entity => entity.TargetDimensionDefinitionId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<TargetNode>().WithMany()
|
|
.HasForeignKey(entity => entity.TargetNodeId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|