feat: complete SaaS commercial delivery workflows

This commit is contained in:
2026-08-01 15:26:21 +08:00
parent 46abf4d62f
commit d58bcd97e9
56 changed files with 27505 additions and 181 deletions

View File

@@ -28,6 +28,50 @@ internal sealed class TenantBillingProfileConfiguration : IEntityTypeConfigurati
}
}
internal sealed class TenantBillingPolicyConfiguration : IEntityTypeConfiguration<TenantBillingPolicy>
{
public void Configure(EntityTypeBuilder<TenantBillingPolicy> builder)
{
builder.ToTable("tenant_billing_policies");
builder.HasKey(entity => entity.TenantId);
builder.ConfigureTimestamps();
builder.Property(entity => entity.CollectionMode).HasSnakeCaseEnum();
builder.Property(entity => entity.DefaultPaymentProvider).HasMaxLength(50);
builder.ToTable(table => table.HasCheckConstraint(
"ck_tenant_billing_policies_renewal_lead_days",
"renewal_lead_days between 1 and 90"));
builder.HasOne<Tenant>().WithOne().HasForeignKey<TenantBillingPolicy>(entity => entity.TenantId).OnDelete(DeleteBehavior.Cascade);
}
}
internal sealed class TenantOwnerActivationGrantConfiguration : IEntityTypeConfiguration<TenantOwnerActivationGrant>
{
public void Configure(EntityTypeBuilder<TenantOwnerActivationGrant> builder)
{
builder.ConfigureTenantEntity("tenant_owner_activation_grants");
builder.ConfigureTimestamps();
builder.Property(entity => entity.TokenHash).HasMaxLength(64);
builder.HasIndex(entity => new { entity.TenantId, entity.UserId, entity.ConsumedAt, entity.ExpiresAt });
builder.HasIndex(entity => entity.TokenHash).IsUnique().HasAnnotation("Tiku:GlobalUnique", true);
builder.HasOne<User>().WithMany().HasForeignKey(entity => entity.UserId).OnDelete(DeleteBehavior.Cascade);
builder.HasOne<User>().WithMany().HasForeignKey(entity => entity.CreatedBy).OnDelete(DeleteBehavior.Restrict);
}
}
internal sealed class PlatformOperationIdempotencyConfiguration : IEntityTypeConfiguration<PlatformOperationIdempotency>
{
public void Configure(EntityTypeBuilder<PlatformOperationIdempotency> builder)
{
builder.ConfigureEntity("platform_operation_idempotencies");
builder.ConfigureTimestamps();
builder.Property(entity => entity.Scope).HasMaxLength(100);
builder.Property(entity => entity.IdempotencyKey).HasMaxLength(200);
builder.Property(entity => entity.RequestHash).HasMaxLength(64);
builder.HasIndex(entity => new { entity.ActorUserId, entity.Scope, entity.IdempotencyKey }).IsUnique();
builder.HasOne<User>().WithMany().HasForeignKey(entity => entity.ActorUserId).OnDelete(DeleteBehavior.Restrict);
}
}
internal sealed class PlatformBillingInvoiceReminderConfiguration : IEntityTypeConfiguration<PlatformBillingInvoiceReminder>
{
public void Configure(EntityTypeBuilder<PlatformBillingInvoiceReminder> builder)