feat(finance): add cost management backend module

This commit is contained in:
2026-03-04 16:07:16 +08:00
parent 39e28c1a62
commit fa6e376b86
24 changed files with 3001 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ using TakeoutSaaS.Domain.Deliveries.Entities;
using TakeoutSaaS.Domain.Distribution.Entities;
using TakeoutSaaS.Domain.Common.Enums;
using TakeoutSaaS.Domain.Engagement.Entities;
using TakeoutSaaS.Domain.Finance.Entities;
using TakeoutSaaS.Domain.GroupBuying.Entities;
using TakeoutSaaS.Domain.Inventory.Entities;
using TakeoutSaaS.Domain.Membership.Entities;
@@ -94,6 +95,14 @@ public sealed class TakeoutAppDbContext(
/// </summary>
public DbSet<TenantVisibilityRoleRule> TenantVisibilityRoleRules => Set<TenantVisibilityRoleRule>();
/// <summary>
/// 成本录入汇总。
/// </summary>
public DbSet<FinanceCostEntry> FinanceCostEntries => Set<FinanceCostEntry>();
/// <summary>
/// 成本录入明细。
/// </summary>
public DbSet<FinanceCostEntryItem> FinanceCostEntryItems => Set<FinanceCostEntryItem>();
/// <summary>
/// 配额包定义。
/// </summary>
public DbSet<QuotaPackage> QuotaPackages => Set<QuotaPackage>();
@@ -525,6 +534,8 @@ public sealed class TakeoutAppDbContext(
ConfigureTenantAnnouncementRead(modelBuilder.Entity<TenantAnnouncementRead>());
ConfigureTenantVerificationProfile(modelBuilder.Entity<TenantVerificationProfile>());
ConfigureTenantVisibilityRoleRule(modelBuilder.Entity<TenantVisibilityRoleRule>());
ConfigureFinanceCostEntry(modelBuilder.Entity<FinanceCostEntry>());
ConfigureFinanceCostEntryItem(modelBuilder.Entity<FinanceCostEntryItem>());
ConfigureQuotaPackage(modelBuilder.Entity<QuotaPackage>());
ConfigureTenantQuotaPackagePurchase(modelBuilder.Entity<TenantQuotaPackagePurchase>());
ConfigureMerchantDocument(modelBuilder.Entity<MerchantDocument>());
@@ -1042,6 +1053,46 @@ public sealed class TakeoutAppDbContext(
builder.HasIndex(x => x.TenantId).IsUnique();
}
private static void ConfigureFinanceCostEntry(EntityTypeBuilder<FinanceCostEntry> builder)
{
builder.ToTable("finance_cost_entries");
builder.HasKey(x => x.Id);
builder.Property(x => x.TenantId).IsRequired();
builder.Property(x => x.Dimension).HasConversion<int>().IsRequired();
builder.Property(x => x.StoreId);
builder.Property(x => x.CostMonth).IsRequired();
builder.Property(x => x.Category).HasConversion<int>().IsRequired();
builder.Property(x => x.TotalAmount).HasPrecision(18, 2);
builder.HasIndex(x => new { x.TenantId, x.Dimension, x.StoreId, x.CostMonth, x.Category }).IsUnique();
builder.HasIndex(x => new { x.TenantId, x.Dimension, x.StoreId, x.CostMonth });
}
private static void ConfigureFinanceCostEntryItem(EntityTypeBuilder<FinanceCostEntryItem> builder)
{
builder.ToTable("finance_cost_entry_items");
builder.HasKey(x => x.Id);
builder.Property(x => x.TenantId).IsRequired();
builder.Property(x => x.EntryId).IsRequired();
builder.Property(x => x.Dimension).HasConversion<int>().IsRequired();
builder.Property(x => x.StoreId);
builder.Property(x => x.CostMonth).IsRequired();
builder.Property(x => x.Category).HasConversion<int>().IsRequired();
builder.Property(x => x.ItemName).HasMaxLength(64).IsRequired();
builder.Property(x => x.Amount).HasPrecision(18, 2);
builder.Property(x => x.Quantity).HasPrecision(18, 2);
builder.Property(x => x.UnitPrice).HasPrecision(18, 2);
builder.Property(x => x.SortOrder).HasDefaultValue(100);
builder.HasOne<FinanceCostEntry>()
.WithMany()
.HasForeignKey(x => x.EntryId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasIndex(x => x.EntryId);
builder.HasIndex(x => new { x.TenantId, x.Dimension, x.StoreId, x.CostMonth, x.Category, x.SortOrder });
}
private static void ConfigureTenantAnnouncement(EntityTypeBuilder<TenantAnnouncement> builder)
{
builder.ToTable("tenant_announcements");