Add GL account configuration and role mapping entities
- Introduced GlAccountConfig entity for mapping accounting roles to GL account codes. - Added GlAccountConfigConfiguration for database configuration of the singleton GL account mapping. - Created GlAccountRole enum to define accounting roles used in GL postings. - Enhanced error handling with new error codes for unconfigured and invalid GL accounts. - Updated existing DbContext to include GlAccountConfig DbSet.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
using ERPCore.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ERPCore.Infra.Persistence.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// Configures the singleton GL account-mapping row. The check constraint is what makes
|
||||
/// "singleton" a database guarantee rather than a convention (mirrors <see cref="GrnConfigConfiguration"/>).
|
||||
/// Backtick quoting is deliberate - MariaDB rejects the double-quoted form, which crash-looped
|
||||
/// startup seeding once already (c97a7e9).
|
||||
/// </summary>
|
||||
public sealed class GlAccountConfigConfiguration : IEntityTypeConfiguration<GlAccountConfig>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<GlAccountConfig> builder)
|
||||
{
|
||||
builder.ToTable("gl_account_config", t =>
|
||||
t.HasCheckConstraint("ck_gl_account_config_singleton", $"`ConfigId` = {GlAccountConfig.SingletonId}"));
|
||||
|
||||
builder.HasKey(c => c.ConfigId);
|
||||
|
||||
// The id is fixed, never generated — there is exactly one row, seeded by DataSeeder.
|
||||
builder.Property(c => c.ConfigId).ValueGeneratedNever();
|
||||
|
||||
foreach (var code in new[]
|
||||
{
|
||||
nameof(GlAccountConfig.InventoryAccountCode),
|
||||
nameof(GlAccountConfig.VatRecoverableAccountCode),
|
||||
nameof(GlAccountConfig.AccountsReceivableCode),
|
||||
nameof(GlAccountConfig.ClearingAccountCode),
|
||||
nameof(GlAccountConfig.TaxPayableAccountCode),
|
||||
nameof(GlAccountConfig.AccountsPayableCode),
|
||||
nameof(GlAccountConfig.SalesRevenueAccountCode),
|
||||
nameof(GlAccountConfig.SalesDiscountAccountCode),
|
||||
nameof(GlAccountConfig.InventoryGainAccountCode),
|
||||
nameof(GlAccountConfig.CogsAccountCode),
|
||||
nameof(GlAccountConfig.InventoryLossAccountCode),
|
||||
nameof(GlAccountConfig.CashAccountCode)
|
||||
})
|
||||
{
|
||||
builder.Property(code).HasMaxLength(GlAccountConfig.CodeMaxLength);
|
||||
}
|
||||
|
||||
// RowVersion is made a concurrency token by the model-wide convention in ErpDbContext.
|
||||
|
||||
builder.HasOne(c => c.UpdatedByUser)
|
||||
.WithMany()
|
||||
.HasForeignKey(c => c.UpdatedBy)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,8 @@ public class ErpDbContext : DbContext
|
||||
public DbSet<BranchConfig> BranchConfig => Set<BranchConfig>();
|
||||
public DbSet<SalesConfig> SalesConfig => Set<SalesConfig>();
|
||||
public DbSet<GrnConfig> GrnConfig => Set<GrnConfig>();
|
||||
/// <summary>Singleton row mapping each accounting role to a GL account code.</summary>
|
||||
public DbSet<GlAccountConfig> GlAccountConfig => Set<GlAccountConfig>();
|
||||
/// <summary>Singleton row for notification delivery preferences.</summary>
|
||||
public DbSet<NotificationConfig> NotificationConfig => Set<NotificationConfig>();
|
||||
public DbSet<NotificationConfigModule> NotificationConfigModules => Set<NotificationConfigModule>();
|
||||
|
||||
Reference in New Issue
Block a user