feat(finance): 完成发票管理模块后端实现

This commit is contained in:
2026-03-04 16:48:58 +08:00
parent 21a689edec
commit c79e9bd6e8
33 changed files with 2970 additions and 0 deletions

View File

@@ -95,6 +95,14 @@ public sealed class TakeoutAppDbContext(
/// </summary>
public DbSet<TenantVisibilityRoleRule> TenantVisibilityRoleRules => Set<TenantVisibilityRoleRule>();
/// <summary>
/// 租户发票设置。
/// </summary>
public DbSet<TenantInvoiceSetting> TenantInvoiceSettings => Set<TenantInvoiceSetting>();
/// <summary>
/// 租户发票记录。
/// </summary>
public DbSet<TenantInvoiceRecord> TenantInvoiceRecords => Set<TenantInvoiceRecord>();
/// <summary>
/// 成本录入汇总。
/// </summary>
public DbSet<FinanceCostEntry> FinanceCostEntries => Set<FinanceCostEntry>();
@@ -534,6 +542,8 @@ public sealed class TakeoutAppDbContext(
ConfigureTenantAnnouncementRead(modelBuilder.Entity<TenantAnnouncementRead>());
ConfigureTenantVerificationProfile(modelBuilder.Entity<TenantVerificationProfile>());
ConfigureTenantVisibilityRoleRule(modelBuilder.Entity<TenantVisibilityRoleRule>());
ConfigureTenantInvoiceSetting(modelBuilder.Entity<TenantInvoiceSetting>());
ConfigureTenantInvoiceRecord(modelBuilder.Entity<TenantInvoiceRecord>());
ConfigureFinanceCostEntry(modelBuilder.Entity<FinanceCostEntry>());
ConfigureFinanceCostEntryItem(modelBuilder.Entity<FinanceCostEntryItem>());
ConfigureQuotaPackage(modelBuilder.Entity<QuotaPackage>());
@@ -1053,6 +1063,52 @@ public sealed class TakeoutAppDbContext(
builder.HasIndex(x => x.TenantId).IsUnique();
}
private static void ConfigureTenantInvoiceSetting(EntityTypeBuilder<TenantInvoiceSetting> builder)
{
builder.ToTable("finance_invoice_settings");
builder.HasKey(x => x.Id);
builder.Property(x => x.TenantId).IsRequired();
builder.Property(x => x.CompanyName).HasMaxLength(128).IsRequired();
builder.Property(x => x.TaxpayerNumber).HasMaxLength(64).IsRequired();
builder.Property(x => x.RegisteredAddress).HasMaxLength(256);
builder.Property(x => x.RegisteredPhone).HasMaxLength(32);
builder.Property(x => x.BankName).HasMaxLength(128);
builder.Property(x => x.BankAccount).HasMaxLength(64);
builder.Property(x => x.EnableElectronicNormalInvoice).IsRequired();
builder.Property(x => x.EnableElectronicSpecialInvoice).IsRequired();
builder.Property(x => x.EnableAutoIssue).IsRequired();
builder.Property(x => x.AutoIssueMaxAmount).HasPrecision(18, 2).IsRequired();
builder.HasIndex(x => x.TenantId).IsUnique();
}
private static void ConfigureTenantInvoiceRecord(EntityTypeBuilder<TenantInvoiceRecord> builder)
{
builder.ToTable("finance_invoice_records");
builder.HasKey(x => x.Id);
builder.Property(x => x.TenantId).IsRequired();
builder.Property(x => x.InvoiceNo).HasMaxLength(32).IsRequired();
builder.Property(x => x.ApplicantName).HasMaxLength(64).IsRequired();
builder.Property(x => x.CompanyName).HasMaxLength(128).IsRequired();
builder.Property(x => x.TaxpayerNumber).HasMaxLength(64);
builder.Property(x => x.InvoiceType).HasConversion<int>().IsRequired();
builder.Property(x => x.Amount).HasPrecision(18, 2).IsRequired();
builder.Property(x => x.OrderNo).HasMaxLength(32).IsRequired();
builder.Property(x => x.ContactEmail).HasMaxLength(128);
builder.Property(x => x.ContactPhone).HasMaxLength(32);
builder.Property(x => x.ApplyRemark).HasMaxLength(256);
builder.Property(x => x.Status).HasConversion<int>().IsRequired();
builder.Property(x => x.AppliedAt).IsRequired();
builder.Property(x => x.IssueRemark).HasMaxLength(256);
builder.Property(x => x.VoidReason).HasMaxLength(256);
builder.HasIndex(x => new { x.TenantId, x.InvoiceNo }).IsUnique();
builder.HasIndex(x => new { x.TenantId, x.OrderNo });
builder.HasIndex(x => new { x.TenantId, x.Status, x.AppliedAt });
builder.HasIndex(x => new { x.TenantId, x.Status, x.IssuedAt });
builder.HasIndex(x => new { x.TenantId, x.InvoiceType, x.AppliedAt });
}
private static void ConfigureFinanceCostEntry(EntityTypeBuilder<FinanceCostEntry> builder)
{
builder.ToTable("finance_cost_entries");