Refactor sales pipeline: ShopPO, Invoice, SysConfig models
Major refactor replacing Sale/Order with ShopPO → Invoice → LoadingSheet flow. Removed legacy Sale/Order models and features; introduced ShopPO, ShopPOItem, Invoice, LoadingSheetOrder, and SysConfig models. Updated related entities, enums, repositories, and controllers. Added new migrations for schema changes and system config. Overhauled business logic and DI registrations. Updated documentation with migration plan.
This commit is contained in:
@@ -17,9 +17,10 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
public DbSet<UomConversion> UomConversions { get; set; }
|
||||
public DbSet<Item> Items { get; set; }
|
||||
public DbSet<SaleRoute> SaleRoutes { get; set; }
|
||||
public DbSet<Sale> Sales { get; set; }
|
||||
public DbSet<Order> Orders { get; set; }
|
||||
public DbSet<OrderItem> OrderItems { get; set; }
|
||||
public DbSet<ShopPO> ShopPOs { get; set; }
|
||||
public DbSet<ShopPOItem> ShopPOItems { get; set; }
|
||||
public DbSet<Invoice> Invoices { get; set; }
|
||||
public DbSet<LoadingSheetOrder> LoadingSheetOrders { get; set; }
|
||||
public DbSet<DeliveryRun> DeliveryRuns { get; set; }
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<Role> Roles { get; set; }
|
||||
@@ -61,11 +62,11 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
public DbSet<RegionAgencyMap> RegionAgencyMaps { get; set; }
|
||||
public DbSet<RegionalTaxRule> RegionalTaxRules { get; set; }
|
||||
public DbSet<RouteVisitLog> RouteVisitLogs { get; set; }
|
||||
public DbSet<SysConfig> SysConfigs { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<OrderItem>()
|
||||
.HasKey(oi => new { oi.FK_OrderId, oi.FK_ItemId });
|
||||
// --- Composite PKs ---
|
||||
|
||||
modelBuilder.Entity<RolePermission>()
|
||||
.HasKey(rp => new { rp.FK_RoleId, rp.FK_PermissionId });
|
||||
@@ -79,11 +80,10 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
modelBuilder.Entity<UserStoreScope>()
|
||||
.HasKey(s => new { s.FK_UserId, s.FK_StoreId });
|
||||
|
||||
modelBuilder.Entity<User>()
|
||||
.HasOne(u => u.ReportsTo)
|
||||
.WithMany()
|
||||
.HasForeignKey(u => u.FK_ReportsToUserId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
modelBuilder.Entity<LoadingSheetOrder>()
|
||||
.HasKey(lo => new { lo.FK_LoadingSheetId, lo.FK_ShopPOId });
|
||||
|
||||
// --- Unique indexes ---
|
||||
|
||||
modelBuilder.Entity<StockBalance>()
|
||||
.HasIndex(sb => new { sb.FK_ItemId, sb.LocationId })
|
||||
@@ -93,14 +93,20 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.HasIndex(pli => new { pli.FK_PriceListId, pli.FK_ItemId })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<Order>()
|
||||
.HasIndex(o => o.FK_SaleId)
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<DriverProfile>()
|
||||
.HasIndex(dp => dp.FK_UserId)
|
||||
.IsUnique();
|
||||
|
||||
// --- User ---
|
||||
|
||||
modelBuilder.Entity<User>()
|
||||
.HasOne(u => u.ReportsTo)
|
||||
.WithMany()
|
||||
.HasForeignKey(u => u.FK_ReportsToUserId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// --- Vehicle ---
|
||||
|
||||
modelBuilder.Entity<Vehicle>()
|
||||
.HasOne<Warehouse>()
|
||||
.WithMany()
|
||||
@@ -108,11 +114,7 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired(false);
|
||||
|
||||
modelBuilder.Entity<DeliveryRun>()
|
||||
.HasOne(r => r.SourceWarehouse)
|
||||
.WithMany()
|
||||
.HasForeignKey(r => r.FK_SourceWarehouseId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
// --- DeliveryRun ---
|
||||
|
||||
modelBuilder.Entity<DeliveryRun>()
|
||||
.HasOne(r => r.DriverProfile)
|
||||
@@ -120,30 +122,97 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.HasForeignKey(r => r.FK_DriverProfileId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Sale>()
|
||||
.HasOne(s => s.Store)
|
||||
// --- ShopPO ---
|
||||
|
||||
modelBuilder.Entity<ShopPO>()
|
||||
.HasOne(p => p.Store)
|
||||
.WithMany()
|
||||
.HasForeignKey(s => s.FK_StoreId)
|
||||
.HasForeignKey(p => p.FK_StoreId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Sale>()
|
||||
.HasOne(s => s.CreatedByUser)
|
||||
.WithMany()
|
||||
.HasForeignKey(s => s.CreatedByUserId)
|
||||
// InvoiceId is a plain column — no FK constraint
|
||||
modelBuilder.Entity<ShopPO>()
|
||||
.Property(p => p.InvoiceId)
|
||||
.HasColumnName("InvoiceId");
|
||||
|
||||
// --- ShopPOItem ---
|
||||
|
||||
modelBuilder.Entity<ShopPOItem>()
|
||||
.HasOne(i => i.ShopPO)
|
||||
.WithMany(p => p.Items)
|
||||
.HasForeignKey(i => i.FK_ShopPOId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Sale>()
|
||||
modelBuilder.Entity<ShopPOItem>()
|
||||
.HasOne(i => i.Item)
|
||||
.WithMany()
|
||||
.HasForeignKey(i => i.FK_ItemId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// --- Invoice ---
|
||||
|
||||
modelBuilder.Entity<Invoice>()
|
||||
.HasOne(i => i.ShopPO)
|
||||
.WithMany()
|
||||
.HasForeignKey(i => i.FK_ShopPOId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<Invoice>()
|
||||
.HasMany(i => i.Payments)
|
||||
.WithOne(p => p.Invoice)
|
||||
.HasForeignKey(p => p.FK_InvoiceId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// --- LoadingSheet ---
|
||||
|
||||
modelBuilder.Entity<LoadingSheet>()
|
||||
.HasOne(s => s.Ride)
|
||||
.WithMany()
|
||||
.HasForeignKey(s => s.FK_RideId)
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// --- LoadingSheetOrder ---
|
||||
|
||||
modelBuilder.Entity<LoadingSheetOrder>()
|
||||
.HasOne(lo => lo.LoadingSheet)
|
||||
.WithMany(s => s.Orders)
|
||||
.HasForeignKey(lo => lo.FK_LoadingSheetId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<LoadingSheetOrder>()
|
||||
.HasOne(lo => lo.ShopPO)
|
||||
.WithMany()
|
||||
.HasForeignKey(lo => lo.FK_ShopPOId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// --- LoadingSheetItem ---
|
||||
|
||||
modelBuilder.Entity<LoadingSheetItem>()
|
||||
.HasOne(i => i.LoadingSheet)
|
||||
.WithMany(s => s.Items)
|
||||
.HasForeignKey(i => i.FK_LoadingSheetId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<LoadingSheetItem>()
|
||||
.HasOne(i => i.Item)
|
||||
.WithMany()
|
||||
.HasForeignKey(i => i.FK_ItemId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<LoadingSheetItem>()
|
||||
.HasOne(i => i.Warehouse)
|
||||
.WithMany()
|
||||
.HasForeignKey(i => i.FK_WarehouseId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<LoadingSheetItem>()
|
||||
.HasOne(i => i.ShopPOItem)
|
||||
.WithMany()
|
||||
.HasForeignKey(i => i.FK_ShopPOItemId)
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.IsRequired(false);
|
||||
|
||||
modelBuilder.Entity<Order>()
|
||||
.HasOne(o => o.Sale)
|
||||
.WithMany()
|
||||
.HasForeignKey(o => o.FK_SaleId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
// --- SchemeRedemption ---
|
||||
|
||||
modelBuilder.Entity<SchemeRedemption>()
|
||||
.HasOne(r => r.Scheme)
|
||||
@@ -152,10 +221,11 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<SchemeRedemption>()
|
||||
.HasOne(r => r.Order)
|
||||
.HasOne(r => r.ShopPO)
|
||||
.WithMany()
|
||||
.HasForeignKey(r => r.FK_OrderId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
.HasForeignKey(r => r.FK_ShopPOId)
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired(false);
|
||||
|
||||
modelBuilder.Entity<SchemeRedemption>()
|
||||
.HasOne(r => r.FreeItem)
|
||||
@@ -163,6 +233,8 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.HasForeignKey(r => r.FK_FreeItemId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// --- Scheme ---
|
||||
|
||||
modelBuilder.Entity<Scheme>()
|
||||
.HasOne(s => s.TriggerItem)
|
||||
.WithMany()
|
||||
@@ -191,23 +263,7 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.HasIndex(c => new { c.FK_SchemeId, c.FK_ItemId })
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<LoadingSheet>()
|
||||
.HasOne(s => s.SourceWarehouse)
|
||||
.WithMany()
|
||||
.HasForeignKey(s => s.FK_SourceWarehouseId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<LoadingSheet>()
|
||||
.HasOne(s => s.Ride)
|
||||
.WithMany()
|
||||
.HasForeignKey(s => s.FK_RideId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<LoadingSheetItem>()
|
||||
.HasOne(i => i.Item)
|
||||
.WithMany()
|
||||
.HasForeignKey(i => i.FK_ItemId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
// --- PurchaseOrder ---
|
||||
|
||||
modelBuilder.Entity<PurchaseOrder>()
|
||||
.HasOne(po => po.Supplier)
|
||||
@@ -227,6 +283,11 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.HasForeignKey(i => i.FK_ItemId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<PurchaseOrderItem>()
|
||||
.HasIndex(i => i.FK_PurchaseOrderId);
|
||||
|
||||
// --- GoodsReceipt ---
|
||||
|
||||
modelBuilder.Entity<GoodsReceipt>()
|
||||
.HasOne(gr => gr.PurchaseOrder)
|
||||
.WithMany()
|
||||
@@ -251,6 +312,14 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.HasForeignKey(i => i.FK_PurchaseOrderItemId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<GoodsReceiptItem>()
|
||||
.HasIndex(i => i.FK_GoodsReceiptId);
|
||||
|
||||
modelBuilder.Entity<GoodsReceiptItem>()
|
||||
.HasIndex(i => i.FK_PurchaseOrderItemId);
|
||||
|
||||
// --- PurchaseReturn ---
|
||||
|
||||
modelBuilder.Entity<PurchaseReturn>()
|
||||
.HasOne(pr => pr.PurchaseOrder)
|
||||
.WithMany()
|
||||
@@ -269,22 +338,15 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.HasForeignKey(i => i.FK_ItemId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<PurchaseOrderItem>()
|
||||
.HasIndex(i => i.FK_PurchaseOrderId);
|
||||
|
||||
modelBuilder.Entity<GoodsReceiptItem>()
|
||||
.HasIndex(i => i.FK_GoodsReceiptId);
|
||||
|
||||
modelBuilder.Entity<GoodsReceiptItem>()
|
||||
.HasIndex(i => i.FK_PurchaseOrderItemId);
|
||||
|
||||
modelBuilder.Entity<PurchaseReturnItem>()
|
||||
.HasIndex(i => i.FK_PurchaseReturnId);
|
||||
|
||||
// --- SaleReturn ---
|
||||
|
||||
modelBuilder.Entity<SaleReturn>()
|
||||
.HasOne(r => r.Order)
|
||||
.HasOne(r => r.ShopPO)
|
||||
.WithMany()
|
||||
.HasForeignKey(r => r.FK_OrderId)
|
||||
.HasForeignKey(r => r.FK_ShopPOId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<SaleReturn>()
|
||||
@@ -308,12 +370,16 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
modelBuilder.Entity<SaleReturnItem>()
|
||||
.HasIndex(i => i.FK_SaleReturnId);
|
||||
|
||||
// --- CreditNote ---
|
||||
|
||||
modelBuilder.Entity<CreditNote>()
|
||||
.HasOne(n => n.SaleReturn)
|
||||
.WithMany()
|
||||
.HasForeignKey(n => n.FK_SaleReturnId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// --- Claims ---
|
||||
|
||||
modelBuilder.Entity<Claim>()
|
||||
.HasOne(c => c.AgencyUser)
|
||||
.WithMany()
|
||||
@@ -366,6 +432,8 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
modelBuilder.Entity<SupplierClaimItem>()
|
||||
.HasIndex(i => i.FK_SupplierClaimId);
|
||||
|
||||
// --- DeliveryTask ---
|
||||
|
||||
modelBuilder.Entity<DeliveryTask>()
|
||||
.HasOne(t => t.Ride)
|
||||
.WithMany()
|
||||
@@ -373,11 +441,13 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
modelBuilder.Entity<DeliveryTask>()
|
||||
.HasOne(t => t.Order)
|
||||
.HasOne(t => t.ShopPO)
|
||||
.WithMany()
|
||||
.HasForeignKey(t => t.FK_OrderId)
|
||||
.HasForeignKey(t => t.FK_ShopPOId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
// --- Regional ---
|
||||
|
||||
modelBuilder.Entity<RegionalTarget>()
|
||||
.HasIndex(t => new { t.FK_RegionId, t.Period })
|
||||
.IsUnique();
|
||||
@@ -400,6 +470,19 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
||||
.HasIndex(r => r.FK_RegionId)
|
||||
.IsUnique();
|
||||
|
||||
// --- SysConfig ---
|
||||
|
||||
modelBuilder.Entity<SysConfig>()
|
||||
.HasKey(c => c.Key);
|
||||
|
||||
modelBuilder.Entity<SysConfig>()
|
||||
.Property(c => c.Key)
|
||||
.HasMaxLength(100);
|
||||
|
||||
modelBuilder.Entity<SysConfig>().HasData(
|
||||
new SysConfig { Key = "InvoiceCreationMode", Value = "ModeB", UpdatedAt = new DateTime(2026, 9, 17), UpdatedBy = null }
|
||||
);
|
||||
|
||||
Seed.RoleAndPermissionSeed.Apply(modelBuilder);
|
||||
Seed.MasterDataSeed.Apply(modelBuilder);
|
||||
Seed.OperationsDataSeed.Apply(modelBuilder);
|
||||
|
||||
Reference in New Issue
Block a user