feat(finance): implement invoice and business report backend modules
This commit is contained in:
@@ -95,6 +95,26 @@ 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<FinanceBusinessReportSnapshot> FinanceBusinessReportSnapshots => Set<FinanceBusinessReportSnapshot>();
|
||||
/// <summary>
|
||||
/// 成本配置。
|
||||
/// </summary>
|
||||
public DbSet<FinanceCostProfile> FinanceCostProfiles => Set<FinanceCostProfile>();
|
||||
/// <summary>
|
||||
/// 成本日覆盖。
|
||||
/// </summary>
|
||||
public DbSet<FinanceCostDailyOverride> FinanceCostDailyOverrides => Set<FinanceCostDailyOverride>();
|
||||
/// <summary>
|
||||
/// 成本录入汇总。
|
||||
/// </summary>
|
||||
public DbSet<FinanceCostEntry> FinanceCostEntries => Set<FinanceCostEntry>();
|
||||
@@ -534,6 +554,11 @@ public sealed class TakeoutAppDbContext(
|
||||
ConfigureTenantAnnouncementRead(modelBuilder.Entity<TenantAnnouncementRead>());
|
||||
ConfigureTenantVerificationProfile(modelBuilder.Entity<TenantVerificationProfile>());
|
||||
ConfigureTenantVisibilityRoleRule(modelBuilder.Entity<TenantVisibilityRoleRule>());
|
||||
ConfigureTenantInvoiceSetting(modelBuilder.Entity<TenantInvoiceSetting>());
|
||||
ConfigureTenantInvoiceRecord(modelBuilder.Entity<TenantInvoiceRecord>());
|
||||
ConfigureFinanceBusinessReportSnapshot(modelBuilder.Entity<FinanceBusinessReportSnapshot>());
|
||||
ConfigureFinanceCostProfile(modelBuilder.Entity<FinanceCostProfile>());
|
||||
ConfigureFinanceCostDailyOverride(modelBuilder.Entity<FinanceCostDailyOverride>());
|
||||
ConfigureFinanceCostEntry(modelBuilder.Entity<FinanceCostEntry>());
|
||||
ConfigureFinanceCostEntryItem(modelBuilder.Entity<FinanceCostEntryItem>());
|
||||
ConfigureQuotaPackage(modelBuilder.Entity<QuotaPackage>());
|
||||
@@ -1053,6 +1078,115 @@ 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 ConfigureFinanceBusinessReportSnapshot(EntityTypeBuilder<FinanceBusinessReportSnapshot> builder)
|
||||
{
|
||||
builder.ToTable("finance_business_report_snapshots");
|
||||
builder.HasKey(x => x.Id);
|
||||
builder.Property(x => x.TenantId).IsRequired();
|
||||
builder.Property(x => x.StoreId).IsRequired();
|
||||
builder.Property(x => x.PeriodType).HasConversion<int>().IsRequired();
|
||||
builder.Property(x => x.PeriodStartAt).IsRequired();
|
||||
builder.Property(x => x.PeriodEndAt).IsRequired();
|
||||
builder.Property(x => x.Status).HasConversion<int>().IsRequired();
|
||||
builder.Property(x => x.RevenueAmount).HasPrecision(18, 2);
|
||||
builder.Property(x => x.OrderCount).IsRequired();
|
||||
builder.Property(x => x.AverageOrderValue).HasPrecision(18, 2);
|
||||
builder.Property(x => x.RefundRate).HasPrecision(9, 4);
|
||||
builder.Property(x => x.CostTotalAmount).HasPrecision(18, 2);
|
||||
builder.Property(x => x.NetProfitAmount).HasPrecision(18, 2);
|
||||
builder.Property(x => x.ProfitRate).HasPrecision(9, 4);
|
||||
builder.Property(x => x.KpiComparisonJson).HasColumnType("text").IsRequired();
|
||||
builder.Property(x => x.IncomeBreakdownJson).HasColumnType("text").IsRequired();
|
||||
builder.Property(x => x.CostBreakdownJson).HasColumnType("text").IsRequired();
|
||||
builder.Property(x => x.LastError).HasMaxLength(1024);
|
||||
builder.Property(x => x.HangfireJobId).HasMaxLength(64);
|
||||
builder.Property(x => x.RetryCount).HasDefaultValue(0);
|
||||
|
||||
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PeriodType, x.PeriodStartAt }).IsUnique();
|
||||
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.PeriodType, x.Status, x.PeriodStartAt });
|
||||
builder.HasIndex(x => new { x.TenantId, x.Status, x.CreatedAt });
|
||||
}
|
||||
|
||||
private static void ConfigureFinanceCostProfile(EntityTypeBuilder<FinanceCostProfile> builder)
|
||||
{
|
||||
builder.ToTable("finance_cost_profiles");
|
||||
builder.HasKey(x => x.Id);
|
||||
builder.Property(x => x.TenantId).IsRequired();
|
||||
builder.Property(x => x.StoreId).IsRequired();
|
||||
builder.Property(x => x.Category).HasConversion<int>().IsRequired();
|
||||
builder.Property(x => x.CalcMode).HasConversion<int>().IsRequired();
|
||||
builder.Property(x => x.Ratio).HasPrecision(9, 6).IsRequired();
|
||||
builder.Property(x => x.FixedDailyAmount).HasPrecision(18, 2).IsRequired();
|
||||
builder.Property(x => x.EffectiveFrom).IsRequired();
|
||||
builder.Property(x => x.EffectiveTo);
|
||||
builder.Property(x => x.IsEnabled).IsRequired();
|
||||
builder.Property(x => x.SortOrder).HasDefaultValue(100);
|
||||
|
||||
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.Category, x.EffectiveFrom, x.EffectiveTo });
|
||||
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.IsEnabled, x.SortOrder });
|
||||
}
|
||||
|
||||
private static void ConfigureFinanceCostDailyOverride(EntityTypeBuilder<FinanceCostDailyOverride> builder)
|
||||
{
|
||||
builder.ToTable("finance_cost_daily_overrides");
|
||||
builder.HasKey(x => x.Id);
|
||||
builder.Property(x => x.TenantId).IsRequired();
|
||||
builder.Property(x => x.StoreId).IsRequired();
|
||||
builder.Property(x => x.BusinessDate).IsRequired();
|
||||
builder.Property(x => x.Category).HasConversion<int>().IsRequired();
|
||||
builder.Property(x => x.Amount).HasPrecision(18, 2).IsRequired();
|
||||
builder.Property(x => x.Remark).HasMaxLength(256);
|
||||
|
||||
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.BusinessDate, x.Category }).IsUnique();
|
||||
builder.HasIndex(x => new { x.TenantId, x.StoreId, x.BusinessDate });
|
||||
}
|
||||
|
||||
private static void ConfigureFinanceCostEntry(EntityTypeBuilder<FinanceCostEntry> builder)
|
||||
{
|
||||
builder.ToTable("finance_cost_entries");
|
||||
|
||||
Reference in New Issue
Block a user