using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Tiku.Domain.Catalog; using Tiku.Domain.Commerce; using Tiku.Domain.Identity; namespace Tiku.Infrastructure.Persistence.Configurations; internal sealed class PointActivityTaskConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("point_activity_tasks"); builder.ConfigureTimestamps(); builder.Property(entity => entity.TaskKey).HasColumnType("citext").HasMaxLength(100); builder.Property(entity => entity.Title).HasMaxLength(200); builder.Property(entity => entity.Description).HasMaxLength(1000); builder.Property(entity => entity.TaskType).HasSnakeCaseEnum(); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.Rules).IsJson("{}"); builder.Property(entity => entity.Metadata).IsJson("{}"); builder.HasIndex(entity => new { entity.TenantId, entity.TaskKey }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.Status, entity.SortOrder }); builder.ToTable(table => { table.HasCheckConstraint("ck_point_activity_tasks_points", "points > 0"); table.HasCheckConstraint("ck_point_activity_tasks_max_claims", "max_claims_per_user > 0"); }); } } internal sealed class PointActivityClaimConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("point_activity_claims"); builder.ConfigureTimestamps(); builder.Property(entity => entity.TaskKey).HasColumnType("citext").HasMaxLength(100); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.SourceType).HasMaxLength(100); builder.Property(entity => entity.Metadata).IsJson("{}"); builder.Property(entity => entity.ClaimedAt).HasDefaultValueSql("now()"); builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.TaskId, entity.SourceType, entity.SourceId }) .IsUnique() .HasFilter("source_type is not null and source_id is not null"); builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.CreatedAt }); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.TaskId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Restrict); builder.HasOne().WithMany().HasForeignKey(entity => entity.UserId).OnDelete(DeleteBehavior.Cascade); builder.ToTable(table => { table.HasCheckConstraint("ck_point_activity_claims_points", "points > 0"); }); } } internal sealed class PointExchangeItemConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("point_exchange_items"); builder.ConfigureTimestamps(); builder.Property(entity => entity.ItemKey).HasColumnType("citext").HasMaxLength(100); builder.Property(entity => entity.Name).HasMaxLength(200); builder.Property(entity => entity.Description).HasMaxLength(1000); builder.Property(entity => entity.ItemType).HasSnakeCaseEnum(); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.FulfillmentPayload).IsJson("{}"); builder.Property(entity => entity.Metadata).IsJson("{}"); builder.HasIndex(entity => new { entity.TenantId, entity.ItemKey }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.RegionId, entity.Status, entity.SortOrder }); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.RegionId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Restrict); builder.ToTable(table => { table.HasCheckConstraint("ck_point_exchange_items_points_cost", "points_cost > 0"); table.HasCheckConstraint("ck_point_exchange_items_stock", "stock is null or stock >= 0"); table.HasCheckConstraint("ck_point_exchange_items_days", "days is null or days >= 0"); }); } } internal sealed class PointExchangeOrderConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ConfigureTenantEntity("point_exchange_orders"); builder.ConfigureTimestamps(); builder.Property(entity => entity.OrderNo).HasMaxLength(100); builder.Property(entity => entity.ItemName).HasMaxLength(200); builder.Property(entity => entity.ItemType).HasSnakeCaseEnum(); builder.Property(entity => entity.Status).HasSnakeCaseEnum(); builder.Property(entity => entity.FulfillmentSnapshot).IsJson("{}"); builder.Property(entity => entity.Metadata).IsJson("{}"); builder.Property(entity => entity.OrderedAt).HasDefaultValueSql("now()"); builder.HasIndex(entity => new { entity.TenantId, entity.OrderNo }).IsUnique(); builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.CreatedAt }); builder.HasOne().WithMany() .HasForeignKey(entity => new { entity.TenantId, entity.ItemId }) .HasPrincipalKey(entity => new { entity.TenantId, entity.Id }) .OnDelete(DeleteBehavior.Restrict); builder.HasOne().WithMany().HasForeignKey(entity => entity.UserId).OnDelete(DeleteBehavior.Cascade); builder.ToTable(table => { table.HasCheckConstraint("ck_point_exchange_orders_points_cost", "points_cost > 0"); }); } }