389 lines
22 KiB
C#
389 lines
22 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
|
using Tiku.Domain.Platform;
|
|
using Tiku.Domain.Tenancy;
|
|
|
|
namespace Tiku.Infrastructure.Persistence.Configurations;
|
|
|
|
internal sealed class SaasFeatureConfiguration : IEntityTypeConfiguration<SaasFeature>
|
|
{
|
|
public void Configure(EntityTypeBuilder<SaasFeature> builder)
|
|
{
|
|
builder.ConfigureEntity("saas_features");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.Code).HasMaxLength(120);
|
|
builder.Property(value => value.Name).HasMaxLength(200);
|
|
builder.Property(value => value.Category).HasMaxLength(100);
|
|
builder.Property(value => value.Description).HasMaxLength(1000);
|
|
builder.Property(value => value.Currency).HasMaxLength(10);
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.HasIndex(value => value.Code).IsUnique();
|
|
builder.HasIndex(value => new { value.Status, value.Category, value.SortOrder });
|
|
builder.ToTable(table =>
|
|
table.HasCheckConstraint("ck_saas_features_reference_price", "reference_price_cents >= 0"));
|
|
}
|
|
}
|
|
|
|
internal sealed class PermissionModuleConfiguration : IEntityTypeConfiguration<PermissionModule>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PermissionModule> builder)
|
|
{
|
|
builder.ConfigureEntity("permission_modules");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.Code).HasMaxLength(120);
|
|
builder.Property(value => value.Name).HasMaxLength(200);
|
|
builder.Property(value => value.Area).HasSnakeCaseEnum();
|
|
builder.Property(value => value.RequiredFeatureCode).HasMaxLength(120);
|
|
builder.Property(value => value.Description).HasMaxLength(1000);
|
|
builder.HasIndex(value => value.Code).IsUnique();
|
|
builder.HasIndex(value => new { value.Area, value.SortOrder });
|
|
builder.HasOne<SaasFeature>().WithMany()
|
|
.HasPrincipalKey(value => value.Code)
|
|
.HasForeignKey(value => value.RequiredFeatureCode)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class SaasOfferingConfiguration : IEntityTypeConfiguration<SaasOffering>
|
|
{
|
|
public void Configure(EntityTypeBuilder<SaasOffering> builder)
|
|
{
|
|
builder.ConfigureEntity("saas_offerings");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.Code).HasMaxLength(120);
|
|
builder.Property(value => value.Name).HasMaxLength(200);
|
|
builder.Property(value => value.Type).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Description).HasMaxLength(1000);
|
|
builder.HasIndex(value => value.Code).IsUnique();
|
|
builder.HasIndex(value => new { value.Type, value.Status, value.SortOrder });
|
|
}
|
|
}
|
|
|
|
internal sealed class SaasOfferingVersionConfiguration : IEntityTypeConfiguration<SaasOfferingVersion>
|
|
{
|
|
public void Configure(EntityTypeBuilder<SaasOfferingVersion> builder)
|
|
{
|
|
builder.ConfigureEntity("saas_offering_versions");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.Property(value => value.BillingCycle).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Currency).HasMaxLength(10);
|
|
builder.Property(value => value.Metadata).IsJson("{}");
|
|
builder.HasIndex(value => new { value.OfferingId, value.Version }).IsUnique();
|
|
builder.HasIndex(value => new { value.OfferingId, value.Status, value.EffectiveAt });
|
|
builder.HasOne<SaasOffering>().WithMany().HasForeignKey(value => value.OfferingId)
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.ToTable(table =>
|
|
{
|
|
table.HasCheckConstraint("ck_saas_offering_versions_version", "version > 0");
|
|
table.HasCheckConstraint("ck_saas_offering_versions_amount",
|
|
"original_amount_cents >= 0 and amount_cents >= 0 and amount_cents <= original_amount_cents");
|
|
});
|
|
}
|
|
}
|
|
|
|
internal sealed class SaasOfferingVersionFeatureConfiguration : IEntityTypeConfiguration<SaasOfferingVersionFeature>
|
|
{
|
|
public void Configure(EntityTypeBuilder<SaasOfferingVersionFeature> builder)
|
|
{
|
|
builder.ConfigureEntity("saas_offering_version_features");
|
|
builder.Property(value => value.FeatureCode).HasMaxLength(120);
|
|
builder.HasIndex(value => new { value.OfferingVersionId, value.FeatureCode }).IsUnique();
|
|
builder.HasOne<SaasOfferingVersion>().WithMany().HasForeignKey(value => value.OfferingVersionId)
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<SaasFeature>().WithMany().HasPrincipalKey(value => value.Code)
|
|
.HasForeignKey(value => value.FeatureCode).OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class SaasFeatureLimitDefinitionConfiguration : IEntityTypeConfiguration<SaasFeatureLimitDefinition>
|
|
{
|
|
public void Configure(EntityTypeBuilder<SaasFeatureLimitDefinition> builder)
|
|
{
|
|
builder.ConfigureEntity("saas_feature_limit_definitions");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.MetricCode).HasMaxLength(120);
|
|
builder.Property(value => value.FeatureCode).HasMaxLength(120);
|
|
builder.Property(value => value.Name).HasMaxLength(200);
|
|
builder.Property(value => value.Unit).HasMaxLength(50);
|
|
builder.Property(value => value.Kind).HasSnakeCaseEnum();
|
|
builder.HasIndex(value => value.MetricCode).IsUnique();
|
|
builder.HasIndex(value => new { value.FeatureCode, value.Kind });
|
|
builder.HasOne<SaasFeature>().WithMany().HasPrincipalKey(value => value.Code)
|
|
.HasForeignKey(value => value.FeatureCode).OnDelete(DeleteBehavior.Cascade);
|
|
builder.ToTable(table =>
|
|
table.HasCheckConstraint("ck_saas_feature_limit_warning", "warning_percent between 1 and 100"));
|
|
}
|
|
}
|
|
|
|
internal sealed class SaasOfferingVersionLimitConfiguration : IEntityTypeConfiguration<SaasOfferingVersionLimit>
|
|
{
|
|
public void Configure(EntityTypeBuilder<SaasOfferingVersionLimit> builder)
|
|
{
|
|
builder.ConfigureEntity("saas_offering_version_limits");
|
|
builder.Property(value => value.MetricCode).HasMaxLength(120);
|
|
builder.HasIndex(value => new { value.OfferingVersionId, value.MetricCode }).IsUnique();
|
|
builder.HasOne<SaasOfferingVersion>().WithMany().HasForeignKey(value => value.OfferingVersionId)
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<SaasFeatureLimitDefinition>().WithMany().HasPrincipalKey(value => value.MetricCode)
|
|
.HasForeignKey(value => value.MetricCode).OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table => table.HasCheckConstraint("ck_saas_offering_version_limits_value", "limit_value >= 0"));
|
|
}
|
|
}
|
|
|
|
internal sealed class TenantSaasSubscriptionConfiguration : IEntityTypeConfiguration<TenantSaasSubscription>
|
|
{
|
|
public void Configure(EntityTypeBuilder<TenantSaasSubscription> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("tenant_saas_subscriptions");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.Property(value => value.LifecycleVersion).IsConcurrencyToken();
|
|
builder.Property(value => value.Metadata).IsJson("{}");
|
|
builder.HasIndex(value => new { value.TenantId, value.Status, value.CurrentPeriodEnd });
|
|
builder.HasIndex(value => value.TenantId).IsUnique()
|
|
.HasFilter("status in ('trial', 'active', 'past_due', 'suspended')");
|
|
builder.HasOne<SaasOfferingVersion>().WithMany().HasForeignKey(value => value.BaseOfferingVersionId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<SaasOfferingVersion>().WithMany().HasForeignKey(value => value.ScheduledBaseOfferingVersionId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table => table.HasCheckConstraint("ck_tenant_saas_subscriptions_period",
|
|
"current_period_end > current_period_start and current_period_start >= starts_at"));
|
|
}
|
|
}
|
|
|
|
internal sealed class TenantSaasSubscriptionItemConfiguration : IEntityTypeConfiguration<TenantSaasSubscriptionItem>
|
|
{
|
|
public void Configure(EntityTypeBuilder<TenantSaasSubscriptionItem> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("tenant_saas_subscription_items");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.ItemType).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.HasIndex(value => new { value.TenantId, value.SubscriptionId, value.OfferingVersionId, value.Status });
|
|
builder.HasIndex(value => new { value.TenantId, value.SubscriptionId, value.ItemType })
|
|
.HasDatabaseName("ux_tenant_saas_subscription_items_current_base")
|
|
.IsUnique()
|
|
.HasFilter("item_type = 'base_plan' and status = 'active'");
|
|
builder.HasIndex(value => new { value.TenantId, value.SubscriptionId, value.Status })
|
|
.HasDatabaseName("ux_tenant_saas_subscription_items_scheduled_base")
|
|
.IsUnique()
|
|
.HasFilter("item_type = 'base_plan' and status = 'scheduled'");
|
|
builder.HasOne<TenantSaasSubscription>().WithMany()
|
|
.HasForeignKey(value => new { value.TenantId, value.SubscriptionId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id })
|
|
.OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<SaasOfferingVersion>().WithMany().HasForeignKey(value => value.OfferingVersionId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<PlatformBillingOrderItem>().WithMany()
|
|
.HasForeignKey(value => new { value.TenantId, value.SourceOrderItemId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id })
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table =>
|
|
table.HasCheckConstraint("ck_tenant_saas_subscription_items_period", "ends_at > starts_at"));
|
|
}
|
|
}
|
|
|
|
internal sealed class TenantFeatureOverrideConfiguration : IEntityTypeConfiguration<TenantFeatureOverride>
|
|
{
|
|
public void Configure(EntityTypeBuilder<TenantFeatureOverride> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("tenant_feature_overrides");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.FeatureCode).HasMaxLength(120);
|
|
builder.Property(value => value.Mode).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Reason).HasMaxLength(1000);
|
|
builder.HasIndex(value => new { value.TenantId, value.FeatureCode }).IsUnique();
|
|
builder.HasOne<SaasFeature>().WithMany().HasPrincipalKey(value => value.Code)
|
|
.HasForeignKey(value => value.FeatureCode).OnDelete(DeleteBehavior.Restrict);
|
|
}
|
|
}
|
|
|
|
internal sealed class TenantFeatureUsageConfiguration : IEntityTypeConfiguration<TenantFeatureUsage>
|
|
{
|
|
public void Configure(EntityTypeBuilder<TenantFeatureUsage> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("tenant_feature_usage");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.MetricCode).HasMaxLength(120);
|
|
builder.Property(value => value.Version).IsConcurrencyToken();
|
|
builder.HasIndex(value => new { value.TenantId, value.MetricCode, value.PeriodStart, value.PeriodEnd })
|
|
.IsUnique();
|
|
builder.HasOne<SaasFeatureLimitDefinition>().WithMany().HasPrincipalKey(value => value.MetricCode)
|
|
.HasForeignKey(value => value.MetricCode).OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table =>
|
|
{
|
|
table.HasCheckConstraint("ck_tenant_feature_usage_values", "used_value >= 0 and limit_value_snapshot >= 0");
|
|
table.HasCheckConstraint("ck_tenant_feature_usage_period", "period_end > period_start");
|
|
});
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformBillingQuoteConfiguration : IEntityTypeConfiguration<PlatformBillingQuote>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformBillingQuote> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("platform_billing_quotes");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.QuoteNo).HasMaxLength(100);
|
|
builder.Property(value => value.IdempotencyKey).HasMaxLength(200);
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Purpose).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Currency).HasMaxLength(10);
|
|
builder.Property(value => value.FeatureSnapshot).IsJson("[]");
|
|
builder.Property(value => value.LimitSnapshot).IsJson("{}");
|
|
builder.HasIndex(value => new { value.TenantId, value.QuoteNo }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.IdempotencyKey }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.Status, value.ExpiresAt });
|
|
builder.ToTable(table => table.HasCheckConstraint("ck_platform_billing_quotes_amounts",
|
|
"original_amount_cents >= 0 and discount_amount_cents >= 0 and total_amount_cents >= 0 and total_amount_cents = original_amount_cents - discount_amount_cents"));
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformBillingQuoteItemConfiguration : IEntityTypeConfiguration<PlatformBillingQuoteItem>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformBillingQuoteItem> builder)
|
|
{
|
|
builder.ConfigureEntity("platform_billing_quote_items");
|
|
builder.HasAlternateKey(value => new { value.TenantId, value.Id });
|
|
builder.Property(value => value.ItemType).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Snapshot).IsJson("{}");
|
|
builder.HasIndex(value => new { value.TenantId, value.QuoteId, value.OfferingVersionId }).IsUnique();
|
|
builder.HasOne<Tenant>().WithMany().HasForeignKey(value => value.TenantId).OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<PlatformBillingQuote>().WithMany().HasForeignKey(value => new { value.TenantId, value.QuoteId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id }).OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<SaasOfferingVersion>().WithMany().HasForeignKey(value => value.OfferingVersionId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table => table.HasCheckConstraint("ck_platform_billing_quote_items_amounts",
|
|
"quantity > 0 and unit_amount_cents >= 0 and amount_cents >= 0"));
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformBillingOrderConfiguration : IEntityTypeConfiguration<PlatformBillingOrder>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformBillingOrder> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("platform_billing_orders");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.OrderNo).HasMaxLength(100);
|
|
builder.Property(value => value.IdempotencyKey).HasMaxLength(200);
|
|
builder.Property(value => value.Purpose).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Currency).HasMaxLength(10);
|
|
builder.Property(value => value.Snapshot).IsJson("{}");
|
|
builder.HasIndex(value => new { value.TenantId, value.OrderNo }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.IdempotencyKey }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.Status, value.CreatedAt });
|
|
builder.HasOne<PlatformBillingQuote>().WithMany().HasForeignKey(value => new { value.TenantId, value.QuoteId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id }).OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table => table.HasCheckConstraint("ck_platform_billing_orders_amounts",
|
|
"original_amount_cents >= 0 and discount_amount_cents >= 0 and total_amount_cents >= 0 and total_amount_cents = original_amount_cents - discount_amount_cents"));
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformBillingOrderItemConfiguration : IEntityTypeConfiguration<PlatformBillingOrderItem>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformBillingOrderItem> builder)
|
|
{
|
|
builder.ConfigureEntity("platform_billing_order_items");
|
|
builder.HasAlternateKey(value => new { value.TenantId, value.Id });
|
|
builder.Property(value => value.ItemType).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Snapshot).IsJson("{}");
|
|
builder.HasIndex(value => new { value.TenantId, value.OrderId, value.OfferingVersionId }).IsUnique();
|
|
builder.HasOne<Tenant>().WithMany().HasForeignKey(value => value.TenantId).OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<PlatformBillingOrder>().WithMany().HasForeignKey(value => new { value.TenantId, value.OrderId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id }).OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<SaasOfferingVersion>().WithMany().HasForeignKey(value => value.OfferingVersionId)
|
|
.OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table => table.HasCheckConstraint("ck_platform_billing_order_items_amounts",
|
|
"quantity > 0 and unit_amount_cents >= 0 and amount_cents >= 0"));
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformBillingPaymentConfiguration : IEntityTypeConfiguration<PlatformBillingPayment>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformBillingPayment> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("platform_billing_payments");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.PaymentNo).HasMaxLength(100);
|
|
builder.Property(value => value.IdempotencyKey).HasMaxLength(200);
|
|
builder.Property(value => value.Provider).HasMaxLength(50);
|
|
builder.Property(value => value.Method).HasMaxLength(50);
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.Property(value => value.ProviderTradeNo).HasMaxLength(200);
|
|
builder.Property(value => value.ClientPayload).IsJson("{}");
|
|
builder.HasIndex(value => new { value.TenantId, value.PaymentNo }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.IdempotencyKey }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.OrderId, value.Status });
|
|
builder.HasOne<PlatformBillingOrder>().WithMany().HasForeignKey(value => new { value.TenantId, value.OrderId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id }).OnDelete(DeleteBehavior.Cascade);
|
|
builder.ToTable(table => table.HasCheckConstraint("ck_platform_billing_payments_amount", "amount_cents >= 0"));
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformBillingPaymentEventConfiguration : IEntityTypeConfiguration<PlatformBillingPaymentEvent>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformBillingPaymentEvent> builder)
|
|
{
|
|
builder.ConfigureEntity("platform_billing_payment_events");
|
|
builder.HasAlternateKey(value => new { value.TenantId, value.Id });
|
|
builder.Property(value => value.Provider).HasMaxLength(50);
|
|
builder.Property(value => value.ProviderEventId).HasMaxLength(200);
|
|
builder.Property(value => value.EventType).HasMaxLength(100);
|
|
builder.Property(value => value.Payload).IsJson("{}");
|
|
builder.Property(value => value.CreatedAt).HasDefaultValueSql("now()");
|
|
builder.HasIndex(value => new { value.TenantId, value.Provider, value.ProviderEventId }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.PaymentId, value.CreatedAt });
|
|
builder.HasOne<Tenant>().WithMany().HasForeignKey(value => value.TenantId).OnDelete(DeleteBehavior.Cascade);
|
|
builder.HasOne<PlatformBillingPayment>().WithMany()
|
|
.HasForeignKey(value => new { value.TenantId, value.PaymentId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id }).OnDelete(DeleteBehavior.Cascade);
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformBillingRefundConfiguration : IEntityTypeConfiguration<PlatformBillingRefund>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformBillingRefund> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("platform_billing_refunds");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.RefundNo).HasMaxLength(100);
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Reason).HasMaxLength(1000);
|
|
builder.Property(value => value.ProviderRefundNo).HasMaxLength(200);
|
|
builder.Property(value => value.IdempotencyKey).HasMaxLength(200);
|
|
builder.Property(value => value.SubscriptionEffect).HasSnakeCaseEnum();
|
|
builder.Property(value => value.ReviewReason).HasMaxLength(1000);
|
|
builder.Property(value => value.LastError).HasMaxLength(2000);
|
|
builder.HasIndex(value => new { value.TenantId, value.RefundNo }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.IdempotencyKey }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.OrderId, value.Status });
|
|
builder.HasOne<PlatformBillingOrder>().WithMany().HasForeignKey(value => new { value.TenantId, value.OrderId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id }).OnDelete(DeleteBehavior.Restrict);
|
|
builder.HasOne<PlatformBillingPayment>().WithMany()
|
|
.HasForeignKey(value => new { value.TenantId, value.PaymentId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id }).OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table => table.HasCheckConstraint("ck_platform_billing_refunds_amount", "amount_cents > 0"));
|
|
}
|
|
}
|
|
|
|
internal sealed class PlatformBillingInvoiceConfiguration : IEntityTypeConfiguration<PlatformBillingInvoice>
|
|
{
|
|
public void Configure(EntityTypeBuilder<PlatformBillingInvoice> builder)
|
|
{
|
|
builder.ConfigureTenantEntity("platform_billing_invoices");
|
|
builder.ConfigureTimestamps();
|
|
builder.Property(value => value.InvoiceNo).HasMaxLength(100);
|
|
builder.Property(value => value.Status).HasSnakeCaseEnum();
|
|
builder.Property(value => value.Currency).HasMaxLength(10);
|
|
builder.Property(value => value.BillingProfileSnapshot).IsJson("{}");
|
|
builder.HasIndex(value => new { value.TenantId, value.InvoiceNo }).IsUnique();
|
|
builder.HasIndex(value => new { value.TenantId, value.Status, value.DueDate });
|
|
builder.HasOne<PlatformBillingOrder>().WithMany().HasForeignKey(value => new { value.TenantId, value.OrderId })
|
|
.HasPrincipalKey(value => new { value.TenantId, value.Id }).OnDelete(DeleteBehavior.Restrict);
|
|
builder.ToTable(table =>
|
|
table.HasCheckConstraint("ck_platform_billing_invoices_amount", "total_amount_cents >= 0"));
|
|
}
|
|
} |