From 93f2f1bd3b01e1282f2d8ee07b36c034e72f0443 Mon Sep 17 00:00:00 2001 From: "Kalana B. Thilakarathna" Date: Thu, 17 Sep 2026 10:03:22 +0530 Subject: [PATCH 01/11] Refactor sales pipeline: ShopPO, Invoice, SysConfig models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- Distribution/Data/AppDBContext.cs | 215 +- Distribution/Data/Seed/CommerceSeed.cs | 6 +- Distribution/Data/Seed/OperationsDataSeed.cs | 126 +- .../Features/DeliveryRide/DeliveryTaskDTOs.cs | 4 +- .../DeliveryRide/DeliveryTaskRepository.cs | 18 +- .../DeliveryRide/DeliveryTaskService.cs | 95 +- .../Features/Invoice/IInvoiceRepository.cs | 13 + .../Features/Invoice/InvoiceController.cs | 29 + Distribution/Features/Invoice/InvoiceDTOs.cs | 22 + .../Features/Invoice/InvoiceRepository.cs | 47 + .../Features/Invoice/InvoiceService.cs | 33 + .../LoadingEvent/ILoadingSheetRepository.cs | 1 - .../LoadingEvent/LoadingSheetController.cs | 88 +- .../Features/LoadingEvent/LoadingSheetDTOs.cs | 34 +- .../LoadingEvent/LoadingSheetRepository.cs | 25 +- .../LoadingEvent/LoadingSheetService.cs | 278 +- .../Features/Order/IOrderRepository.cs | 15 - .../Features/Order/OrderController.cs | 55 - Distribution/Features/Order/OrderDTOs.cs | 21 - .../Features/Order/OrderRepository.cs | 49 - Distribution/Features/Order/OrderService.cs | 158 - .../Features/Payment/FlatPaymentController.cs | 38 - .../Features/Payment/IPaymentRepository.cs | 9 +- .../Features/Payment/PaymentController.cs | 10 +- Distribution/Features/Payment/PaymentDTOs.cs | 12 +- .../Features/Payment/PaymentRepository.cs | 22 +- .../Features/Payment/PaymentService.cs | 52 +- .../Features/Region/IRegionRepository.cs | 2 +- .../Features/Region/RegionRepository.cs | 6 +- Distribution/Features/Region/RegionService.cs | 2 +- .../Features/Returns/IReturnRepository.cs | 4 +- .../Features/Returns/ReturnController.cs | 13 +- Distribution/Features/Returns/ReturnDTOs.cs | 2 +- .../Features/Returns/ReturnRepository.cs | 16 +- .../Features/Returns/ReturnService.cs | 150 +- Distribution/Features/Ride/IRideRepository.cs | 17 +- Distribution/Features/Ride/RideController.cs | 103 +- Distribution/Features/Ride/RideDTOs.cs | 52 +- Distribution/Features/Ride/RideRepository.cs | 37 +- Distribution/Features/Ride/RideService.cs | 246 +- Distribution/Features/Sale/ISaleRepository.cs | 15 - Distribution/Features/Sale/SaleController.cs | 51 - Distribution/Features/Sale/SaleDTOs.cs | 36 - Distribution/Features/Sale/SaleRepository.cs | 45 - Distribution/Features/Sale/SaleService.cs | 273 -- Distribution/Features/Scheme/SchemeDTOs.cs | 2 +- .../Features/Scheme/SchemeRepository.cs | 6 +- Distribution/Features/Scheme/SchemeService.cs | 72 +- .../Features/ShopPO/IShopPORepository.cs | 18 + .../Features/ShopPO/ShopPOController.cs | 28 + Distribution/Features/ShopPO/ShopPODTOs.cs | 24 + .../Features/ShopPO/ShopPORepository.cs | 91 + Distribution/Features/ShopPO/ShopPOService.cs | 32 + .../Features/Store/IStoreRepository.cs | 2 +- .../Features/Store/StoreRepository.cs | 6 +- Distribution/Features/Store/StoreService.cs | 2 +- .../SysConfig/ISysConfigRepository.cs | 8 + .../Features/SysConfig/SysConfigController.cs | 53 + .../Features/SysConfig/SysConfigDTOs.cs | 9 + .../Features/SysConfig/SysConfigRepository.cs | 29 + .../Features/SysConfig/SysConfigService.cs | 67 + ...efactorSalesToShopPOAndInvoice.Designer.cs | 4026 ++++++++++++++++ ...7034841_RefactorSalesToShopPOAndInvoice.cs | 961 ++++ .../20260917042658_AddSysConfig.Designer.cs | 4055 +++++++++++++++++ .../Migrations/20260917042658_AddSysConfig.cs | 44 + .../Migrations/AppDBContextModelSnapshot.cs | 788 ++-- Distribution/Models/DeliveryRun.cs | 12 +- Distribution/Models/DeliveryTask.cs | 6 +- Distribution/Models/Enums.cs | 22 +- Distribution/Models/Invoice.cs | 26 + Distribution/Models/LoadingSheet.cs | 14 +- Distribution/Models/LoadingSheetItem.cs | 14 +- Distribution/Models/LoadingSheetOrder.cs | 15 + Distribution/Models/Order.cs | 21 - Distribution/Models/Payment.cs | 10 +- Distribution/Models/Sale.cs | 27 - Distribution/Models/SaleReturn.cs | 6 +- Distribution/Models/SchemeRedemption.cs | 6 +- Distribution/Models/ShopPO.cs | 25 + .../Models/{OrderItem.cs => ShopPOItem.cs} | 12 +- Distribution/Models/SysConfig.cs | 10 + Distribution/Program.cs | 14 +- .../docs/refactor_docs/refactor_plan.md | 704 +++ 83 files changed, 11274 insertions(+), 2538 deletions(-) create mode 100644 Distribution/Features/Invoice/IInvoiceRepository.cs create mode 100644 Distribution/Features/Invoice/InvoiceController.cs create mode 100644 Distribution/Features/Invoice/InvoiceDTOs.cs create mode 100644 Distribution/Features/Invoice/InvoiceRepository.cs create mode 100644 Distribution/Features/Invoice/InvoiceService.cs delete mode 100644 Distribution/Features/Order/IOrderRepository.cs delete mode 100644 Distribution/Features/Order/OrderController.cs delete mode 100644 Distribution/Features/Order/OrderDTOs.cs delete mode 100644 Distribution/Features/Order/OrderRepository.cs delete mode 100644 Distribution/Features/Order/OrderService.cs delete mode 100644 Distribution/Features/Payment/FlatPaymentController.cs delete mode 100644 Distribution/Features/Sale/ISaleRepository.cs delete mode 100644 Distribution/Features/Sale/SaleController.cs delete mode 100644 Distribution/Features/Sale/SaleDTOs.cs delete mode 100644 Distribution/Features/Sale/SaleRepository.cs delete mode 100644 Distribution/Features/Sale/SaleService.cs create mode 100644 Distribution/Features/ShopPO/IShopPORepository.cs create mode 100644 Distribution/Features/ShopPO/ShopPOController.cs create mode 100644 Distribution/Features/ShopPO/ShopPODTOs.cs create mode 100644 Distribution/Features/ShopPO/ShopPORepository.cs create mode 100644 Distribution/Features/ShopPO/ShopPOService.cs create mode 100644 Distribution/Features/SysConfig/ISysConfigRepository.cs create mode 100644 Distribution/Features/SysConfig/SysConfigController.cs create mode 100644 Distribution/Features/SysConfig/SysConfigDTOs.cs create mode 100644 Distribution/Features/SysConfig/SysConfigRepository.cs create mode 100644 Distribution/Features/SysConfig/SysConfigService.cs create mode 100644 Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.Designer.cs create mode 100644 Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs create mode 100644 Distribution/Migrations/20260917042658_AddSysConfig.Designer.cs create mode 100644 Distribution/Migrations/20260917042658_AddSysConfig.cs create mode 100644 Distribution/Models/Invoice.cs create mode 100644 Distribution/Models/LoadingSheetOrder.cs delete mode 100644 Distribution/Models/Order.cs delete mode 100644 Distribution/Models/Sale.cs create mode 100644 Distribution/Models/ShopPO.cs rename Distribution/Models/{OrderItem.cs => ShopPOItem.cs} (58%) create mode 100644 Distribution/Models/SysConfig.cs create mode 100644 Distribution/docs/refactor_docs/refactor_plan.md diff --git a/Distribution/Data/AppDBContext.cs b/Distribution/Data/AppDBContext.cs index 16cd3f6..d7130b8 100644 --- a/Distribution/Data/AppDBContext.cs +++ b/Distribution/Data/AppDBContext.cs @@ -17,9 +17,10 @@ public class AppDBContext(DbContextOptions options) : DbContext(op public DbSet UomConversions { get; set; } public DbSet Items { get; set; } public DbSet SaleRoutes { get; set; } - public DbSet Sales { get; set; } - public DbSet Orders { get; set; } - public DbSet OrderItems { get; set; } + public DbSet ShopPOs { get; set; } + public DbSet ShopPOItems { get; set; } + public DbSet Invoices { get; set; } + public DbSet LoadingSheetOrders { get; set; } public DbSet DeliveryRuns { get; set; } public DbSet Users { get; set; } public DbSet Roles { get; set; } @@ -61,11 +62,11 @@ public class AppDBContext(DbContextOptions options) : DbContext(op public DbSet RegionAgencyMaps { get; set; } public DbSet RegionalTaxRules { get; set; } public DbSet RouteVisitLogs { get; set; } + public DbSet SysConfigs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity() - .HasKey(oi => new { oi.FK_OrderId, oi.FK_ItemId }); + // --- Composite PKs --- modelBuilder.Entity() .HasKey(rp => new { rp.FK_RoleId, rp.FK_PermissionId }); @@ -79,11 +80,10 @@ public class AppDBContext(DbContextOptions options) : DbContext(op modelBuilder.Entity() .HasKey(s => new { s.FK_UserId, s.FK_StoreId }); - modelBuilder.Entity() - .HasOne(u => u.ReportsTo) - .WithMany() - .HasForeignKey(u => u.FK_ReportsToUserId) - .OnDelete(DeleteBehavior.Restrict); + modelBuilder.Entity() + .HasKey(lo => new { lo.FK_LoadingSheetId, lo.FK_ShopPOId }); + + // --- Unique indexes --- modelBuilder.Entity() .HasIndex(sb => new { sb.FK_ItemId, sb.LocationId }) @@ -93,14 +93,20 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasIndex(pli => new { pli.FK_PriceListId, pli.FK_ItemId }) .IsUnique(); - modelBuilder.Entity() - .HasIndex(o => o.FK_SaleId) - .IsUnique(); - modelBuilder.Entity() .HasIndex(dp => dp.FK_UserId) .IsUnique(); + // --- User --- + + modelBuilder.Entity() + .HasOne(u => u.ReportsTo) + .WithMany() + .HasForeignKey(u => u.FK_ReportsToUserId) + .OnDelete(DeleteBehavior.Restrict); + + // --- Vehicle --- + modelBuilder.Entity() .HasOne() .WithMany() @@ -108,11 +114,7 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .OnDelete(DeleteBehavior.Restrict) .IsRequired(false); - modelBuilder.Entity() - .HasOne(r => r.SourceWarehouse) - .WithMany() - .HasForeignKey(r => r.FK_SourceWarehouseId) - .OnDelete(DeleteBehavior.Restrict); + // --- DeliveryRun --- modelBuilder.Entity() .HasOne(r => r.DriverProfile) @@ -120,30 +122,97 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(r => r.FK_DriverProfileId) .OnDelete(DeleteBehavior.Restrict); - modelBuilder.Entity() - .HasOne(s => s.Store) + // --- ShopPO --- + + modelBuilder.Entity() + .HasOne(p => p.Store) .WithMany() - .HasForeignKey(s => s.FK_StoreId) + .HasForeignKey(p => p.FK_StoreId) .OnDelete(DeleteBehavior.Restrict); - modelBuilder.Entity() - .HasOne(s => s.CreatedByUser) - .WithMany() - .HasForeignKey(s => s.CreatedByUserId) + // InvoiceId is a plain column — no FK constraint + modelBuilder.Entity() + .Property(p => p.InvoiceId) + .HasColumnName("InvoiceId"); + + // --- ShopPOItem --- + + modelBuilder.Entity() + .HasOne(i => i.ShopPO) + .WithMany(p => p.Items) + .HasForeignKey(i => i.FK_ShopPOId) .OnDelete(DeleteBehavior.Restrict); - modelBuilder.Entity() + modelBuilder.Entity() + .HasOne(i => i.Item) + .WithMany() + .HasForeignKey(i => i.FK_ItemId) + .OnDelete(DeleteBehavior.Restrict); + + // --- Invoice --- + + modelBuilder.Entity() + .HasOne(i => i.ShopPO) + .WithMany() + .HasForeignKey(i => i.FK_ShopPOId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasMany(i => i.Payments) + .WithOne(p => p.Invoice) + .HasForeignKey(p => p.FK_InvoiceId) + .OnDelete(DeleteBehavior.Restrict); + + // --- LoadingSheet --- + + modelBuilder.Entity() .HasOne(s => s.Ride) .WithMany() .HasForeignKey(s => s.FK_RideId) - .OnDelete(DeleteBehavior.Restrict) + .OnDelete(DeleteBehavior.Restrict); + + // --- LoadingSheetOrder --- + + modelBuilder.Entity() + .HasOne(lo => lo.LoadingSheet) + .WithMany(s => s.Orders) + .HasForeignKey(lo => lo.FK_LoadingSheetId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasOne(lo => lo.ShopPO) + .WithMany() + .HasForeignKey(lo => lo.FK_ShopPOId) + .OnDelete(DeleteBehavior.Restrict); + + // --- LoadingSheetItem --- + + modelBuilder.Entity() + .HasOne(i => i.LoadingSheet) + .WithMany(s => s.Items) + .HasForeignKey(i => i.FK_LoadingSheetId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasOne(i => i.Item) + .WithMany() + .HasForeignKey(i => i.FK_ItemId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasOne(i => i.Warehouse) + .WithMany() + .HasForeignKey(i => i.FK_WarehouseId) + .OnDelete(DeleteBehavior.Restrict); + + modelBuilder.Entity() + .HasOne(i => i.ShopPOItem) + .WithMany() + .HasForeignKey(i => i.FK_ShopPOItemId) + .OnDelete(DeleteBehavior.SetNull) .IsRequired(false); - modelBuilder.Entity() - .HasOne(o => o.Sale) - .WithMany() - .HasForeignKey(o => o.FK_SaleId) - .OnDelete(DeleteBehavior.Restrict); + // --- SchemeRedemption --- modelBuilder.Entity() .HasOne(r => r.Scheme) @@ -152,10 +221,11 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() - .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() .HasOne(r => r.FreeItem) @@ -163,6 +233,8 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(r => r.FK_FreeItemId) .OnDelete(DeleteBehavior.Restrict); + // --- Scheme --- + modelBuilder.Entity() .HasOne(s => s.TriggerItem) .WithMany() @@ -191,23 +263,7 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasIndex(c => new { c.FK_SchemeId, c.FK_ItemId }) .IsUnique(); - modelBuilder.Entity() - .HasOne(s => s.SourceWarehouse) - .WithMany() - .HasForeignKey(s => s.FK_SourceWarehouseId) - .OnDelete(DeleteBehavior.Restrict); - - modelBuilder.Entity() - .HasOne(s => s.Ride) - .WithMany() - .HasForeignKey(s => s.FK_RideId) - .OnDelete(DeleteBehavior.Restrict); - - modelBuilder.Entity() - .HasOne(i => i.Item) - .WithMany() - .HasForeignKey(i => i.FK_ItemId) - .OnDelete(DeleteBehavior.Restrict); + // --- PurchaseOrder --- modelBuilder.Entity() .HasOne(po => po.Supplier) @@ -227,6 +283,11 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(i => i.FK_ItemId) .OnDelete(DeleteBehavior.Restrict); + modelBuilder.Entity() + .HasIndex(i => i.FK_PurchaseOrderId); + + // --- GoodsReceipt --- + modelBuilder.Entity() .HasOne(gr => gr.PurchaseOrder) .WithMany() @@ -251,6 +312,14 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(i => i.FK_PurchaseOrderItemId) .OnDelete(DeleteBehavior.Restrict); + modelBuilder.Entity() + .HasIndex(i => i.FK_GoodsReceiptId); + + modelBuilder.Entity() + .HasIndex(i => i.FK_PurchaseOrderItemId); + + // --- PurchaseReturn --- + modelBuilder.Entity() .HasOne(pr => pr.PurchaseOrder) .WithMany() @@ -269,22 +338,15 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasForeignKey(i => i.FK_ItemId) .OnDelete(DeleteBehavior.Restrict); - modelBuilder.Entity() - .HasIndex(i => i.FK_PurchaseOrderId); - - modelBuilder.Entity() - .HasIndex(i => i.FK_GoodsReceiptId); - - modelBuilder.Entity() - .HasIndex(i => i.FK_PurchaseOrderItemId); - modelBuilder.Entity() .HasIndex(i => i.FK_PurchaseReturnId); + // --- SaleReturn --- + modelBuilder.Entity() - .HasOne(r => r.Order) + .HasOne(r => r.ShopPO) .WithMany() - .HasForeignKey(r => r.FK_OrderId) + .HasForeignKey(r => r.FK_ShopPOId) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() @@ -308,12 +370,16 @@ public class AppDBContext(DbContextOptions options) : DbContext(op modelBuilder.Entity() .HasIndex(i => i.FK_SaleReturnId); + // --- CreditNote --- + modelBuilder.Entity() .HasOne(n => n.SaleReturn) .WithMany() .HasForeignKey(n => n.FK_SaleReturnId) .OnDelete(DeleteBehavior.Restrict); + // --- Claims --- + modelBuilder.Entity() .HasOne(c => c.AgencyUser) .WithMany() @@ -366,6 +432,8 @@ public class AppDBContext(DbContextOptions options) : DbContext(op modelBuilder.Entity() .HasIndex(i => i.FK_SupplierClaimId); + // --- DeliveryTask --- + modelBuilder.Entity() .HasOne(t => t.Ride) .WithMany() @@ -373,11 +441,13 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() - .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() .HasIndex(t => new { t.FK_RegionId, t.Period }) .IsUnique(); @@ -400,6 +470,19 @@ public class AppDBContext(DbContextOptions options) : DbContext(op .HasIndex(r => r.FK_RegionId) .IsUnique(); + // --- SysConfig --- + + modelBuilder.Entity() + .HasKey(c => c.Key); + + modelBuilder.Entity() + .Property(c => c.Key) + .HasMaxLength(100); + + modelBuilder.Entity().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); diff --git a/Distribution/Data/Seed/CommerceSeed.cs b/Distribution/Data/Seed/CommerceSeed.cs index a200354..b3bc233 100644 --- a/Distribution/Data/Seed/CommerceSeed.cs +++ b/Distribution/Data/Seed/CommerceSeed.cs @@ -80,15 +80,15 @@ public static class CommerceSeed ); modelBuilder.Entity().HasData( - new SchemeRedemption { Id = SchemeRedemption1Id, FK_SchemeId = Scheme1Id, FK_OrderId = OperationsDataSeed.Order1Id, FieldInvoiceId = null, DiscountAmount = 0m, FK_FreeItemId = MasterDataSeed.Coke500ItemId, FreeQty = 1m, FreeItemCostValue = 40m, RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0) } + new SchemeRedemption { Id = SchemeRedemption1Id, FK_SchemeId = Scheme1Id, FK_ShopPOId = OperationsDataSeed.ShopPO1Id, FieldInvoiceId = null, DiscountAmount = 0m, FK_FreeItemId = MasterDataSeed.Coke500ItemId, FreeQty = 1m, FreeItemCostValue = 40m, RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0) } ); modelBuilder.Entity().HasData( - new Payment { Id = Payment1Id, FK_SaleId = OperationsDataSeed.Sale1Id, FK_StoreId = MasterDataSeed.FortStoreId, Amount = 3000m, Method = PaymentMethod.Cash, CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0), CollectedBy = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0), IsActive = true } + new Payment { Id = Payment1Id, FK_InvoiceId = OperationsDataSeed.Invoice1Id, Amount = 3000m, Method = PaymentMethod.Cash, CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0), CollectedBy = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0), IsActive = true } ); modelBuilder.Entity().HasData( - new SaleReturn { Id = SaleReturn1Id, FK_OrderId = OperationsDataSeed.Order1Id, Mode = ReturnMode.CreditDeduction, TotalCreditAmount = 300m, CreatedByUserId = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 26), IsActive = true } + new SaleReturn { Id = SaleReturn1Id, FK_ShopPOId = OperationsDataSeed.ShopPO1Id, Mode = ReturnMode.CreditDeduction, TotalCreditAmount = 300m, CreatedByUserId = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 26), IsActive = true } ); modelBuilder.Entity().HasData( diff --git a/Distribution/Data/Seed/OperationsDataSeed.cs b/Distribution/Data/Seed/OperationsDataSeed.cs index bb502ef..a0953d2 100644 --- a/Distribution/Data/Seed/OperationsDataSeed.cs +++ b/Distribution/Data/Seed/OperationsDataSeed.cs @@ -8,15 +8,17 @@ public static class OperationsDataSeed internal static readonly Guid ClosedSaleRunId = new("31000000-0000-0000-0000-000000000001"); internal static readonly Guid ActiveDeliveryRunId = new("31000000-0000-0000-0000-000000000002"); + // Kept for OperationsExtrasSeed stock movement reference (ReferenceId on MovementType.Sale) internal static readonly Guid Sale1Id = new("32000000-0000-0000-0000-000000000001"); - internal static readonly Guid Sale2Id = new("32000000-0000-0000-0000-000000000002"); - internal static readonly Guid Order1Id = new("33000000-0000-0000-0000-000000000001"); - internal static readonly Guid Order2Id = new("33000000-0000-0000-0000-000000000002"); + internal static readonly Guid ShopPO1Id = new("33000000-0000-0000-0000-000000000001"); + internal static readonly Guid ShopPO2Id = new("33000000-0000-0000-0000-000000000002"); - internal static readonly Guid OrderItem1Id = new("34000000-0000-0000-0000-000000000001"); - internal static readonly Guid OrderItem2Id = new("34000000-0000-0000-0000-000000000002"); - internal static readonly Guid OrderItem3Id = new("34000000-0000-0000-0000-000000000003"); + internal static readonly Guid ShopPOItem1Id = new("34000000-0000-0000-0000-000000000001"); + internal static readonly Guid ShopPOItem2Id = new("34000000-0000-0000-0000-000000000002"); + internal static readonly Guid ShopPOItem3Id = new("34000000-0000-0000-0000-000000000003"); + + internal static readonly Guid Invoice1Id = new("34500000-0000-0000-0000-000000000001"); internal static readonly Guid LoadingSheet1Id = new("35000000-0000-0000-0000-000000000001"); @@ -31,16 +33,12 @@ public static class OperationsDataSeed new DeliveryRun { Id = ClosedSaleRunId, - RideType = RideType.Sale, Status = RideStatus.Closed, FK_VehicleId = MasterDataSeed.VanVehicleId, FK_DriverProfileId = MasterDataSeed.Driver1ProfileId, - FK_RouteId = MasterDataSeed.ColomboRouteId, - FK_SourceWarehouseId = MasterDataSeed.ColomboWarehouseId, Meterstart = 10500, Meterend = 10550, StartedAt = new DateTime(2026, 8, 25, 8, 0, 0), - ActivatedAt = new DateTime(2026, 8, 25, 8, 15, 0), ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0), CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0), IsActive = true @@ -48,86 +46,71 @@ public static class OperationsDataSeed new DeliveryRun { Id = ActiveDeliveryRunId, - RideType = RideType.Delivery, - Status = RideStatus.Active, + Status = RideStatus.Open, FK_VehicleId = MasterDataSeed.TruckVehicleId, FK_DriverProfileId = MasterDataSeed.Driver2ProfileId, - FK_RouteId = MasterDataSeed.KandyRouteId, - FK_SourceWarehouseId = MasterDataSeed.KandyWarehouseId, Meterstart = 20300, Meterend = 0, StartedAt = new DateTime(2026, 8, 30, 9, 0, 0), - ActivatedAt = new DateTime(2026, 8, 30, 9, 20, 0), ClosedAt = null, CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0), IsActive = true } ); - modelBuilder.Entity().HasData( - new Sale + modelBuilder.Entity().HasData( + new ShopPO { - Id = Sale1Id, - SaleDate = new DateTime(2026, 8, 25, 9, 0, 0), + Id = ShopPO1Id, FK_StoreId = MasterDataSeed.FortStoreId, - CreatedByUserId = MasterDataSeed.SalesRep1UserId, - FK_RideId = ClosedSaleRunId, + RaisedById = MasterDataSeed.SalesRep1UserId, + InvoiceId = Invoice1Id, TotalAmount = 3000m, - Status = SaleStatus.Completed, - PaymentStatus = PaymentStatus.Paid, - FulfillImmediately = false, - CompletedAt = new DateTime(2026, 8, 25, 9, 30, 0), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), - IsActive = true - }, - new Sale - { - Id = Sale2Id, - SaleDate = new DateTime(2026, 8, 30, 10, 0, 0), - FK_StoreId = MasterDataSeed.KandyStoreId, - CreatedByUserId = MasterDataSeed.SalesRep2UserId, - FK_RideId = ActiveDeliveryRunId, - TotalAmount = 1200m, - Status = SaleStatus.Pending, - PaymentStatus = PaymentStatus.Pending, - FulfillImmediately = false, - CompletedAt = null, - CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), - IsActive = true - } - ); - - modelBuilder.Entity().HasData( - new Order - { - Id = Order1Id, - FK_SaleId = Sale1Id, - OrderDate = new DateTime(2026, 8, 25, 9, 0, 0), - FK_StoreId = MasterDataSeed.FortStoreId, - TotalAmount = 3000m, - Status = OrderStatus.Fulfilled, + Status = ShopPOStatus.Fulfilled, + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0), + ConfirmedBy = MasterDataSeed.Supervisor1UserId, FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0), CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, - new Order + new ShopPO { - Id = Order2Id, - FK_SaleId = Sale2Id, - OrderDate = new DateTime(2026, 8, 30, 10, 0, 0), + Id = ShopPO2Id, FK_StoreId = MasterDataSeed.KandyStoreId, + RaisedById = MasterDataSeed.SalesRep2UserId, + InvoiceId = null, TotalAmount = 1200m, - Status = OrderStatus.Pending, + Status = ShopPOStatus.Pending, + ConfirmedAt = null, + ConfirmedBy = null, FulfilledAt = null, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true } ); - modelBuilder.Entity().HasData( - new OrderItem { Id = OrderItem1Id, FK_OrderId = Order1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, Quantity = 30, QuantityFulfilled = 30, UnitPrice = 60m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, - new OrderItem { Id = OrderItem2Id, FK_OrderId = Order1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, Quantity = 24, QuantityFulfilled = 24, UnitPrice = 50m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, - new OrderItem { Id = OrderItem3Id, FK_OrderId = Order2Id, FK_ItemId = MasterDataSeed.Coke1500ItemId, Quantity = 10, QuantityFulfilled = 0, UnitPrice = 120m, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true } + modelBuilder.Entity().HasData( + new ShopPOItem { Id = ShopPOItem1Id, FK_ShopPOId = ShopPO1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, Quantity = 30, QuantityFulfilled = 30, UnitPrice = 60m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, + new ShopPOItem { Id = ShopPOItem2Id, FK_ShopPOId = ShopPO1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, Quantity = 24, QuantityFulfilled = 24, UnitPrice = 50m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, + new ShopPOItem { Id = ShopPOItem3Id, FK_ShopPOId = ShopPO2Id, FK_ItemId = MasterDataSeed.Coke1500ItemId, Quantity = 10, QuantityFulfilled = 0, UnitPrice = 120m, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true } + ); + + modelBuilder.Entity().HasData( + new Invoice + { + Id = Invoice1Id, + FK_ShopPOId = ShopPO1Id, + Status = InvoiceStatus.Finalized, + PaymentStatus = PaymentStatus.Paid, + CreatedBy = MasterDataSeed.SalesRep1UserId, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0), + PrintedBy = MasterDataSeed.SalesRep1UserId, + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0), + FinalizedBy = MasterDataSeed.Supervisor1UserId, + TotalAmount = 3000m, + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0), + IsActive = true + } ); modelBuilder.Entity().HasData( @@ -135,20 +118,19 @@ public static class OperationsDataSeed { Id = LoadingSheet1Id, FK_RideId = ClosedSaleRunId, - FK_SourceWarehouseId = MasterDataSeed.ColomboWarehouseId, - Status = LoadingSheetStatus.ReceiptConfirmed, - DispatchConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0), - DispatchConfirmedBy = MasterDataSeed.Supervisor1UserId, - ReceiptConfirmedAt = new DateTime(2026, 8, 25, 14, 5, 0), - ReceiptConfirmedBy = MasterDataSeed.Driver1UserId, + Status = LoadingSheetStatus.Confirmed, + PopulatedBy = MasterDataSeed.Supervisor1UserId, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0), + ConfirmedBy = MasterDataSeed.Supervisor1UserId, CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0), IsActive = true } ); modelBuilder.Entity().HasData( - new LoadingSheetItem { Id = LoadingSheetItem1Id, FK_LoadingSheetId = LoadingSheet1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, QuantityDispatched = 50m, QuantityReceived = 50m, QuantityResolved = null }, - new LoadingSheetItem { Id = LoadingSheetItem2Id, FK_LoadingSheetId = LoadingSheet1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, QuantityDispatched = 30m, QuantityReceived = 30m, QuantityResolved = null } + new LoadingSheetItem { Id = LoadingSheetItem1Id, FK_LoadingSheetId = LoadingSheet1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, FK_WarehouseId = MasterDataSeed.ColomboWarehouseId, QuantityDispatched = 50m, CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0), IsActive = true }, + new LoadingSheetItem { Id = LoadingSheetItem2Id, FK_LoadingSheetId = LoadingSheet1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, FK_WarehouseId = MasterDataSeed.ColomboWarehouseId, QuantityDispatched = 30m, CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0), IsActive = true } ); modelBuilder.Entity().HasData( @@ -156,7 +138,7 @@ public static class OperationsDataSeed { Id = DeliveryTask1Id, FK_RideId = ActiveDeliveryRunId, - FK_OrderId = Order2Id, + FK_ShopPOId = ShopPO2Id, Sequence = 1, Status = DeliveryTaskStatus.Pending, CustomerConfirmed = false, diff --git a/Distribution/Features/DeliveryRide/DeliveryTaskDTOs.cs b/Distribution/Features/DeliveryRide/DeliveryTaskDTOs.cs index fd8a1ab..9fbe5e1 100644 --- a/Distribution/Features/DeliveryRide/DeliveryTaskDTOs.cs +++ b/Distribution/Features/DeliveryRide/DeliveryTaskDTOs.cs @@ -1,4 +1,4 @@ -using Distribution.Models; +using Distribution.Models; namespace Distribution.Features.DeliveryRide; @@ -7,7 +7,7 @@ public record DeliveryTaskItemResponse(Guid ItemId, string ItemName, int Quantit public record DeliveryTaskResponse( Guid Id, Guid FK_RideId, - Guid FK_OrderId, + Guid FK_ShopPOId, Guid StoreId, string StoreName, int Sequence, diff --git a/Distribution/Features/DeliveryRide/DeliveryTaskRepository.cs b/Distribution/Features/DeliveryRide/DeliveryTaskRepository.cs index 3e7aea7..e096063 100644 --- a/Distribution/Features/DeliveryRide/DeliveryTaskRepository.cs +++ b/Distribution/Features/DeliveryRide/DeliveryTaskRepository.cs @@ -1,4 +1,4 @@ -using Distribution.Data; +using Distribution.Data; using Distribution.Models; using Microsoft.EntityFrameworkCore; @@ -8,27 +8,27 @@ public class DeliveryTaskRepository(AppDBContext context) : IDeliveryTaskReposit { public async Task GetByIdAsync(Guid id) => await context.DeliveryTasks - .Include(t => t.Order) + .Include(t => t.ShopPO) .ThenInclude(o => o.Store) - .Include(t => t.Order) - .ThenInclude(o => o.OrderItems) + .Include(t => t.ShopPO) + .ThenInclude(o => o.Items.Where(i => i.IsActive)) .ThenInclude(i => i.Item) .FirstOrDefaultAsync(t => t.Id == id); public async Task> GetByRideIdAsync(Guid rideId) => await context.DeliveryTasks - .Include(t => t.Order) + .Include(t => t.ShopPO) .ThenInclude(o => o.Store) - .Include(t => t.Order) - .ThenInclude(o => o.OrderItems) + .Include(t => t.ShopPO) + .ThenInclude(o => o.Items.Where(i => i.IsActive)) .ThenInclude(i => i.Item) .Where(t => t.FK_RideId == rideId) .OrderBy(t => t.Sequence) .ToListAsync(); - public async Task ExistsForOrderAndRideAsync(Guid orderId, Guid rideId) => + public async Task ExistsForOrderAndRideAsync(Guid shopPOId, Guid rideId) => await context.DeliveryTasks - .AnyAsync(t => t.FK_OrderId == orderId && t.FK_RideId == rideId); + .AnyAsync(t => t.FK_ShopPOId == shopPOId && t.FK_RideId == rideId); public async Task AddAsync(DeliveryTask task) => await context.DeliveryTasks.AddAsync(task); diff --git a/Distribution/Features/DeliveryRide/DeliveryTaskService.cs b/Distribution/Features/DeliveryRide/DeliveryTaskService.cs index 265ef1f..5f1f336 100644 --- a/Distribution/Features/DeliveryRide/DeliveryTaskService.cs +++ b/Distribution/Features/DeliveryRide/DeliveryTaskService.cs @@ -1,6 +1,5 @@ -using Distribution.Features.Order; using Distribution.Features.Ride; -using Distribution.Features.Sale; +using Distribution.Features.ShopPO; using Distribution.Features.Stock; using Distribution.Infra.UoW; using Distribution.Models; @@ -10,23 +9,22 @@ namespace Distribution.Features.DeliveryRide; public class DeliveryTaskService( IDeliveryTaskRepository repo, IRideRepository rideRepo, - IOrderRepository orderRepo, - ISaleRepository saleRepo, + IShopPORepository shopPORepo, IStockRepository stockRepo, IUnitOfWork uow) { private static DeliveryTaskResponse ToResponse(DeliveryTask t) => new(t.Id, t.FK_RideId, - t.FK_OrderId, - t.Order.FK_StoreId, - t.Order.Store?.StoreName ?? string.Empty, + t.FK_ShopPOId, + t.ShopPO.FK_StoreId, + t.ShopPO.Store?.StoreName ?? string.Empty, t.Sequence, t.Status, t.CustomerConfirmed, t.ConfirmedAt, t.Note, - t.Order.OrderItems.Select(i => new DeliveryTaskItemResponse( + t.ShopPO.Items.Select(i => new DeliveryTaskItemResponse( i.FK_ItemId, i.Item?.Name ?? string.Empty, i.Quantity, @@ -34,52 +32,8 @@ public class DeliveryTaskService( i.UnitPrice)).ToList(), t.CreatedAt); - public async Task> GenerateAsync(Guid rideId, CancellationToken ct = default) - { - var ride = await rideRepo.GetByIdAsync(rideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.Active) - throw new InvalidOperationException("Tasks can only be generated for an Active ride"); - - if (ride.RideType != RideType.Delivery) - throw new InvalidOperationException("Tasks can only be generated for a Delivery ride"); - - var orders = await orderRepo.GetPendingByRouteIdAsync(ride.FK_RouteId); - - var created = new List(); - int sequence = 1; - - foreach (var order in orders) - { - if (await repo.ExistsForOrderAndRideAsync(order.Id, rideId)) - continue; - - var task = new DeliveryTask - { - FK_RideId = rideId, - FK_OrderId = order.Id, - Sequence = sequence++, - Status = DeliveryTaskStatus.Pending - }; - created.Add(task); - } - - if (created.Count == 0) - return new List(); - - await uow.BeginAsync(ct); - try - { - foreach (var task in created) - await repo.AddAsync(task); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - var saved = await repo.GetByRideIdAsync(rideId); - return saved.Select(ToResponse).ToList(); - } + public Task> GenerateAsync(Guid rideId, CancellationToken ct = default) => + throw new NotImplementedException("Delivery task auto-generation is deferred — route-based dispatch not yet implemented."); public async Task> GetByRideIdAsync(Guid rideId) { @@ -103,16 +57,16 @@ public class DeliveryTaskService( foreach (var input in request.Items) { - var orderItem = task.Order.OrderItems.FirstOrDefault(i => i.FK_ItemId == input.ItemId) - ?? throw new InvalidOperationException($"Item {input.ItemId} is not on this order"); + var shopPOItem = task.ShopPO.Items.FirstOrDefault(i => i.FK_ItemId == input.ItemId) + ?? throw new InvalidOperationException($"Item {input.ItemId} is not on this ShopPO"); if (input.QuantityFulfilled < 0) throw new InvalidOperationException($"QuantityFulfilled cannot be negative for item {input.ItemId}"); - if (input.QuantityFulfilled > orderItem.Quantity) + if (input.QuantityFulfilled > shopPOItem.Quantity) throw new InvalidOperationException($"QuantityFulfilled exceeds ordered quantity for item {input.ItemId}"); - orderItem.QuantityFulfilled = input.QuantityFulfilled; + shopPOItem.QuantityFulfilled = input.QuantityFulfilled; } await uow.BeginAsync(ct); @@ -135,7 +89,7 @@ public class DeliveryTaskService( if (task.Status != DeliveryTaskStatus.Pending) throw new InvalidOperationException("Only a Pending task can be confirmed"); - if (!task.Order.OrderItems.Any(i => i.QuantityFulfilled > 0)) + if (!task.ShopPO.Items.Any(i => i.QuantityFulfilled > 0)) throw new InvalidOperationException("Set quantities before confirming — at least one item must have a fulfilled quantity greater than zero"); var ride = await rideRepo.GetByIdAsync(task.FK_RideId) @@ -143,21 +97,21 @@ public class DeliveryTaskService( var vehicleId = ride.FK_VehicleId; - bool fullyDelivered = task.Order.OrderItems.All(i => i.QuantityFulfilled == i.Quantity); + bool fullyDelivered = task.ShopPO.Items.All(i => i.QuantityFulfilled == i.Quantity); task.CustomerConfirmed = true; task.ConfirmedAt = DateTime.Now; task.Status = fullyDelivered ? DeliveryTaskStatus.Delivered : DeliveryTaskStatus.PartiallyDelivered; - var order = task.Order; - order.Status = fullyDelivered ? OrderStatus.Fulfilled : OrderStatus.PartiallyFulfilled; + var shopPO = task.ShopPO; + shopPO.Status = fullyDelivered ? ShopPOStatus.Fulfilled : ShopPOStatus.PartiallyFulfilled; if (fullyDelivered) - order.FulfilledAt = DateTime.Now; + shopPO.FulfilledAt = DateTime.Now; await uow.BeginAsync(ct); try { - foreach (var item in task.Order.OrderItems.Where(i => i.QuantityFulfilled > 0)) + foreach (var item in task.ShopPO.Items.Where(i => i.QuantityFulfilled > 0)) { var vehicleBalance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId); var availableQuantity = vehicleBalance?.Quantity ?? 0; @@ -180,21 +134,12 @@ public class DeliveryTaskService( ToLocationType = LocationType.External, Quantity = item.QuantityFulfilled, Type = MovementType.Sale, - ReferenceId = task.FK_OrderId + ReferenceId = task.FK_ShopPOId }); } repo.Update(task); - orderRepo.Update(order); - - if (fullyDelivered) - { - var sale = await saleRepo.GetByIdAsync(order.FK_SaleId) - ?? throw new KeyNotFoundException("Sale not found"); - sale.Status = SaleStatus.Completed; - sale.CompletedAt = DateTime.Now; - saleRepo.Update(sale); - } + shopPORepo.Update(shopPO); await uow.CommitAsync(ct); } diff --git a/Distribution/Features/Invoice/IInvoiceRepository.cs b/Distribution/Features/Invoice/IInvoiceRepository.cs new file mode 100644 index 0000000..c4dc6ad --- /dev/null +++ b/Distribution/Features/Invoice/IInvoiceRepository.cs @@ -0,0 +1,13 @@ +using Distribution.Models; + +namespace Distribution.Features.Invoice; + +public interface IInvoiceRepository +{ + Task GetByIdAsync(Guid id); + Task GetByShopPOIdAsync(Guid shopPOId); + Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, int page, int pageSize); + Task GetCountAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status); + Task AddAsync(Models.Invoice invoice); + void Update(Models.Invoice invoice); +} diff --git a/Distribution/Features/Invoice/InvoiceController.cs b/Distribution/Features/Invoice/InvoiceController.cs new file mode 100644 index 0000000..5060dcf --- /dev/null +++ b/Distribution/Features/Invoice/InvoiceController.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Mvc; +using Distribution.Models; + +namespace Distribution.Features.Invoice; + +[ApiController] +[Route("api/invoices")] +public class InvoiceController(InvoiceService service) : ControllerBase +{ + [HttpGet] + public async Task GetAll( + [FromQuery] Guid? agentId, + [FromQuery] Guid? routeId, + [FromQuery] Guid? shopId, + [FromQuery] InvoiceStatus? status, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 20) + { + var result = await service.GetAllAsync(agentId, routeId, shopId, status, page, pageSize); + return Ok(result); + } + + [HttpGet("{id:guid}")] + public async Task GetById(Guid id) + { + var result = await service.GetByIdAsync(id); + return result is null ? NotFound() : Ok(result); + } +} diff --git a/Distribution/Features/Invoice/InvoiceDTOs.cs b/Distribution/Features/Invoice/InvoiceDTOs.cs new file mode 100644 index 0000000..dd1b413 --- /dev/null +++ b/Distribution/Features/Invoice/InvoiceDTOs.cs @@ -0,0 +1,22 @@ +using Distribution.Models; + +namespace Distribution.Features.Invoice; + +public record CreateInvoiceRequest(Guid ShopPOId); +public record InvoiceItemAdjustment(Guid ShopPOItemId, int AdjustedQuantity, string? Note = null); +public record FinalizeInvoiceRequest(List Adjustments); + +public record InvoiceResponse( + Guid Id, + Guid ShopPOId, + string StoreName, + InvoiceStatus Status, + PaymentStatus PaymentStatus, + Guid CreatedBy, + DateTime? PrintedAt, + Guid? PrintedBy, + DateTime? FinalizedAt, + Guid? FinalizedBy, + decimal TotalAmount, + bool IsActive, + DateTime CreatedAt); diff --git a/Distribution/Features/Invoice/InvoiceRepository.cs b/Distribution/Features/Invoice/InvoiceRepository.cs new file mode 100644 index 0000000..72faf5f --- /dev/null +++ b/Distribution/Features/Invoice/InvoiceRepository.cs @@ -0,0 +1,47 @@ +using Distribution.Data; +using Distribution.Models; +using Microsoft.EntityFrameworkCore; + +namespace Distribution.Features.Invoice; + +public class InvoiceRepository(AppDBContext context) : IInvoiceRepository +{ + public async Task GetByIdAsync(Guid id) => + await context.Invoices + .Include(i => i.ShopPO).ThenInclude(p => p.Store) + .Include(i => i.Payments.Where(p => p.IsActive)) + .FirstOrDefaultAsync(i => i.Id == id && i.IsActive); + + public async Task GetByShopPOIdAsync(Guid shopPOId) => + await context.Invoices + .Include(i => i.ShopPO) + .FirstOrDefaultAsync(i => i.FK_ShopPOId == shopPOId && i.IsActive); + + public async Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, int page, int pageSize) => + await context.Invoices + .Include(i => i.ShopPO).ThenInclude(p => p.Store) + .Where(i => i.IsActive + && (agentId == null || i.ShopPO.RaisedById == agentId) + && (routeId == null || i.ShopPO.Store.FK_RouteId == routeId) + && (shopId == null || i.ShopPO.FK_StoreId == shopId) + && (status == null || i.Status == status)) + .OrderByDescending(i => i.CreatedAt) + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + + public async Task GetCountAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status) => + await context.Invoices + .Include(i => i.ShopPO).ThenInclude(p => p.Store) + .CountAsync(i => i.IsActive + && (agentId == null || i.ShopPO.RaisedById == agentId) + && (routeId == null || i.ShopPO.Store.FK_RouteId == routeId) + && (shopId == null || i.ShopPO.FK_StoreId == shopId) + && (status == null || i.Status == status)); + + public async Task AddAsync(Models.Invoice invoice) => + await context.Invoices.AddAsync(invoice); + + public void Update(Models.Invoice invoice) => + context.Invoices.Update(invoice); +} diff --git a/Distribution/Features/Invoice/InvoiceService.cs b/Distribution/Features/Invoice/InvoiceService.cs new file mode 100644 index 0000000..51e20f1 --- /dev/null +++ b/Distribution/Features/Invoice/InvoiceService.cs @@ -0,0 +1,33 @@ +using Distribution.Features.Stock; +using Distribution.Infra.Authorization; +using Distribution.Infra.UoW; +using Distribution.Models; + +namespace Distribution.Features.Invoice; + +public class InvoiceService( + IInvoiceRepository repo, + IUnitOfWork uow, + ICurrentUserService currentUser) +{ + private static InvoiceResponse ToResponse(Models.Invoice i) => + new(i.Id, i.FK_ShopPOId, + i.ShopPO?.Store?.StoreName ?? string.Empty, + i.Status, i.PaymentStatus, i.CreatedBy, + i.PrintedAt, i.PrintedBy, + i.FinalizedAt, i.FinalizedBy, + i.TotalAmount, i.IsActive, i.CreatedAt); + + public async Task GetByIdAsync(Guid id) + { + var invoice = await repo.GetByIdAsync(id); + return invoice is null ? null : ToResponse(invoice); + } + + public async Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, int page, int pageSize) + { + var total = await repo.GetCountAsync(agentId, routeId, shopId, status); + var items = await repo.GetAllAsync(agentId, routeId, shopId, status, page, pageSize); + return new PagedResponse(page, pageSize, total, items.Select(ToResponse).ToList()); + } +} diff --git a/Distribution/Features/LoadingEvent/ILoadingSheetRepository.cs b/Distribution/Features/LoadingEvent/ILoadingSheetRepository.cs index 3e3cf52..44c24bf 100644 --- a/Distribution/Features/LoadingEvent/ILoadingSheetRepository.cs +++ b/Distribution/Features/LoadingEvent/ILoadingSheetRepository.cs @@ -8,7 +8,6 @@ public interface ILoadingSheetRepository Task GetActiveByRideIdAsync(Guid rideId); Task> GetAllAsync(Guid? rideId, LoadingSheetStatus? status, int page, int pageSize); Task GetCountAsync(Guid? rideId, LoadingSheetStatus? status); - Task> GetAggregatedOrderItemsByRouteIdAsync(Guid routeId); Task AddAsync(LoadingSheet sheet); void Update(LoadingSheet sheet); void RemoveItems(IEnumerable items); diff --git a/Distribution/Features/LoadingEvent/LoadingSheetController.cs b/Distribution/Features/LoadingEvent/LoadingSheetController.cs index 3d233ae..2c8ec3d 100644 --- a/Distribution/Features/LoadingEvent/LoadingSheetController.cs +++ b/Distribution/Features/LoadingEvent/LoadingSheetController.cs @@ -1,4 +1,4 @@ -using Distribution.Models; +using Distribution.Models; using Distribution.Infra.Authorization; using Microsoft.AspNetCore.Mvc; @@ -29,9 +29,10 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer [HttpPost] public async Task Create(CreateLoadingSheetRequest request, CancellationToken ct) { + var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); try { - var result = await service.CreateAsync(request, ct); + var result = await service.CreateAsync(request, userId, ct); return CreatedAtAction(nameof(GetById), new { id = result.Id }, result); } catch (KeyNotFoundException) { return NotFound(); } @@ -50,90 +51,13 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } - [HttpPost("{id:guid}/confirm-dispatch")] - public async Task ConfirmDispatch(Guid id, CancellationToken ct) + [HttpPost("{id:guid}/confirm")] + public async Task Confirm(Guid id, CancellationToken ct) { var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); try { - var result = await service.ConfirmDispatchAsync(id, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPut("{id:guid}/receipt-items")] - public async Task SetReceiptItems(Guid id, SetReceiptItemsRequest request, CancellationToken ct) - { - try - { - var result = await service.SetReceiptItemsAsync(id, request, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPost("{id:guid}/confirm-receipt")] - public async Task ConfirmReceipt(Guid id, ConfirmReceiptRequest request, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.ConfirmReceiptAsync(id, request, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPost("{id:guid}/resolve")] - public async Task Resolve(Guid id, ResolveDiscrepancyRequest request, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.ResolveAsync(id, request, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/dispatch")] - public async Task PatchDispatch(Guid id, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.ConfirmDispatchAsync(id, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/receipt")] - public async Task PatchReceipt(Guid id, PatchReceiptRequest request, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.PatchReceiptAsync(id, request.Items, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/resolve")] - public async Task PatchResolve(Guid id, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.PatchResolveAsync(id, userId, ct); + var result = await service.ConfirmAsync(id, userId, ct); return Ok(result); } catch (KeyNotFoundException) { return NotFound(); } diff --git a/Distribution/Features/LoadingEvent/LoadingSheetDTOs.cs b/Distribution/Features/LoadingEvent/LoadingSheetDTOs.cs index ae2e0d6..cbd9a23 100644 --- a/Distribution/Features/LoadingEvent/LoadingSheetDTOs.cs +++ b/Distribution/Features/LoadingEvent/LoadingSheetDTOs.cs @@ -5,37 +5,27 @@ namespace Distribution.Features.LoadingEvent; public record LoadingSheetResponse( Guid Id, Guid FK_RideId, - Guid FK_SourceWarehouseId, - string WarehouseName, LoadingSheetStatus Status, - DateTime? DispatchConfirmedAt, - Guid? DispatchConfirmedBy, - DateTime? ReceiptConfirmedAt, - Guid? ReceiptConfirmedBy, + Guid PopulatedBy, + DateTime PopulatedAt, + DateTime? ConfirmedAt, + Guid? ConfirmedBy, DateTime CreatedAt, - List Items); + List Items, + List Orders); public record LoadingSheetItemResponse( Guid Id, Guid FK_ItemId, string ItemName, + Guid FK_WarehouseId, + string WarehouseName, decimal QuantityDispatched, - decimal? QuantityReceived, - decimal? QuantityResolved); + Guid? FK_ShopPOItemId); + +public record LoadingSheetOrderResponse(Guid ShopPOId); public record CreateLoadingSheetRequest(Guid FK_RideId); public record SetItemsRequest(List Items); -public record SetItemInput(Guid FK_ItemId, decimal Quantity); - -public record SetReceiptItemsRequest(List Items); -public record ReceiptItemInput(Guid FK_ItemId, decimal QuantityReceived); - -public record ConfirmReceiptRequest(int Meterstart); - -public record ResolveDiscrepancyRequest(List Items, int Meterstart); -public record ResolveItemInput(Guid FK_ItemId, decimal QuantityResolved); - -// Combined PATCH endpoints used by the frontend -public record PatchReceiptItemInput(Guid ItemId, decimal QuantityReceived); -public record PatchReceiptRequest(List Items); +public record SetItemInput(Guid FK_ItemId, Guid FK_WarehouseId, decimal Quantity, Guid? FK_ShopPOItemId = null); diff --git a/Distribution/Features/LoadingEvent/LoadingSheetRepository.cs b/Distribution/Features/LoadingEvent/LoadingSheetRepository.cs index bb6c404..b4080e4 100644 --- a/Distribution/Features/LoadingEvent/LoadingSheetRepository.cs +++ b/Distribution/Features/LoadingEvent/LoadingSheetRepository.cs @@ -8,20 +8,20 @@ public class LoadingSheetRepository(AppDBContext context) : ILoadingSheetReposit { public async Task GetByIdAsync(Guid id) => await context.LoadingSheets - .Include(s => s.SourceWarehouse) .Include(s => s.Items).ThenInclude(i => i.Item) + .Include(s => s.Items).ThenInclude(i => i.Warehouse) + .Include(s => s.Orders) .FirstOrDefaultAsync(s => s.Id == id); public async Task GetActiveByRideIdAsync(Guid rideId) => await context.LoadingSheets - .FirstOrDefaultAsync(s => - s.FK_RideId == rideId && - s.Status != LoadingSheetStatus.ReceiptConfirmed && - s.Status != LoadingSheetStatus.Resolved); + .FirstOrDefaultAsync(s => s.FK_RideId == rideId && s.Status == LoadingSheetStatus.Planned); public async Task> GetAllAsync(Guid? rideId, LoadingSheetStatus? status, int page, int pageSize) => await context.LoadingSheets - .Include(s => s.SourceWarehouse) + .Include(s => s.Items).ThenInclude(i => i.Item) + .Include(s => s.Items).ThenInclude(i => i.Warehouse) + .Include(s => s.Orders) .Where(s => (rideId == null || s.FK_RideId == rideId) && (status == null || s.Status == status)) @@ -36,19 +36,6 @@ public class LoadingSheetRepository(AppDBContext context) : ILoadingSheetReposit (rideId == null || s.FK_RideId == rideId) && (status == null || s.Status == status)); - public async Task> GetAggregatedOrderItemsByRouteIdAsync(Guid routeId) - { - var groups = await context.OrderItems - .Where(oi => oi.IsActive - && oi.Order.IsActive - && oi.Order.Store.FK_RouteId == routeId - && (oi.Order.Status == OrderStatus.Pending || oi.Order.Status == OrderStatus.PartiallyFulfilled)) - .GroupBy(oi => oi.FK_ItemId) - .Select(g => new { ItemId = g.Key, TotalQty = g.Sum(oi => (decimal)(oi.Quantity - oi.QuantityFulfilled)) }) - .ToListAsync(); - return groups.Select(x => (x.ItemId, x.TotalQty)).ToList(); - } - public async Task AddAsync(LoadingSheet sheet) => await context.LoadingSheets.AddAsync(sheet); diff --git a/Distribution/Features/LoadingEvent/LoadingSheetService.cs b/Distribution/Features/LoadingEvent/LoadingSheetService.cs index dadcc42..a37d1e1 100644 --- a/Distribution/Features/LoadingEvent/LoadingSheetService.cs +++ b/Distribution/Features/LoadingEvent/LoadingSheetService.cs @@ -24,7 +24,7 @@ public class LoadingSheetService( return sheet is null ? null : ToResponse(sheet); } - public async Task CreateAsync(CreateLoadingSheetRequest request, CancellationToken ct = default) + public async Task CreateAsync(CreateLoadingSheetRequest request, Guid userId, CancellationToken ct = default) { var ride = await rideRepo.GetByIdAsync(request.FK_RideId) ?? throw new KeyNotFoundException("Ride not found"); @@ -34,22 +34,16 @@ public class LoadingSheetService( var existing = await repo.GetActiveByRideIdAsync(request.FK_RideId); if (existing is not null) - throw new InvalidOperationException("This ride already has an active loading sheet"); + throw new InvalidOperationException("This ride already has a Planned loading sheet"); var sheet = new LoadingSheet { FK_RideId = ride.Id, - FK_SourceWarehouseId = ride.FK_SourceWarehouseId, - Status = LoadingSheetStatus.Pending + Status = LoadingSheetStatus.Planned, + PopulatedBy = userId, + PopulatedAt = DateTime.Now }; - if (ride.RideType == RideType.Delivery) - { - var orderItems = await repo.GetAggregatedOrderItemsByRouteIdAsync(ride.FK_RouteId); - foreach (var (itemId, qty) in orderItems) - sheet.Items.Add(new LoadingSheetItem { FK_ItemId = itemId, QuantityDispatched = qty }); - } - await uow.BeginAsync(ct); try { @@ -67,8 +61,8 @@ public class LoadingSheetService( var sheet = await repo.GetByIdAsync(id) ?? throw new KeyNotFoundException("Loading sheet not found"); - if (sheet.Status != LoadingSheetStatus.Pending) - throw new InvalidOperationException("Items can only be changed while the sheet is Pending"); + if (sheet.Status != LoadingSheetStatus.Planned) + throw new InvalidOperationException("Items can only be changed while the sheet is Planned"); await uow.BeginAsync(ct); try @@ -78,6 +72,8 @@ public class LoadingSheetService( { FK_LoadingSheetId = sheet.Id, FK_ItemId = i.FK_ItemId, + FK_WarehouseId = i.FK_WarehouseId, + FK_ShopPOItemId = i.FK_ShopPOItemId, QuantityDispatched = i.Quantity })); await uow.CommitAsync(ct); @@ -88,289 +84,91 @@ public class LoadingSheetService( return ToResponse(saved!); } - public async Task ConfirmDispatchAsync(Guid id, Guid userId, CancellationToken ct = default) + public async Task ConfirmAsync(Guid id, Guid userId, CancellationToken ct = default) { var sheet = await repo.GetByIdAsync(id) ?? throw new KeyNotFoundException("Loading sheet not found"); - if (sheet.Status != LoadingSheetStatus.Pending) - throw new InvalidOperationException($"Cannot confirm dispatch for a sheet in {sheet.Status} status"); + if (sheet.Status != LoadingSheetStatus.Planned) + throw new InvalidOperationException($"Cannot confirm a sheet in {sheet.Status} status"); if (!sheet.Items.Any(i => i.QuantityDispatched > 0)) throw new InvalidOperationException("Sheet must have at least one item with quantity greater than zero"); - sheet.Status = LoadingSheetStatus.DispatchConfirmed; - sheet.DispatchConfirmedAt = DateTime.Now; - sheet.DispatchConfirmedBy = userId; - - await uow.BeginAsync(ct); - try { repo.Update(sheet); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - public async Task SetReceiptItemsAsync(Guid id, SetReceiptItemsRequest request, CancellationToken ct = default) - { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DispatchConfirmed) - throw new InvalidOperationException("Receipt quantities can only be set after dispatch is confirmed"); - - foreach (var input in request.Items) - { - var item = sheet.Items.FirstOrDefault(i => i.FK_ItemId == input.FK_ItemId) - ?? throw new InvalidOperationException($"Item {input.FK_ItemId} is not on this loading sheet"); - item.QuantityReceived = input.QuantityReceived; - } - - await uow.BeginAsync(ct); - try { repo.Update(sheet); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - public async Task ConfirmReceiptAsync(Guid id, ConfirmReceiptRequest request, Guid userId, CancellationToken ct = default) - { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DispatchConfirmed) - throw new InvalidOperationException($"Cannot confirm receipt for a sheet in {sheet.Status} status"); - - if (sheet.Items.Any(i => !i.QuantityReceived.HasValue)) - throw new InvalidOperationException("All items must have a received quantity before confirming receipt"); - var ride = await rideRepo.GetByIdAsync(sheet.FK_RideId) ?? throw new KeyNotFoundException("Ride not found"); - var hasDiscrepancy = sheet.Items.Any(i => i.QuantityReceived != i.QuantityDispatched); - await uow.BeginAsync(ct); try { - if (hasDiscrepancy) - { - sheet.Status = LoadingSheetStatus.DiscrepancyFlagged; - } - else - { - sheet.Status = LoadingSheetStatus.ReceiptConfirmed; - sheet.ReceiptConfirmedAt = DateTime.Now; - sheet.ReceiptConfirmedBy = userId; + await ApplyLoadMovementsAsync(sheet.Id, ride.FK_VehicleId, sheet.Items, userId); - var lines = sheet.Items.Select(i => (i.FK_ItemId, i.QuantityReceived!.Value)).ToList(); - await ApplyLoadMovementsAsync(sheet, ride.FK_VehicleId, lines, userId); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = request.Meterstart; - rideRepo.Update(ride); - } + sheet.Status = LoadingSheetStatus.Confirmed; + sheet.ConfirmedAt = DateTime.Now; + sheet.ConfirmedBy = userId; repo.Update(sheet); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } - return ToResponse(sheet); + var saved = await repo.GetByIdAsync(id); + return ToResponse(saved!); } - public async Task ResolveAsync(Guid id, ResolveDiscrepancyRequest request, Guid userId, CancellationToken ct = default) + private async Task ApplyLoadMovementsAsync(Guid sheetId, Guid vehicleId, List items, Guid userId) { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DiscrepancyFlagged) - throw new InvalidOperationException($"Cannot resolve a sheet in {sheet.Status} status"); - - foreach (var input in request.Items) + foreach (var item in items.Where(i => i.QuantityDispatched > 0)) { - var item = sheet.Items.FirstOrDefault(i => i.FK_ItemId == input.FK_ItemId) - ?? throw new InvalidOperationException($"Item {input.FK_ItemId} is not on this loading sheet"); - if (input.QuantityResolved < 0) - throw new InvalidOperationException("Resolved quantity cannot be negative"); - item.QuantityResolved = input.QuantityResolved; - } + var warehouseBalance = await stockRepo.GetBalanceAsync(item.FK_ItemId, item.FK_WarehouseId) + ?? throw new InvalidOperationException($"No stock found in warehouse for item {item.FK_ItemId}"); - if (sheet.Items.Any(i => !i.QuantityResolved.HasValue)) - throw new InvalidOperationException("All items must have a resolved quantity"); + if (warehouseBalance.Quantity < item.QuantityDispatched) + throw new InvalidOperationException($"Insufficient warehouse stock for item {item.FK_ItemId}"); - var ride = await rideRepo.GetByIdAsync(sheet.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - sheet.Status = LoadingSheetStatus.Resolved; - sheet.ReceiptConfirmedAt = DateTime.Now; - sheet.ReceiptConfirmedBy = userId; - - var lines = sheet.Items.Select(i => (i.FK_ItemId, i.QuantityResolved!.Value)).ToList(); - - await uow.BeginAsync(ct); - try - { - await ApplyLoadMovementsAsync(sheet, ride.FK_VehicleId, lines, userId); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = request.Meterstart; - rideRepo.Update(ride); - - repo.Update(sheet); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - public async Task PatchReceiptAsync(Guid id, List items, Guid userId, CancellationToken ct = default) - { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DispatchConfirmed) - throw new InvalidOperationException($"Cannot set receipt for a sheet in {sheet.Status} status"); - - foreach (var input in items) - { - var sheetItem = sheet.Items.FirstOrDefault(i => i.FK_ItemId == input.ItemId) - ?? throw new InvalidOperationException($"Item {input.ItemId} is not on this loading sheet"); - sheetItem.QuantityReceived = input.QuantityReceived; - } - - var ride = await rideRepo.GetByIdAsync(sheet.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - var hasDiscrepancy = sheet.Items.Any(i => i.QuantityReceived != i.QuantityDispatched); - - await uow.BeginAsync(ct); - try - { - if (hasDiscrepancy) - { - sheet.Status = LoadingSheetStatus.DiscrepancyFlagged; - } - else - { - sheet.Status = LoadingSheetStatus.ReceiptConfirmed; - sheet.ReceiptConfirmedAt = DateTime.Now; - sheet.ReceiptConfirmedBy = userId; - - var lines = sheet.Items.Select(i => (i.FK_ItemId, i.QuantityReceived!.Value)).ToList(); - await ApplyLoadMovementsAsync(sheet, ride.FK_VehicleId, lines, userId); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = 0; - rideRepo.Update(ride); - } - - repo.Update(sheet); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - public async Task PatchResolveAsync(Guid id, Guid userId, CancellationToken ct = default) - { - var sheet = await repo.GetByIdAsync(id) - ?? throw new KeyNotFoundException("Loading sheet not found"); - - if (sheet.Status != LoadingSheetStatus.DiscrepancyFlagged) - throw new InvalidOperationException($"Cannot resolve a sheet in {sheet.Status} status"); - - foreach (var item in sheet.Items) - { - if (!item.QuantityReceived.HasValue) - throw new InvalidOperationException($"Item {item.FK_ItemId} has no received quantity to resolve from"); - item.QuantityResolved = item.QuantityReceived.Value; - } - - var ride = await rideRepo.GetByIdAsync(sheet.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - sheet.Status = LoadingSheetStatus.Resolved; - sheet.ReceiptConfirmedAt = DateTime.Now; - sheet.ReceiptConfirmedBy = userId; - - var lines = sheet.Items.Select(i => (i.FK_ItemId, i.QuantityResolved!.Value)).ToList(); - - await uow.BeginAsync(ct); - try - { - await ApplyLoadMovementsAsync(sheet, ride.FK_VehicleId, lines, userId); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = 0; - rideRepo.Update(ride); - - repo.Update(sheet); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(sheet); - } - - private async Task ApplyLoadMovementsAsync(LoadingSheet sheet, Guid vehicleId, List<(Guid ItemId, decimal Qty)> lines, Guid userId) - { - foreach (var (itemId, qty) in lines.Where(l => l.Qty > 0)) - { - var warehouseBalance = await stockRepo.GetBalanceAsync(itemId, sheet.FK_SourceWarehouseId) - ?? throw new InvalidOperationException($"No stock found in warehouse for item {itemId}"); - if (warehouseBalance.Quantity < qty) - throw new InvalidOperationException($"Insufficient warehouse stock for item {itemId}"); - - warehouseBalance.Quantity -= qty; + warehouseBalance.Quantity -= item.QuantityDispatched; warehouseBalance.UpdatedAt = DateTime.Now; stockRepo.UpdateBalance(warehouseBalance); - var vehicleBalance = await stockRepo.GetBalanceAsync(itemId, vehicleId); + var vehicleBalance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId); if (vehicleBalance is null) { await stockRepo.AddBalanceAsync(new StockBalance { - FK_ItemId = itemId, + FK_ItemId = item.FK_ItemId, LocationId = vehicleId, LocationType = LocationType.Vehicle, - Quantity = qty + Quantity = item.QuantityDispatched }); } else { - vehicleBalance.Quantity += qty; + vehicleBalance.Quantity += item.QuantityDispatched; vehicleBalance.UpdatedAt = DateTime.Now; stockRepo.UpdateBalance(vehicleBalance); } await stockRepo.AddMovementAsync(new StockMovement { - FK_ItemId = itemId, - FromLocationId = sheet.FK_SourceWarehouseId, + FK_ItemId = item.FK_ItemId, + FromLocationId = item.FK_WarehouseId, FromLocationType = LocationType.Warehouse, ToLocationId = vehicleId, ToLocationType = LocationType.Vehicle, - Quantity = qty, + Quantity = item.QuantityDispatched, Type = MovementType.Load, - ReferenceId = sheet.Id, + ReferenceId = sheetId, CreatedBy = userId }); } } private static LoadingSheetResponse ToResponse(LoadingSheet s) => - new(s.Id, s.FK_RideId, s.FK_SourceWarehouseId, - s.SourceWarehouse?.Name ?? string.Empty, - s.Status, - s.DispatchConfirmedAt, s.DispatchConfirmedBy, - s.ReceiptConfirmedAt, s.ReceiptConfirmedBy, - s.CreatedAt, + new(s.Id, s.FK_RideId, s.Status, s.PopulatedBy, s.PopulatedAt, + s.ConfirmedAt, s.ConfirmedBy, s.CreatedAt, s.Items.Select(i => new LoadingSheetItemResponse( i.Id, i.FK_ItemId, i.Item?.Name ?? string.Empty, - i.QuantityDispatched, i.QuantityReceived, i.QuantityResolved)).ToList()); + i.FK_WarehouseId, i.Warehouse?.Name ?? string.Empty, + i.QuantityDispatched, i.FK_ShopPOItemId)).ToList(), + s.Orders.Select(o => new LoadingSheetOrderResponse(o.FK_ShopPOId)).ToList()); } diff --git a/Distribution/Features/Order/IOrderRepository.cs b/Distribution/Features/Order/IOrderRepository.cs deleted file mode 100644 index 856f12c..0000000 --- a/Distribution/Features/Order/IOrderRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Distribution.Features.Order; - -public interface IOrderRepository -{ - Task GetByIdAsync(Guid id); - Task> GetAllAsync(); - Task GetBySaleIdAsync(Guid saleId); - Task AddAsync(Models.Order entity); - void Update(Models.Order entity); - void Remove(Models.Order entity); - Task> GetItemsByOrderIdAsync(Guid orderId); - Task> GetByStoreIdAsync(Guid storeId); - Task AddItemsAsync(IEnumerable items); - Task> GetPendingByRouteIdAsync(Guid routeId); -} diff --git a/Distribution/Features/Order/OrderController.cs b/Distribution/Features/Order/OrderController.cs deleted file mode 100644 index a5f528c..0000000 --- a/Distribution/Features/Order/OrderController.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Distribution.Features.Order; - -[ApiController] -[Route("api/orders")] -public class OrderController(OrderService service) : ControllerBase -{ - [HttpGet] - public async Task GetAll() => - Ok(await service.GetAllAsync()); - - [HttpGet("{id:guid}")] - public async Task GetById(Guid id) - { - var result = await service.GetByIdAsync(id); - return result is null ? NotFound() : Ok(result); - } - - [HttpGet("store/{storeId:guid}")] - public async Task GetByStore(Guid storeId) - { - var result = await service.GetByStoreIdAsync(storeId); - return result is null ? StatusCode(StatusCodes.Status403Forbidden) : Ok(result); - } - - [HttpPost] - public async Task Create(CreateOrderRequest request, CancellationToken ct) - { - try - { - var result = await service.CreateAsync(request, ct); - return result is null ? StatusCode(StatusCodes.Status403Forbidden) : CreatedAtAction(nameof(GetById), new { id = result.Id }, result); - } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPut("{id:guid}")] - public async Task Update(Guid id, UpdateOrderRequest request, CancellationToken ct) - { - try - { - var result = await service.UpdateAsync(id, request, ct); - return result is null ? NotFound() : Ok(result); - } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpDelete("{id:guid}")] - public async Task Delete(Guid id, CancellationToken ct) - { - var deleted = await service.DeleteAsync(id, ct); - return deleted ? NoContent() : NotFound(); - } -} diff --git a/Distribution/Features/Order/OrderDTOs.cs b/Distribution/Features/Order/OrderDTOs.cs deleted file mode 100644 index 247eea4..0000000 --- a/Distribution/Features/Order/OrderDTOs.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Distribution.Models; - -namespace Distribution.Features.Order; - -public record CreateOrderRequest(Guid SaleId); - -public record UpdateOrderRequest(OrderStatus Status); - -public record OrderItemResponse(Guid ItemId, int Quantity, int QuantityFulfilled, decimal UnitPrice); - -public record OrderResponse( - Guid Id, - Guid SaleId, - DateTime OrderDate, - Guid StoreId, - decimal TotalAmount, - OrderStatus Status, - DateTime? FulfilledAt, - List Items, - bool IsActive, - DateTime CreatedAt); diff --git a/Distribution/Features/Order/OrderRepository.cs b/Distribution/Features/Order/OrderRepository.cs deleted file mode 100644 index 20fe8bb..0000000 --- a/Distribution/Features/Order/OrderRepository.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Distribution.Data; -using Distribution.Models; -using Microsoft.EntityFrameworkCore; - -namespace Distribution.Features.Order; - -public class OrderRepository(AppDBContext context) : IOrderRepository -{ - public async Task GetByIdAsync(Guid id) => - await context.Orders.FindAsync(id); - - public async Task> GetAllAsync() => - await context.Orders.ToListAsync(); - - public async Task GetBySaleIdAsync(Guid saleId) => - await context.Orders.FirstOrDefaultAsync(o => o.FK_SaleId == saleId && o.IsActive); - - public async Task AddAsync(Models.Order entity) => - await context.Orders.AddAsync(entity); - - public void Update(Models.Order entity) => - context.Orders.Update(entity); - - public void Remove(Models.Order entity) - { - entity.Status = Models.OrderStatus.Cancelled; - entity.IsActive = false; - context.Orders.Update(entity); - } - - public async Task> GetItemsByOrderIdAsync(Guid orderId) => - await context.OrderItems.Where(oi => oi.FK_OrderId == orderId).ToListAsync(); - - public async Task> GetByStoreIdAsync(Guid storeId) => - await context.Orders.Where(o => o.FK_StoreId == storeId && o.IsActive).ToListAsync(); - - public async Task AddItemsAsync(IEnumerable items) => - await context.OrderItems.AddRangeAsync(items); - - public async Task> GetPendingByRouteIdAsync(Guid routeId) => - await context.Orders - .Include(o => o.Store) - .Include(o => o.OrderItems) - .ThenInclude(i => i.Item) - .Where(o => o.IsActive - && o.Store.FK_RouteId == routeId - && (o.Status == OrderStatus.Pending || o.Status == OrderStatus.PartiallyFulfilled)) - .ToListAsync(); -} diff --git a/Distribution/Features/Order/OrderService.cs b/Distribution/Features/Order/OrderService.cs deleted file mode 100644 index 9e9f8b7..0000000 --- a/Distribution/Features/Order/OrderService.cs +++ /dev/null @@ -1,158 +0,0 @@ -using Distribution.Features.Sale; -using Distribution.Features.Item; -using Distribution.Features.PriceList; -using Distribution.Features.Store; -using Distribution.Features.Stock; -using Distribution.Infra.Authorization; -using Distribution.Infra.UoW; -using Distribution.Models; - -namespace Distribution.Features.Order; - -public class OrderService( - IOrderRepository repo, - IStoreRepository storeRepo, - IItemRepository itemRepo, - IStockRepository stockRepo, - PriceListService priceListService, - ISaleRepository saleRepo, - IUnitOfWork uow, - ICurrentUserService currentUser, - IScopeAccessService scopeAccess) -{ - private const int GlobalScopeRoleLevel = 50; - - private static OrderResponse ToResponse(Models.Order o, List items) => - new(o.Id, o.FK_SaleId, o.OrderDate, o.FK_StoreId, o.TotalAmount, o.Status, o.FulfilledAt, - items.Select(i => new OrderItemResponse(i.FK_ItemId, i.Quantity, i.QuantityFulfilled, i.UnitPrice)).ToList(), - o.IsActive, o.CreatedAt); - - private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel; - - private async Task HasStoreScopeAsync(Guid storeId) - { - if (HasGlobalScope || currentUser.UserId is null) return HasGlobalScope; - return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId); - } - - public async Task> GetAllAsync() - { - // Deleted orders stay IsActive=false but remain visible with a Cancelled status — - // Delete never removes the row from the list, only marks it cancelled. - var orders = (await repo.GetAllAsync()).ToList(); - if (!HasGlobalScope && currentUser.UserId is not null) - { - var accessibleStoreIds = (await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value)).ToHashSet(); - orders = orders.Where(o => accessibleStoreIds.Contains(o.FK_StoreId)).ToList(); - } - var result = new List(); - foreach (var order in orders) - { - var items = await repo.GetItemsByOrderIdAsync(order.Id); - result.Add(ToResponse(order, items)); - } - return result; - } - - public async Task GetByIdAsync(Guid id) - { - var order = await repo.GetByIdAsync(id); - if (order is null || !order.IsActive) return null; - if (!await HasStoreScopeAsync(order.FK_StoreId)) return null; - var items = await repo.GetItemsByOrderIdAsync(id); - return ToResponse(order, items); - } - - public async Task?> GetByStoreIdAsync(Guid storeId) - { - if (!await HasStoreScopeAsync(storeId)) return null; - var orders = await repo.GetByStoreIdAsync(storeId); - var result = new List(); - foreach (var order in orders) - { - var items = await repo.GetItemsByOrderIdAsync(order.Id); - result.Add(ToResponse(order, items)); - } - return result; - } - - public async Task CreateAsync(CreateOrderRequest request, CancellationToken ct = default) - { - var sale = await saleRepo.GetByIdAsync(request.SaleId); - if (sale is null || !sale.IsActive) return null; - if (!await HasStoreScopeAsync(sale.FK_StoreId)) return null; - - var existingOrder = await repo.GetBySaleIdAsync(request.SaleId) - ?? throw new InvalidOperationException("Orders are created automatically from sales"); - - var items = await repo.GetItemsByOrderIdAsync(existingOrder.Id); - return ToResponse(existingOrder, items); - } - - public async Task UpdateAsync(Guid id, UpdateOrderRequest request, CancellationToken ct = default) - { - // TEMPORARY: see DeleteAsync/SaleService — store-scope enforcement depends on the broken - // auth middleware (testbug.md #28) and would reject every update. Skipped for now. - var order = await repo.GetByIdAsync(id); - if (order is null || !order.IsActive) return null; - - var sale = await saleRepo.GetByIdAsync(order.FK_SaleId) - ?? throw new InvalidOperationException("Sale not found for this order"); - - order.Status = request.Status; - order.FulfilledAt = request.Status == OrderStatus.Fulfilled ? DateTime.Now : null; - - sale.Status = request.Status switch - { - OrderStatus.Fulfilled => SaleStatus.Completed, - OrderStatus.Cancelled => SaleStatus.Cancelled, - _ => SaleStatus.Pending - }; - sale.CompletedAt = request.Status == OrderStatus.Fulfilled ? DateTime.Now : null; - - await uow.BeginAsync(ct); - try - { - repo.Update(order); - saleRepo.Update(sale); - await uow.CommitAsync(ct); - } - catch - { - await uow.RollbackAsync(ct); - throw; - } - - var items = await repo.GetItemsByOrderIdAsync(id); - return ToResponse(order, items); - } - - public async Task DeleteAsync(Guid id, CancellationToken ct = default) - { - // TEMPORARY: see SaleService — store-scope enforcement depends on the broken auth - // middleware (testbug.md #28) and would reject every delete. Skipped for now. - var order = await repo.GetByIdAsync(id); - if (order is null || !order.IsActive) return false; - - var sale = await saleRepo.GetByIdAsync(order.FK_SaleId); - - await uow.BeginAsync(ct); - try - { - repo.Remove(order); - if (sale is not null) - { - sale.Status = SaleStatus.Cancelled; - sale.CompletedAt = null; - saleRepo.Update(sale); - } - await uow.CommitAsync(ct); - } - catch - { - await uow.RollbackAsync(ct); - throw; - } - return true; - } -} diff --git a/Distribution/Features/Payment/FlatPaymentController.cs b/Distribution/Features/Payment/FlatPaymentController.cs deleted file mode 100644 index a927c47..0000000 --- a/Distribution/Features/Payment/FlatPaymentController.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Distribution.Features.Payment; - -[ApiController] -[Route("api/payments")] -public class FlatPaymentController(PaymentService service) : ControllerBase -{ - [HttpGet] - public async Task GetAll( - [FromQuery] Guid? storeId, - [FromQuery] Guid? saleId, - [FromQuery] int page = 1, - [FromQuery] int pageSize = 20) - { - var result = await service.GetAllAsync(storeId, saleId, page, pageSize); - return Ok(result); - } - - [HttpGet("{id:guid}")] - public async Task GetById(Guid id) - { - var result = await service.GetByIdAsync(id); - return result is null ? NotFound() : Ok(result); - } - - [HttpPost] - public async Task Create(CreateFlatPaymentRequest request, CancellationToken ct) - { - try - { - var inner = new CreatePaymentRequest(request.Amount, request.Method, request.CollectedByUserId); - var result = await service.CreateAsync(request.SaleId, inner, ct); - return result is null ? NotFound(new { error = "Sale not found or access denied" }) : Ok(result); - } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } -} diff --git a/Distribution/Features/Payment/IPaymentRepository.cs b/Distribution/Features/Payment/IPaymentRepository.cs index 5e7d79d..6d26d14 100644 --- a/Distribution/Features/Payment/IPaymentRepository.cs +++ b/Distribution/Features/Payment/IPaymentRepository.cs @@ -1,12 +1,13 @@ -using Distribution.Models; +using Distribution.Models; namespace Distribution.Features.Payment; public interface IPaymentRepository { Task GetByIdAsync(Guid id); - Task> GetAllAsync(Guid? storeId, Guid? saleId, int page, int pageSize); - Task GetCountAsync(Guid? storeId, Guid? saleId); - Task> GetBySaleIdAsync(Guid saleId); + Task> GetAllAsync(Guid? invoiceId, int page, int pageSize); + Task GetCountAsync(Guid? invoiceId); + Task> GetByInvoiceIdAsync(Guid invoiceId); Task AddAsync(Models.Payment payment); + void Update(Models.Payment payment); } diff --git a/Distribution/Features/Payment/PaymentController.cs b/Distribution/Features/Payment/PaymentController.cs index 18fe7f3..d3e6e91 100644 --- a/Distribution/Features/Payment/PaymentController.cs +++ b/Distribution/Features/Payment/PaymentController.cs @@ -3,22 +3,22 @@ namespace Distribution.Features.Payment; [ApiController] -[Route("api/sales/{saleId:guid}/payments")] +[Route("api/invoices/{invoiceId:guid}/payments")] public class PaymentController(PaymentService service) : ControllerBase { [HttpGet] - public async Task GetBySale(Guid saleId) + public async Task GetByInvoice(Guid invoiceId) { - var result = await service.GetBySaleIdAsync(saleId); + var result = await service.GetByInvoiceIdAsync(invoiceId); return result is null ? NotFound() : Ok(result); } [HttpPost] - public async Task Create(Guid saleId, CreatePaymentRequest request, CancellationToken ct) + public async Task Create(Guid invoiceId, CreatePaymentRequest request, CancellationToken ct) { try { - var result = await service.CreateAsync(saleId, request, ct); + var result = await service.CreateAsync(invoiceId, request, ct); return result is null ? NotFound() : Ok(result); } catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } diff --git a/Distribution/Features/Payment/PaymentDTOs.cs b/Distribution/Features/Payment/PaymentDTOs.cs index 83e978a..20b886f 100644 --- a/Distribution/Features/Payment/PaymentDTOs.cs +++ b/Distribution/Features/Payment/PaymentDTOs.cs @@ -1,23 +1,15 @@ -using Distribution.Models; +using Distribution.Models; namespace Distribution.Features.Payment; public record CreatePaymentRequest( - decimal Amount, - PaymentMethod Method, - // TEMPORARY: auth middleware doesn't resolve a logged-in user yet — see testbug.md #28. - Guid? CollectedByUserId = null); - -public record CreateFlatPaymentRequest( - Guid SaleId, decimal Amount, PaymentMethod Method, Guid? CollectedByUserId = null); public record PaymentResponse( Guid Id, - Guid SaleId, - Guid StoreId, + Guid InvoiceId, decimal Amount, PaymentMethod Method, DateTime CollectedAt, diff --git a/Distribution/Features/Payment/PaymentRepository.cs b/Distribution/Features/Payment/PaymentRepository.cs index 13cd944..b490bf7 100644 --- a/Distribution/Features/Payment/PaymentRepository.cs +++ b/Distribution/Features/Payment/PaymentRepository.cs @@ -1,4 +1,4 @@ -using Distribution.Data; +using Distribution.Data; using Distribution.Models; using Microsoft.EntityFrameworkCore; @@ -9,29 +9,27 @@ public class PaymentRepository(AppDBContext context) : IPaymentRepository public async Task GetByIdAsync(Guid id) => await context.Payments.FirstOrDefaultAsync(p => p.Id == id && p.IsActive); - public async Task> GetAllAsync(Guid? storeId, Guid? saleId, int page, int pageSize) => + public async Task> GetAllAsync(Guid? invoiceId, int page, int pageSize) => await context.Payments - .Where(p => p.IsActive - && (storeId == null || p.FK_StoreId == storeId) - && (saleId == null || p.FK_SaleId == saleId)) + .Where(p => p.IsActive && (invoiceId == null || p.FK_InvoiceId == invoiceId)) .OrderByDescending(p => p.CollectedAt) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); - public async Task GetCountAsync(Guid? storeId, Guid? saleId) => + public async Task GetCountAsync(Guid? invoiceId) => await context.Payments - .Where(p => p.IsActive - && (storeId == null || p.FK_StoreId == storeId) - && (saleId == null || p.FK_SaleId == saleId)) - .CountAsync(); + .CountAsync(p => p.IsActive && (invoiceId == null || p.FK_InvoiceId == invoiceId)); - public async Task> GetBySaleIdAsync(Guid saleId) => + public async Task> GetByInvoiceIdAsync(Guid invoiceId) => await context.Payments - .Where(p => p.FK_SaleId == saleId && p.IsActive) + .Where(p => p.FK_InvoiceId == invoiceId && p.IsActive) .OrderBy(p => p.CollectedAt) .ToListAsync(); public async Task AddAsync(Models.Payment payment) => await context.Payments.AddAsync(payment); + + public void Update(Models.Payment payment) => + context.Payments.Update(payment); } diff --git a/Distribution/Features/Payment/PaymentService.cs b/Distribution/Features/Payment/PaymentService.cs index e98cdc1..43a9e5d 100644 --- a/Distribution/Features/Payment/PaymentService.cs +++ b/Distribution/Features/Payment/PaymentService.cs @@ -1,5 +1,4 @@ -using Distribution.Features.Sale; -using Distribution.Features.Stock; +using Distribution.Features.Invoice; using Distribution.Infra.Authorization; using Distribution.Infra.UoW; using Distribution.Models; @@ -8,51 +7,35 @@ namespace Distribution.Features.Payment; public class PaymentService( IPaymentRepository repo, - ISaleRepository saleRepo, + IInvoiceRepository invoiceRepo, IUnitOfWork uow, ICurrentUserService currentUser) { private static PaymentResponse ToResponse(Models.Payment p) => - new(p.Id, p.FK_SaleId, p.FK_StoreId, p.Amount, p.Method, p.CollectedAt, p.CollectedBy, p.CreatedAt); + new(p.Id, p.FK_InvoiceId, p.Amount, p.Method, p.CollectedAt, p.CollectedBy, p.CreatedAt); - public async Task> GetAllAsync(Guid? storeId, Guid? saleId, int page, int pageSize) + public async Task?> GetByInvoiceIdAsync(Guid invoiceId) { - var total = await repo.GetCountAsync(storeId, saleId); - var items = await repo.GetAllAsync(storeId, saleId, page, pageSize); - return new PagedResponse(page, pageSize, total, items.Select(ToResponse).ToList()); - } + var invoice = await invoiceRepo.GetByIdAsync(invoiceId); + if (invoice is null || !invoice.IsActive) return null; - public async Task GetByIdAsync(Guid id) - { - var payment = await repo.GetByIdAsync(id); - return payment is null ? null : ToResponse(payment); - } - - public async Task?> GetBySaleIdAsync(Guid saleId) - { - var sale = await saleRepo.GetByIdAsync(saleId); - if (sale is null || !sale.IsActive) return null; - - var payments = await repo.GetBySaleIdAsync(saleId); + var payments = await repo.GetByInvoiceIdAsync(invoiceId); return payments.Select(ToResponse).ToList(); } - public async Task CreateAsync(Guid saleId, CreatePaymentRequest request, CancellationToken ct = default) + public async Task CreateAsync(Guid invoiceId, CreatePaymentRequest request, CancellationToken ct = default) { - var sale = await saleRepo.GetByIdAsync(saleId); - if (sale is null || !sale.IsActive) return null; - if (sale.Status == SaleStatus.Cancelled) - throw new InvalidOperationException("Cannot record a payment against a cancelled sale"); + var invoice = await invoiceRepo.GetByIdAsync(invoiceId); + if (invoice is null || !invoice.IsActive) return null; + if (invoice.Status == InvoiceStatus.Finalized) + throw new InvalidOperationException("Cannot record a payment against a finalized invoice"); - // TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware - // (testbug.md #28) — fall back to the explicitly supplied user until that's fixed. var userId = currentUser.UserId ?? request.CollectedByUserId ?? throw new InvalidOperationException("CollectedByUserId is required while auth is unavailable"); var payment = new Models.Payment { - FK_SaleId = saleId, - FK_StoreId = sale.FK_StoreId, + FK_InvoiceId = invoiceId, Amount = request.Amount, Method = request.Method, CollectedAt = DateTime.Now, @@ -64,17 +47,16 @@ public class PaymentService( { await repo.AddAsync(payment); - var allPayments = await repo.GetBySaleIdAsync(saleId); + var allPayments = await repo.GetByInvoiceIdAsync(invoiceId); var total = allPayments.Sum(p => p.Amount) + request.Amount; - sale.PaymentStatus = total == 0 + invoice.PaymentStatus = total == 0 ? PaymentStatus.Pending - : total < sale.TotalAmount + : total < invoice.TotalAmount ? PaymentStatus.PartiallyPaid : PaymentStatus.Paid; - saleRepo.Update(sale); - + invoiceRepo.Update(invoice); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } diff --git a/Distribution/Features/Region/IRegionRepository.cs b/Distribution/Features/Region/IRegionRepository.cs index de27c38..36b8c95 100644 --- a/Distribution/Features/Region/IRegionRepository.cs +++ b/Distribution/Features/Region/IRegionRepository.cs @@ -42,5 +42,5 @@ public interface IRegionRepository Task> GetRoutesAsync(Guid regionId); Task> GetStoresByRouteIdsAsync(List routeIds); - Task> GetOrdersForDashboardAsync(Guid regionId, DateTime periodStart, DateTime periodEndExclusive); + Task> GetOrdersForDashboardAsync(Guid regionId, DateTime periodStart, DateTime periodEndExclusive); } diff --git a/Distribution/Features/Region/RegionRepository.cs b/Distribution/Features/Region/RegionRepository.cs index 428ad5e..c760c31 100644 --- a/Distribution/Features/Region/RegionRepository.cs +++ b/Distribution/Features/Region/RegionRepository.cs @@ -129,11 +129,11 @@ public class RegionRepository(AppDBContext context) : IRegionRepository public async Task> GetStoresByRouteIdsAsync(List routeIds) => await context.Stores.Where(s => routeIds.Contains(s.FK_RouteId) && s.IsActive).ToListAsync(); - public async Task> GetOrdersForDashboardAsync(Guid regionId, DateTime periodStart, DateTime periodEndExclusive) => - await (from o in context.Orders + public async Task> GetOrdersForDashboardAsync(Guid regionId, DateTime periodStart, DateTime periodEndExclusive) => + await (from o in context.ShopPOs join s in context.Stores on o.FK_StoreId equals s.Id join r in context.Routes on s.FK_RouteId equals r.Id where r.FK_RegionId == regionId && o.IsActive && s.IsActive && r.IsActive - && o.OrderDate >= periodStart && o.OrderDate < periodEndExclusive + && o.CreatedAt >= periodStart && o.CreatedAt < periodEndExclusive select o).ToListAsync(); } diff --git a/Distribution/Features/Region/RegionService.cs b/Distribution/Features/Region/RegionService.cs index e04cc2d..ce26dc8 100644 --- a/Distribution/Features/Region/RegionService.cs +++ b/Distribution/Features/Region/RegionService.cs @@ -219,7 +219,7 @@ public class RegionService(IRegionRepository repo, IUnitOfWork uow, ICurrentUser budget?.BudgetAmount, orders.Count, orders.Sum(o => o.TotalAmount), - orders.Count == 0 ? null : orders.Max(o => o.OrderDate), + orders.Count == 0 ? null : orders.Max(o => o.CreatedAt), taxRule?.RuleConfig, agencyMaps.Select(m => m.FK_AgencyUserId).ToList()); } diff --git a/Distribution/Features/Returns/IReturnRepository.cs b/Distribution/Features/Returns/IReturnRepository.cs index efd2bce..3dc7545 100644 --- a/Distribution/Features/Returns/IReturnRepository.cs +++ b/Distribution/Features/Returns/IReturnRepository.cs @@ -4,11 +4,11 @@ public interface IReturnRepository { Task GetByIdAsync(Guid id); Task> GetAllAsync(); - Task> GetByOrderIdAsync(Guid orderId); + Task> GetByShopPOIdAsync(Guid shopPOId); Task AddAsync(Models.SaleReturn entity); void Update(Models.SaleReturn entity); Task AddCreditNoteAsync(Models.CreditNote entity); - /// Whether this store has ever had this item on any of its (active) orders. + /// Whether this store has ever had this item on any of its (active) ShopPOs. Task StoreHasPriorSaleAsync(Guid storeId, Guid itemId); } diff --git a/Distribution/Features/Returns/ReturnController.cs b/Distribution/Features/Returns/ReturnController.cs index 4612ed5..24cfb7c 100644 --- a/Distribution/Features/Returns/ReturnController.cs +++ b/Distribution/Features/Returns/ReturnController.cs @@ -1,4 +1,4 @@ -using Distribution.Infra.Authorization; +using Distribution.Infra.Authorization; using Microsoft.AspNetCore.Mvc; namespace Distribution.Features.Returns; @@ -28,15 +28,13 @@ public class ReturnController(ReturnService service, ICurrentUserService current catch (InvalidOperationException ex) { return Conflict(new { error = ex.Message }); } } - [HttpGet("api/orders/{id:guid}/returns")] - public async Task GetByOrder(Guid id) => - Ok(await service.GetByOrderIdAsync(id)); + [HttpGet("api/shop-pos/{id:guid}/returns")] + public async Task GetByShopPO(Guid id) => + Ok(await service.GetByShopPOIdAsync(id)); - [HttpPost("api/orders/{id:guid}/returns")] + [HttpPost("api/shop-pos/{id:guid}/returns")] public async Task Create(Guid id, CreateSaleReturnRequest request, CancellationToken ct) { - // TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware - // (testbug.md #28) — fall back to the explicitly supplied user until that's fixed. var userId = currentUser.UserId ?? request.CreatedByUserId; if (userId is null) return BadRequest(new { error = "CreatedByUserId is required while auth is unavailable" }); try @@ -44,6 +42,7 @@ public class ReturnController(ReturnService service, ICurrentUserService current var result = await service.CreateAsync(id, request, userId.Value, ct); return CreatedAtAction(nameof(GetById), new { id = result.Id }, result); } + catch (NotImplementedException ex) { return StatusCode(501, new { error = ex.Message }); } catch (InvalidOperationException ex) { return Conflict(new { error = ex.Message }); } } } diff --git a/Distribution/Features/Returns/ReturnDTOs.cs b/Distribution/Features/Returns/ReturnDTOs.cs index 834ca98..ead721d 100644 --- a/Distribution/Features/Returns/ReturnDTOs.cs +++ b/Distribution/Features/Returns/ReturnDTOs.cs @@ -27,7 +27,7 @@ public record SaleReturnItemResponse( public record SaleReturnResponse( Guid Id, - Guid OrderId, + Guid ShopPOId, ReturnMode Mode, decimal TotalCreditAmount, decimal OrderTotalAmountAfter, diff --git a/Distribution/Features/Returns/ReturnRepository.cs b/Distribution/Features/Returns/ReturnRepository.cs index ee553f5..497f8ae 100644 --- a/Distribution/Features/Returns/ReturnRepository.cs +++ b/Distribution/Features/Returns/ReturnRepository.cs @@ -7,23 +7,23 @@ public class ReturnRepository(AppDBContext context) : IReturnRepository { public async Task GetByIdAsync(Guid id) => await context.SaleReturns - .Include(r => r.Order) + .Include(r => r.ShopPO) .Include(r => r.Items).ThenInclude(i => i.Item) .FirstOrDefaultAsync(r => r.Id == id); public async Task> GetAllAsync() => await context.SaleReturns - .Include(r => r.Order) + .Include(r => r.ShopPO) .Include(r => r.Items).ThenInclude(i => i.Item) .Where(r => r.IsActive) .OrderByDescending(r => r.CreatedAt) .ToListAsync(); - public async Task> GetByOrderIdAsync(Guid orderId) => + public async Task> GetByShopPOIdAsync(Guid shopPOId) => await context.SaleReturns - .Include(r => r.Order) + .Include(r => r.ShopPO) .Include(r => r.Items).ThenInclude(i => i.Item) - .Where(r => r.FK_OrderId == orderId && r.IsActive) + .Where(r => r.FK_ShopPOId == shopPOId && r.IsActive) .OrderByDescending(r => r.CreatedAt) .ToListAsync(); @@ -37,7 +37,7 @@ public class ReturnRepository(AppDBContext context) : IReturnRepository await context.CreditNotes.AddAsync(entity); public async Task StoreHasPriorSaleAsync(Guid storeId, Guid itemId) => - await context.OrderItems - .Include(oi => oi.Order) - .AnyAsync(oi => oi.Order.FK_StoreId == storeId && oi.Order.IsActive && oi.FK_ItemId == itemId); + await context.ShopPOItems + .Include(oi => oi.ShopPO) + .AnyAsync(oi => oi.ShopPO.FK_StoreId == storeId && oi.ShopPO.IsActive && oi.FK_ItemId == itemId); } diff --git a/Distribution/Features/Returns/ReturnService.cs b/Distribution/Features/Returns/ReturnService.cs index 731bc18..83ab2e5 100644 --- a/Distribution/Features/Returns/ReturnService.cs +++ b/Distribution/Features/Returns/ReturnService.cs @@ -1,7 +1,5 @@ using Distribution.Features.Item; -using Distribution.Features.Order; -using Distribution.Features.Ride; -using Distribution.Features.Sale; +using Distribution.Features.ShopPO; using Distribution.Features.Stock; using Distribution.Infra.UoW; using Distribution.Models; @@ -10,9 +8,7 @@ namespace Distribution.Features.Returns; public class ReturnService( IReturnRepository repo, - IOrderRepository orderRepo, - ISaleRepository saleRepo, - IRideRepository rideRepo, + IShopPORepository shopPORepo, IItemRepository itemRepo, IStockRepository stockRepo, IUnitOfWork uow) @@ -21,7 +17,7 @@ public class ReturnService( new(i.Id, i.FK_ItemId, i.Item.Sku, i.Item.Name, i.Quantity, i.ReasonCode, i.UnitPrice); private static SaleReturnResponse Map(SaleReturn r) => - new(r.Id, r.FK_OrderId, r.Mode, r.TotalCreditAmount, r.Order.TotalAmount, r.IsActive, r.CreatedAt, + new(r.Id, r.FK_ShopPOId, r.Mode, r.TotalCreditAmount, r.ShopPO.TotalAmount, r.IsActive, r.CreatedAt, r.Items.Where(i => i.IsActive).Select(MapItem).ToList()); public async Task GetByIdAsync(Guid id) @@ -58,141 +54,9 @@ public class ReturnService( return Map(r); } - public async Task> GetByOrderIdAsync(Guid orderId) => - (await repo.GetByOrderIdAsync(orderId)).Select(Map).ToList(); + public async Task> GetByShopPOIdAsync(Guid shopPOId) => + (await repo.GetByShopPOIdAsync(shopPOId)).Select(Map).ToList(); - /// - /// Records a return recognized during the same store visit as an open order and settles it - /// immediately: stock is credited back to the rep's vehicle, and either the order total is - /// reduced (CreditDeduction) or the matching order line quantities are reduced (ItemExchange). - /// A return is only allowed for an item the store has previously ordered. - /// - public async Task CreateAsync(Guid orderId, CreateSaleReturnRequest request, Guid createdByUserId, CancellationToken ct = default) - { - var order = await orderRepo.GetByIdAsync(orderId); - if (order is null || !order.IsActive) - throw new InvalidOperationException("Order not found."); - if (order.Status is OrderStatus.Cancelled or OrderStatus.Fulfilled) - throw new InvalidOperationException("Cannot record a return against a closed order."); - - if (request.Items is null || request.Items.Count == 0) - throw new InvalidOperationException("A return must have at least one line item."); - - var sale = await saleRepo.GetByIdAsync(order.FK_SaleId) - ?? throw new InvalidOperationException("Sale not found for this order."); - if (sale.FK_RideId is null) - throw new InvalidOperationException("A return can only be recorded for an order created during an active ride."); - - var ride = await rideRepo.GetByIdAsync(sale.FK_RideId.Value) - ?? throw new InvalidOperationException("Ride not found."); - var vehicleId = ride.FK_VehicleId; - - var orderItems = await orderRepo.GetItemsByOrderIdAsync(orderId); - var orderItemsByItemId = orderItems.ToDictionary(oi => oi.FK_ItemId); - - var saleReturn = new SaleReturn - { - FK_OrderId = orderId, - Mode = request.Mode, - CreatedByUserId = createdByUserId - }; - - foreach (var line in request.Items) - { - if (line.Quantity <= 0) - throw new InvalidOperationException("Return quantity must be greater than zero."); - - var item = await itemRepo.GetByIdAsync(line.ItemId) - ?? throw new InvalidOperationException($"Item {line.ItemId} not found."); - - if (!await repo.StoreHasPriorSaleAsync(order.FK_StoreId, line.ItemId)) - throw new InvalidOperationException($"No prior sale of item '{item.Name}' found for this store."); - - var unitPrice = orderItemsByItemId.TryGetValue(line.ItemId, out var matchingOrderItem) - ? matchingOrderItem.UnitPrice - : item.SalePrice ?? 0; - - saleReturn.Items.Add(new SaleReturnItem - { - FK_ItemId = line.ItemId, - Quantity = line.Quantity, - ReasonCode = line.ReasonCode, - UnitPrice = unitPrice - }); - } - - await uow.BeginAsync(ct); - try - { - foreach (var line in saleReturn.Items) - { - var balance = await stockRepo.GetBalanceAsync(line.FK_ItemId, vehicleId); - if (balance is null) - { - await stockRepo.AddBalanceAsync(new StockBalance - { - FK_ItemId = line.FK_ItemId, - LocationId = vehicleId, - LocationType = LocationType.Vehicle, - Quantity = line.Quantity - }); - } - else - { - balance.Quantity += line.Quantity; - balance.UpdatedAt = DateTime.Now; - stockRepo.UpdateBalance(balance); - } - - await stockRepo.AddMovementAsync(new StockMovement - { - FK_ItemId = line.FK_ItemId, - FromLocationId = StockService.ExternalLocationId, - FromLocationType = LocationType.External, - ToLocationId = vehicleId, - ToLocationType = LocationType.Vehicle, - Quantity = line.Quantity, - Type = MovementType.CustomerReturn, - ReasonCode = line.ReasonCode.ToString(), - ReferenceId = saleReturn.Id, - CreatedBy = createdByUserId - }); - } - - await repo.AddAsync(saleReturn); - - if (request.Mode == ReturnMode.CreditDeduction) - { - var total = saleReturn.Items.Sum(i => i.Quantity * i.UnitPrice); - saleReturn.TotalCreditAmount = total; - order.TotalAmount = Math.Max(0, order.TotalAmount - total); - orderRepo.Update(order); - - await repo.AddCreditNoteAsync(new CreditNote - { - FK_SaleReturnId = saleReturn.Id, - Amount = total - }); - } - else // ItemExchange - { - foreach (var line in saleReturn.Items) - { - if (!orderItemsByItemId.TryGetValue(line.FK_ItemId, out var orderItem)) - continue; // no matching line on this order — nothing to offset - - var offsetQty = Math.Min(line.Quantity, orderItem.Quantity); - orderItem.Quantity -= (int)offsetQty; - order.TotalAmount = Math.Max(0, order.TotalAmount - offsetQty * orderItem.UnitPrice); - } - orderRepo.Update(order); - } - - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - var saved = await repo.GetByIdAsync(saleReturn.Id); - return Map(saved!); - } + public Task CreateAsync(Guid shopPOId, CreateSaleReturnRequest request, Guid createdByUserId, CancellationToken ct = default) => + throw new NotImplementedException("Return flow is being redesigned — not yet implemented."); } diff --git a/Distribution/Features/Ride/IRideRepository.cs b/Distribution/Features/Ride/IRideRepository.cs index 8a44d30..bc6206c 100644 --- a/Distribution/Features/Ride/IRideRepository.cs +++ b/Distribution/Features/Ride/IRideRepository.cs @@ -1,22 +1,13 @@ -using Distribution.Models; +using Distribution.Models; namespace Distribution.Features.Ride; public interface IRideRepository { Task GetByIdAsync(Guid id); - Task> GetAllAsync(RideStatus? status, RideType? type, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize); - Task GetCountAsync(RideStatus? status, RideType? type, Guid? driverProfileId, Guid? vehicleId); - Task HasOpenOrActiveRideForVehicleAsync(Guid vehicleId, Guid? excludeRideId = null); - Task> GetActiveRidesAsync(Guid? excludeRideId = null); - Task> GetActiveOrdersByRouteIdAsync(Guid routeId); + Task> GetAllAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize); + Task GetCountAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId); + Task HasOpenRideForVehicleAsync(Guid vehicleId, Guid? excludeRideId = null); Task AddAsync(DeliveryRun ride); void Update(DeliveryRun ride); } - -public record OrderSummaryModel( - Guid Id, - Guid StoreId, - string StoreName, - DateTime OrderDate, - decimal TotalAmount); diff --git a/Distribution/Features/Ride/RideController.cs b/Distribution/Features/Ride/RideController.cs index 008d8ee..ec0086d 100644 --- a/Distribution/Features/Ride/RideController.cs +++ b/Distribution/Features/Ride/RideController.cs @@ -1,23 +1,21 @@ -using Distribution.Infra.Authorization; -using Distribution.Models; +using Distribution.Models; using Microsoft.AspNetCore.Mvc; namespace Distribution.Features.Ride; [ApiController] [Route("api/rides")] -public class RideController(RideService service, ICurrentUserService currentUser) : ControllerBase +public class RideController(RideService service) : ControllerBase { [HttpGet] public async Task GetAll( [FromQuery] RideStatus? status, - [FromQuery] RideType? type, [FromQuery] Guid? driverProfileId, [FromQuery] Guid? vehicleId, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { - var result = await service.GetAllAsync(status, type, driverProfileId, vehicleId, page, pageSize); + var result = await service.GetAllAsync(status, driverProfileId, vehicleId, page, pageSize); return Ok(result); } @@ -31,8 +29,12 @@ public class RideController(RideService service, ICurrentUserService currentUser [HttpPost] public async Task Create(CreateRideRequest request, CancellationToken ct) { - var result = await service.CreateAsync(request, ct); - return CreatedAtAction(nameof(GetById), new { id = result.Id }, result); + try + { + var result = await service.CreateAsync(request, ct); + return CreatedAtAction(nameof(GetById), new { id = result.Id }, result); + } + catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } [HttpPut("{id:guid}/driver")] @@ -47,32 +49,6 @@ public class RideController(RideService service, ICurrentUserService currentUser catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } - [HttpPost("{id:guid}/open")] - public async Task Open(Guid id, CancellationToken ct) - { - try - { - var result = await service.OpenAsync(id, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/activate")] - [HttpPost("{id:guid}/activate")] - public async Task Activate(Guid id, ActivateRideRequest request, CancellationToken ct) - { - try - { - var result = await service.ActivateAsync(id, request, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/close")] [HttpPost("{id:guid}/close")] public async Task Close(Guid id, CloseRideRequest request, CancellationToken ct) { @@ -85,70 +61,15 @@ public class RideController(RideService service, ICurrentUserService currentUser catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } - [HttpPost("{id:guid}/cancel-request")] - public async Task RaiseCancelRequest(Guid id, RaiseCancelRequest request, CancellationToken ct) + [HttpPost("{id:guid}/cancel")] + public async Task Cancel(Guid id, CancelRideRequest request, CancellationToken ct) { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); try { - var result = await service.RaiseCancelRequestAsync(id, request, userId, ct); + var result = await service.CancelAsync(id, request, ct); return Ok(result); } catch (KeyNotFoundException) { return NotFound(); } catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } - - [HttpGet("cancel-requests")] - public async Task GetCancelRequests( - [FromQuery] CancelRequestStatus? status, - [FromQuery] int page = 1, - [FromQuery] int pageSize = 20) - { - var result = await service.GetCancelRequestsAsync(status, page, pageSize); - return Ok(result); - } - - [HttpPost("cancel-requests/{id:guid}/approve")] - public async Task ApproveCancelRequest(Guid id, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.ApproveCancelAsync(id, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPost("cancel-requests/{id:guid}/reject")] - public async Task RejectCancelRequest(Guid id, CancellationToken ct) - { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); - try - { - var result = await service.RejectCancelAsync(id, userId, ct); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpGet("{id:guid}/cancel-request")] - public async Task GetCancelRequest(Guid id) - { - var result = await service.GetCancelRequestAsync(id); - return result is null ? NotFound() : Ok(result); - } - - [HttpGet("breakdown-assist/{rideId:guid}")] - public async Task GetBreakdownAssist(Guid rideId) - { - try - { - var result = await service.GetBreakdownAssistAsync(rideId); - return Ok(result); - } - catch (KeyNotFoundException) { return NotFound(); } - } } diff --git a/Distribution/Features/Ride/RideDTOs.cs b/Distribution/Features/Ride/RideDTOs.cs index d43b3c3..49beed7 100644 --- a/Distribution/Features/Ride/RideDTOs.cs +++ b/Distribution/Features/Ride/RideDTOs.cs @@ -1,73 +1,27 @@ -using Distribution.Models; -using Distribution.Features.Stock; +using Distribution.Models; namespace Distribution.Features.Ride; -// Ride (DeliveryRun) public record RideResponse( Guid Id, - RideType RideType, RideStatus Status, Guid VehicleId, string VehicleNumberPlate, Guid DriverProfileId, string DriverFullName, - Guid RouteId, - string RouteName, - Guid SourceWarehouseId, - string SourceWarehouseName, int Meterstart, int Meterend, DateTime? StartedAt, - DateTime? ActivatedAt, DateTime? ClosedAt, DateTime CreatedAt); public record CreateRideRequest( - RideType RideType, Guid VehicleId, Guid DriverProfileId, - Guid RouteId, - Guid? SourceWarehouseId); + int Meterstart); public record AssignRideDriverRequest(Guid DriverProfileId); -public record ActivateRideRequest(int Meterstart); - public record CloseRideRequest(int Meterend); -public record RaiseCancelRequest(CancelRequestType TypeCode, string Reason); - -// Cancel Request -public record RideCancelRequestResponse( - Guid Id, - Guid RideId, - CancelRequestType TypeCode, - string Reason, - Guid RequestedBy, - DateTime RequestedAt, - CancelRequestStatus Status, - Guid? ApprovedBy, - DateTime? ApprovedAt); - -public record BreakdownAssistRideResponse( - Guid RideId, - Guid VehicleId, - string VehicleNumberPlate, - Guid DriverProfileId, - string DriverFullName, - Guid RouteId, - string RouteName, - List StockLevels); - -public record BreakdownAssistOrderResponse( - Guid OrderId, - Guid StoreId, - string StoreName, - DateTime OrderDate, - decimal TotalAmount); - -public record BreakdownAssistResponse( - Guid RideId, - List ActiveRides, - List OpenOrders); +public record CancelRideRequest(CancelRequestType TypeCode, string Reason); diff --git a/Distribution/Features/Ride/RideRepository.cs b/Distribution/Features/Ride/RideRepository.cs index d2b0d07..6c52907 100644 --- a/Distribution/Features/Ride/RideRepository.cs +++ b/Distribution/Features/Ride/RideRepository.cs @@ -1,4 +1,4 @@ -using Distribution.Data; +using Distribution.Data; using Distribution.Models; using Microsoft.EntityFrameworkCore; @@ -10,59 +10,32 @@ public class RideRepository(AppDBContext context) : IRideRepository await context.DeliveryRuns .Include(r => r.Vehicle) .Include(r => r.DriverProfile).ThenInclude(dp => dp.User) - .Include(r => r.Route) - .Include(r => r.SourceWarehouse) .FirstOrDefaultAsync(r => r.Id == id); - public async Task> GetAllAsync(RideStatus? status, RideType? type, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize) => + public async Task> GetAllAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize) => await context.DeliveryRuns .Include(r => r.Vehicle) .Include(r => r.DriverProfile).ThenInclude(dp => dp.User) - .Include(r => r.Route) - .Include(r => r.SourceWarehouse) .Where(r => (status == null || r.Status == status) && - (type == null || r.RideType == type) && (driverProfileId == null || r.FK_DriverProfileId == driverProfileId) && (vehicleId == null || r.FK_VehicleId == vehicleId)) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); - public async Task GetCountAsync(RideStatus? status, RideType? type, Guid? driverProfileId, Guid? vehicleId) => + public async Task GetCountAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId) => await context.DeliveryRuns .CountAsync(r => (status == null || r.Status == status) && - (type == null || r.RideType == type) && (driverProfileId == null || r.FK_DriverProfileId == driverProfileId) && (vehicleId == null || r.FK_VehicleId == vehicleId)); - public async Task HasOpenOrActiveRideForVehicleAsync(Guid vehicleId, Guid? excludeRideId = null) => + public async Task HasOpenRideForVehicleAsync(Guid vehicleId, Guid? excludeRideId = null) => await context.DeliveryRuns.AnyAsync(r => r.FK_VehicleId == vehicleId && r.Id != excludeRideId && - (r.Status == RideStatus.Open || r.Status == RideStatus.Active)); - - public async Task> GetActiveRidesAsync(Guid? excludeRideId = null) => - await context.DeliveryRuns - .Include(r => r.Vehicle) - .Include(r => r.DriverProfile).ThenInclude(dp => dp.User) - .Include(r => r.Route) - .Where(r => r.Id != excludeRideId && r.Status == RideStatus.Active) - .ToListAsync(); - - public async Task> GetActiveOrdersByRouteIdAsync(Guid routeId) => - await context.Orders - .Include(o => o.Store) - .Where(o => o.IsActive && o.Store.FK_RouteId == routeId) - .OrderByDescending(o => o.OrderDate) - .Select(o => new OrderSummaryModel( - o.Id, - o.FK_StoreId, - o.Store.StoreName, - o.OrderDate, - o.TotalAmount)) - .ToListAsync(); + r.Status == RideStatus.Open); public async Task AddAsync(DeliveryRun ride) => await context.DeliveryRuns.AddAsync(ride); diff --git a/Distribution/Features/Ride/RideService.cs b/Distribution/Features/Ride/RideService.cs index 4d872a0..d4a0037 100644 --- a/Distribution/Features/Ride/RideService.cs +++ b/Distribution/Features/Ride/RideService.cs @@ -1,4 +1,4 @@ -using Distribution.Features.Stock; +using Distribution.Features.Stock; using Distribution.Features.DriverComplianceConfig; using Distribution.Features.DriverProfile; using Distribution.Infra.UoW; @@ -10,21 +10,13 @@ public class RideService( IRideRepository rideRepo, IDriverProfileRepository driverRepo, IDriverComplianceConfigRepository complianceRepo, - IRideCancelRequestRepository cancelRepo, - Features.Vehicle.IVehicleRepository vehicleRepo, IStockRepository stockRepo, IUnitOfWork uow) { - public async Task> GetAllAsync( - RideStatus? status, - RideType? type, - Guid? driverProfileId, - Guid? vehicleId, - int page, - int pageSize) + public async Task> GetAllAsync(RideStatus? status, Guid? driverProfileId, Guid? vehicleId, int page, int pageSize) { - var total = await rideRepo.GetCountAsync(status, type, driverProfileId, vehicleId); - var items = await rideRepo.GetAllAsync(status, type, driverProfileId, vehicleId, page, pageSize); + var total = await rideRepo.GetCountAsync(status, driverProfileId, vehicleId); + var items = await rideRepo.GetAllAsync(status, driverProfileId, vehicleId, page, pageSize); return new PagedResponse(page, pageSize, total, items.Select(ToResponse).ToList()); } @@ -36,21 +28,18 @@ public class RideService( public async Task CreateAsync(CreateRideRequest request, CancellationToken ct = default) { - var vehicle = await vehicleRepo.GetByIdAsync(request.VehicleId) - ?? throw new InvalidOperationException("Vehicle not found"); + if (await rideRepo.HasOpenRideForVehicleAsync(request.VehicleId)) + throw new InvalidOperationException("Vehicle already has an open ride"); - var sourceWarehouseId = vehicle.DefaultWarehouseId ?? request.SourceWarehouseId; - if (!sourceWarehouseId.HasValue) - throw new InvalidOperationException("Source warehouse is required for this vehicle"); + await CheckDriverComplianceAsync(request.DriverProfileId); var ride = new DeliveryRun { - RideType = request.RideType, FK_VehicleId = request.VehicleId, FK_DriverProfileId = request.DriverProfileId, - FK_RouteId = request.RouteId, - FK_SourceWarehouseId = sourceWarehouseId.Value, - Status = RideStatus.Draft + Status = RideStatus.Open, + Meterstart = request.Meterstart, + StartedAt = DateTime.Now }; await uow.BeginAsync(ct); @@ -59,46 +48,19 @@ public class RideService( await rideRepo.AddAsync(ride); await uow.CommitAsync(ct); } - catch - { - await uow.RollbackAsync(ct); - throw; - } + catch { await uow.RollbackAsync(ct); throw; } var saved = await rideRepo.GetByIdAsync(ride.Id); return ToResponse(saved!); } - public async Task OpenAsync(Guid rideId, CancellationToken ct = default) - { - var ride = await rideRepo.GetByIdAsync(rideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.Draft) - throw new InvalidOperationException($"Cannot open a ride in {ride.Status} status"); - - if (await rideRepo.HasOpenOrActiveRideForVehicleAsync(ride.FK_VehicleId, ride.Id)) - throw new InvalidOperationException("Vehicle already has an open or active ride"); - - await CheckDriverComplianceAsync(ride.FK_DriverProfileId); - - ride.Status = RideStatus.Open; - ride.StartedAt = DateTime.Now; - - await uow.BeginAsync(ct); - try { rideRepo.Update(ride); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(ride); - } - public async Task AssignDriverAsync(Guid rideId, Guid driverProfileId, CancellationToken ct = default) { var ride = await rideRepo.GetByIdAsync(rideId) ?? throw new KeyNotFoundException("Ride not found"); - if (ride.Status != RideStatus.Draft) - throw new InvalidOperationException("Driver can only be changed while the ride is in Draft status"); + if (ride.Status != RideStatus.Open) + throw new InvalidOperationException("Driver can only be changed while the ride is Open"); var driver = await driverRepo.GetByIdAsync(driverProfileId); if (driver is null || !driver.IsActive) @@ -114,31 +76,12 @@ public class RideService( return ToResponse(saved!); } - public async Task ActivateAsync(Guid rideId, ActivateRideRequest request, CancellationToken ct = default) - { - var ride = await rideRepo.GetByIdAsync(rideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.Open) - throw new InvalidOperationException($"Cannot activate a ride in {ride.Status} status"); - - ride.Status = RideStatus.Active; - ride.ActivatedAt = DateTime.Now; - ride.Meterstart = request.Meterstart; - - await uow.BeginAsync(ct); - try { rideRepo.Update(ride); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - return ToResponse(ride); - } - public async Task CloseAsync(Guid rideId, CloseRideRequest request, CancellationToken ct = default) { var ride = await rideRepo.GetByIdAsync(rideId) ?? throw new KeyNotFoundException("Ride not found"); - if (ride.Status != RideStatus.Active) + if (ride.Status != RideStatus.Open) throw new InvalidOperationException($"Cannot close a ride in {ride.Status} status"); if (request.Meterend < ride.Meterstart) @@ -157,162 +100,21 @@ public class RideService( return ToResponse(ride); } - public async Task RaiseCancelRequestAsync(Guid rideId, RaiseCancelRequest request, Guid requestedBy, CancellationToken ct = default) + public async Task CancelAsync(Guid rideId, CancelRideRequest request, CancellationToken ct = default) { var ride = await rideRepo.GetByIdAsync(rideId) ?? throw new KeyNotFoundException("Ride not found"); - if (ride.Status != RideStatus.Active) - throw new InvalidOperationException($"Cannot raise a cancel request for a ride in {ride.Status} status"); - - var existing = await cancelRepo.GetPendingByRideIdAsync(rideId); - if (existing is not null) - throw new InvalidOperationException("There is already a pending cancel request for this ride"); - - var cancelRequest = new RideCancelRequest - { - FK_RideId = rideId, - TypeCode = request.TypeCode, - Reason = request.Reason, - RequestedBy = requestedBy, - RequestedAt = DateTime.Now, - Status = CancelRequestStatus.Pending - }; - - ride.Status = RideStatus.CancelRequested; - - await uow.BeginAsync(ct); - try - { - await cancelRepo.AddAsync(cancelRequest); - rideRepo.Update(ride); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToCancelResponse(cancelRequest); - } - - public async Task> GetCancelRequestsAsync(CancelRequestStatus? status, int page, int pageSize) - { - var total = await cancelRepo.GetCountAsync(status); - var items = await cancelRepo.GetAllAsync(status, page, pageSize); - return new PagedResponse(page, pageSize, total, items.Select(ToCancelResponse).ToList()); - } - - public async Task ApproveCancelAsync(Guid cancelRequestId, Guid approvedBy, CancellationToken ct = default) - { - var cancelRequest = await cancelRepo.GetByIdAsync(cancelRequestId) - ?? throw new KeyNotFoundException("Cancel request not found"); - - if (cancelRequest.Status != CancelRequestStatus.Pending) - throw new InvalidOperationException("Cancel request is not pending"); - - var ride = await rideRepo.GetByIdAsync(cancelRequest.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.CancelRequested) - throw new InvalidOperationException("Ride is not in CancelRequested status"); - - await EnsureVehicleStockClearedAsync(ride.FK_VehicleId); - - cancelRequest.Status = CancelRequestStatus.Approved; - cancelRequest.ApprovedBy = approvedBy; - cancelRequest.ApprovedAt = DateTime.Now; + if (ride.Status != RideStatus.Open) + throw new InvalidOperationException($"Cannot cancel a ride in {ride.Status} status"); ride.Status = RideStatus.Cancelled; await uow.BeginAsync(ct); - try - { - cancelRepo.Update(cancelRequest); - rideRepo.Update(ride); - await uow.CommitAsync(ct); - } + try { rideRepo.Update(ride); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } - return ToCancelResponse(cancelRequest); - } - - public async Task RejectCancelAsync(Guid cancelRequestId, Guid rejectedBy, CancellationToken ct = default) - { - var cancelRequest = await cancelRepo.GetByIdAsync(cancelRequestId) - ?? throw new KeyNotFoundException("Cancel request not found"); - - if (cancelRequest.Status != CancelRequestStatus.Pending) - throw new InvalidOperationException("Cancel request is not pending"); - - var ride = await rideRepo.GetByIdAsync(cancelRequest.FK_RideId) - ?? throw new KeyNotFoundException("Ride not found"); - - if (ride.Status != RideStatus.CancelRequested) - throw new InvalidOperationException("Ride is not in CancelRequested status"); - - cancelRequest.Status = CancelRequestStatus.Rejected; - cancelRequest.ApprovedBy = rejectedBy; - cancelRequest.ApprovedAt = DateTime.Now; - - // Restore to previous status: Active if ActivatedAt is set, else Open - ride.Status = ride.ActivatedAt.HasValue ? RideStatus.Active : RideStatus.Open; - - await uow.BeginAsync(ct); - try - { - cancelRepo.Update(cancelRequest); - rideRepo.Update(ride); - await uow.CommitAsync(ct); - } - catch { await uow.RollbackAsync(ct); throw; } - - return ToCancelResponse(cancelRequest); - } - - public async Task GetCancelRequestAsync(Guid rideId) - { - var cancelRequest = await cancelRepo.GetByRideIdAsync(rideId); - return cancelRequest is null ? null : ToCancelResponse(cancelRequest); - } - - public async Task GetBreakdownAssistAsync(Guid rideId) - { - var strandedRide = await rideRepo.GetByIdAsync(rideId) - ?? throw new KeyNotFoundException("Ride not found"); - - var activeRides = await rideRepo.GetActiveRidesAsync(rideId); - var activeRideResponses = new List(); - - foreach (var ride in activeRides) - { - var stockLevels = await stockRepo.GetBalancesByLocationAsync(ride.FK_VehicleId, LocationType.Vehicle); - activeRideResponses.Add(new BreakdownAssistRideResponse( - ride.Id, - ride.FK_VehicleId, - ride.Vehicle?.NumberPlate ?? string.Empty, - ride.FK_DriverProfileId, - ride.DriverProfile?.User?.FullName ?? string.Empty, - ride.FK_RouteId, - ride.Route?.RouteName ?? string.Empty, - stockLevels.Select(b => new StockBalanceResponse( - b.FK_ItemId, - b.Item.Name, - b.LocationId, - b.LocationType, - b.Quantity, - b.UpdatedAt, - ride.Vehicle?.NumberPlate ?? string.Empty)).ToList())); - } - - var openOrders = await rideRepo.GetActiveOrdersByRouteIdAsync(strandedRide.FK_RouteId); - - return new BreakdownAssistResponse( - strandedRide.Id, - activeRideResponses, - openOrders.Select(o => new BreakdownAssistOrderResponse( - o.Id, - o.StoreId, - o.StoreName, - o.OrderDate, - o.TotalAmount)).ToList()); + return ToResponse(ride); } private async Task CheckDriverComplianceAsync(Guid driverProfileId) @@ -343,15 +145,9 @@ public class RideService( } private static RideResponse ToResponse(DeliveryRun r) => - new(r.Id, r.RideType, r.Status, + new(r.Id, r.Status, r.FK_VehicleId, r.Vehicle?.NumberPlate ?? string.Empty, r.FK_DriverProfileId, r.DriverProfile?.User?.FullName ?? string.Empty, - r.FK_RouteId, r.Route?.RouteName ?? string.Empty, - r.FK_SourceWarehouseId, r.SourceWarehouse?.Name ?? string.Empty, r.Meterstart, r.Meterend, - r.StartedAt, r.ActivatedAt, r.ClosedAt, r.CreatedAt); - - private static RideCancelRequestResponse ToCancelResponse(RideCancelRequest c) => - new(c.Id, c.FK_RideId, c.TypeCode, c.Reason, c.RequestedBy, c.RequestedAt, - c.Status, c.ApprovedBy, c.ApprovedAt); + r.StartedAt, r.ClosedAt, r.CreatedAt); } diff --git a/Distribution/Features/Sale/ISaleRepository.cs b/Distribution/Features/Sale/ISaleRepository.cs deleted file mode 100644 index 92ea633..0000000 --- a/Distribution/Features/Sale/ISaleRepository.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Distribution.Models; - -namespace Distribution.Features.Sale; - -public interface ISaleRepository -{ - Task GetByIdAsync(Guid id); - Task> GetAllAsync(Guid? rideId, IEnumerable? storeIds, int page, int pageSize); - Task GetCountAsync(Guid? rideId, IEnumerable? storeIds); - Task> GetByStoreIdAsync(Guid storeId); - Task AddAsync(Models.Sale sale); - void Update(Models.Sale sale); - void Remove(Models.Sale sale); - Task GetOrderBySaleIdAsync(Guid saleId); -} diff --git a/Distribution/Features/Sale/SaleController.cs b/Distribution/Features/Sale/SaleController.cs deleted file mode 100644 index 714b489..0000000 --- a/Distribution/Features/Sale/SaleController.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Distribution.Features.Sale; - -[ApiController] -[Route("api/sales")] -public class SaleController(SaleService service) : ControllerBase -{ - [HttpGet] - public async Task GetAll( - [FromQuery] Guid? rideId, - [FromQuery] int page = 1, - [FromQuery] int pageSize = 20) => - Ok(await service.GetAllAsync(rideId, page, pageSize)); - - [HttpGet("{id:guid}")] - public async Task GetById(Guid id) - { - var result = await service.GetByIdAsync(id); - return result is null ? NotFound() : Ok(result); - } - - [HttpGet("store/{storeId:guid}")] - public async Task GetByStore(Guid storeId) - { - var result = await service.GetByStoreIdAsync(storeId); - return result is null ? StatusCode(StatusCodes.Status403Forbidden) : Ok(result); - } - - [HttpPost] - public async Task Create(CreateSaleRequest request, CancellationToken ct) - { - try - { - var result = await service.CreateAsync(request, ct); - return result is null ? StatusCode(StatusCodes.Status403Forbidden) : CreatedAtAction(nameof(GetById), new { id = result.Id }, result); - } - catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } - } - - [HttpPatch("{id:guid}/cancel")] - public async Task Cancel(Guid id, CancellationToken ct) - { - try - { - var result = await service.CancelAsync(id, ct); - return result is null ? NotFound() : Ok(result); - } - catch (InvalidOperationException ex) { return Conflict(new { error = ex.Message }); } - } -} diff --git a/Distribution/Features/Sale/SaleDTOs.cs b/Distribution/Features/Sale/SaleDTOs.cs deleted file mode 100644 index 171b788..0000000 --- a/Distribution/Features/Sale/SaleDTOs.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Distribution.Models; - -namespace Distribution.Features.Sale; - -public record SaleItemRequest(Guid ItemId, int Quantity, decimal? UnitPrice = null); - -public record CreateSaleRequest( - Guid StoreId, - DateTime SaleDate, - decimal TotalAmount, - bool FulfillImmediately, - Guid? RideId, - List Items, - // TEMPORARY: auth middleware doesn't attach a resolvable user yet (see testbug.md #28), so the - // caller supplies the acting user explicitly. Remove once currentUser.UserId is reliable again. - Guid? CreatedByUserId = null); - -public record SaleItemResponse(Guid ItemId, int Quantity, int QuantityFulfilled, decimal UnitPrice); - -public record SaleResponse( - Guid Id, - DateTime SaleDate, - Guid StoreId, - Guid CreatedByUserId, - Guid? RideId, - decimal TotalAmount, - SaleStatus Status, - PaymentStatus PaymentStatus, - bool FulfillImmediately, - DateTime? CompletedAt, - Guid OrderId, - OrderStatus OrderStatus, - DateTime? OrderFulfilledAt, - List Items, - bool IsActive, - DateTime CreatedAt); diff --git a/Distribution/Features/Sale/SaleRepository.cs b/Distribution/Features/Sale/SaleRepository.cs deleted file mode 100644 index 4768aba..0000000 --- a/Distribution/Features/Sale/SaleRepository.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Distribution.Data; -using Distribution.Models; -using Microsoft.EntityFrameworkCore; - -namespace Distribution.Features.Sale; - -public class SaleRepository(AppDBContext context) : ISaleRepository -{ - public async Task GetByIdAsync(Guid id) => - await context.Sales.FindAsync(id); - - public async Task> GetAllAsync(Guid? rideId, IEnumerable? storeIds, int page, int pageSize) => - await context.Sales - .Where(s => s.IsActive && - (rideId == null || s.FK_RideId == rideId) && - (storeIds == null || storeIds.Contains(s.FK_StoreId))) - .OrderByDescending(s => s.CreatedAt) - .Skip((page - 1) * pageSize) - .Take(pageSize) - .ToListAsync(); - - public async Task GetCountAsync(Guid? rideId, IEnumerable? storeIds) => - await context.Sales - .CountAsync(s => s.IsActive && - (rideId == null || s.FK_RideId == rideId) && - (storeIds == null || storeIds.Contains(s.FK_StoreId))); - - public async Task> GetByStoreIdAsync(Guid storeId) => - await context.Sales.Where(s => s.FK_StoreId == storeId && s.IsActive).ToListAsync(); - - public async Task AddAsync(Models.Sale sale) => - await context.Sales.AddAsync(sale); - - public void Update(Models.Sale sale) => - context.Sales.Update(sale); - - public void Remove(Models.Sale sale) - { - sale.IsActive = false; - context.Sales.Update(sale); - } - - public async Task GetOrderBySaleIdAsync(Guid saleId) => - await context.Orders.FirstOrDefaultAsync(o => o.FK_SaleId == saleId && o.IsActive); -} diff --git a/Distribution/Features/Sale/SaleService.cs b/Distribution/Features/Sale/SaleService.cs deleted file mode 100644 index 4028144..0000000 --- a/Distribution/Features/Sale/SaleService.cs +++ /dev/null @@ -1,273 +0,0 @@ -using Distribution.Features.Item; -using Distribution.Features.Order; -using Distribution.Features.PriceList; -using Distribution.Features.Ride; -using Distribution.Features.Stock; -using Distribution.Features.Store; -using Distribution.Infra.Authorization; -using Distribution.Infra.UoW; -using Distribution.Models; -using Microsoft.Extensions.Configuration; - -namespace Distribution.Features.Sale; - -public class SaleService( - ISaleRepository repo, - IOrderRepository orderRepo, - IStoreRepository storeRepo, - IItemRepository itemRepo, - PriceListService priceListService, - IStockRepository stockRepo, - IRideRepository rideRepo, - IUnitOfWork uow, - ICurrentUserService currentUser, - IScopeAccessService scopeAccess, - IConfiguration configuration) -{ - private const int GlobalScopeRoleLevel = 50; - - private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel; - - private async Task HasStoreScopeAsync(Guid storeId) - { - if (HasGlobalScope || currentUser.UserId is null) return HasGlobalScope; - return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId); - } - - private async Task ResolveUnitPriceAsync(Guid itemId, decimal? requestedUnitPrice, Models.Store store, DateTime saleDate) - { - var item = await itemRepo.GetByIdAsync(itemId); - if (item is null) return null; - - var regionId = store.Route?.FK_RegionId; - var resolution = await priceListService.ResolvePriceAsync(itemId, regionId, item.SalePrice, saleDate); - if (resolution is null) return null; - - if (!requestedUnitPrice.HasValue) return resolution.Price; - - var min = resolution.MinPrice ?? resolution.Price; - var max = resolution.Price; - if (requestedUnitPrice.Value < min || requestedUnitPrice.Value > max) return null; - - return requestedUnitPrice.Value; - } - - private static SaleResponse ToResponse(Models.Sale sale, Models.Order order, List items) => - new( - sale.Id, - sale.SaleDate, - sale.FK_StoreId, - sale.CreatedByUserId, - sale.FK_RideId, - sale.TotalAmount, - sale.Status, - sale.PaymentStatus, - sale.FulfillImmediately, - sale.CompletedAt, - order.Id, - order.Status, - order.FulfilledAt, - items.Select(i => new SaleItemResponse(i.FK_ItemId, i.Quantity, i.QuantityFulfilled, i.UnitPrice)).ToList(), - sale.IsActive, - sale.CreatedAt); - - public async Task> GetAllAsync(Guid? rideId, int page, int pageSize) - { - IEnumerable? storeIds = null; - if (!HasGlobalScope && currentUser.UserId is not null) - storeIds = await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value); - - var total = await repo.GetCountAsync(rideId, storeIds); - var sales = await repo.GetAllAsync(rideId, storeIds, page, pageSize); - - var result = new List(); - foreach (var sale in sales) - { - var order = await repo.GetOrderBySaleIdAsync(sale.Id); - if (order is null) continue; - var items = await orderRepo.GetItemsByOrderIdAsync(order.Id); - result.Add(ToResponse(sale, order, items)); - } - return new PagedResponse(page, pageSize, total, result); - } - - public async Task GetByIdAsync(Guid id) - { - var sale = await repo.GetByIdAsync(id); - if (sale is null || !sale.IsActive) return null; - if (!await HasStoreScopeAsync(sale.FK_StoreId)) return null; - - var order = await repo.GetOrderBySaleIdAsync(id); - if (order is null) return null; - var items = await orderRepo.GetItemsByOrderIdAsync(order.Id); - return ToResponse(sale, order, items); - } - - public async Task?> GetByStoreIdAsync(Guid storeId) - { - if (!await HasStoreScopeAsync(storeId)) return null; - - var sales = await repo.GetByStoreIdAsync(storeId); - var result = new List(); - foreach (var sale in sales) - { - var order = await repo.GetOrderBySaleIdAsync(sale.Id); - if (order is null) continue; - var items = await orderRepo.GetItemsByOrderIdAsync(order.Id); - result.Add(ToResponse(sale, order, items)); - } - return result; - } - - public async Task CancelAsync(Guid id, CancellationToken ct = default) - { - // TEMPORARY: see CreateAsync — store-scope enforcement depends on the broken auth - // middleware (testbug.md #28) and would reject every cancel. Skipped for now. - var sale = await repo.GetByIdAsync(id); - if (sale is null || !sale.IsActive) return null; - if (sale.Status == SaleStatus.Cancelled) - throw new InvalidOperationException("Sale is already cancelled"); - - sale.Status = SaleStatus.Cancelled; - - await uow.BeginAsync(ct); - try { repo.Update(sale); await uow.CommitAsync(ct); } - catch { await uow.RollbackAsync(ct); throw; } - - var order = await repo.GetOrderBySaleIdAsync(id); - if (order is null) return null; - var items = await orderRepo.GetItemsByOrderIdAsync(order.Id); - return ToResponse(sale, order, items); - } - - public async Task CreateAsync(CreateSaleRequest request, CancellationToken ct = default) - { - // TEMPORARY: store-scope enforcement and currentUser resolution both depend on the broken - // auth middleware (see testbug.md #28) — currentUser.UserId/RoleLevel are always unset, so - // both checks would reject every sale. Skipped for now; restore once auth is fixed. - var userId = currentUser.UserId ?? request.CreatedByUserId - ?? throw new InvalidOperationException("CreatedByUserId is required while auth is unavailable"); - var store = await storeRepo.GetByIdWithRegionAsync(request.StoreId) - ?? throw new InvalidOperationException("Store not found"); - if (!store.IsActive) - throw new InvalidOperationException("Store is inactive"); - - if (store.KycStatus != KycStatus.Verified) - { - var threshold = configuration.GetValue("StoreManagement:UnverifiedKycOrderThreshold"); - if (request.TotalAmount > threshold) - throw new InvalidOperationException( - $"Store KYC is not verified — sale amount ({request.TotalAmount}) exceeds the unverified-store threshold ({threshold})"); - } - - var sale = new Models.Sale - { - FK_StoreId = request.StoreId, - SaleDate = request.SaleDate, - CreatedByUserId = userId, - FK_RideId = request.RideId, - FulfillImmediately = request.FulfillImmediately - }; - - var orderItems = new List(); - foreach (var item in request.Items) - { - var unitPrice = await ResolveUnitPriceAsync(item.ItemId, item.UnitPrice, store, request.SaleDate) - ?? throw new InvalidOperationException( - $"Could not resolve a price for item {item.ItemId} on {request.SaleDate:yyyy-MM-dd} — check the item exists, an active price list covers this date/region, and any supplied unit price is within its min/max range"); - - orderItems.Add(new Models.OrderItem - { - FK_ItemId = item.ItemId, - Quantity = item.Quantity, - UnitPrice = unitPrice - }); - } - - var order = new Models.Order - { - FK_SaleId = sale.Id, - FK_StoreId = request.StoreId, - OrderDate = request.SaleDate, - }; - - foreach (var orderItem in orderItems) - orderItem.FK_OrderId = order.Id; - - // For a van sale against a specific ride, sell whatever quantity is actually on that - // vehicle instead of rejecting the whole sale over one short item — the sale is always a - // clean, completed sale of what's handed over, never a "partially fulfilled" order. - Guid? vehicleId = null; - if (request.FulfillImmediately && request.RideId.HasValue) - { - var ride = await rideRepo.GetByIdAsync(request.RideId.Value) - ?? throw new InvalidOperationException("Ride not found"); - vehicleId = ride.FK_VehicleId; - - foreach (var item in orderItems) - { - var balance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId.Value); - item.Quantity = Math.Min(item.Quantity, (int)(balance?.Quantity ?? 0)); - } - } - - foreach (var item in orderItems) - item.QuantityFulfilled = request.FulfillImmediately ? item.Quantity : 0; - - if (request.FulfillImmediately) - { - sale.Status = SaleStatus.Completed; - sale.CompletedAt = DateTime.Now; - order.Status = OrderStatus.Fulfilled; - order.FulfilledAt = DateTime.Now; - } - else - { - sale.Status = SaleStatus.Pending; - order.Status = OrderStatus.Pending; - } - - sale.TotalAmount = orderItems.Sum(i => i.Quantity * i.UnitPrice); - order.TotalAmount = sale.TotalAmount; - - await uow.BeginAsync(ct); - try - { - await repo.AddAsync(sale); - await orderRepo.AddAsync(order); - await orderRepo.AddItemsAsync(orderItems); - - if (vehicleId.HasValue) - { - foreach (var item in orderItems.Where(i => i.QuantityFulfilled > 0)) - { - var balance = await stockRepo.GetBalanceAsync(item.FK_ItemId, vehicleId.Value); - balance!.Quantity -= item.QuantityFulfilled; - balance.UpdatedAt = DateTime.Now; - stockRepo.UpdateBalance(balance); - - await stockRepo.AddMovementAsync(new StockMovement - { - FK_ItemId = item.FK_ItemId, - FromLocationId = vehicleId.Value, - FromLocationType = LocationType.Vehicle, - ToLocationId = StockService.ExternalLocationId, - ToLocationType = LocationType.External, - Quantity = item.QuantityFulfilled, - Type = MovementType.Sale, - ReferenceId = order.Id - }); - } - } - - await uow.CommitAsync(ct); - } - catch - { - await uow.RollbackAsync(ct); - throw; - } - - return ToResponse(sale, order, orderItems); - } -} diff --git a/Distribution/Features/Scheme/SchemeDTOs.cs b/Distribution/Features/Scheme/SchemeDTOs.cs index 5e49bb7..28ec165 100644 --- a/Distribution/Features/Scheme/SchemeDTOs.cs +++ b/Distribution/Features/Scheme/SchemeDTOs.cs @@ -99,7 +99,7 @@ public record SchemeEligibilityResponse( public record SchemeRedemptionResponse( Guid Id, Guid SchemeId, - Guid? OrderId, + Guid? ShopPOId, decimal? DiscountAmount, Guid? FreeItemId, string? FreeItemName, diff --git a/Distribution/Features/Scheme/SchemeRepository.cs b/Distribution/Features/Scheme/SchemeRepository.cs index 123ca69..2d22e62 100644 --- a/Distribution/Features/Scheme/SchemeRepository.cs +++ b/Distribution/Features/Scheme/SchemeRepository.cs @@ -42,15 +42,15 @@ public class SchemeRepository(AppDBContext context) : ISchemeRepository public async Task> GetRedemptionsAsync(Guid schemeId) => await context.SchemeRedemptions .Include(r => r.FreeItem) - .Include(r => r.Order) + .Include(r => r.ShopPO) .Where(r => r.FK_SchemeId == schemeId) .ToListAsync(); public async Task AddRedemptionAsync(Models.SchemeRedemption entity) => await context.SchemeRedemptions.AddAsync(entity); - public async Task HasRedemptionAsync(Guid schemeId, Guid orderId) => - await context.SchemeRedemptions.AnyAsync(r => r.FK_SchemeId == schemeId && r.FK_OrderId == orderId); + public async Task HasRedemptionAsync(Guid schemeId, Guid shopPOId) => + await context.SchemeRedemptions.AnyAsync(r => r.FK_SchemeId == schemeId && r.FK_ShopPOId == shopPOId); public async Task GetBundleComponentAsync(Guid schemeId, Guid itemId) => await context.SchemeBundleComponents diff --git a/Distribution/Features/Scheme/SchemeService.cs b/Distribution/Features/Scheme/SchemeService.cs index ebf4329..e17f810 100644 --- a/Distribution/Features/Scheme/SchemeService.cs +++ b/Distribution/Features/Scheme/SchemeService.cs @@ -1,6 +1,6 @@ using System.Text.Json; using Distribution.Features.Item; -using Distribution.Features.Order; +using Distribution.Features.ShopPO; using Distribution.Features.Stock; using Distribution.Features.Store; using Distribution.Infra.UoW; @@ -10,7 +10,7 @@ namespace Distribution.Features.Scheme; public class SchemeService( ISchemeRepository repo, - IOrderRepository orderRepo, + IShopPORepository shopPORepo, IItemRepository itemRepo, IStoreRepository storeRepo, IStockRepository stockRepo, @@ -27,7 +27,7 @@ public class SchemeService( s.DateRangeFrom, s.DateRangeTo, s.AgentLimitExempt, s.BaselineExpectedSales, s.IsActive, s.CreatedAt); private static SchemeRedemptionResponse ToRedemptionResponse(SchemeRedemption r) => - new(r.Id, r.FK_SchemeId, r.FK_OrderId, r.DiscountAmount, r.FK_FreeItemId, r.FreeItem?.Name, + new(r.Id, r.FK_SchemeId, r.FK_ShopPOId, r.DiscountAmount, r.FK_FreeItemId, r.FreeItem?.Name, r.FreeQty, r.FreeItemCostValue, r.RedeemedAt); // ── CRUD ─────────────────────────────────────────────────────────────── @@ -243,17 +243,17 @@ public class SchemeService( return (await GetByIdAsync(schemeId))!; } - // ── evaluateSchemeEligibility(storeId, orderId) ────────────────────────── + // ── evaluateSchemeEligibility(storeId, shopPOId) ────────────────────────── - public async Task?> EvaluateEligibilityAsync(Guid storeId, Guid orderId) + public async Task?> EvaluateEligibilityAsync(Guid storeId, Guid shopPOId) { var store = await storeRepo.GetByIdWithRegionAsync(storeId); if (store is null || !store.IsActive) return null; - var order = await orderRepo.GetByIdAsync(orderId); - if (order is null || !order.IsActive) return null; + var shopPO = await shopPORepo.GetByIdAsync(shopPOId); + if (shopPO is null || !shopPO.IsActive) return null; - var orderItems = await orderRepo.GetItemsByOrderIdAsync(orderId); + var items = await shopPORepo.GetActiveItemsByShopPOIdAsync(shopPOId); var regionId = store.Route?.FK_RegionId; var candidates = (await repo.GetAllAsync()).Where(s => s.IsActive); @@ -266,21 +266,21 @@ public class SchemeService( if (!string.IsNullOrEmpty(scheme.EligibleSegment) && !string.Equals(scheme.EligibleSegment, store.Segment, StringComparison.OrdinalIgnoreCase)) continue; - if (order.OrderDate < scheme.DateRangeFrom || order.OrderDate > scheme.DateRangeTo) + if (shopPO.CreatedAt < scheme.DateRangeFrom || shopPO.CreatedAt > scheme.DateRangeTo) continue; - result.Add(EvaluateRule(scheme, orderItems)); + result.Add(EvaluateRule(scheme, items)); } return result; } /// - /// Scope-only check (region, segment, date range as of today) with no order to evaluate line + /// Scope-only check (region, segment, date range as of today) with no ShopPO to evaluate line /// items against — used by Store Management's `checkStoreSchemeEligibility(storeId, schemeId)` /// (12_store_management.md), which has no order context. Returns null if the store or scheme /// doesn't exist; otherwise (Eligible, Reason) — Eligible here means "in scope for this store", - /// not "this order's items satisfy the rule" (use EvaluateEligibilityAsync for that). + /// not "this ShopPO's items satisfy the rule" (use EvaluateEligibilityAsync for that). /// public async Task<(bool Eligible, string? Reason)?> CheckStoreScopeEligibilityAsync(Guid storeId, Guid schemeId) { @@ -305,7 +305,7 @@ public class SchemeService( return (true, null); } - private static SchemeEligibilityResponse EvaluateRule(Models.Scheme scheme, List orderItems) + private static SchemeEligibilityResponse EvaluateRule(Models.Scheme scheme, List items) { switch (scheme.RuleType) { @@ -316,10 +316,10 @@ public class SchemeService( return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, "Scheme has no free-goods rule configured.", null, null, null); - var boughtQty = orderItems.Where(i => i.FK_ItemId == scheme.FK_TriggerItemId).Sum(i => i.Quantity); + var boughtQty = items.Where(i => i.FK_ItemId == scheme.FK_TriggerItemId).Sum(i => i.Quantity); if (boughtQty < scheme.TriggerQty) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, - $"Requires {scheme.TriggerQty} of the trigger item; order has {boughtQty}.", null, null, null); + $"Requires {scheme.TriggerQty} of the trigger item; ShopPO has {boughtQty}.", null, null, null); var multiplier = boughtQty / scheme.TriggerQty.Value; return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, true, null, @@ -332,11 +332,11 @@ public class SchemeService( "Scheme has no bundle components or free-goods payout configured.", null, null, null); var missing = scheme.BundleComponents - .Where(c => orderItems.Where(i => i.FK_ItemId == c.FK_ItemId).Sum(i => i.Quantity) < c.Qty) + .Where(c => items.Where(i => i.FK_ItemId == c.FK_ItemId).Sum(i => i.Quantity) < c.Qty) .ToList(); if (missing.Count > 0) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, - "Order is missing required bundle components.", null, null, null); + "ShopPO is missing required bundle components.", null, null, null); return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, true, null, null, scheme.FK_FreeItemId, scheme.FreeQty); @@ -346,7 +346,7 @@ public class SchemeService( if (string.IsNullOrEmpty(scheme.RuleConfig)) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, "Scheme has no RuleConfig.", null, null, null); var cfg = JsonSerializer.Deserialize(scheme.RuleConfig, JsonOptions)!; - var orderTotal = orderItems.Sum(i => i.Quantity * i.UnitPrice); + var orderTotal = items.Sum(i => i.Quantity * i.UnitPrice); return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, true, null, Math.Round(orderTotal * cfg.DiscountPercent / 100m, 2), null, null); } @@ -355,12 +355,12 @@ public class SchemeService( if (string.IsNullOrEmpty(scheme.RuleConfig)) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, "Scheme has no RuleConfig.", null, null, null); var cfg = JsonSerializer.Deserialize(scheme.RuleConfig, JsonOptions)!; - var orderTotal = orderItems.Sum(i => i.Quantity * i.UnitPrice); + var orderTotal = items.Sum(i => i.Quantity * i.UnitPrice); var tier = cfg.Tiers.Where(t => orderTotal >= t.MinOrderAmount) .OrderByDescending(t => t.MinOrderAmount).FirstOrDefault(); if (tier is null) return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, false, - "Order total does not meet any slab threshold.", null, null, null); + "ShopPO total does not meet any slab threshold.", null, null, null); return new SchemeEligibilityResponse(scheme.Id, scheme.Name, scheme.RuleType, true, null, Math.Round(orderTotal * tier.DiscountPercent / 100m, 2), null, null); @@ -370,32 +370,32 @@ public class SchemeService( } } - // ── applySchemeDiscount(orderId, schemeId) ─────────────────────────────── + // ── applySchemeDiscount(shopPOId, schemeId) ─────────────────────────────── - public async Task ApplySchemeAsync(Guid orderId, Guid schemeId, CancellationToken ct = default) + public async Task ApplySchemeAsync(Guid shopPOId, Guid schemeId, CancellationToken ct = default) { var scheme = await repo.GetByIdAsync(schemeId); if (scheme is null || !scheme.IsActive) return null; - var order = await orderRepo.GetByIdAsync(orderId); - if (order is null || !order.IsActive) return null; + var shopPO = await shopPORepo.GetByIdAsync(shopPOId); + if (shopPO is null || !shopPO.IsActive) return null; - if (await repo.HasRedemptionAsync(schemeId, orderId)) - throw new InvalidOperationException("This scheme has already been redeemed against this order."); + if (await repo.HasRedemptionAsync(schemeId, shopPOId)) + throw new InvalidOperationException("This scheme has already been redeemed against this ShopPO."); - var orderItems = await orderRepo.GetItemsByOrderIdAsync(orderId); - var eligibility = EvaluateRule(scheme, orderItems); + var items = await shopPORepo.GetActiveItemsByShopPOIdAsync(shopPOId); + var eligibility = EvaluateRule(scheme, items); if (!eligibility.Eligible) - throw new InvalidOperationException(eligibility.Reason ?? "Order is not eligible for this scheme."); + throw new InvalidOperationException(eligibility.Reason ?? "ShopPO is not eligible for this scheme."); var redemption = new SchemeRedemption { FK_SchemeId = schemeId, - FK_OrderId = orderId, + FK_ShopPOId = shopPOId, DiscountAmount = eligibility.DiscountAmount }; - var newOrderItems = new List(); + var newItems = new List(); if (eligibility.FreeItemId.HasValue && eligibility.FreeQty is > 0) { @@ -406,9 +406,9 @@ public class SchemeService( if (availableQty < eligibility.FreeQty.Value) throw new InvalidOperationException($"Insufficient stock of '{freeItem.Sku}' to fulfil the free-goods scheme."); - newOrderItems.Add(new OrderItem + newItems.Add(new ShopPOItem { - FK_OrderId = orderId, + FK_ShopPOId = shopPOId, FK_ItemId = freeItem.Id, Quantity = (int)eligibility.FreeQty.Value, UnitPrice = 0m @@ -422,7 +422,7 @@ public class SchemeService( await uow.BeginAsync(ct); try { - if (newOrderItems.Count > 0) await orderRepo.AddItemsAsync(newOrderItems); + if (newItems.Count > 0) await shopPORepo.AddItemsAsync(newItems); await repo.AddRedemptionAsync(redemption); await uow.CommitAsync(ct); } @@ -457,8 +457,8 @@ public class SchemeService( var spend = await GetSpendAsync(schemeId); var actualSales = redemptions - .Where(r => r.Order is not null) - .Select(r => r.Order!) + .Where(r => r.ShopPO is not null) + .Select(r => r.ShopPO!) .Distinct() .Sum(o => o.TotalAmount); diff --git a/Distribution/Features/ShopPO/IShopPORepository.cs b/Distribution/Features/ShopPO/IShopPORepository.cs new file mode 100644 index 0000000..4a15739 --- /dev/null +++ b/Distribution/Features/ShopPO/IShopPORepository.cs @@ -0,0 +1,18 @@ +using Distribution.Models; + +namespace Distribution.Features.ShopPO; + +public interface IShopPORepository +{ + Task GetByIdAsync(Guid id); + Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed, int page, int pageSize); + Task GetCountAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed); + Task> GetConfirmedWithoutInvoiceAsync(Guid? agentId, Guid? routeId, Guid? shopId); + Task> GetActiveItemsByShopPOIdAsync(Guid shopPOId); + Task> GetByStoreIdAsync(Guid storeId); + Task AddAsync(Models.ShopPO entity); + void Update(Models.ShopPO entity); + void Remove(Models.ShopPO entity); + Task AddItemsAsync(IEnumerable items); + Task ReplaceItemsAsync(Guid shopPOId, List newItems); +} diff --git a/Distribution/Features/ShopPO/ShopPOController.cs b/Distribution/Features/ShopPO/ShopPOController.cs new file mode 100644 index 0000000..a7fb4c7 --- /dev/null +++ b/Distribution/Features/ShopPO/ShopPOController.cs @@ -0,0 +1,28 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Distribution.Features.ShopPO; + +[ApiController] +[Route("api/shop-pos")] +public class ShopPOController(ShopPOService service) : ControllerBase +{ + [HttpGet] + public async Task GetAll( + [FromQuery] Guid? agentId, + [FromQuery] Guid? routeId, + [FromQuery] Guid? shopId, + [FromQuery] bool? confirmed, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 20) + { + var result = await service.GetAllAsync(agentId, routeId, shopId, confirmed, page, pageSize); + return Ok(result); + } + + [HttpGet("{id:guid}")] + public async Task GetById(Guid id) + { + var result = await service.GetByIdAsync(id); + return result is null ? NotFound() : Ok(result); + } +} diff --git a/Distribution/Features/ShopPO/ShopPODTOs.cs b/Distribution/Features/ShopPO/ShopPODTOs.cs new file mode 100644 index 0000000..2eb2604 --- /dev/null +++ b/Distribution/Features/ShopPO/ShopPODTOs.cs @@ -0,0 +1,24 @@ +using Distribution.Models; + +namespace Distribution.Features.ShopPO; + +public record CreateShopPORequest(Guid StoreId, List Items); +public record ShopPOItemRequest(Guid ItemId, int Quantity, decimal? UnitPrice = null); +public record UpdateShopPOItemsRequest(List Items); + +public record ShopPOItemResponse(Guid Id, Guid ItemId, string ItemName, int Quantity, int QuantityFulfilled, decimal UnitPrice, bool IsActive); + +public record ShopPOResponse( + Guid Id, + Guid StoreId, + string StoreName, + Guid RaisedById, + Guid? InvoiceId, + decimal TotalAmount, + ShopPOStatus Status, + DateTime? ConfirmedAt, + Guid? ConfirmedBy, + DateTime? FulfilledAt, + List Items, + bool IsActive, + DateTime CreatedAt); diff --git a/Distribution/Features/ShopPO/ShopPORepository.cs b/Distribution/Features/ShopPO/ShopPORepository.cs new file mode 100644 index 0000000..2933fdc --- /dev/null +++ b/Distribution/Features/ShopPO/ShopPORepository.cs @@ -0,0 +1,91 @@ +using Distribution.Data; +using Distribution.Models; +using Microsoft.EntityFrameworkCore; + +namespace Distribution.Features.ShopPO; + +public class ShopPORepository(AppDBContext context) : IShopPORepository +{ + public async Task GetByIdAsync(Guid id) => + await context.ShopPOs + .Include(p => p.Store) + .Include(p => p.Items.Where(i => i.IsActive)) + .ThenInclude(i => i.Item) + .FirstOrDefaultAsync(p => p.Id == id && p.IsActive); + + public async Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed, int page, int pageSize) => + await context.ShopPOs + .Include(p => p.Store) + .Where(p => p.IsActive + && (agentId == null || p.RaisedById == agentId) + && (routeId == null || p.Store.FK_RouteId == routeId) + && (shopId == null || p.FK_StoreId == shopId) + && (confirmed == null || (confirmed == true ? p.ConfirmedAt != null : p.ConfirmedAt == null))) + .OrderByDescending(p => p.CreatedAt) + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + + public async Task GetCountAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed) => + await context.ShopPOs + .Include(p => p.Store) + .CountAsync(p => p.IsActive + && (agentId == null || p.RaisedById == agentId) + && (routeId == null || p.Store.FK_RouteId == routeId) + && (shopId == null || p.FK_StoreId == shopId) + && (confirmed == null || (confirmed == true ? p.ConfirmedAt != null : p.ConfirmedAt == null))); + + public async Task> GetConfirmedWithoutInvoiceAsync(Guid? agentId, Guid? routeId, Guid? shopId) => + await context.ShopPOs + .Include(p => p.Store) + .Include(p => p.Items.Where(i => i.IsActive)) + .Where(p => p.IsActive + && p.ConfirmedAt != null + && p.InvoiceId == null + && (agentId == null || p.RaisedById == agentId) + && (routeId == null || p.Store.FK_RouteId == routeId) + && (shopId == null || p.FK_StoreId == shopId)) + .ToListAsync(); + + public async Task> GetActiveItemsByShopPOIdAsync(Guid shopPOId) => + await context.ShopPOItems + .Include(i => i.Item) + .Where(i => i.FK_ShopPOId == shopPOId && i.IsActive) + .ToListAsync(); + + public async Task> GetByStoreIdAsync(Guid storeId) => + await context.ShopPOs + .Include(p => p.Items.Where(i => i.IsActive)) + .Where(p => p.FK_StoreId == storeId && p.IsActive) + .ToListAsync(); + + public async Task AddAsync(Models.ShopPO entity) => + await context.ShopPOs.AddAsync(entity); + + public void Update(Models.ShopPO entity) => + context.ShopPOs.Update(entity); + + public void Remove(Models.ShopPO entity) + { + entity.IsActive = false; + context.ShopPOs.Update(entity); + } + + public async Task AddItemsAsync(IEnumerable items) => + await context.ShopPOItems.AddRangeAsync(items); + + public async Task ReplaceItemsAsync(Guid shopPOId, List newItems) + { + var current = await context.ShopPOItems + .Where(i => i.FK_ShopPOId == shopPOId && i.IsActive) + .ToListAsync(); + + foreach (var item in current) + { + item.IsActive = false; + context.ShopPOItems.Update(item); + } + + await context.ShopPOItems.AddRangeAsync(newItems); + } +} diff --git a/Distribution/Features/ShopPO/ShopPOService.cs b/Distribution/Features/ShopPO/ShopPOService.cs new file mode 100644 index 0000000..1f5fda0 --- /dev/null +++ b/Distribution/Features/ShopPO/ShopPOService.cs @@ -0,0 +1,32 @@ +using Distribution.Features.Stock; +using Distribution.Infra.UoW; +using Distribution.Models; + +namespace Distribution.Features.ShopPO; + +public class ShopPOService( + IShopPORepository repo, + IUnitOfWork uow) +{ + private static ShopPOResponse ToResponse(Models.ShopPO p) => + new(p.Id, p.FK_StoreId, p.Store?.StoreName ?? string.Empty, + p.RaisedById, p.InvoiceId, p.TotalAmount, p.Status, + p.ConfirmedAt, p.ConfirmedBy, p.FulfilledAt, + p.Items.Where(i => i.IsActive).Select(i => + new ShopPOItemResponse(i.Id, i.FK_ItemId, i.Item?.Name ?? string.Empty, + i.Quantity, i.QuantityFulfilled, i.UnitPrice, i.IsActive)).ToList(), + p.IsActive, p.CreatedAt); + + public async Task> GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed, int page, int pageSize) + { + var total = await repo.GetCountAsync(agentId, routeId, shopId, confirmed); + var items = await repo.GetAllAsync(agentId, routeId, shopId, confirmed, page, pageSize); + return new PagedResponse(page, pageSize, total, items.Select(ToResponse).ToList()); + } + + public async Task GetByIdAsync(Guid id) + { + var po = await repo.GetByIdAsync(id); + return po is null ? null : ToResponse(po); + } +} diff --git a/Distribution/Features/Store/IStoreRepository.cs b/Distribution/Features/Store/IStoreRepository.cs index 6633023..dc3f81b 100644 --- a/Distribution/Features/Store/IStoreRepository.cs +++ b/Distribution/Features/Store/IStoreRepository.cs @@ -12,5 +12,5 @@ public interface IStoreRepository Task AddAsync(Models.Store entity); void Update(Models.Store entity); void Remove(Models.Store entity); - Task> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive); + Task> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive); } diff --git a/Distribution/Features/Store/StoreRepository.cs b/Distribution/Features/Store/StoreRepository.cs index 6e28d24..db56e9a 100644 --- a/Distribution/Features/Store/StoreRepository.cs +++ b/Distribution/Features/Store/StoreRepository.cs @@ -48,8 +48,8 @@ public class StoreRepository(AppDBContext context) : IStoreRepository context.Stores.Update(entity); } - public async Task> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive) => - await context.Orders - .Where(o => o.FK_StoreId == storeId && o.IsActive && o.OrderDate >= periodStart && o.OrderDate < periodEndExclusive) + public async Task> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive) => + await context.ShopPOs + .Where(o => o.FK_StoreId == storeId && o.IsActive && o.CreatedAt >= periodStart && o.CreatedAt < periodEndExclusive) .ToListAsync(); } diff --git a/Distribution/Features/Store/StoreService.cs b/Distribution/Features/Store/StoreService.cs index bcb1c72..e7a2383 100644 --- a/Distribution/Features/Store/StoreService.cs +++ b/Distribution/Features/Store/StoreService.cs @@ -268,6 +268,6 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe periodStart.ToString("yyyy-MM"), orders.Count, orders.Sum(o => o.TotalAmount), - orders.Count == 0 ? null : orders.Max(o => o.OrderDate)); + orders.Count == 0 ? null : orders.Max(o => o.CreatedAt)); } } diff --git a/Distribution/Features/SysConfig/ISysConfigRepository.cs b/Distribution/Features/SysConfig/ISysConfigRepository.cs new file mode 100644 index 0000000..73cc902 --- /dev/null +++ b/Distribution/Features/SysConfig/ISysConfigRepository.cs @@ -0,0 +1,8 @@ +namespace Distribution.Features.SysConfig; + +public interface ISysConfigRepository +{ + Task GetByKeyAsync(string key); + Task> GetAllAsync(); + Task UpsertAsync(Models.SysConfig entity); +} diff --git a/Distribution/Features/SysConfig/SysConfigController.cs b/Distribution/Features/SysConfig/SysConfigController.cs new file mode 100644 index 0000000..a2571bc --- /dev/null +++ b/Distribution/Features/SysConfig/SysConfigController.cs @@ -0,0 +1,53 @@ +using Distribution.Infra.Authorization; +using Distribution.Models; +using Microsoft.AspNetCore.Mvc; + +namespace Distribution.Features.SysConfig; + +[ApiController] +[Route("api/sys-config")] +public class SysConfigController(SysConfigService service, ICurrentUserService currentUser) : ControllerBase +{ + [HttpGet] + public async Task GetAll() => + Ok(await service.GetAllAsync()); + + // Typed shortcut — must be declared before {key} to take precedence + [HttpGet("invoice-creation-mode")] + public async Task GetInvoiceCreationMode() + { + var mode = await service.GetInvoiceCreationModeAsync(); + return Ok(new { Mode = mode }); + } + + [HttpPut("invoice-creation-mode")] + public async Task SetInvoiceCreationMode(SetInvoiceCreationModeRequest request, CancellationToken ct) + { + var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); + try + { + var result = await service.SetAsync(SysConfigService.KeyInvoiceCreationMode, request.Mode.ToString(), userId, ct); + return Ok(result); + } + catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } + } + + [HttpGet("{key}")] + public async Task GetByKey(string key) + { + var result = await service.GetByKeyAsync(key); + return result is null ? NotFound() : Ok(result); + } + + [HttpPut("{key}")] + public async Task Set(string key, SetSysConfigRequest request, CancellationToken ct) + { + var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); + try + { + var result = await service.SetAsync(key, request.Value, userId, ct); + return Ok(result); + } + catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } + } +} diff --git a/Distribution/Features/SysConfig/SysConfigDTOs.cs b/Distribution/Features/SysConfig/SysConfigDTOs.cs new file mode 100644 index 0000000..6084673 --- /dev/null +++ b/Distribution/Features/SysConfig/SysConfigDTOs.cs @@ -0,0 +1,9 @@ +using Distribution.Models; + +namespace Distribution.Features.SysConfig; + +public record SysConfigResponse(string Key, string Value, DateTime UpdatedAt, Guid? UpdatedBy); + +public record SetSysConfigRequest(string Value); + +public record SetInvoiceCreationModeRequest(InvoiceCreationMode Mode); diff --git a/Distribution/Features/SysConfig/SysConfigRepository.cs b/Distribution/Features/SysConfig/SysConfigRepository.cs new file mode 100644 index 0000000..f5282d2 --- /dev/null +++ b/Distribution/Features/SysConfig/SysConfigRepository.cs @@ -0,0 +1,29 @@ +using Distribution.Data; +using Microsoft.EntityFrameworkCore; + +namespace Distribution.Features.SysConfig; + +public class SysConfigRepository(AppDBContext context) : ISysConfigRepository +{ + public async Task GetByKeyAsync(string key) => + await context.SysConfigs.FindAsync(key); + + public async Task> GetAllAsync() => + await context.SysConfigs.OrderBy(c => c.Key).ToListAsync(); + + public async Task UpsertAsync(Models.SysConfig entity) + { + var existing = await context.SysConfigs.FindAsync(entity.Key); + if (existing is null) + { + await context.SysConfigs.AddAsync(entity); + } + else + { + existing.Value = entity.Value; + existing.UpdatedAt = entity.UpdatedAt; + existing.UpdatedBy = entity.UpdatedBy; + context.SysConfigs.Update(existing); + } + } +} diff --git a/Distribution/Features/SysConfig/SysConfigService.cs b/Distribution/Features/SysConfig/SysConfigService.cs new file mode 100644 index 0000000..397d53c --- /dev/null +++ b/Distribution/Features/SysConfig/SysConfigService.cs @@ -0,0 +1,67 @@ +using Distribution.Infra.UoW; +using Distribution.Models; + +namespace Distribution.Features.SysConfig; + +public class SysConfigService(ISysConfigRepository repo, IUnitOfWork uow) +{ + public const string KeyInvoiceCreationMode = "InvoiceCreationMode"; + + public async Task> GetAllAsync() + { + var configs = await repo.GetAllAsync(); + return configs.Select(ToResponse).ToList(); + } + + public async Task GetByKeyAsync(string key) + { + var config = await repo.GetByKeyAsync(key); + return config is null ? null : ToResponse(config); + } + + public async Task SetAsync(string key, string value, Guid userId, CancellationToken ct = default) + { + ValidateValue(key, value); + + var config = new Models.SysConfig + { + Key = key, + Value = value, + UpdatedAt = DateTime.Now, + UpdatedBy = userId + }; + + await uow.BeginAsync(ct); + try + { + await repo.UpsertAsync(config); + await uow.CommitAsync(ct); + } + catch { await uow.RollbackAsync(ct); throw; } + + var saved = await repo.GetByKeyAsync(key); + return ToResponse(saved!); + } + + /// + /// Returns the current InvoiceCreationMode, defaulting to ModeB if not configured. + /// ModeA = invoice auto-created on ShopPO confirmation. + /// ModeB = invoice created as a separate explicit step. + /// + public async Task GetInvoiceCreationModeAsync() + { + var config = await repo.GetByKeyAsync(KeyInvoiceCreationMode); + if (config is null) return InvoiceCreationMode.ModeB; + return Enum.TryParse(config.Value, out var mode) ? mode : InvoiceCreationMode.ModeB; + } + + private static void ValidateValue(string key, string value) + { + if (key == KeyInvoiceCreationMode && !Enum.TryParse(value, out _)) + throw new InvalidOperationException( + $"Invalid value '{value}' for '{key}'. Allowed values: {string.Join(", ", Enum.GetNames())}."); + } + + private static SysConfigResponse ToResponse(Models.SysConfig c) => + new(c.Key, c.Value, c.UpdatedAt, c.UpdatedBy); +} diff --git a/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.Designer.cs b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.Designer.cs new file mode 100644 index 0000000..c4c191f --- /dev/null +++ b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.Designer.cs @@ -0,0 +1,4026 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917034841_RefactorSalesToShopPOAndInvoice")] + partial class RefactorSalesToShopPOAndInvoice + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ApprovedAt") + .HasColumnType("datetime(6)"); + + b.Property("ApprovedBy") + .HasColumnType("char(36)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RequestedAt") + .HasColumnType("datetime(6)"); + + b.Property("RequestedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TypeCode") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("RideCancelRequests"); + + b.HasData( + new + { + Id = new Guid("65000000-0000-0000-0000-000000000001"), + ApprovedAt = new DateTime(2026, 8, 30, 9, 15, 0, 0, DateTimeKind.Unspecified), + ApprovedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + Reason = "Reported minor engine issue, resolved after inspection", + RequestedAt = new DateTime(2026, 8, 30, 9, 10, 0, 0, DateTimeKind.Unspecified), + RequestedBy = new Guid("29000000-0000-0000-0000-000000000005"), + Status = 2, + TypeCode = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs new file mode 100644 index 0000000..a12b129 --- /dev/null +++ b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs @@ -0,0 +1,961 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Distribution.Migrations +{ + /// + public partial class RefactorSalesToShopPOAndInvoice : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_DeliveryRuns_Routes_FK_RouteId", + table: "DeliveryRuns"); + + migrationBuilder.DropForeignKey( + name: "FK_DeliveryRuns_Warehouses_FK_SourceWarehouseId", + table: "DeliveryRuns"); + + migrationBuilder.DropForeignKey( + name: "FK_DeliveryTasks_Orders_FK_OrderId", + table: "DeliveryTasks"); + + migrationBuilder.DropForeignKey( + name: "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId", + table: "LoadingSheetItems"); + + migrationBuilder.DropForeignKey( + name: "FK_LoadingSheets_Warehouses_FK_SourceWarehouseId", + table: "LoadingSheets"); + + migrationBuilder.DropForeignKey( + name: "FK_Payments_Sales_FK_SaleId", + table: "Payments"); + + migrationBuilder.DropForeignKey( + name: "FK_Payments_Stores_FK_StoreId", + table: "Payments"); + + migrationBuilder.DropForeignKey( + name: "FK_SaleReturns_Orders_FK_OrderId", + table: "SaleReturns"); + + migrationBuilder.DropForeignKey( + name: "FK_SchemeRedemptions_Orders_FK_OrderId", + table: "SchemeRedemptions"); + + migrationBuilder.DropTable( + name: "OrderItems"); + + migrationBuilder.DropTable( + name: "Orders"); + + migrationBuilder.DropTable( + name: "Sales"); + + migrationBuilder.DropIndex( + name: "IX_Payments_FK_SaleId", + table: "Payments"); + + migrationBuilder.DropIndex( + name: "IX_LoadingSheets_FK_SourceWarehouseId", + table: "LoadingSheets"); + + migrationBuilder.DropIndex( + name: "IX_DeliveryRuns_FK_RouteId", + table: "DeliveryRuns"); + + migrationBuilder.DropIndex( + name: "IX_DeliveryRuns_FK_SourceWarehouseId", + table: "DeliveryRuns"); + + migrationBuilder.DropColumn( + name: "FK_SaleId", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "DispatchConfirmedAt", + table: "LoadingSheets"); + + migrationBuilder.DropColumn( + name: "DispatchConfirmedBy", + table: "LoadingSheets"); + + migrationBuilder.DropColumn( + name: "QuantityReceived", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "QuantityResolved", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "ActivatedAt", + table: "DeliveryRuns"); + + migrationBuilder.DropColumn( + name: "FK_RouteId", + table: "DeliveryRuns"); + + migrationBuilder.DropColumn( + name: "FK_SourceWarehouseId", + table: "DeliveryRuns"); + + migrationBuilder.DropColumn( + name: "RideType", + table: "DeliveryRuns"); + + migrationBuilder.RenameColumn( + name: "FK_OrderId", + table: "SchemeRedemptions", + newName: "FK_ShopPOId"); + + migrationBuilder.RenameIndex( + name: "IX_SchemeRedemptions_FK_OrderId", + table: "SchemeRedemptions", + newName: "IX_SchemeRedemptions_FK_ShopPOId"); + + migrationBuilder.RenameColumn( + name: "FK_OrderId", + table: "SaleReturns", + newName: "FK_ShopPOId"); + + migrationBuilder.RenameIndex( + name: "IX_SaleReturns_FK_OrderId", + table: "SaleReturns", + newName: "IX_SaleReturns_FK_ShopPOId"); + + migrationBuilder.RenameColumn( + name: "FK_StoreId", + table: "Payments", + newName: "FK_InvoiceId"); + + migrationBuilder.RenameIndex( + name: "IX_Payments_FK_StoreId", + table: "Payments", + newName: "IX_Payments_FK_InvoiceId"); + + migrationBuilder.RenameColumn( + name: "ReceiptConfirmedBy", + table: "LoadingSheets", + newName: "ConfirmedBy"); + + migrationBuilder.RenameColumn( + name: "ReceiptConfirmedAt", + table: "LoadingSheets", + newName: "ConfirmedAt"); + + migrationBuilder.RenameColumn( + name: "FK_SourceWarehouseId", + table: "LoadingSheets", + newName: "PopulatedBy"); + + migrationBuilder.RenameColumn( + name: "FK_OrderId", + table: "DeliveryTasks", + newName: "FK_ShopPOId"); + + migrationBuilder.RenameIndex( + name: "IX_DeliveryTasks_FK_OrderId", + table: "DeliveryTasks", + newName: "IX_DeliveryTasks_FK_ShopPOId"); + + migrationBuilder.AddColumn( + name: "PopulatedAt", + table: "LoadingSheets", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "CreatedAt", + table: "LoadingSheetItems", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "FK_ShopPOItemId", + table: "LoadingSheetItems", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "FK_WarehouseId", + table: "LoadingSheetItems", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "IsActive", + table: "LoadingSheetItems", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.CreateTable( + name: "ShopPOs", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_StoreId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + RaisedById = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + InvoiceId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + TotalAmount = table.Column(type: "decimal(65,30)", nullable: false), + Status = table.Column(type: "int", nullable: false), + ConfirmedAt = table.Column(type: "datetime(6)", nullable: true), + ConfirmedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + FulfilledAt = table.Column(type: "datetime(6)", nullable: true), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ShopPOs", x => x.Id); + table.ForeignKey( + name: "FK_ShopPOs_Stores_FK_StoreId", + column: x => x.FK_StoreId, + principalTable: "Stores", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Invoices", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ShopPOId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Status = table.Column(type: "int", nullable: false), + PaymentStatus = table.Column(type: "int", nullable: false), + CreatedBy = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + PrintedAt = table.Column(type: "datetime(6)", nullable: true), + PrintedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + FinalizedAt = table.Column(type: "datetime(6)", nullable: true), + FinalizedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + TotalAmount = table.Column(type: "decimal(65,30)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Invoices", x => x.Id); + table.ForeignKey( + name: "FK_Invoices_ShopPOs_FK_ShopPOId", + column: x => x.FK_ShopPOId, + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "LoadingSheetOrders", + columns: table => new + { + FK_LoadingSheetId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ShopPOId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_LoadingSheetOrders", x => new { x.FK_LoadingSheetId, x.FK_ShopPOId }); + table.ForeignKey( + name: "FK_LoadingSheetOrders_LoadingSheets_FK_LoadingSheetId", + column: x => x.FK_LoadingSheetId, + principalTable: "LoadingSheets", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_LoadingSheetOrders_ShopPOs_FK_ShopPOId", + column: x => x.FK_ShopPOId, + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ShopPOItems", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ShopPOId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ItemId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Quantity = table.Column(type: "int", nullable: false), + QuantityFulfilled = table.Column(type: "int", nullable: false), + UnitPrice = table.Column(type: "decimal(65,30)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ShopPOItems", x => x.Id); + table.ForeignKey( + name: "FK_ShopPOItems_Items_FK_ItemId", + column: x => x.FK_ItemId, + principalTable: "Items", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_ShopPOItems_ShopPOs_FK_ShopPOId", + column: x => x.FK_ShopPOId, + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "DeliveryRuns", + keyColumn: "Id", + keyValue: new Guid("31000000-0000-0000-0000-000000000001"), + column: "Status", + value: 2); + + migrationBuilder.UpdateData( + table: "DeliveryRuns", + keyColumn: "Id", + keyValue: new Guid("31000000-0000-0000-0000-000000000002"), + column: "Status", + value: 0); + + migrationBuilder.UpdateData( + table: "LoadingSheetItems", + keyColumn: "Id", + keyValue: new Guid("36000000-0000-0000-0000-000000000001"), + columns: new[] { "CreatedAt", "FK_ShopPOItemId", "FK_WarehouseId", "IsActive" }, + values: new object[] { new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), null, new Guid("27000000-0000-0000-0000-000000000001"), true }); + + migrationBuilder.UpdateData( + table: "LoadingSheetItems", + keyColumn: "Id", + keyValue: new Guid("36000000-0000-0000-0000-000000000002"), + columns: new[] { "CreatedAt", "FK_ShopPOItemId", "FK_WarehouseId", "IsActive" }, + values: new object[] { new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), null, new Guid("27000000-0000-0000-0000-000000000001"), true }); + + migrationBuilder.UpdateData( + table: "LoadingSheets", + keyColumn: "Id", + keyValue: new Guid("35000000-0000-0000-0000-000000000001"), + columns: new[] { "ConfirmedAt", "ConfirmedBy", "PopulatedAt", "PopulatedBy", "Status" }, + values: new object[] { new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), 1 }); + + migrationBuilder.UpdateData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000001"), + column: "FK_InvoiceId", + value: new Guid("34500000-0000-0000-0000-000000000001")); + + migrationBuilder.InsertData( + table: "ShopPOs", + columns: new[] { "Id", "ConfirmedAt", "ConfirmedBy", "CreatedAt", "FK_StoreId", "FulfilledAt", "InvoiceId", "IsActive", "RaisedById", "Status", "TotalAmount" }, + values: new object[,] + { + { new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("26000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34500000-0000-0000-0000-000000000001"), true, new Guid("29000000-0000-0000-0000-000000000002"), 2, 3000m }, + { new Guid("33000000-0000-0000-0000-000000000002"), null, null, new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("26000000-0000-0000-0000-000000000005"), null, null, true, new Guid("29000000-0000-0000-0000-000000000003"), 0, 1200m } + }); + + migrationBuilder.InsertData( + table: "Invoices", + columns: new[] { "Id", "CreatedAt", "CreatedBy", "FK_ShopPOId", "FinalizedAt", "FinalizedBy", "IsActive", "PaymentStatus", "PrintedAt", "PrintedBy", "Status", "TotalAmount" }, + values: new object[] { new Guid("34500000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), true, 2, new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000002"), 2, 3000m }); + + migrationBuilder.InsertData( + table: "ShopPOItems", + columns: new[] { "Id", "CreatedAt", "FK_ItemId", "FK_ShopPOId", "IsActive", "Quantity", "QuantityFulfilled", "UnitPrice" }, + values: new object[,] + { + { new Guid("34000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000001"), new Guid("33000000-0000-0000-0000-000000000001"), true, 30, 30, 60m }, + { new Guid("34000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000001"), true, 24, 24, 50m }, + { new Guid("34000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000002"), true, 10, 0, 120m } + }); + + migrationBuilder.CreateIndex( + name: "IX_LoadingSheetItems_FK_ShopPOItemId", + table: "LoadingSheetItems", + column: "FK_ShopPOItemId"); + + migrationBuilder.CreateIndex( + name: "IX_LoadingSheetItems_FK_WarehouseId", + table: "LoadingSheetItems", + column: "FK_WarehouseId"); + + migrationBuilder.CreateIndex( + name: "IX_Invoices_FK_ShopPOId", + table: "Invoices", + column: "FK_ShopPOId"); + + migrationBuilder.CreateIndex( + name: "IX_LoadingSheetOrders_FK_ShopPOId", + table: "LoadingSheetOrders", + column: "FK_ShopPOId"); + + migrationBuilder.CreateIndex( + name: "IX_ShopPOItems_FK_ItemId", + table: "ShopPOItems", + column: "FK_ItemId"); + + migrationBuilder.CreateIndex( + name: "IX_ShopPOItems_FK_ShopPOId", + table: "ShopPOItems", + column: "FK_ShopPOId"); + + migrationBuilder.CreateIndex( + name: "IX_ShopPOs_FK_StoreId", + table: "ShopPOs", + column: "FK_StoreId"); + + migrationBuilder.AddForeignKey( + name: "FK_DeliveryTasks_ShopPOs_FK_ShopPOId", + table: "DeliveryTasks", + column: "FK_ShopPOId", + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId", + table: "LoadingSheetItems", + column: "FK_LoadingSheetId", + principalTable: "LoadingSheets", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheetItems_ShopPOItems_FK_ShopPOItemId", + table: "LoadingSheetItems", + column: "FK_ShopPOItemId", + principalTable: "ShopPOItems", + principalColumn: "Id", + onDelete: ReferentialAction.SetNull); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheetItems_Warehouses_FK_WarehouseId", + table: "LoadingSheetItems", + column: "FK_WarehouseId", + principalTable: "Warehouses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_Payments_Invoices_FK_InvoiceId", + table: "Payments", + column: "FK_InvoiceId", + principalTable: "Invoices", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_SaleReturns_ShopPOs_FK_ShopPOId", + table: "SaleReturns", + column: "FK_ShopPOId", + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_SchemeRedemptions_ShopPOs_FK_ShopPOId", + table: "SchemeRedemptions", + column: "FK_ShopPOId", + principalTable: "ShopPOs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_DeliveryTasks_ShopPOs_FK_ShopPOId", + table: "DeliveryTasks"); + + migrationBuilder.DropForeignKey( + name: "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId", + table: "LoadingSheetItems"); + + migrationBuilder.DropForeignKey( + name: "FK_LoadingSheetItems_ShopPOItems_FK_ShopPOItemId", + table: "LoadingSheetItems"); + + migrationBuilder.DropForeignKey( + name: "FK_LoadingSheetItems_Warehouses_FK_WarehouseId", + table: "LoadingSheetItems"); + + migrationBuilder.DropForeignKey( + name: "FK_Payments_Invoices_FK_InvoiceId", + table: "Payments"); + + migrationBuilder.DropForeignKey( + name: "FK_SaleReturns_ShopPOs_FK_ShopPOId", + table: "SaleReturns"); + + migrationBuilder.DropForeignKey( + name: "FK_SchemeRedemptions_ShopPOs_FK_ShopPOId", + table: "SchemeRedemptions"); + + migrationBuilder.DropTable( + name: "Invoices"); + + migrationBuilder.DropTable( + name: "LoadingSheetOrders"); + + migrationBuilder.DropTable( + name: "ShopPOItems"); + + migrationBuilder.DropTable( + name: "ShopPOs"); + + migrationBuilder.DropIndex( + name: "IX_LoadingSheetItems_FK_ShopPOItemId", + table: "LoadingSheetItems"); + + migrationBuilder.DropIndex( + name: "IX_LoadingSheetItems_FK_WarehouseId", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "PopulatedAt", + table: "LoadingSheets"); + + migrationBuilder.DropColumn( + name: "CreatedAt", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "FK_ShopPOItemId", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "FK_WarehouseId", + table: "LoadingSheetItems"); + + migrationBuilder.DropColumn( + name: "IsActive", + table: "LoadingSheetItems"); + + migrationBuilder.RenameColumn( + name: "FK_ShopPOId", + table: "SchemeRedemptions", + newName: "FK_OrderId"); + + migrationBuilder.RenameIndex( + name: "IX_SchemeRedemptions_FK_ShopPOId", + table: "SchemeRedemptions", + newName: "IX_SchemeRedemptions_FK_OrderId"); + + migrationBuilder.RenameColumn( + name: "FK_ShopPOId", + table: "SaleReturns", + newName: "FK_OrderId"); + + migrationBuilder.RenameIndex( + name: "IX_SaleReturns_FK_ShopPOId", + table: "SaleReturns", + newName: "IX_SaleReturns_FK_OrderId"); + + migrationBuilder.RenameColumn( + name: "FK_InvoiceId", + table: "Payments", + newName: "FK_StoreId"); + + migrationBuilder.RenameIndex( + name: "IX_Payments_FK_InvoiceId", + table: "Payments", + newName: "IX_Payments_FK_StoreId"); + + migrationBuilder.RenameColumn( + name: "PopulatedBy", + table: "LoadingSheets", + newName: "FK_SourceWarehouseId"); + + migrationBuilder.RenameColumn( + name: "ConfirmedBy", + table: "LoadingSheets", + newName: "ReceiptConfirmedBy"); + + migrationBuilder.RenameColumn( + name: "ConfirmedAt", + table: "LoadingSheets", + newName: "ReceiptConfirmedAt"); + + migrationBuilder.RenameColumn( + name: "FK_ShopPOId", + table: "DeliveryTasks", + newName: "FK_OrderId"); + + migrationBuilder.RenameIndex( + name: "IX_DeliveryTasks_FK_ShopPOId", + table: "DeliveryTasks", + newName: "IX_DeliveryTasks_FK_OrderId"); + + migrationBuilder.AddColumn( + name: "FK_SaleId", + table: "Payments", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "DispatchConfirmedAt", + table: "LoadingSheets", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "DispatchConfirmedBy", + table: "LoadingSheets", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "QuantityReceived", + table: "LoadingSheetItems", + type: "decimal(65,30)", + nullable: true); + + migrationBuilder.AddColumn( + name: "QuantityResolved", + table: "LoadingSheetItems", + type: "decimal(65,30)", + nullable: true); + + migrationBuilder.AddColumn( + name: "ActivatedAt", + table: "DeliveryRuns", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "FK_RouteId", + table: "DeliveryRuns", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "FK_SourceWarehouseId", + table: "DeliveryRuns", + type: "char(36)", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + collation: "ascii_general_ci"); + + migrationBuilder.AddColumn( + name: "RideType", + table: "DeliveryRuns", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateTable( + name: "Sales", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CreatedByUserId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_RideId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + FK_StoreId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CompletedAt = table.Column(type: "datetime(6)", nullable: true), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + FulfillImmediately = table.Column(type: "tinyint(1)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + PaymentStatus = table.Column(type: "int", nullable: false), + SaleDate = table.Column(type: "datetime(6)", nullable: false), + Status = table.Column(type: "int", nullable: false), + TotalAmount = table.Column(type: "decimal(65,30)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Sales", x => x.Id); + table.ForeignKey( + name: "FK_Sales_DeliveryRuns_FK_RideId", + column: x => x.FK_RideId, + principalTable: "DeliveryRuns", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Sales_Stores_FK_StoreId", + column: x => x.FK_StoreId, + principalTable: "Stores", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Sales_Users_CreatedByUserId", + column: x => x.CreatedByUserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Orders", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_SaleId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_StoreId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + FulfilledAt = table.Column(type: "datetime(6)", nullable: true), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + OrderDate = table.Column(type: "datetime(6)", nullable: false), + Status = table.Column(type: "int", nullable: false), + TotalAmount = table.Column(type: "decimal(65,30)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Orders", x => x.Id); + table.ForeignKey( + name: "FK_Orders_Sales_FK_SaleId", + column: x => x.FK_SaleId, + principalTable: "Sales", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_Orders_Stores_FK_StoreId", + column: x => x.FK_StoreId, + principalTable: "Stores", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "OrderItems", + columns: table => new + { + FK_OrderId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_ItemId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + Quantity = table.Column(type: "int", nullable: false), + QuantityFulfilled = table.Column(type: "int", nullable: false), + UnitPrice = table.Column(type: "decimal(65,30)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_OrderItems", x => new { x.FK_OrderId, x.FK_ItemId }); + table.ForeignKey( + name: "FK_OrderItems_Items_FK_ItemId", + column: x => x.FK_ItemId, + principalTable: "Items", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_OrderItems_Orders_FK_OrderId", + column: x => x.FK_OrderId, + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.UpdateData( + table: "DeliveryRuns", + keyColumn: "Id", + keyValue: new Guid("31000000-0000-0000-0000-000000000001"), + columns: new[] { "ActivatedAt", "FK_RouteId", "FK_SourceWarehouseId", "RideType", "Status" }, + values: new object[] { new DateTime(2026, 8, 25, 8, 15, 0, 0, DateTimeKind.Unspecified), new Guid("25000000-0000-0000-0000-000000000001"), new Guid("27000000-0000-0000-0000-000000000001"), 1, 5 }); + + migrationBuilder.UpdateData( + table: "DeliveryRuns", + keyColumn: "Id", + keyValue: new Guid("31000000-0000-0000-0000-000000000002"), + columns: new[] { "ActivatedAt", "FK_RouteId", "FK_SourceWarehouseId", "RideType", "Status" }, + values: new object[] { new DateTime(2026, 8, 30, 9, 20, 0, 0, DateTimeKind.Unspecified), new Guid("25000000-0000-0000-0000-000000000003"), new Guid("27000000-0000-0000-0000-000000000002"), 0, 2 }); + + migrationBuilder.UpdateData( + table: "LoadingSheetItems", + keyColumn: "Id", + keyValue: new Guid("36000000-0000-0000-0000-000000000001"), + columns: new[] { "QuantityReceived", "QuantityResolved" }, + values: new object[] { 50m, null }); + + migrationBuilder.UpdateData( + table: "LoadingSheetItems", + keyColumn: "Id", + keyValue: new Guid("36000000-0000-0000-0000-000000000002"), + columns: new[] { "QuantityReceived", "QuantityResolved" }, + values: new object[] { 30m, null }); + + migrationBuilder.UpdateData( + table: "LoadingSheets", + keyColumn: "Id", + keyValue: new Guid("35000000-0000-0000-0000-000000000001"), + columns: new[] { "DispatchConfirmedAt", "DispatchConfirmedBy", "FK_SourceWarehouseId", "ReceiptConfirmedAt", "ReceiptConfirmedBy", "Status" }, + values: new object[] { new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new Guid("27000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 14, 5, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000004"), 2 }); + + migrationBuilder.UpdateData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000001"), + columns: new[] { "FK_SaleId", "FK_StoreId" }, + values: new object[] { new Guid("32000000-0000-0000-0000-000000000001"), new Guid("26000000-0000-0000-0000-000000000001") }); + + migrationBuilder.InsertData( + table: "Sales", + columns: new[] { "Id", "CompletedAt", "CreatedAt", "CreatedByUserId", "FK_RideId", "FK_StoreId", "FulfillImmediately", "IsActive", "PaymentStatus", "SaleDate", "Status", "TotalAmount" }, + values: new object[,] + { + { new Guid("32000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000002"), new Guid("31000000-0000-0000-0000-000000000001"), new Guid("26000000-0000-0000-0000-000000000001"), false, true, 2, new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), 1, 3000m }, + { new Guid("32000000-0000-0000-0000-000000000002"), null, new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new Guid("31000000-0000-0000-0000-000000000002"), new Guid("26000000-0000-0000-0000-000000000005"), false, true, 0, new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), 0, 1200m } + }); + + migrationBuilder.InsertData( + table: "Orders", + columns: new[] { "Id", "CreatedAt", "FK_SaleId", "FK_StoreId", "FulfilledAt", "IsActive", "OrderDate", "Status", "TotalAmount" }, + values: new object[,] + { + { new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("32000000-0000-0000-0000-000000000001"), new Guid("26000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), true, new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), 2, 3000m }, + { new Guid("33000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("32000000-0000-0000-0000-000000000002"), new Guid("26000000-0000-0000-0000-000000000005"), null, true, new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), 0, 1200m } + }); + + migrationBuilder.InsertData( + table: "OrderItems", + columns: new[] { "FK_ItemId", "FK_OrderId", "CreatedAt", "Id", "IsActive", "Quantity", "QuantityFulfilled", "UnitPrice" }, + values: new object[,] + { + { new Guid("23000000-0000-0000-0000-000000000001"), new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000001"), true, 30, 30, 60m }, + { new Guid("23000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000002"), true, 24, 24, 50m }, + { new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34000000-0000-0000-0000-000000000003"), true, 10, 0, 120m } + }); + + migrationBuilder.CreateIndex( + name: "IX_Payments_FK_SaleId", + table: "Payments", + column: "FK_SaleId"); + + migrationBuilder.CreateIndex( + name: "IX_LoadingSheets_FK_SourceWarehouseId", + table: "LoadingSheets", + column: "FK_SourceWarehouseId"); + + migrationBuilder.CreateIndex( + name: "IX_DeliveryRuns_FK_RouteId", + table: "DeliveryRuns", + column: "FK_RouteId"); + + migrationBuilder.CreateIndex( + name: "IX_DeliveryRuns_FK_SourceWarehouseId", + table: "DeliveryRuns", + column: "FK_SourceWarehouseId"); + + migrationBuilder.CreateIndex( + name: "IX_OrderItems_FK_ItemId", + table: "OrderItems", + column: "FK_ItemId"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_FK_SaleId", + table: "Orders", + column: "FK_SaleId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Orders_FK_StoreId", + table: "Orders", + column: "FK_StoreId"); + + migrationBuilder.CreateIndex( + name: "IX_Sales_CreatedByUserId", + table: "Sales", + column: "CreatedByUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Sales_FK_RideId", + table: "Sales", + column: "FK_RideId"); + + migrationBuilder.CreateIndex( + name: "IX_Sales_FK_StoreId", + table: "Sales", + column: "FK_StoreId"); + + migrationBuilder.AddForeignKey( + name: "FK_DeliveryRuns_Routes_FK_RouteId", + table: "DeliveryRuns", + column: "FK_RouteId", + principalTable: "Routes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_DeliveryRuns_Warehouses_FK_SourceWarehouseId", + table: "DeliveryRuns", + column: "FK_SourceWarehouseId", + principalTable: "Warehouses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_DeliveryTasks_Orders_FK_OrderId", + table: "DeliveryTasks", + column: "FK_OrderId", + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId", + table: "LoadingSheetItems", + column: "FK_LoadingSheetId", + principalTable: "LoadingSheets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_LoadingSheets_Warehouses_FK_SourceWarehouseId", + table: "LoadingSheets", + column: "FK_SourceWarehouseId", + principalTable: "Warehouses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_Payments_Sales_FK_SaleId", + table: "Payments", + column: "FK_SaleId", + principalTable: "Sales", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_Payments_Stores_FK_StoreId", + table: "Payments", + column: "FK_StoreId", + principalTable: "Stores", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_SaleReturns_Orders_FK_OrderId", + table: "SaleReturns", + column: "FK_OrderId", + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + + migrationBuilder.AddForeignKey( + name: "FK_SchemeRedemptions_Orders_FK_OrderId", + table: "SchemeRedemptions", + column: "FK_OrderId", + principalTable: "Orders", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + } +} diff --git a/Distribution/Migrations/20260917042658_AddSysConfig.Designer.cs b/Distribution/Migrations/20260917042658_AddSysConfig.Designer.cs new file mode 100644 index 0000000..8470a58 --- /dev/null +++ b/Distribution/Migrations/20260917042658_AddSysConfig.Designer.cs @@ -0,0 +1,4055 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917042658_AddSysConfig")] + partial class AddSysConfig + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ApprovedAt") + .HasColumnType("datetime(6)"); + + b.Property("ApprovedBy") + .HasColumnType("char(36)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RequestedAt") + .HasColumnType("datetime(6)"); + + b.Property("RequestedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TypeCode") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("RideCancelRequests"); + + b.HasData( + new + { + Id = new Guid("65000000-0000-0000-0000-000000000001"), + ApprovedAt = new DateTime(2026, 8, 30, 9, 15, 0, 0, DateTimeKind.Unspecified), + ApprovedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + Reason = "Reported minor engine issue, resolved after inspection", + RequestedAt = new DateTime(2026, 8, 30, 9, 10, 0, 0, DateTimeKind.Unspecified), + RequestedBy = new Guid("29000000-0000-0000-0000-000000000005"), + Status = 2, + TypeCode = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917042658_AddSysConfig.cs b/Distribution/Migrations/20260917042658_AddSysConfig.cs new file mode 100644 index 0000000..b566652 --- /dev/null +++ b/Distribution/Migrations/20260917042658_AddSysConfig.cs @@ -0,0 +1,44 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Distribution.Migrations +{ + /// + public partial class AddSysConfig : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "SysConfigs", + columns: table => new + { + Key = table.Column(type: "varchar(100)", maxLength: 100, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + UpdatedAt = table.Column(type: "datetime(6)", nullable: false), + UpdatedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_SysConfigs", x => x.Key); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.InsertData( + table: "SysConfigs", + columns: new[] { "Key", "UpdatedAt", "UpdatedBy", "Value" }, + values: new object[] { "InvoiceCreationMode", new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), null, "ModeB" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "SysConfigs"); + } + } +} diff --git a/Distribution/Migrations/AppDBContextModelSnapshot.cs b/Distribution/Migrations/AppDBContextModelSnapshot.cs index 53c706b..e0d3129 100644 --- a/Distribution/Migrations/AppDBContextModelSnapshot.cs +++ b/Distribution/Migrations/AppDBContextModelSnapshot.cs @@ -206,9 +206,6 @@ namespace Distribution.Migrations .ValueGeneratedOnAdd() .HasColumnType("char(36)"); - b.Property("ActivatedAt") - .HasColumnType("datetime(6)"); - b.Property("ClosedAt") .HasColumnType("datetime(6)"); @@ -218,12 +215,6 @@ namespace Distribution.Migrations b.Property("FK_DriverProfileId") .HasColumnType("char(36)"); - b.Property("FK_RouteId") - .HasColumnType("char(36)"); - - b.Property("FK_SourceWarehouseId") - .HasColumnType("char(36)"); - b.Property("FK_VehicleId") .HasColumnType("char(36)"); @@ -236,9 +227,6 @@ namespace Distribution.Migrations b.Property("Meterstart") .HasColumnType("int"); - b.Property("RideType") - .HasColumnType("int"); - b.Property("StartedAt") .HasColumnType("datetime(6)"); @@ -249,10 +237,6 @@ namespace Distribution.Migrations b.HasIndex("FK_DriverProfileId"); - b.HasIndex("FK_RouteId"); - - b.HasIndex("FK_SourceWarehouseId"); - b.HasIndex("FK_VehicleId"); b.ToTable("DeliveryRuns"); @@ -261,35 +245,27 @@ namespace Distribution.Migrations new { Id = new Guid("31000000-0000-0000-0000-000000000001"), - ActivatedAt = new DateTime(2026, 8, 25, 8, 15, 0, 0, DateTimeKind.Unspecified), ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), - FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), - FK_SourceWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), IsActive = true, Meterend = 10550, Meterstart = 10500, - RideType = 1, StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), - Status = 5 + Status = 2 }, new { Id = new Guid("31000000-0000-0000-0000-000000000002"), - ActivatedAt = new DateTime(2026, 8, 30, 9, 20, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), - FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), - FK_SourceWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), IsActive = true, Meterend = 0, Meterstart = 20300, - RideType = 0, StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), - Status = 2 + Status = 0 }); }); @@ -308,10 +284,10 @@ namespace Distribution.Migrations b.Property("CustomerConfirmed") .HasColumnType("tinyint(1)"); - b.Property("FK_OrderId") + b.Property("FK_RideId") .HasColumnType("char(36)"); - b.Property("FK_RideId") + b.Property("FK_ShopPOId") .HasColumnType("char(36)"); b.Property("IsActive") @@ -328,10 +304,10 @@ namespace Distribution.Migrations b.HasKey("Id"); - b.HasIndex("FK_OrderId"); - b.HasIndex("FK_RideId"); + b.HasIndex("FK_ShopPOId"); + b.ToTable("DeliveryTasks"); b.HasData( @@ -340,8 +316,8 @@ namespace Distribution.Migrations Id = new Guid("37000000-0000-0000-0000-000000000001"), CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), CustomerConfirmed = false, - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000002"), FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), IsActive = true, Sequence = 1, Status = 0 @@ -536,6 +512,69 @@ namespace Distribution.Migrations }); }); + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + modelBuilder.Entity("Distribution.Models.Item", b => { b.Property("Id") @@ -663,28 +702,25 @@ namespace Distribution.Migrations .ValueGeneratedOnAdd() .HasColumnType("char(36)"); + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + b.Property("CreatedAt") .HasColumnType("datetime(6)"); - b.Property("DispatchConfirmedAt") - .HasColumnType("datetime(6)"); - - b.Property("DispatchConfirmedBy") - .HasColumnType("char(36)"); - b.Property("FK_RideId") .HasColumnType("char(36)"); - b.Property("FK_SourceWarehouseId") - .HasColumnType("char(36)"); - b.Property("IsActive") .HasColumnType("tinyint(1)"); - b.Property("ReceiptConfirmedAt") + b.Property("PopulatedAt") .HasColumnType("datetime(6)"); - b.Property("ReceiptConfirmedBy") + b.Property("PopulatedBy") .HasColumnType("char(36)"); b.Property("Status") @@ -694,23 +730,20 @@ namespace Distribution.Migrations b.HasIndex("FK_RideId"); - b.HasIndex("FK_SourceWarehouseId"); - b.ToTable("LoadingSheets"); b.HasData( new { Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), - DispatchConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), - DispatchConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), - FK_SourceWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), IsActive = true, - ReceiptConfirmedAt = new DateTime(2026, 8, 25, 14, 5, 0, 0, DateTimeKind.Unspecified), - ReceiptConfirmedBy = new Guid("29000000-0000-0000-0000-000000000004"), - Status = 2 + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 }); }); @@ -720,179 +753,75 @@ namespace Distribution.Migrations .ValueGeneratedOnAdd() .HasColumnType("char(36)"); + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + b.Property("FK_ItemId") .HasColumnType("char(36)"); b.Property("FK_LoadingSheetId") .HasColumnType("char(36)"); + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + b.Property("QuantityDispatched") .HasColumnType("decimal(65,30)"); - b.Property("QuantityReceived") - .HasColumnType("decimal(65,30)"); - - b.Property("QuantityResolved") - .HasColumnType("decimal(65,30)"); - b.HasKey("Id"); b.HasIndex("FK_ItemId"); b.HasIndex("FK_LoadingSheetId"); + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + b.ToTable("LoadingSheetItems"); b.HasData( new { Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), - QuantityDispatched = 50m, - QuantityReceived = 50m + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m }, new { Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), - QuantityDispatched = 30m, - QuantityReceived = 30m + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m }); }); - modelBuilder.Entity("Distribution.Models.Order", b => + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => { - b.Property("Id") - .ValueGeneratedOnAdd() + b.Property("FK_LoadingSheetId") .HasColumnType("char(36)"); - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("FK_SaleId") + b.Property("FK_ShopPOId") .HasColumnType("char(36)"); - b.Property("FK_StoreId") - .HasColumnType("char(36)"); + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); - b.Property("FulfilledAt") - .HasColumnType("datetime(6)"); + b.HasIndex("FK_ShopPOId"); - b.Property("IsActive") - .HasColumnType("tinyint(1)"); - - b.Property("OrderDate") - .HasColumnType("datetime(6)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TotalAmount") - .HasColumnType("decimal(65,30)"); - - b.HasKey("Id"); - - b.HasIndex("FK_SaleId") - .IsUnique(); - - b.HasIndex("FK_StoreId"); - - b.ToTable("Orders"); - - b.HasData( - new - { - Id = new Guid("33000000-0000-0000-0000-000000000001"), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - FK_SaleId = new Guid("32000000-0000-0000-0000-000000000001"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), - FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), - IsActive = true, - OrderDate = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - Status = 2, - TotalAmount = 3000m - }, - new - { - Id = new Guid("33000000-0000-0000-0000-000000000002"), - CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - FK_SaleId = new Guid("32000000-0000-0000-0000-000000000002"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), - IsActive = true, - OrderDate = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - Status = 0, - TotalAmount = 1200m - }); - }); - - modelBuilder.Entity("Distribution.Models.OrderItem", b => - { - b.Property("FK_OrderId") - .HasColumnType("char(36)"); - - b.Property("FK_ItemId") - .HasColumnType("char(36)"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Id") - .HasColumnType("char(36)"); - - b.Property("IsActive") - .HasColumnType("tinyint(1)"); - - b.Property("Quantity") - .HasColumnType("int"); - - b.Property("QuantityFulfilled") - .HasColumnType("int"); - - b.Property("UnitPrice") - .HasColumnType("decimal(65,30)"); - - b.HasKey("FK_OrderId", "FK_ItemId"); - - b.HasIndex("FK_ItemId"); - - b.ToTable("OrderItems"); - - b.HasData( - new - { - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000001"), - FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - Id = new Guid("34000000-0000-0000-0000-000000000001"), - IsActive = true, - Quantity = 30, - QuantityFulfilled = 30, - UnitPrice = 60m - }, - new - { - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000001"), - FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - Id = new Guid("34000000-0000-0000-0000-000000000002"), - IsActive = true, - Quantity = 24, - QuantityFulfilled = 24, - UnitPrice = 50m - }, - new - { - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000002"), - FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), - CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - Id = new Guid("34000000-0000-0000-0000-000000000003"), - IsActive = true, - Quantity = 10, - QuantityFulfilled = 0, - UnitPrice = 120m - }); + b.ToTable("LoadingSheetOrders"); }); modelBuilder.Entity("Distribution.Models.Payment", b => @@ -913,10 +842,7 @@ namespace Distribution.Migrations b.Property("CreatedAt") .HasColumnType("datetime(6)"); - b.Property("FK_SaleId") - .HasColumnType("char(36)"); - - b.Property("FK_StoreId") + b.Property("FK_InvoiceId") .HasColumnType("char(36)"); b.Property("IsActive") @@ -927,9 +853,7 @@ namespace Distribution.Migrations b.HasKey("Id"); - b.HasIndex("FK_SaleId"); - - b.HasIndex("FK_StoreId"); + b.HasIndex("FK_InvoiceId"); b.ToTable("Payments"); @@ -941,8 +865,7 @@ namespace Distribution.Migrations CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), - FK_SaleId = new Guid("32000000-0000-0000-0000-000000000001"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), IsActive = true, Method = 0 }); @@ -1802,87 +1725,6 @@ namespace Distribution.Migrations }); }); - modelBuilder.Entity("Distribution.Models.Sale", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("char(36)"); - - b.Property("CompletedAt") - .HasColumnType("datetime(6)"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("CreatedByUserId") - .HasColumnType("char(36)"); - - b.Property("FK_RideId") - .HasColumnType("char(36)"); - - b.Property("FK_StoreId") - .HasColumnType("char(36)"); - - b.Property("FulfillImmediately") - .HasColumnType("tinyint(1)"); - - b.Property("IsActive") - .HasColumnType("tinyint(1)"); - - b.Property("PaymentStatus") - .HasColumnType("int"); - - b.Property("SaleDate") - .HasColumnType("datetime(6)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TotalAmount") - .HasColumnType("decimal(65,30)"); - - b.HasKey("Id"); - - b.HasIndex("CreatedByUserId"); - - b.HasIndex("FK_RideId"); - - b.HasIndex("FK_StoreId"); - - b.ToTable("Sales"); - - b.HasData( - new - { - Id = new Guid("32000000-0000-0000-0000-000000000001"), - CompletedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), - CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), - FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), - FulfillImmediately = false, - IsActive = true, - PaymentStatus = 2, - SaleDate = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), - Status = 1, - TotalAmount = 3000m - }, - new - { - Id = new Guid("32000000-0000-0000-0000-000000000002"), - CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000003"), - FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), - FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), - FulfillImmediately = false, - IsActive = true, - PaymentStatus = 0, - SaleDate = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), - Status = 0, - TotalAmount = 1200m - }); - }); - modelBuilder.Entity("Distribution.Models.SaleReturn", b => { b.Property("Id") @@ -1895,7 +1737,7 @@ namespace Distribution.Migrations b.Property("CreatedByUserId") .HasColumnType("char(36)"); - b.Property("FK_OrderId") + b.Property("FK_ShopPOId") .HasColumnType("char(36)"); b.Property("IsActive") @@ -1911,7 +1753,7 @@ namespace Distribution.Migrations b.HasIndex("CreatedByUserId"); - b.HasIndex("FK_OrderId"); + b.HasIndex("FK_ShopPOId"); b.ToTable("SaleReturns"); @@ -1921,7 +1763,7 @@ namespace Distribution.Migrations Id = new Guid("51000000-0000-0000-0000-000000000001"), CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), IsActive = true, Mode = 0, TotalCreditAmount = 300m @@ -2153,10 +1995,10 @@ namespace Distribution.Migrations b.Property("FK_FreeItemId") .HasColumnType("char(36)"); - b.Property("FK_OrderId") + b.Property("FK_SchemeId") .HasColumnType("char(36)"); - b.Property("FK_SchemeId") + b.Property("FK_ShopPOId") .HasColumnType("char(36)"); b.Property("FieldInvoiceId") @@ -2175,10 +2017,10 @@ namespace Distribution.Migrations b.HasIndex("FK_FreeItemId"); - b.HasIndex("FK_OrderId"); - b.HasIndex("FK_SchemeId"); + b.HasIndex("FK_ShopPOId"); + b.ToTable("SchemeRedemptions"); b.HasData( @@ -2187,14 +2029,155 @@ namespace Distribution.Migrations Id = new Guid("50000000-0000-0000-0000-000000000001"), DiscountAmount = 0m, FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), - FK_OrderId = new Guid("33000000-0000-0000-0000-000000000001"), FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), FreeItemCostValue = 40m, FreeQty = 1m, RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) }); }); + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + modelBuilder.Entity("Distribution.Models.StockBalance", b => { b.Property("Id") @@ -2761,6 +2744,35 @@ namespace Distribution.Migrations }); }); + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + modelBuilder.Entity("Distribution.Models.Uom", b => { b.Property("Id") @@ -3205,18 +3217,6 @@ namespace Distribution.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Route", "Route") - .WithMany() - .HasForeignKey("FK_RouteId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Distribution.Models.Warehouse", "SourceWarehouse") - .WithMany() - .HasForeignKey("FK_SourceWarehouseId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - b.HasOne("Distribution.Models.Vehicle", "Vehicle") .WithMany() .HasForeignKey("FK_VehicleId") @@ -3225,30 +3225,26 @@ namespace Distribution.Migrations b.Navigation("DriverProfile"); - b.Navigation("Route"); - - b.Navigation("SourceWarehouse"); - b.Navigation("Vehicle"); }); modelBuilder.Entity("Distribution.Models.DeliveryTask", b => { - b.HasOne("Distribution.Models.Order", "Order") - .WithMany() - .HasForeignKey("FK_OrderId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - b.HasOne("Distribution.Models.DeliveryRun", "Ride") .WithMany() .HasForeignKey("FK_RideId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.Navigation("Order"); + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); b.Navigation("Ride"); + + b.Navigation("ShopPO"); }); modelBuilder.Entity("Distribution.Models.DriverProfile", b => @@ -3300,6 +3296,17 @@ namespace Distribution.Migrations b.Navigation("PurchaseOrderItem"); }); + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + modelBuilder.Entity("Distribution.Models.Item", b => { b.HasOne("Distribution.Models.Uom", "BaseUom") @@ -3339,15 +3346,7 @@ namespace Distribution.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Warehouse", "SourceWarehouse") - .WithMany() - .HasForeignKey("FK_SourceWarehouseId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - b.Navigation("Ride"); - - b.Navigation("SourceWarehouse"); }); modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => @@ -3361,69 +3360,57 @@ namespace Distribution.Migrations b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") .WithMany("Items") .HasForeignKey("FK_LoadingSheetId") - .OnDelete(DeleteBehavior.Cascade) + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) .IsRequired(); b.Navigation("Item"); b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); }); - modelBuilder.Entity("Distribution.Models.Order", b => + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => { - b.HasOne("Distribution.Models.Sale", "Sale") - .WithMany() - .HasForeignKey("FK_SaleId") + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Store", "Store") + b.HasOne("Distribution.Models.ShopPO", "ShopPO") .WithMany() - .HasForeignKey("FK_StoreId") - .OnDelete(DeleteBehavior.Cascade) + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.Navigation("Sale"); + b.Navigation("LoadingSheet"); - b.Navigation("Store"); - }); - - modelBuilder.Entity("Distribution.Models.OrderItem", b => - { - b.HasOne("Distribution.Models.Item", "Item") - .WithMany() - .HasForeignKey("FK_ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Distribution.Models.Order", "Order") - .WithMany("OrderItems") - .HasForeignKey("FK_OrderId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("Order"); + b.Navigation("ShopPO"); }); modelBuilder.Entity("Distribution.Models.Payment", b => { - b.HasOne("Distribution.Models.Sale", "Sale") - .WithMany() - .HasForeignKey("FK_SaleId") - .OnDelete(DeleteBehavior.Cascade) + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Store", "Store") - .WithMany() - .HasForeignKey("FK_StoreId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Sale"); - - b.Navigation("Store"); + b.Navigation("Invoice"); }); modelBuilder.Entity("Distribution.Models.PriceList", b => @@ -3640,32 +3627,6 @@ namespace Distribution.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Distribution.Models.Sale", b => - { - b.HasOne("Distribution.Models.User", "CreatedByUser") - .WithMany() - .HasForeignKey("CreatedByUserId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("Distribution.Models.DeliveryRun", "Ride") - .WithMany() - .HasForeignKey("FK_RideId") - .OnDelete(DeleteBehavior.Restrict); - - b.HasOne("Distribution.Models.Store", "Store") - .WithMany() - .HasForeignKey("FK_StoreId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("CreatedByUser"); - - b.Navigation("Ride"); - - b.Navigation("Store"); - }); - modelBuilder.Entity("Distribution.Models.SaleReturn", b => { b.HasOne("Distribution.Models.User", "CreatedByUser") @@ -3674,15 +3635,15 @@ namespace Distribution.Migrations .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("Distribution.Models.Order", "Order") + b.HasOne("Distribution.Models.ShopPO", "ShopPO") .WithMany() - .HasForeignKey("FK_OrderId") + .HasForeignKey("FK_ShopPOId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); b.Navigation("CreatedByUser"); - b.Navigation("Order"); + b.Navigation("ShopPO"); }); modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => @@ -3753,22 +3714,52 @@ namespace Distribution.Migrations .HasForeignKey("FK_FreeItemId") .OnDelete(DeleteBehavior.Restrict); - b.HasOne("Distribution.Models.Order", "Order") - .WithMany() - .HasForeignKey("FK_OrderId") - .OnDelete(DeleteBehavior.Restrict); - b.HasOne("Distribution.Models.Scheme", "Scheme") .WithMany("Redemptions") .HasForeignKey("FK_SchemeId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + b.Navigation("FreeItem"); - b.Navigation("Order"); - b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); }); modelBuilder.Entity("Distribution.Models.StockBalance", b => @@ -4002,6 +3993,11 @@ namespace Distribution.Migrations b.Navigation("Items"); }); + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + modelBuilder.Entity("Distribution.Models.Item", b => { b.Navigation("Conversions"); @@ -4010,11 +4006,8 @@ namespace Distribution.Migrations modelBuilder.Entity("Distribution.Models.LoadingSheet", b => { b.Navigation("Items"); - }); - modelBuilder.Entity("Distribution.Models.Order", b => - { - b.Navigation("OrderItems"); + b.Navigation("Orders"); }); modelBuilder.Entity("Distribution.Models.PriceList", b => @@ -4044,6 +4037,11 @@ namespace Distribution.Migrations b.Navigation("Redemptions"); }); + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => { b.Navigation("Items"); diff --git a/Distribution/Models/DeliveryRun.cs b/Distribution/Models/DeliveryRun.cs index 492f3b6..66c801c 100644 --- a/Distribution/Models/DeliveryRun.cs +++ b/Distribution/Models/DeliveryRun.cs @@ -4,8 +4,7 @@ namespace Distribution.Models { public class DeliveryRun : Template { - public RideType RideType { get; set; } - public RideStatus Status { get; set; } = RideStatus.Draft; + public RideStatus Status { get; set; } = RideStatus.Open; public Guid FK_VehicleId { get; set; } [ForeignKey("FK_VehicleId")] @@ -15,19 +14,10 @@ namespace Distribution.Models [ForeignKey("FK_DriverProfileId")] public DriverProfile DriverProfile { get; set; } - public Guid FK_RouteId { get; set; } - [ForeignKey("FK_RouteId")] - public Route Route { get; set; } - - public Guid FK_SourceWarehouseId { get; set; } - [ForeignKey("FK_SourceWarehouseId")] - public Warehouse SourceWarehouse { get; set; } - public int Meterstart { get; set; } public int Meterend { get; set; } public DateTime? StartedAt { get; set; } - public DateTime? ActivatedAt { get; set; } public DateTime? ClosedAt { get; set; } } } diff --git a/Distribution/Models/DeliveryTask.cs b/Distribution/Models/DeliveryTask.cs index b28bdc1..e1e9bd1 100644 --- a/Distribution/Models/DeliveryTask.cs +++ b/Distribution/Models/DeliveryTask.cs @@ -8,9 +8,9 @@ namespace Distribution.Models [ForeignKey("FK_RideId")] public DeliveryRun Ride { get; set; } - public Guid FK_OrderId { get; set; } - [ForeignKey("FK_OrderId")] - public Order Order { get; set; } + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } public int Sequence { get; set; } public DeliveryTaskStatus Status { get; set; } = DeliveryTaskStatus.Pending; diff --git a/Distribution/Models/Enums.cs b/Distribution/Models/Enums.cs index ed2aa7f..e8621d2 100644 --- a/Distribution/Models/Enums.cs +++ b/Distribution/Models/Enums.cs @@ -3,15 +3,14 @@ namespace Distribution.Models public enum LocationType { Warehouse, Vehicle, External } - public enum KycStatus { Pending,Verified, Rejected } - public enum MovementType { Sale, CustomerReturn, Transfer, Damage, Adjustment, Load, PurchaseReceipt, PurchaseReturn } + public enum KycStatus { Pending, Verified, Rejected } - public enum LoadingSheetStatus { Pending, DispatchConfirmed, ReceiptConfirmed, DiscrepancyFlagged, Resolved } + public enum MovementType { Sale, CustomerReturn, Transfer, Damage, Adjustment, Load, PurchaseReceipt, PurchaseReturn } - public enum RideType { Delivery, Sale } + public enum LoadingSheetStatus { Planned, Confirmed } - public enum RideStatus { Draft, Open, Active, CancelRequested, Cancelled, Closed } + public enum RideStatus { Open, Cancelled, Closed } public enum CancelRequestType { VehicleBreakdown, DriverUnavailable, RouteIssue, Other } @@ -19,16 +18,15 @@ namespace Distribution.Models public enum PurchaseOrderStatus { Issued, PartiallyReceived, Received, Closed, Cancelled } - public enum SaleStatus { Pending, Completed, Cancelled } + public enum ShopPOStatus { Pending, PartiallyFulfilled, Fulfilled, Cancelled } - public enum OrderStatus { Pending, PartiallyFulfilled, Fulfilled, Cancelled } + public enum InvoiceStatus { Draft, Printed, Finalized } public enum PaymentStatus { Pending, PartiallyPaid, Paid } public enum PaymentMethod { Cash, Credit } - public enum DeliveryTaskStatus - { Pending, Delivered, PartiallyDelivered, Failed} + public enum DeliveryTaskStatus { Pending, Delivered, PartiallyDelivered, Failed } public enum ReturnMode { CreditDeduction, ItemExchange } @@ -41,4 +39,10 @@ namespace Distribution.Models public enum SupplierClaimIssueType { Damaged, Short, Expired, WrongItem, Other } public enum SupplierClaimResolutionType { Replacement, Credit, Refund, PriceAdjustment } + + /// + /// ModeA: Invoice auto-created when ShopPO is confirmed. + /// ModeB: Invoice created as a separate explicit step. + /// + public enum InvoiceCreationMode { ModeA, ModeB } } diff --git a/Distribution/Models/Invoice.cs b/Distribution/Models/Invoice.cs new file mode 100644 index 0000000..dc60e80 --- /dev/null +++ b/Distribution/Models/Invoice.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Distribution.Models +{ + public class Invoice : Template + { + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } + + public InvoiceStatus Status { get; set; } = InvoiceStatus.Draft; + public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Pending; + + public Guid CreatedBy { get; set; } + + public DateTime? PrintedAt { get; set; } + public Guid? PrintedBy { get; set; } + + public DateTime? FinalizedAt { get; set; } + public Guid? FinalizedBy { get; set; } + + public decimal TotalAmount { get; set; } + + public ICollection Payments { get; set; } = new List(); + } +} diff --git a/Distribution/Models/LoadingSheet.cs b/Distribution/Models/LoadingSheet.cs index a74f085..db88cc1 100644 --- a/Distribution/Models/LoadingSheet.cs +++ b/Distribution/Models/LoadingSheet.cs @@ -8,17 +8,15 @@ namespace Distribution.Models [ForeignKey("FK_RideId")] public DeliveryRun Ride { get; set; } - public Guid FK_SourceWarehouseId { get; set; } - [ForeignKey("FK_SourceWarehouseId")] - public Warehouse SourceWarehouse { get; set; } + public LoadingSheetStatus Status { get; set; } = LoadingSheetStatus.Planned; - public LoadingSheetStatus Status { get; set; } = LoadingSheetStatus.Pending; + public Guid PopulatedBy { get; set; } + public DateTime PopulatedAt { get; set; } - public DateTime? DispatchConfirmedAt { get; set; } - public Guid? DispatchConfirmedBy { get; set; } - public DateTime? ReceiptConfirmedAt { get; set; } - public Guid? ReceiptConfirmedBy { get; set; } + public DateTime? ConfirmedAt { get; set; } + public Guid? ConfirmedBy { get; set; } public List Items { get; set; } = []; + public List Orders { get; set; } = []; } } diff --git a/Distribution/Models/LoadingSheetItem.cs b/Distribution/Models/LoadingSheetItem.cs index 2976dbf..3f9df91 100644 --- a/Distribution/Models/LoadingSheetItem.cs +++ b/Distribution/Models/LoadingSheetItem.cs @@ -2,10 +2,8 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Distribution.Models { - public class LoadingSheetItem + public class LoadingSheetItem : Template { - public Guid Id { get; set; } = Guid.NewGuid(); - public Guid FK_LoadingSheetId { get; set; } [ForeignKey("FK_LoadingSheetId")] public LoadingSheet LoadingSheet { get; set; } @@ -14,8 +12,14 @@ namespace Distribution.Models [ForeignKey("FK_ItemId")] public Item Item { get; set; } + public Guid FK_WarehouseId { get; set; } + [ForeignKey("FK_WarehouseId")] + public Warehouse Warehouse { get; set; } + + public Guid? FK_ShopPOItemId { get; set; } + [ForeignKey("FK_ShopPOItemId")] + public ShopPOItem? ShopPOItem { get; set; } + public decimal QuantityDispatched { get; set; } - public decimal? QuantityReceived { get; set; } - public decimal? QuantityResolved { get; set; } } } diff --git a/Distribution/Models/LoadingSheetOrder.cs b/Distribution/Models/LoadingSheetOrder.cs new file mode 100644 index 0000000..dca6d18 --- /dev/null +++ b/Distribution/Models/LoadingSheetOrder.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Distribution.Models +{ + public class LoadingSheetOrder + { + public Guid FK_LoadingSheetId { get; set; } + [ForeignKey("FK_LoadingSheetId")] + public LoadingSheet LoadingSheet { get; set; } + + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } + } +} diff --git a/Distribution/Models/Order.cs b/Distribution/Models/Order.cs deleted file mode 100644 index ef7448f..0000000 --- a/Distribution/Models/Order.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace Distribution.Models -{ - public class Order : Template - { - public Guid FK_SaleId { get; set; } - [ForeignKey("FK_SaleId")] - public Sale Sale { get; set; } - - public DateTime OrderDate { get; set; } - public Guid FK_StoreId { get; set; } - [ForeignKey("FK_StoreId")] - public Store Store { get; set; } - public decimal TotalAmount { get; set; } - public OrderStatus Status { get; set; } = OrderStatus.Pending; - public DateTime? FulfilledAt { get; set; } - - public ICollection OrderItems { get; set; } = new List(); - } -} diff --git a/Distribution/Models/Payment.cs b/Distribution/Models/Payment.cs index 79a7bac..f466283 100644 --- a/Distribution/Models/Payment.cs +++ b/Distribution/Models/Payment.cs @@ -4,13 +4,9 @@ namespace Distribution.Models { public class Payment : Template { - public Guid FK_SaleId { get; set; } - [ForeignKey("FK_SaleId")] - public Sale Sale { get; set; } - - public Guid FK_StoreId { get; set; } - [ForeignKey("FK_StoreId")] - public Store Store { get; set; } + public Guid FK_InvoiceId { get; set; } + [ForeignKey("FK_InvoiceId")] + public Invoice Invoice { get; set; } public decimal Amount { get; set; } public PaymentMethod Method { get; set; } diff --git a/Distribution/Models/Sale.cs b/Distribution/Models/Sale.cs deleted file mode 100644 index 68eaae8..0000000 --- a/Distribution/Models/Sale.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace Distribution.Models -{ - public class Sale : Template - { - public DateTime SaleDate { get; set; } - - public Guid FK_StoreId { get; set; } - [ForeignKey("FK_StoreId")] - public Store Store { get; set; } - - public Guid CreatedByUserId { get; set; } - [ForeignKey("CreatedByUserId")] - public User CreatedByUser { get; set; } - - public Guid? FK_RideId { get; set; } - [ForeignKey("FK_RideId")] - public DeliveryRun? Ride { get; set; } - - public decimal TotalAmount { get; set; } - public SaleStatus Status { get; set; } = SaleStatus.Pending; - public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Pending; - public bool FulfillImmediately { get; set; } - public DateTime? CompletedAt { get; set; } - } -} diff --git a/Distribution/Models/SaleReturn.cs b/Distribution/Models/SaleReturn.cs index 48375b6..0d5e58a 100644 --- a/Distribution/Models/SaleReturn.cs +++ b/Distribution/Models/SaleReturn.cs @@ -8,9 +8,9 @@ namespace Distribution.Models /// public class SaleReturn : Template { - public Guid FK_OrderId { get; set; } - [ForeignKey("FK_OrderId")] - public Order Order { get; set; } + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } public ReturnMode Mode { get; set; } diff --git a/Distribution/Models/SchemeRedemption.cs b/Distribution/Models/SchemeRedemption.cs index 78dbf7b..6aeaff2 100644 --- a/Distribution/Models/SchemeRedemption.cs +++ b/Distribution/Models/SchemeRedemption.cs @@ -10,9 +10,9 @@ namespace Distribution.Models [ForeignKey("FK_SchemeId")] public Scheme Scheme { get; set; } - public Guid? FK_OrderId { get; set; } - [ForeignKey("FK_OrderId")] - public Order? Order { get; set; } + public Guid? FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO? ShopPO { get; set; } /// Placeholder for the future field-invoice module — no FieldInvoice entity exists yet. public Guid? FieldInvoiceId { get; set; } diff --git a/Distribution/Models/ShopPO.cs b/Distribution/Models/ShopPO.cs new file mode 100644 index 0000000..f30fa0d --- /dev/null +++ b/Distribution/Models/ShopPO.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Distribution.Models +{ + public class ShopPO : Template + { + public Guid FK_StoreId { get; set; } + [ForeignKey("FK_StoreId")] + public Store Store { get; set; } + + public Guid RaisedById { get; set; } + + public Guid? InvoiceId { get; set; } + + public decimal TotalAmount { get; set; } + public ShopPOStatus Status { get; set; } = ShopPOStatus.Pending; + + public DateTime? ConfirmedAt { get; set; } + public Guid? ConfirmedBy { get; set; } + + public DateTime? FulfilledAt { get; set; } + + public ICollection Items { get; set; } = new List(); + } +} diff --git a/Distribution/Models/OrderItem.cs b/Distribution/Models/ShopPOItem.cs similarity index 58% rename from Distribution/Models/OrderItem.cs rename to Distribution/Models/ShopPOItem.cs index 07dfa15..0b7b7ec 100644 --- a/Distribution/Models/OrderItem.cs +++ b/Distribution/Models/ShopPOItem.cs @@ -1,15 +1,17 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations.Schema; namespace Distribution.Models { - public class OrderItem : Template + public class ShopPOItem : Template { - public Guid FK_OrderId { get; set; } - [ForeignKey("FK_OrderId")] - public Order Order { get; set; } + public Guid FK_ShopPOId { get; set; } + [ForeignKey("FK_ShopPOId")] + public ShopPO ShopPO { get; set; } + public Guid FK_ItemId { get; set; } [ForeignKey("FK_ItemId")] public Item Item { get; set; } + public int Quantity { get; set; } public int QuantityFulfilled { get; set; } = 0; public decimal UnitPrice { get; set; } diff --git a/Distribution/Models/SysConfig.cs b/Distribution/Models/SysConfig.cs new file mode 100644 index 0000000..379ba4d --- /dev/null +++ b/Distribution/Models/SysConfig.cs @@ -0,0 +1,10 @@ +namespace Distribution.Models +{ + public class SysConfig + { + public string Key { get; set; } + public string Value { get; set; } + public DateTime UpdatedAt { get; set; } = DateTime.Now; + public Guid? UpdatedBy { get; set; } + } +} diff --git a/Distribution/Program.cs b/Distribution/Program.cs index e93eb77..7308d1a 100644 --- a/Distribution/Program.cs +++ b/Distribution/Program.cs @@ -10,7 +10,8 @@ using Distribution.Features.DriverComplianceConfig; using Distribution.Features.DriverProfile; using Distribution.Features.Grn; using Distribution.Features.Item; -using Distribution.Features.Order; +using Distribution.Features.ShopPO; +using Distribution.Features.Invoice; using Distribution.Features.PriceList; using Distribution.Features.Po; using Distribution.Features.PurchaseReturn; @@ -22,7 +23,6 @@ using Distribution.Features.LoadingEvent; using Distribution.Features.Ride; using Distribution.Features.Role; using Distribution.Features.Route; -using Distribution.Features.Sale; using Distribution.Features.Scheme; using Distribution.Features.Store; using Distribution.Features.Store.Kyc; @@ -32,6 +32,7 @@ using Distribution.Features.Uom; using Distribution.Features.User; using Distribution.Features.Vehicle; using Distribution.Features.Stock; +using Distribution.Features.SysConfig; using Distribution.Features.Warehouse; using Distribution.Infra.Authorization; using Distribution.Infra.UoW; @@ -52,8 +53,8 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -65,7 +66,6 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -85,8 +85,8 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Distribution/docs/refactor_docs/refactor_plan.md b/Distribution/docs/refactor_docs/refactor_plan.md new file mode 100644 index 0000000..b688a38 --- /dev/null +++ b/Distribution/docs/refactor_docs/refactor_plan.md @@ -0,0 +1,704 @@ +# Refactor Implementation Plan + +**Status**: Ready to implement +**Design docs**: [order_invoice_lifecycle.md](./order_invoice_lifecycle.md), [loading_event.md](./loading_event.md), [dispatch_pipeline.md](./dispatch_pipeline.md), [ride_lifecycle.md](./ride_lifecycle.md) + +--- + +## Scope + +Replace the Sale/Order/LoadingSheet pipeline with a unified ShopPO → Invoice → LoadingSheet flow: + +- `Order` entity renamed to `ShopPO` throughout +- `Sale` entity and feature removed entirely +- `Invoice` entity introduced as the billing document +- `Payment` moved from Sale to Invoice +- `LoadingSheet` overhauled: dispatcher-triggered, multi-PO, per-item warehouse +- `DeliveryRun` (Ride) simplified: no route, no type, no Active state +- `SaleReturn` FK renamed only — full redesign is a separate pass + +--- + +## Execution Order + +``` +Phase 1 → Phase 2 → Phase 3 → Phase 4 → Phase 5 (migration) +→ Phase 6, 7, 8, 9, 10 (independent after migration) +→ Phase 11 → Phase 12 +``` + +Phases 6–10 have no dependencies on each other and can be worked in parallel. + +--- + +## Phase 1 — Enums + +**File**: `Models/Enums.cs` + +| Enum | Action | New Values | +|---|---|---| +| `LoadingSheetStatus` | Replace all values | `Planned`, `Confirmed` | +| `RideStatus` | Remove `Draft`, `Active`, `CancelRequested` | Keep `Open`, `Cancelled`, `Closed` | +| `RideType` | **Delete entire enum** | — | +| `InvoiceStatus` | **Add new** | `Draft`, `Printed`, `Finalized` | +| `OrderStatus` | Rename to `ShopPOStatus` | Keep values: `Pending`, `PartiallyFulfilled`, `Fulfilled`, `Cancelled` | +| `SaleStatus` | **Delete entire enum** | — | + +--- + +## Phase 2 — Remove Sale + +Sale has no downstream model dependencies except `Order.FK_SaleId` and `Payment.FK_SaleId` — both handled in Phase 3. + +### Delete files +- `Models/Sale.cs` +- `Features/Sale/SaleController.cs` +- `Features/Sale/SaleService.cs` +- `Features/Sale/ISaleRepository.cs` +- `Features/Sale/SaleRepository.cs` +- `Features/Sale/SaleDTOs.cs` + +### Update `Data/AppDBContext.cs` +- Remove `DbSet Sales` +- Remove all Fluent API config blocks referencing `Sale` + +### Update `Program.cs` +- Remove `ISaleRepository` / `SaleRepository` registration +- Remove `SaleService` registration + +--- + +## Phase 3 — Model Changes + +### 3.1 Rename `Order` → `ShopPO` + +Create `Models/ShopPO.cs`. Delete `Models/Order.cs`. + +```csharp +public class ShopPO : Template +{ + public Guid FK_StoreId { get; set; } + public Store Store { get; set; } + + public Guid RaisedById { get; set; } // agent who created the PO + + public Guid? InvoiceId { get; set; } // set when Invoice is created — NO FK constraint + + public decimal TotalAmount { get; set; } + + public ShopPOStatus Status { get; set; } = ShopPOStatus.Pending; + + public DateTime? ConfirmedAt { get; set; } // null = Shop PO, set = Confirmed PO + public Guid? ConfirmedBy { get; set; } + + public DateTime? FulfilledAt { get; set; } + + public ICollection Items { get; set; } +} +``` + +Removed from current `Order.cs`: `FK_SaleId`, `OrderDate` (use `CreatedAt` from Template). + +### 3.2 Rename `OrderItem` → `ShopPOItem` + +Create `Models/ShopPOItem.cs`. Delete `Models/OrderItem.cs`. + +```csharp +public class ShopPOItem : Template // Template gives Id, IsActive, CreatedAt +{ + public Guid FK_ShopPOId { get; set; } + public ShopPO ShopPO { get; set; } + + public Guid FK_ItemId { get; set; } + public Item Item { get; set; } + + public int Quantity { get; set; } + public int QuantityFulfilled { get; set; } = 0; + public decimal UnitPrice { get; set; } +} +``` + +No property changes beyond the FK rename. The existing `IsActive` (from Template) already supports versioning. + +### 3.3 Update `Models/LoadingSheet.cs` + +Remove: +- `FK_SourceWarehouseId` and its navigation property +- `DispatchConfirmedAt`, `DispatchConfirmedBy` +- `ReceiptConfirmedAt`, `ReceiptConfirmedBy` + +Add: +- `PopulatedBy` (Guid) +- `PopulatedAt` (DateTime) +- `ConfirmedAt` (DateTime?) +- `ConfirmedBy` (Guid?) + +`FK_RideId` already exists — no change needed. + +### 3.4 Update `Models/LoadingSheetItem.cs` + +Make it inherit `Template` (adds `Id` PK, `IsActive`, `CreatedAt`). + +Remove: +- `QuantityReceived` +- `QuantityResolved` + +Add: +- `FK_WarehouseId` (Guid, required) — warehouse this item is loaded from +- `FK_ShopPOItemId` (Guid?, nullable) — traces back to source `ShopPOItem` + +### 3.5 New `Models/LoadingSheetOrder.cs` + +```csharp +public class LoadingSheetOrder +{ + public Guid FK_LoadingSheetId { get; set; } + public LoadingSheet LoadingSheet { get; set; } + + public Guid FK_ShopPOId { get; set; } + public ShopPO ShopPO { get; set; } +} +``` + +Composite PK on `(FK_LoadingSheetId, FK_ShopPOId)` — configured in DbContext. + +### 3.6 Update `Models/DeliveryRun.cs` + +Remove: +- `RideType` (enum deleted in Phase 1) +- `FK_RouteId` and its navigation property +- `FK_SourceWarehouseId` and its navigation property +- `ActivatedAt` + +Keep: `FK_VehicleId`, `FK_DriverProfileId`, `Status`, `Meterstart`, `Meterend`, `StartedAt`, `ClosedAt`. + +### 3.7 Update `Models/Payment.cs` + +Remove: +- `FK_SaleId` +- `FK_StoreId` (derivable via Invoice → ShopPO → Store) + +Add: +- `FK_InvoiceId` (Guid, required) + +### 3.8 New `Models/Invoice.cs` + +```csharp +public class Invoice : Template +{ + public Guid FK_ShopPOId { get; set; } + public ShopPO ShopPO { get; set; } + + public InvoiceStatus Status { get; set; } = InvoiceStatus.Draft; + public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Pending; + + public Guid CreatedBy { get; set; } + + public DateTime? PrintedAt { get; set; } + public Guid? PrintedBy { get; set; } + + public DateTime? FinalizedAt { get; set; } + public Guid? FinalizedBy { get; set; } + + public decimal TotalAmount { get; set; } + + public ICollection Payments { get; set; } +} +``` + +### 3.9 FK Renames on Other Models + +These models reference `Order` only — no Sale reference. Rename FK and navigation property only: + +| File | Change | +|---|---| +| `Models/DeliveryTask.cs` | `FK_OrderId` → `FK_ShopPOId`, navigation `Order` → `ShopPO` | +| `Models/SchemeRedemption.cs` | `FK_OrderId` → `FK_ShopPOId`, navigation `Order` → `ShopPO` | +| `Models/SaleReturn.cs` | `FK_OrderId` → `FK_ShopPOId`, navigation `Order` → `ShopPO` | + +--- + +## Phase 4 — DbContext (`Data/AppDBContext.cs`) + +### DbSet changes +```csharp +// Remove +DbSet Sales +DbSet Orders +DbSet OrderItems + +// Add +DbSet ShopPOs +DbSet ShopPOItems +DbSet Invoices +DbSet LoadingSheetOrders +``` + +### Fluent API changes + +**`ShopPO`** +- `ShopPO.InvoiceId`: configure as plain column with no FK constraint — `builder.Property(x => x.InvoiceId).HasColumnName("InvoiceId")` (no `HasForeignKey`) +- `ShopPO` → `Store`: Restrict delete +- Remove previous unique index on `FK_SaleId` + +**`ShopPOItem`** +- Remove unique composite index on `(FK_OrderId, FK_ItemId)` — versioning requires multiple rows with same combo +- `ShopPOItem` → `ShopPO`: Restrict delete +- `ShopPOItem` → `Item`: Restrict delete + +**`Invoice`** +- `Invoice` → `ShopPO`: Restrict delete +- One-to-one: one ShopPO has at most one Invoice + +**`LoadingSheetOrder`** +- Composite PK: `(FK_LoadingSheetId, FK_ShopPOId)` +- `LoadingSheetOrder` → `LoadingSheet`: Restrict delete +- `LoadingSheetOrder` → `ShopPO`: Restrict delete + +**`LoadingSheet`** +- Remove: Warehouse relation for `FK_SourceWarehouseId` + +**`LoadingSheetItem`** +- Add: `FK_WarehouseId` → Warehouse (Restrict delete) +- Add: `FK_ShopPOItemId` → ShopPOItem (SetNull — nullable FK) + +**`Payment`** +- Remove: Sale relation for `FK_SaleId`, Store relation for `FK_StoreId` +- Add: `FK_InvoiceId` → Invoice (Restrict delete) + +**`DeliveryRun`** +- Remove: Route relation for `FK_RouteId`, Warehouse relation for `FK_SourceWarehouseId`, RideType property + +**`DeliveryTask`**, **`SchemeRedemption`**, **`SaleReturn`** +- Update FK navigation references from `Order` → `ShopPO` + +--- + +## Phase 5 — Migration + +One EF Core migration: `RefactorSalesToShopPOAndInvoice` + +Key DDL generated: +```sql +-- ShopPO (was Orders table) +RENAME TABLE Orders TO ShopPOs; +ALTER TABLE ShopPOs DROP COLUMN FK_SaleId, DROP COLUMN OrderDate; +ALTER TABLE ShopPOs ADD RaisedById CHAR(36) NOT NULL, + InvoiceId CHAR(36) NULL, + ConfirmedAt DATETIME NULL, + ConfirmedBy CHAR(36) NULL; +ALTER TABLE ShopPOs RENAME COLUMN Status TO Status; -- enum value update handled by app +DROP INDEX IX_Orders_FK_SaleId ON ShopPOs; + +-- ShopPOItems (was OrderItems table) +RENAME TABLE OrderItems TO ShopPOItems; +ALTER TABLE ShopPOItems RENAME COLUMN FK_OrderId TO FK_ShopPOId; +DROP INDEX IX_OrderItems_FK_OrderId_FK_ItemId ON ShopPOItems; -- remove unique constraint + +-- LoadingSheets +ALTER TABLE LoadingSheets DROP COLUMN FK_SourceWarehouseId, + DROP COLUMN DispatchConfirmedAt, DROP COLUMN DispatchConfirmedBy, + DROP COLUMN ReceiptConfirmedAt, DROP COLUMN ReceiptConfirmedBy; +ALTER TABLE LoadingSheets ADD PopulatedBy CHAR(36) NOT NULL, + PopulatedAt DATETIME NOT NULL, + ConfirmedAt DATETIME NULL, + ConfirmedBy CHAR(36) NULL; + +-- LoadingSheetItems +ALTER TABLE LoadingSheetItems DROP COLUMN QuantityReceived, DROP COLUMN QuantityResolved; +ALTER TABLE LoadingSheetItems ADD FK_WarehouseId CHAR(36) NOT NULL, + FK_ShopPOItemId CHAR(36) NULL, + IsActive TINYINT(1) NOT NULL DEFAULT 1, + CreatedAt DATETIME NOT NULL; + +-- DeliveryRuns +ALTER TABLE DeliveryRuns DROP COLUMN RideType, DROP COLUMN FK_RouteId, + DROP COLUMN FK_SourceWarehouseId, DROP COLUMN ActivatedAt; + +-- Payments +ALTER TABLE Payments DROP COLUMN FK_SaleId, DROP COLUMN FK_StoreId; +ALTER TABLE Payments ADD FK_InvoiceId CHAR(36) NOT NULL; + +-- DeliveryTasks, SchemeRedemptions, SaleReturns +ALTER TABLE DeliveryTasks RENAME COLUMN FK_OrderId TO FK_ShopPOId; +ALTER TABLE SchemeRedemptions RENAME COLUMN FK_OrderId TO FK_ShopPOId; +ALTER TABLE SaleReturns RENAME COLUMN FK_OrderId TO FK_ShopPOId; + +-- New tables +CREATE TABLE Invoices (...); +CREATE TABLE LoadingSheetOrders (FK_LoadingSheetId, FK_ShopPOId, PRIMARY KEY (FK_LoadingSheetId, FK_ShopPOId)); + +-- Drop Sale table +DROP TABLE Sales; +``` + +--- + +## Phase 6 — New Invoice Feature + +**New folder**: `Features/Invoice/` + +### `InvoiceDTOs.cs` + +```csharp +// Mode B create +record CreateInvoiceRequest(Guid ShopPOId); + +// Mode A — called internally from ShopPOService, no separate request needed + +record InvoiceResponse(Guid Id, Guid ShopPOId, InvoiceStatus Status, + PaymentStatus PaymentStatus, Guid CreatedBy, + DateTime? PrintedAt, Guid? PrintedBy, + DateTime? FinalizedAt, Guid? FinalizedBy, + decimal TotalAmount, DateTime CreatedAt); + +// Finalize payload — exact adjustment fields TBD (free issues handling open) +record FinalizeInvoiceRequest(List Adjustments); +record InvoiceItemAdjustment(Guid ShopPOItemId, int AdjustedQuantity, string? Note); +``` + +### `IInvoiceRepository.cs` +- `GetByIdAsync(Guid id)` +- `GetByShopPOIdAsync(Guid shopPOId)` +- `GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, InvoiceStatus? status, int page, int pageSize)` +- `AddAsync(Invoice invoice)` +- `Update(Invoice invoice)` + +### `InvoiceRepository.cs` +EF implementation of above. + +### `InvoiceService.cs` +- `CreateAsync(Guid shopPOId, Guid createdBy)` — Mode B; validates ShopPO is Confirmed, no Invoice exists yet; sets `ShopPO.InvoiceId` in same transaction +- `PrintAsync(Guid id)` — `Draft → Printed`; sets `PrintedAt`/`PrintedBy` +- `FinalizeAsync(Guid id, FinalizeInvoiceRequest request)` — `Printed → Finalized`; applies adjustments, locks `TotalAmount`, sets `FinalizedAt`/`FinalizedBy` + +### `InvoiceController.cs` + +| Method | Route | Mode gate | Description | +|---|---|---|---| +| POST | `/api/invoices` | Mode B only | Create Invoice for a Confirmed ShopPO | +| GET | `/api/invoices` | Any | List with filters | +| GET | `/api/invoices/{id}` | Any | Get detail | +| POST | `/api/invoices/{id}/print` | Any | `Draft → Printed` | +| POST | `/api/invoices/{id}/finalize` | Any | `Printed → Finalized` | + +--- + +## Phase 7 — ShopPO Feature (replaces Order) + +**Delete**: `Features/Order/` (all files) +**New folder**: `Features/ShopPO/` + +### `ShopPODTOs.cs` + +```csharp +record CreateShopPORequest(Guid StoreId, List Items); +record ShopPOItemRequest(Guid ItemId, int Quantity, decimal? UnitPrice = null); + +record UpdateShopPOItemsRequest(List Items); // versioned rewrite + +record ShopPOResponse(Guid Id, Guid StoreId, Guid RaisedById, + Guid? InvoiceId, decimal TotalAmount, ShopPOStatus Status, + DateTime? ConfirmedAt, Guid? ConfirmedBy, DateTime? FulfilledAt, + List Items, bool IsActive, DateTime CreatedAt); + +record ShopPOItemResponse(Guid Id, Guid ItemId, int Quantity, + int QuantityFulfilled, decimal UnitPrice, bool IsActive); +``` + +### `IShopPORepository.cs` +- `GetByIdAsync(Guid id)` — active items only by default +- `GetAllAsync(Guid? agentId, Guid? routeId, Guid? shopId, bool? confirmed, int page, int pageSize)` +- `GetConfirmedWithoutInvoiceAsync(Guid? agentId, Guid? routeId, Guid? shopId)` — used by Mode B invoice creation and LoadingSheet population +- `AddAsync(ShopPO po)` +- `ReplaceItemsAsync(Guid shopPOId, List newItems)` — soft-delete current IsActive rows, insert fresh set +- `Update(ShopPO po)` + +### `ShopPOService.cs` +- `CreateAsync(CreateShopPORequest request)` — creates ShopPO with `ConfirmedAt = null`; resolves item prices via `PriceListService` +- `UpdateItemsAsync(Guid id, UpdateShopPOItemsRequest request)` — only while `ConfirmedAt == null`; calls versioned replace +- `ConfirmAsync(Guid id)` — Mode B: sets `ConfirmedAt`/`ConfirmedBy`; locks items +- `ConfirmAndCreateInvoiceAsync(Guid id)` — Mode A: confirm + create Invoice atomically in one transaction; sets `ShopPO.InvoiceId` +- `CancelAsync(Guid id)` — sets `Status = Cancelled`; throws if linked Invoice exists (cascade rules not yet defined — see Open Items) +- `GetAllAsync(...)`, `GetByIdAsync(...)` + +### `ShopPOController.cs` + +| Method | Route | Who | Description | +|---|---|---|---| +| POST | `/api/shop-pos` | Agent | Create Shop PO | +| GET | `/api/shop-pos` | Any | List (filter: agentId, routeId, shopId, confirmed) | +| GET | `/api/shop-pos/{id}` | Any | Get detail | +| PUT | `/api/shop-pos/{id}/items` | Agent | Versioned item rewrite (Shop PO only) | +| POST | `/api/shop-pos/{id}/confirm` | Office | Mode B — confirm PO only | +| POST | `/api/shop-pos/{id}/confirm-and-create-invoice` | Office | Mode A — atomic confirm + invoice | +| POST | `/api/shop-pos/{id}/cancel` | Agent/Office | Cancel Shop PO or Confirmed PO | + +Mode A endpoint returns `405 Method Not Allowed` when `InvoiceCreationMode = "B"` and vice versa. + +--- + +## Phase 8 — Update Payment Feature + +### `Models/Payment.cs` +Already updated in Phase 3 (`FK_InvoiceId`, removed `FK_SaleId` and `FK_StoreId`). + +### `PaymentDTOs.cs` +```csharp +// Before: CreatePaymentRequest(Amount, Method) against saleId in route +// After: CreatePaymentRequest(Amount, Method) against invoiceId in route +record CreatePaymentRequest(decimal Amount, PaymentMethod Method); +record PaymentResponse(Guid Id, Guid InvoiceId, decimal Amount, + PaymentMethod Method, DateTime CollectedAt, Guid CollectedBy); +``` + +### `IPaymentRepository.cs` / `PaymentRepository.cs` +- Replace `GetBySaleIdAsync` → `GetByInvoiceIdAsync(Guid invoiceId)` +- `AddAsync`, `Update` unchanged + +### `PaymentService.cs` +On `RecordPaymentAsync(Guid invoiceId, CreatePaymentRequest request)`: +1. Validate Invoice exists and is not `Cancelled`/voided +2. Add `Payment` record with `FK_InvoiceId` +3. Sum all payments for this Invoice +4. Recalculate `Invoice.PaymentStatus`: + - `sum == 0` → `Pending` + - `sum < Invoice.TotalAmount` → `PartiallyPaid` + - `sum >= Invoice.TotalAmount` → `Paid` +5. Update `Invoice.PaymentStatus` in same transaction + +### `PaymentController.cs` +Change route from `/api/sales/{saleId}/payments` → `/api/invoices/{invoiceId}/payments` + +| Method | Route | Description | +|---|---|---| +| POST | `/api/invoices/{invoiceId}/payments` | Record payment against invoice | +| GET | `/api/invoices/{invoiceId}/payments` | List payments for invoice | + +--- + +## Phase 9 — Overhaul LoadingEvent Feature + +Near-complete rewrite of service and controller. See `loading_event.md` for full state machine. + +### `LoadingSheetDTOs.cs` — replace with + +```csharp +record PopulateRequest(Guid RideId, Guid? RouteId, Guid? AgentId, Guid? ShopId); + +record UpdateLoadingSheetItemsRequest(List Items); +record LoadingSheetItemInput(Guid ItemId, Guid WarehouseId, decimal Quantity, Guid? ShopPOItemId = null); + +record LoadingSheetResponse(Guid Id, Guid RideId, LoadingSheetStatus Status, + Guid PopulatedBy, DateTime PopulatedAt, + DateTime? ConfirmedAt, Guid? ConfirmedBy, + List SourceShopPOIds, + List Items, + DateTime CreatedAt); + +record LoadingSheetItemResponse(Guid Id, Guid ItemId, Guid WarehouseId, + decimal QuantityDispatched, Guid? ShopPOItemId, bool IsActive); +``` + +### `ILoadingSheetRepository.cs` / `LoadingSheetRepository.cs` — replace with + +- `PopulateAsync(PopulateRequest request, Guid populatedBy)` — finds all Confirmed ShopPOs matching filters, creates one `LoadingSheet` at `Planned`, populates `LoadingSheetItem` rows from active `ShopPOItem` lines, inserts `LoadingSheetOrder` rows +- `GetAllAsync(Guid? routeId, Guid? agentId, Guid? shopId, Guid? rideId, LoadingSheetStatus? status, int page, int pageSize)` — `routeId` filter joins via `Store.FK_RouteId → ShopPO.FK_StoreId → LoadingSheetOrder.FK_ShopPOId` +- `GetByIdAsync(Guid id, bool includeHistory = false)` — `includeHistory = true` includes `IsActive = false` items +- `ReplaceItemsAsync(Guid sheetId, List items)` — soft-delete all current `IsActive = true` rows, insert fresh set +- `ConfirmAsync(Guid id, Guid confirmedBy)` — `Planned → Confirmed`; creates stock movements in transaction + +### `LoadingSheetService.cs` — replace with + +- `PopulateAsync(PopulateRequest request)` — validates ride is `Open`; at least one filter provided; all matching ShopPOs are Confirmed; delegates to repository +- `UpdateItemsAsync(Guid id, UpdateLoadingSheetItemsRequest request)` — validates sheet is `Planned`; calls versioned replace +- `ConfirmAsync(Guid id)` — validates sheet is `Planned`; creates stock movements: one `Load` debit per `LoadingSheetItem.FK_WarehouseId`, one credit to ride's vehicle (`LoadingSheet.FK_RideId → DeliveryRun.FK_VehicleId`); all in one transaction; transitions to `Confirmed` + +### `LoadingSheetController.cs` — replace endpoints + +| Remove | Add | +|---|---| +| `POST /` | `POST /populate` | +| `POST /{id}/confirm-dispatch` | `POST /{id}/confirm` | +| `PUT /{id}/receipt-items` | *(removed)* | +| `POST /{id}/confirm-receipt` | *(removed)* | +| `POST /{id}/resolve` | *(removed)* | +| `PATCH /{id}/dispatch` | *(removed)* | +| `PATCH /{id}/receipt` | *(removed)* | +| `PATCH /{id}/resolve` | *(removed)* | +| `GET /` | `GET /` (add routeId, agentId, shopId filters) | +| `GET /{id}` | `GET /{id}` (add `?history=true`) | +| `PUT /{id}/items` | `PUT /{id}/items` (versioned, Planned only) | + +--- + +## Phase 10 — Overhaul Ride Feature + +See `ride_lifecycle.md` for full state machine. Ride now starts `Open` immediately on creation. + +### `RideDTOs.cs` +```csharp +// Remove: RouteId, SourceWarehouseId, RideType from request and response +record CreateRideRequest(Guid VehicleId, Guid DriverProfileId, int Meterstart); +record RideResponse(Guid Id, Guid VehicleId, Guid DriverProfileId, + RideStatus Status, int Meterstart, int? Meterend, + DateTime? StartedAt, DateTime? ClosedAt, DateTime CreatedAt); +``` + +### `RideService.cs` — replace state machine + +| Remove | Replace with | +|---|---| +| `CreateAsync` (creates Draft) | `CreateAsync` (creates at `Open` directly) | +| `OpenAsync` (Draft → Open) | *(merged into create)* | +| `ActivateAsync` (Open → Active) | *(removed)* | +| `RaiseCancelRequestAsync` | *(removed — no approval flow)* | +| `ApproveCancelAsync` | *(removed)* | +| `RejectCancelAsync` | *(removed)* | +| `GetCancelRequestsAsync` | *(removed)* | +| `GetCancelRequestAsync` | *(removed)* | +| `GetBreakdownAssistAsync` | *(removed)* | +| `CloseAsync` (Active → Closed) | `CloseAsync` (Open → Closed) | +| *(no cancel)* | `CancelAsync` (Open → Cancelled, direct) | + +`AssignDriverAsync` — keep, remove Draft-status guard. + +### `RideController.cs` +Remove endpoints: open, activate, cancel-request, approve-cancel, reject-cancel, breakdown-assist. +Add endpoint: `POST /{id}/cancel`. + +### FK renames in other features +- `Features/DeliveryRide/DeliveryTaskService.cs` — rename `FK_OrderId` → `FK_ShopPOId` references; update Active status guard to `Open` (**note**: full delivery redesign is deferred — minimum change only) +- `Features/Returns/ReturnService.cs` — rename `FK_OrderId` → `FK_ShopPOId` references only (full redesign deferred) + +--- + +## Phase 11 — Program.cs + Config + +### `Program.cs` +```csharp +// Remove +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); // approval flow removed + +// Add +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Update (rename existing registrations) +// IOrderRepository → IShopPORepository (above replaces it) +``` + +### `appsettings.json` / `appsettings.Development.json` +```json +{ + "InvoiceCreationMode": "B" +} +``` + +Read in `ShopPOController` via `IConfiguration` to gate Mode A vs Mode B endpoints. + +--- + +## Phase 12 — Permission Seeding + +Add two permission records (seed migration or data seeder): + +| Code | Description | Role | +|---|---|---| +| `loading.populate` | Trigger loading sheet population; edit items | Dispatcher | +| `loading.confirm` | Confirm loading sheet; commits stock movements | TBD (see Open Items) | + +--- + +## File Change Summary + +### New files +``` +Models/ShopPO.cs +Models/ShopPOItem.cs +Models/Invoice.cs +Models/LoadingSheetOrder.cs +Features/ShopPO/ShopPOController.cs +Features/ShopPO/ShopPOService.cs +Features/ShopPO/IShopPORepository.cs +Features/ShopPO/ShopPORepository.cs +Features/ShopPO/ShopPODTOs.cs +Features/Invoice/InvoiceController.cs +Features/Invoice/InvoiceService.cs +Features/Invoice/IInvoiceRepository.cs +Features/Invoice/InvoiceRepository.cs +Features/Invoice/InvoiceDTOs.cs +``` + +### Deleted files +``` +Models/Sale.cs +Models/Order.cs +Models/OrderItem.cs +Features/Sale/SaleController.cs +Features/Sale/SaleService.cs +Features/Sale/ISaleRepository.cs +Features/Sale/SaleRepository.cs +Features/Sale/SaleDTOs.cs +Features/Order/OrderController.cs +Features/Order/OrderService.cs +Features/Order/IOrderRepository.cs +Features/Order/OrderRepository.cs +Features/Order/OrderDTOs.cs +``` + +### Modified files +``` +Models/Enums.cs +Models/LoadingSheet.cs +Models/LoadingSheetItem.cs +Models/DeliveryRun.cs +Models/Payment.cs +Models/DeliveryTask.cs (FK rename only) +Models/SchemeRedemption.cs (FK rename only) +Models/SaleReturn.cs (FK rename only) +Data/AppDBContext.cs +Features/LoadingEvent/LoadingSheetService.cs +Features/LoadingEvent/LoadingSheetController.cs +Features/LoadingEvent/ILoadingSheetRepository.cs +Features/LoadingEvent/LoadingSheetRepository.cs +Features/LoadingEvent/LoadingSheetDTOs.cs +Features/Payment/PaymentService.cs +Features/Payment/PaymentController.cs +Features/Payment/IPaymentRepository.cs +Features/Payment/PaymentRepository.cs +Features/Payment/PaymentDTOs.cs +Features/Ride/RideService.cs +Features/Ride/RideController.cs +Features/Ride/RideDTOs.cs +Features/DeliveryRide/DeliveryTaskService.cs (FK rename + Active→Open guard) +Features/Returns/ReturnService.cs (FK rename only) +Program.cs +appsettings.json +appsettings.Development.json +``` + +--- + +## Open Items (must resolve before coding the relevant phase) + +| # | Item | Blocks | +|---|---|---| +| 1 | Who holds `loading.confirm` permission? | Phase 9 — ConfirmAsync auth guard | +| 2 | Cascade when Confirmed ShopPO is cancelled and Invoice already exists | Phase 7 — CancelAsync | +| 3 | Cascade when Confirmed ShopPO is cancelled and it's in a LoadingSheet | Phase 7 — CancelAsync | +| 4 | `FinalizeInvoiceRequest` payload — free issues field shape | Phase 6 — FinalizeAsync | +| 5 | Who can confirm a ShopPO? (agent, office, either?) | Phase 7 — ConfirmAsync permission | + +--- + +## Deferred (not in this refactor) + +- `SaleReturn` / `CreditNote` — full redesign is a separate pass +- `DeliveryTask` full redesign (Stage 5 — Delivery) — separate pass +- Vehicle stock reconciliation at ride Close/Cancel — separate pass +- Order attachment mechanism for delivery tasks — separate pass From 03d01d4c4e11da2a7ef9c49119cbcd50b7313592 Mon Sep 17 00:00:00 2001 From: "Kalana B. Thilakarathna" Date: Thu, 17 Sep 2026 13:59:05 +0530 Subject: [PATCH 02/11] name: CI/CD - ERP Core Monorepo on: pull_request: branches: - production types: - closed jobs: backend-build-and-deploy: name: Build & Deploy ERP Core Backend runs-on: linux if: github.event.pull_request.merged == true steps: - name: Checkout code run: | git clone \ --depth 1 \ --branch production \ https://oauth2:${{ secrets.ERPCORE }}@gitea.hexdive.com/New_REP_SYSTEM/ERP-core.git \ . - name: Restore backend run: dotnet restore Backend/ERPCore.sln - name: Publish backend run: | rm -rf /tmp/erpcore-deploy mkdir -p /tmp/erpcore-deploy dotnet publish Backend/ERPCore/ERPCore.csproj \ -c Release \ -r linux-x64 \ --self-contained true \ -o /tmp/erpcore-deploy - name: Stop backend service run: systemctl stop erpcore.service - name: Copy backend to deploy folder run: | mkdir -p /home/erp/core/publish rm -rf /home/erp/core/publish/* cp -r /tmp/erpcore-deploy/* /home/erp/core/publish/ - name: Fix backend ownership and permissions run: | chown -R erpuser:erpuser /home/erp/core/publish find /home/erp/core/publish -type d -exec chmod 755 {} + find /home/erp/core/publish -type f -exec chmod 644 {} + chmod +x /home/erp/core/publish/ERPCore - name: Restart backend service run: systemctl restart erpcore.service - name: Verify backend run: | systemctl is-active erpcore.service && echo "Backend service running" || echo "Backend service failed" frontend-build-and-deploy: name: Build & Deploy ERP Core Frontend runs-on: linux needs: backend-build-and-deploy if: github.event.pull_request.merged == true steps: - name: Checkout code run: | git clone \ --depth 1 \ --branch Production \ https://oauth2:${{ secrets.ERPCORE }}@gitea.hexdive.com/New_REP_SYSTEM/ERP-core.git \ . - name: Build frontend Docker image run: docker build -t erpcore-frontend:latest Frontend/erp-system - name: Stop & remove existing frontend container run: | docker stop erpcore-frontend 2>/dev/null || true docker rm erpcore-frontend 2>/dev/null || true - name: Start frontend container run: | docker run -d \ --name erpcore-frontend \ -p 6702:6702 \ --add-host=host.docker.internal:host-gateway \ -e BACKEND_ORIGIN=http://host.docker.internal:6701 \ --restart unless-stopped \ --memory="512m" \ --cpus="1.0" \ --cap-drop ALL \ --security-opt no-new-privileges \ erpcore-frontend:latest - name: Remove old frontend images run: docker image prune -f - name: Verify frontend run: | docker ps --filter name=erpcore-frontend --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" \ | grep erpcore-frontend && echo "Frontend container running" || echo "Frontend container failed" --- ...orkloadAdvertisingManifestSentinel10.0.300 | 0 .../10.0.303.aspNetCertificateSentinel | 0 .../.dotnet/10.0.303.dotnetFirstUseSentinel | 0 .../.dotnet/10.0.303.toolpath.sentinel | 0 ...303_IsDockerContainer.dotnetUserLevelCache | 1 + .../10.0.303_MachineId.dotnetUserLevelCache | 1 + ...54849_3c2c0c4055d6437591042769f431029b.trn | 5 + ...54849_5d637cd612c34f1d8c78e7f3b2716acb.trn | 5 + ...54849_5e3ab89dd1164922b68cd8a91afb4dd1.trn | 5 + ...54849_7f218358f90d4dea89beb22e746aaa5e.trn | 5 + ...54849_a1db53cd4756496796a45e4d0e060b23.trn | 5 + ...54849_ace67540371e4eae93f6d0895b617653.trn | 5 + ...54849_b532e6064ddb4074a63b8d295ce297d9.trn | 5 + ...54849_f3a1d0f218a5492cacc3df523c5ff9b2.trn | 5 + ...54850_55c23537298a4cdd905fff2a066c61c8.trn | 5 + ...54850_6247cb09d42c4e96ace11389a1a91bf7.trn | 5 + ...54850_965e4b827a0a4c4d8d08cc2d43e6bc44.trn | 5 + ...54850_dcc554cb89e74159855b8fda6d16c235.trn | 5 + ...54856_09e56a2b38574bdb8e196ea189c58142.trn | 5 + ...54856_3e9580a6a36741b390d50bd290250e42.trn | 5 + ...54856_5d9eff7293784d3c9fe7fbec6ab2a85b.trn | 5 + .../7b4fdabac24445e18bb7e730fceaf989 | 5 + .../microsoft.net.workloads.workloadset.json | 18 + .../AdvertisedManifestFeatureBand.txt | 1 + .../workloadVersion.txt | 1 + ...7034841_RefactorSalesToShopPOAndInvoice.cs | 167 ++- Distribution/appsettings.json | 2 +- .../docs/refactor_docs/refactor_plan.md | 30 +- .../docs/refactor_frontend_api_reference.md | 978 ++++++++++++++++++ .../_components/delivery-tasks-client.tsx | 4 +- .../loading-sheet-create-dialog.tsx | 113 ++ .../_components/loading-sheet-view-sheet.tsx | 30 +- .../_components/loading-sheets-client.tsx | 87 +- .../rides/_components/ride-cancel-dialog.tsx | 10 +- .../_components/ride-edit-driver-sheet.tsx | 2 +- .../rides/_components/ride-sheet.tsx | 88 +- .../rides/_components/ride-view-sheet.tsx | 20 +- .../rides/_components/rides-client.tsx | 65 +- .../_components/order-return-dialog.tsx | 71 +- .../_components/order-return-view-sheet.tsx | 2 +- .../_components/order-returns-client.tsx | 14 +- .../sales/_components/sale-view-sheet.tsx | 113 +- .../sales/_components/sales-client.tsx | 124 ++- .../_components/shop-po-create-sheet.tsx | 217 ++++ .../sales/_components/shop-po-view-sheet.tsx | 106 ++ .../app/(dashboard)/sales/new/page.tsx | 218 +--- .../_components/order-edit-status-dialog.tsx | 113 +- .../orders/_components/order-view-sheet.tsx | 80 +- .../orders/_components/orders-client.tsx | 151 ++- .../payments/_components/payment-sheet.tsx | 87 +- .../_components/payment-view-sheet.tsx | 10 +- .../payments/_components/payments-client.tsx | 105 +- .../stores/_components/store-sheet.tsx | 6 +- .../components/shared/data-table/types.ts | 4 +- .../components/shared/row-actions.tsx | 4 + distribution_fe/config/nav.ts | 10 +- distribution_fe/lib/api/index.ts | 2 +- distribution_fe/lib/api/operations.ts | 65 +- distribution_fe/lib/api/returns-claims.ts | 8 +- distribution_fe/lib/api/sales.ts | 114 +- distribution_fe/types/api.ts | 118 +-- 61 files changed, 2195 insertions(+), 1245 deletions(-) create mode 100644 Distribution/.dotnet/.workloadAdvertisingManifestSentinel10.0.300 create mode 100644 Distribution/.dotnet/10.0.303.aspNetCertificateSentinel create mode 100644 Distribution/.dotnet/10.0.303.dotnetFirstUseSentinel create mode 100644 Distribution/.dotnet/10.0.303.toolpath.sentinel create mode 100644 Distribution/.dotnet/10.0.303_IsDockerContainer.dotnetUserLevelCache create mode 100644 Distribution/.dotnet/10.0.303_MachineId.dotnetUserLevelCache create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054849_3c2c0c4055d6437591042769f431029b.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054849_5d637cd612c34f1d8c78e7f3b2716acb.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054849_5e3ab89dd1164922b68cd8a91afb4dd1.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054849_7f218358f90d4dea89beb22e746aaa5e.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054849_a1db53cd4756496796a45e4d0e060b23.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054849_ace67540371e4eae93f6d0895b617653.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054849_b532e6064ddb4074a63b8d295ce297d9.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054849_f3a1d0f218a5492cacc3df523c5ff9b2.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054850_55c23537298a4cdd905fff2a066c61c8.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054850_6247cb09d42c4e96ace11389a1a91bf7.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054850_965e4b827a0a4c4d8d08cc2d43e6bc44.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054850_dcc554cb89e74159855b8fda6d16c235.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054856_09e56a2b38574bdb8e196ea189c58142.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054856_3e9580a6a36741b390d50bd290250e42.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/20260917054856_5d9eff7293784d3c9fe7fbec6ab2a85b.trn create mode 100644 Distribution/.dotnet/TelemetryStorageService/7b4fdabac24445e18bb7e730fceaf989 create mode 100644 Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/10.0.303.1/microsoft.net.workloads.workloadset.json create mode 100644 Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/AdvertisedManifestFeatureBand.txt create mode 100644 Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/workloadVersion.txt create mode 100644 Distribution/docs/refactor_frontend_api_reference.md create mode 100644 distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-create-dialog.tsx create mode 100644 distribution_fe/app/(dashboard)/sales/_components/shop-po-create-sheet.tsx create mode 100644 distribution_fe/app/(dashboard)/sales/_components/shop-po-view-sheet.tsx diff --git a/Distribution/.dotnet/.workloadAdvertisingManifestSentinel10.0.300 b/Distribution/.dotnet/.workloadAdvertisingManifestSentinel10.0.300 new file mode 100644 index 0000000..e69de29 diff --git a/Distribution/.dotnet/10.0.303.aspNetCertificateSentinel b/Distribution/.dotnet/10.0.303.aspNetCertificateSentinel new file mode 100644 index 0000000..e69de29 diff --git a/Distribution/.dotnet/10.0.303.dotnetFirstUseSentinel b/Distribution/.dotnet/10.0.303.dotnetFirstUseSentinel new file mode 100644 index 0000000..e69de29 diff --git a/Distribution/.dotnet/10.0.303.toolpath.sentinel b/Distribution/.dotnet/10.0.303.toolpath.sentinel new file mode 100644 index 0000000..e69de29 diff --git a/Distribution/.dotnet/10.0.303_IsDockerContainer.dotnetUserLevelCache b/Distribution/.dotnet/10.0.303_IsDockerContainer.dotnetUserLevelCache new file mode 100644 index 0000000..c1f22fb --- /dev/null +++ b/Distribution/.dotnet/10.0.303_IsDockerContainer.dotnetUserLevelCache @@ -0,0 +1 @@ +False \ No newline at end of file diff --git a/Distribution/.dotnet/10.0.303_MachineId.dotnetUserLevelCache b/Distribution/.dotnet/10.0.303_MachineId.dotnetUserLevelCache new file mode 100644 index 0000000..1216177 --- /dev/null +++ b/Distribution/.dotnet/10.0.303_MachineId.dotnetUserLevelCache @@ -0,0 +1 @@ +bf7d0202-9a86-43b3-8323-402073a8c61a \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_3c2c0c4055d6437591042769f431029b.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_3c2c0c4055d6437591042769f431029b.trn new file mode 100644 index 0000000..3cc1bfa --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_3c2c0c4055d6437591042769f431029b.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTyW7bMBD9FYFnUaFIaqFuSeygRpDaiI226I3LKCaikAZFZUHgfy8oO0jTWy8EMeCbecvwHTn5BKhDl4fD8hlcHFGOop1LlNAaE4HLZkeqjrcdF0VZcUoZ+41yZG/hDXWo4VqXWgBmUAPmhlRYsV5jY0CUpDSEVjz1lA8j6t6RtIWBZ6uh8OMPCKP1DnXop3XGv6TZ0hZ68JMpgh9g5cYonU5kFsvt7W69wTdN/X15dXV6OcKYGhTWoA61VUW10AJzISrMdcOx7BuKe6r6UpVNRQScYNZFCE4OxWgePzkYHx1E3dGCsoJgKtAxR0ZGmWgrOcLu7ZCYzDYtUj2fy/O1e0fPEFBH8w9DT+0u9GAvnkY12cFcnM4ox8ek9BD8AUK0MPsySx0GGa132XnS9WDBRZSj9TbbDDL2Pjx9MWt70r/6D/m7NH35CnqKYK795GLCohzdSb23DrLVAnWoLrnhghjMSyUxb3qBJTCJVVUL3ipmakihXnsXrZv8NGYrF+EhzPRRh27kMKZp6212GfTeRtBxCknTrzoBN8GbScfs0/2SFKRghCXQFA9TzO7B2AA6QlK3C9O53z8QWlNCEpUpBHAx28i4z77JcZ8emMZUmgKYkqmGqB6q1rRVqxtT123da15pwspKc65Zr4yQSgmmKae94tDUKEeQws7m/Wr6viW1ajEXjcJcMo6VIBzzsq4kV9JUMiE+fczWQ8KpvjGEEoqFbGvMmWK4ZZRhTihpmGx1XaZV+rDknD1PmdxCcDD8JfnO6uBH38fsvATZFxPuJ5f+bjYvxIt1+HV2e+H1I4QspSWtS2t6Duh4PB7/AAAA//8DAAY6R+UCBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_5d637cd612c34f1d8c78e7f3b2716acb.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_5d637cd612c34f1d8c78e7f3b2716acb.trn new file mode 100644 index 0000000..6b90bcc --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_5d637cd612c34f1d8c78e7f3b2716acb.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTyU7dMBT9lcjrOHiKHWfHqCJEQYDaqjvHvuFZBPvJcRiE3r9XDg9RuuvOuvI5PsP1GwrmEVCPDrfb0ycIeUY1yn4dMcIkJhpTdUfaXnS90A2VHVdK/UY18hfwinqkhLXUasAcJGDhSIsHPlrsHGhKqCOsFYXT3M+of0PGNw6evIUmzj8gzT4G1KOfPrj4XN42vrFTXFyT4gTnYc4m2CLm5PT24u7qGp8p+f306Oj95gxzIWi8Qz3q2pZZbTUWWrdYWCWwGRXDIxtGOlDVEg3vMB8ypGCmZnYPnxpczAGy7VnDeEMw02hXI2eyKbIHM8Pd67YoWWM6KfN6Ha/H/g09QUI9qz8Cfac7sJM/sPHx0QR3MPrg5w2q0TbFLaTsYY1kdTlNJvsYqv0jx5OHkFGNrm6r68nkMabHLzndvls//w/nl8ZufIDq/AT1SFLhhCYOCzoYLNSosQFu8NBKLbqBOwmltuMYsg9LXObqPGS4T6tK1KMzM82F9Oq2Okx24zPYvKQi/ZcsQHjx+Ti6MiCoRtcpusXm6jNuShrScMILx5K3S65uwPkENkPxdJeWPf0/ECYZKYzHS0oQcnVt8qb6ZuZNueCUay0DcJQPigwjtJ3r2s4qJ2UnRytaSzhtrRCWj4PTZhg0t0ywcRCgZNFd2q3WhQJCmNCK4lGqFgupKDbcScwJjAoYpa4riM9Yq6up4IZROcIIw9p0Egs+cNxxxrEgjChuOitp2Z2PSPaNiw7V6AJSgOkvy5fepjjHMVf76qsvIdwsoXzWal2DZx/wyxr+SbQPkKpSnvGh7OW+r91ut/sDAAD//wMAfxRohPMDAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_5e3ab89dd1164922b68cd8a91afb4dd1.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_5e3ab89dd1164922b68cd8a91afb4dd1.trn new file mode 100644 index 0000000..8742053 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_5e3ab89dd1164922b68cd8a91afb4dd1.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTS0/jMBD+K5HPdXBsJ3FyA1q0FWKpoNpd7c0eT6hFcCrH4SHU/75yWsSyt73E0cgz8738Trx+QtKS8/1+9Yw+jmRBoptLnPGKsoYW9ZaVrVStbHKlmkpU8jdZEHeNb6QltQQooEEqsEIqLSupER1Qa7EpWGEZL2WaqR9G0r4T7XKLzw4wH8YfGEY3eNKSn87b4SXt1i6HfphsHoYe136M2kMCs1zdX29vN/Sqrr6vLi6ON0cc04DcWdKSqkOjrC5p3TRAJTSGqrqpqdaisx2W6Ty2OR8xeN3no338xGCH6DFCy3MuckZ5Qw4LYnXUCbbRI27f9gnJLNMy1Rdzef5t38kzBtLyxYegx3Fn0Luzp9FMrrdnx2/U42Niug/DHkN0OOsyU+17Hd3gs9Omy96hj2RBbu+zTa9jN4SnL2LdH/mv/4P+Nm1fvSJMEe3lMPlIWqLIgtxo2DmP2XqZhhXSyoZZKgujqay7hmoUmpqyaqQywlaYTL0cfHR+GqYxW/uID2GGT1pypfsRj8DPA+xcRIhTSJx+ValxEwY7Qcw+1S9YznLBRGqa4n6K2R1aFxAiJnbbMJ3m/dPCK85YgjKFgD5mGx132Tc97tIFW9sSOKIthKmZ6bBUVpUKaltVqupAlsBEUYKUIDpjG21MI4BL3hmJdUUWBJPZ2ZwvbQ2zrKip6rim0uqCKgBGrapBAGCBUHzRMbvtU5/pass447TRqqJSGEGV4IJKxlkttIKqSFH6kOTkvUyeXGPw2P9F+cZBGMahi9kpBNkXEe4mn95uNgfixXn6Oqu9HOARQ5bc0s6nmJ4MOhwOhz8AAAD//wMACwdnnQIEAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_7f218358f90d4dea89beb22e746aaa5e.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_7f218358f90d4dea89beb22e746aaa5e.trn new file mode 100644 index 0000000..54d09a2 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_7f218358f90d4dea89beb22e746aaa5e.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpSTS2/cIBSF/4rF2jgYsA3e5alGUZooGbVVdzyuExQHRoDzUDT/vcIzVZvuusHoinM5fOf6A3n1DGhEx9vt+Qv4nFCNsltLlNAeE4nbYUO6kYuRy0aInhJJfqIauSt4RyMauDGtkYAZ9IC5JR3WbDLYWpAtaS2hHS891UNC4wdSrrHw4gw0IX2DmFzwaETfnbfhtdytXGPmsNgmhhkufcrKm2Lm7Pz+anNziy+G/uv5ycn+ZIJUGjTOohH1E2hhVYcHKQ3mRmosBjlgpdhkJ+jKdy9zPkP0am6SffrjwYbsIZuRNpQ1BFOJdjWyKqtiW6sEm/dtcbJiOiv1ei2v2/EDvUBEI61/A923OzKzO3pOenGzPdqvWaWntK6TMjnEd1SjbQxbiNnByug4JXjW8/tGpaeL/ZmyTedvYJYM9jQsPqMRCVSjFdE8q+yCrw4OT2cHPqMa3dxXt7PKU4jPnyDf77ld/ge2a2UenYfq8qxoWm65JBbzVivMh0liBUxh3fWSC81sDyXz0+Cz80tYUnXpMzzE1SUa0YWaE+z9HUfz6DKYvMRi/UdfhLcx2MXk6k84LWlIwwgroiVvl1zdgXURTIbyiE1cDv3+kdCeElKsLDGCz9Wtyo/VF5UeywE72M5QANsyPRA9QSes6IQZbN+LfjK8M4S1neHcsElbqbSWzFBOJ81h6FGNoMxCtY6fsUQTbQQeqLGYc9liwcSAmSJaU2HEpOUnjtXNXHR6GiyhhGKpRI850wwLRhnmhJKBKWH6tkzabySHiHnJ/gqih/mvJ187E0MKU64OWVefINwtvvza1Zr7q/P4baV9FswTxKqkpZwvU3wIaLfb7X4BAAD//wMA4dUdUiEEAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_a1db53cd4756496796a45e4d0e060b23.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_a1db53cd4756496796a45e4d0e060b23.trn new file mode 100644 index 0000000..f7486e8 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_a1db53cd4756496796a45e4d0e060b23.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpSUTW/cNhCG/4rAsyhTJMUP3ZLYQV0j9SJeNEVvQ3JkC9FSC4raNDD2vxfUbuCmt5xIDPgOZx6+nFcS4YCkJ++Ox7sTxryQmuRxC3HGFWWWtnrPul6aXtpGWGN5K/8mNRkf8DvpiZbet94iFaiQysA66sTgaQhoW9YGxjtZcsLzQvpXAmMT8DR6bOblT0zLOEfSky9jDPO3cjeMjZ/mNTRpnvA+LhmiL8Xc3j097B939KNWf9y9f385ueBSEjRjID1RAzoToKPaWk+lt44abTUFEEMYsCvrRTbGjCnC1Czh61sNYc4Rs+95w0XDKLfkXJMAGUrZDhbcfz+WSjZMtyVeb+Ft27+SEybS8/oH0Eu6Gz+NN3k+TnjC6QhpwXTj58MBYiA1Oab5iCmPuKHZup0myOMcq+tlH6YRYyY1eXyqdhPkYU6Hn3g9XRDc/wKBEyZHetKZDkSrEWQwaMOgOuS2E6ZlKCUIzQODYZBK+KCYVQMCD156r1vOgxWK1OR5mh1Mvy8bP8uZM4FprjhKtFwqZT1DYXDoNLIASjllvA3CaC5NMAIsQGsdam+VLyb5BP5ljFjd35ZuWhmkZYHK1gGVerAUUAB1nbLSOBEUFs2HOeYxrvO6VPcx43Pa+JGefIRpwQu5d8m/jBl9XlOB+pcqwl2aw+pz9eaAljWsEUwU0ZqPa64+YxgT+owF7z6t13z/k3DFGSulrClhzNUO8kv1Gywv5UDQofMcMbTCaeYG7EwwnfE6KGXU4GXnmWg7L6UXgwsWnLPCc8kHJ1EXylgMV20ed8xLaNFT7V1HJVhDQYKhxjDDW9VxZouv3jhWj9OmG3RgnHFqwSgqhRPUCC6oZJxpAcarttj5B5Kr+aQhNXnAFHH6T8ufRp/mZR5ydXVh9ROEz2ss86PaHPltjPSfjfbt7L9iqsprwRjLV7k+0LkmB4RlTXjYxk//Snbln1T7bQpx1TBjTE2eMqS8Hq/hrmsMk+fz+fwvAAAA//8DALVuXjbCBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_ace67540371e4eae93f6d0895b617653.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_ace67540371e4eae93f6d0895b617653.trn new file mode 100644 index 0000000..e621363 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_ace67540371e4eae93f6d0895b617653.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRU207kOBD9lcivGwffEtt5A7rRIsRF063d1b75UgEvaaflODAI9b+vkoYBZrQP+xJHJVfVqXOO6xVFswPUotP9fv0EMY+oRDksIUZYg4nGVG5J3QrVCl0pzZlk9d+oROEKXlCLpHCOOg2YQwNYeFJjyzuHvQdNCfWE1WKuae5H1L4iEyoPT8FBNYx/QBrDEFGL/gzRD89zbxMq1w+Tr9LQw2Ucs4luBrNab662t3f4QjY367Oz480RxrlAFTxqUdOBVd7UWGrtsHDaYiW1xMbwzndQz+cxLcQMKZq+Gv3jBwY/5AjZtaxivCKYaXQokTfZzLCtGWH7sp+RLDSt5ni5hJff9hU9QUItK98JPZY7cX042Y12Cr0/Wb6oRPs07CHlAAsjy5B9b3IYYvHW47wPEDMq0dmcspmcg3FELdqmCd6j63gfIlwks4PnIT3eHNtWN+stKtFdGv4Bl+9MfkAt4p1TvrOOGqFtZ8HrhtQGtOmEFarznlPXOUY70khpmei48taappG1t5YxVKLbTXHXm9wNafdFr81Rgsv/ocDm9Hwdje1hzrkw/fhjpK1J95BRiyylnVNSa+FZrT0H4xQI2lhPjFIcBHgute6o4pxxRTtFrNKmVsTWIDxHJbocN9lEb/ohwvo7uGnm94PCa+MeQoTicjUDp8ILTTwW1BosZKexAW6wrRstlOW+gdnD50PMIU7DNBaXMcN9WjT7NMTtpjhN7iFkcHlKsxx/NXPiXRr85HLxYTZKKlJxMgO9nfJ+ysU38CGBywsrbyBvNz+nsIYRMkOZUoKYi1ng4nczzipTL33tGICn3EpiO6iVV7Vy0jeNajonakc4rZ0QjnfWa2Ot5o4J1lkBskElgtnbxfKcrGkceEewB6OwUKrBhmuPQVsKXBkpmPjCY3HbL3md9IQRhrVRDRbccqw441gQRiQ3yjXUfLXwpxFV1VRUVFyqhZp33t5ehVCoRFeQIvSfeLkOLg3j0OXizZXFF6Y+NVqFcd+bl1/6/QaSk456K9/vnz+Ae/zVpN+mOO/GYnH7c4j4+yLvanCPkIrZHibEeQ38yLie+hy2DwmMB389ePi56KFEOzDjlGC3bN9lIURIC4zVdLTYZbwOfR9GcEP0I2oFUxUlgr6h/c9rmlVSE3U4HA7/AgAA//8DADlZ+rXpBQAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_b532e6064ddb4074a63b8d295ce297d9.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_b532e6064ddb4074a63b8d295ce297d9.trn new file mode 100644 index 0000000..e9d61aa --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_b532e6064ddb4074a63b8d295ce297d9.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACoxTTW/bOBD9K8KcRYUSqQ/q1sQJNkhbB7V3u9gbP0YOEYU0KCptEPi/F5Sdtm572JOE0ejNm/fevIKTTwg9vNvvr5/RxQlyiHYpVbRqCBWkbLe07nnXc1Hwpu2qlv4HOdg7fIEeWq51qQUShg0SbmhNFBs0MQZFSUtDq5onTLmboH8FaQuDz1Zj4ad/MEzWO+jhs3XGf0mzpS306GdTBD/irZuidDqRWV1v7rbre3LTNh+vLy+PnRNOCaCwBnpoBlSdkTVphdCEa6FI14qWSMkGM2CdnsffrIsYnByLyTz+4GB8dBh1XxUVKyipBBxyMDLKRFvJCbcv+8RkkWmV6vlSXl77V3jGAH2Vvwl6hLvQo714mtRsR3Mx+t3Out2Vd4PdzUHGNDiHffB7DNHiItB6k/3gVNKCFlVTUQo5fJD6wTrMblfZekwbq6E1tKIVEbJrCGeKkY5VjHBa0ZbJTjdlInmHweH4E+oHq4Of/BCzk+7Z2Zwr76J1s5+n7NZF3J2I9nAjxwlTwxwCupjdy/iQ/SWnh8TUtKbWFaIpmWqpGrDuTFd3ujVN0zWD5rWmrKw155oNygiplGC64tWgOLYN5LDF8GSdHN/73S5p+X3e+YcVDnIe48bPYUnGZB4hh0vrZHg5dvw9oTl1fTya8Ya0BGocl4Wyk59Xo0UXz/RNaSq54YIawkslCW8HQSQySVTdCN4pZhpMsb4P3sw6/moZowxy+DS7dErZbTLri3Xka8N/ofoTN0y5ypYoCymVarQgjFEkvCkrIriQhCGTkg+a8UFADiuvHzFkyS9p3RnYepO9C/rBRtRxDmnNf5fZ6012P8o4+PB0dnbrOe7nmH1CYwPqiInFNswJ6saO+BvZt71PGvIOctgcr3HZ9n8e45V3k/8D/B8dhx7kHD0cDofDNwAAAP//AwDB5+uJuAQAAA== \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054849_f3a1d0f218a5492cacc3df523c5ff9b2.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054849_f3a1d0f218a5492cacc3df523c5ff9b2.trn new file mode 100644 index 0000000..073bb91 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054849_f3a1d0f218a5492cacc3df523c5ff9b2.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTy07cMBT9lcjrODi248TZwQyoCFEQjNqqOz9uGItgjxyHh9D8e+XMIEp3XcW68jk+j5t35NUToB6d7nbnz+DThEqU3DKihApMJK7bDWl63vVcVpIwSrr2NyqRu4I31KOWG1MbCZiBAMwtabBmg8HWgqxJbQlteOZUDxPq35FylYVnZ6AK0w+Ikwse9ein8za85LeVq8wYZlvFMMKln5LyJotZn99fbW5u8UUrvp+fnR1uTjBlgspZ1CMxgO6sanArpcHcSI27VrZYKTbYAZr8PcCcTxC9GqvJPn5qsCF5SKanFWUVwVSifYmsSirL1mqCzdsuK1liWud5uYyXY/+OniGinpYfgR7oTszoTkx4elLengzOu2mLSrSLYQcxOVgiWVyOo0ou+OL4yGp04BMq0c19cTuqNIT49CWn+4P1y/9wfq3M1nkoLtcZU3PLJbGY11ph3g4SK2AK60ZI3mlmBeTaVsEn5+cwT8WlT/AQF5WoRxdqnOCg7zSarUtg0hyz9F8iA+HVpVWweUBQiW5jsLNJxWfcNalIxQjLHHPazam4A+simATZ0ybOR/p/IFRQkhlXc4zgU3Gr0rb4pqZtvmBb2xgKYGumW6IHaDrbNZ1prRCdGAxvDGF1Yzg3bNBWKq0lM5TTQXNoRdad2y2WhSINlxKswMKQBnMuNdaSMtxo0tq2YVTorP4z1uJmzDg9tJZQQrFUncCcaYY7RhnmhJKWqc6IOu/ORyTHxnmHSnQF0cP4l+VrZ2KYwpCKY/XFlxDuZp9/1mJZgxfn8esS/jqYR4hFLk85n/fy2Nd+v9//AQAA//8DAB8jFwPzAwAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054850_55c23537298a4cdd905fff2a066c61c8.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054850_55c23537298a4cdd905fff2a066c61c8.trn new file mode 100644 index 0000000..7e7861e --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054850_55c23537298a4cdd905fff2a066c61c8.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpSUS2/dNhCF/4rAtSjzJT60S2IHdY3URmw0RXdDcmQL0aUuKMppYNz/XlC+gZvusiMGPMPDj4fzQhIckAzk3fF49YyprKQlZdpLgglNmaPcPLB+UHboWccsF9rwv0lLphv8TgZiVAg8OKQSNVIVWU+9HAONER1nPDLRq9oTHlcyvBCYuojPU8BuWf/EvE5LIgP5MqW4fKtnw9SFedlil5cZr9NaIIVq5vLq/ubh9o5+NPqPq/fvX3euuNYG3RTJQKKzIVghqTGipwowUDcCUAAZIcKoneOvsikVzAnmbo1f3zzEpSQsYRCdkB2jwpFTSyIUqLY9rPjw/Vid7Jgua73dy/tyeCHPmMkg2h9AX9tdhHm6KMtxxmecj5BXzBdhORwgRdKSY16OmMuEO5r9tvMMZVpScz7swzxhKqQlt/fN3QxlXPLhJ173rwiuf4HAM2ZPBiJZL7UxqKSU4LQXDKPRQWvhAzAzeoE8IOudMo4bxqUTzMleG2siMBdISx7nxcP8+7rzc4J5G5kRWqBCJ5TWLjCUFsfeIIugtdc2uCitEcpGK8EBcOfRBKdDDcknCE9Twub6kgxEcxWVY5Eq7oEqMzoKKIH6XjtlvYwaq+bDksqUtmVbm+tU8DHv/MhAPsK84iu5dzk8TQVD2XKF+peuwru8xC2U5i0BnHWsk0xW0VaOW2k+Y5wyhoIV70Pezv3+JxFaMFatbDljKs0dlKfmN1if6oZoYh8EYuTSG+ZH7G20vQ0mam31GFQfmOR9UCrI0UcH3jsZhBKjV2g0aQnWwDV7xsMYjRo9Uo9CUqUsp1b3hkouNToEiLuRN47N7Vx1fjSRCSaoA6upkl5SK2sHJpiRYIPmNc4/kJzDpyxpyQ3mhPN/rvxpCnlZl7E05xQ2P0H4vKU6P5o9kd+mRP/ZaV8u4Svmpr4WTKl+lfMDnVpyQFi3jId9/Awv5K7+k+Zhn0JCdZpz05L7Arlsx3NZ6c4xrU6n0+lfAAAA//8DAMJGy6DDBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054850_6247cb09d42c4e96ace11389a1a91bf7.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054850_6247cb09d42c4e96ace11389a1a91bf7.trn new file mode 100644 index 0000000..18211b7 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054850_6247cb09d42c4e96ace11389a1a91bf7.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpSUy27dNhCGX0XgWpR5v2iXxA5qGKmN+CAtuuNlFBPRoQ4oymlgnHcvKJ/ATXfdEQPO8J9vfs4Lyu4IaETvTqebZ8h1RT2qaQ8xwhQmFlN9IHIUZpRkoMRYQsVfqEfpDn6gEWkRAg0WMAcFWEQisedTwDGCpYRGwqRoNd3XFY0vyKUhwnMKMCzrFyhrWjIa0R8px+V7e9ulIczLFoeyzHCb1+pyaGKubx7vDvcP+KNWv9+8f/96c4W1FRhSRCOK1oRgGMdaM4mFg4Dt5Bx2jkcX3aSspa9pKVco2c3DGr+9aYhLzVDDyAbGB4KZReceRVddk+3dCocfp6Zkx3Td4v0e3o/jC3qGgkbW/wT6Wu4qzOlq3fwMzzCfXFmhXIXleHQ5oh6dynKCUhPsaJ6h+GVNtVENQTtjKI3GaSF1NFwyriMnEA3RMtponRJqYkHKKXpjtZhEZFREBUJ4jXq0w5tnV9OSu4v2D3OCXFGP7h+7h9nVaSnHX/A/vhK9/R9Am2w0Ik4kV1qD4Jw7qzwjELUKSjEfHNGTZ0ADEGmFtlQTyi0jlkuljY6O2IB69MmFp5Shu71GI1JURGFJxIJ6h4WeLHbAHfZSWWE8b42iHn1Yck15W7a1u80Vvpa9XzSij25e4bXTdyU8pQqhbqVB+FO1xIeyxC3U7s0AlAxk4IS3pK2ettp9hpgKhAoNx6Fsl3r/SWGKEdKkbKVArt2Dq0/db259aheijjIwgEi518RPIE000gQdlTJqCkIGwqkMQgQ++Wid95YHJtjkBWiFegTNb91u8TBJyi112BhtsIheYi8Nw0QqYo0xOoo2kTeO3f3c8vykI2GEYeuMwoJ7jg1nHAvCiObOBEWbm38iuZhFGNSjOygZ5n+1/CmFsqzLVLuLa7pfIHzeclsf3e6g7ynjv3fa10v4BqVr03Ipt59yGdC5R0dw61bguG+f8QU9tG/SHfYlxMSgKNU9eqyu1O10CQs1WKLE+Xw+/wMAAP//AwC8ws6OwgQAAA== \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054850_965e4b827a0a4c4d8d08cc2d43e6bc44.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054850_965e4b827a0a4c4d8d08cc2d43e6bc44.trn new file mode 100644 index 0000000..31ea21a --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054850_965e4b827a0a4c4d8d08cc2d43e6bc44.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACoyUTW/bOBCG/4owZ1GhSOrz1sQJNsi2Tmu3u9gbRY4cIgppkFS6QeD/vqDsbOp2D3sTRqN3nnlnRq9g5RNCDx/2++tntDFADtEsIUZZTWhHymZLq160fUWLsmmrqhJ/QQ7mDl+gh0YoVaoOCccaidC0IgMfFdEau5KWmrJKJE25C9C/gjSFxmejsHDhG/pgnIUe/jBWu++ptjSFmtysC+8mvLUhSqsSzOp6c7dd35Obpv50fXl5zAwYkkBhNPSgu1aplnHSNKwiQqIi3SglkZJrqeVYd115/MzYiN7KqQj68Z1Bu2gxqp4VjBeUsA4OOWgZZcIeZMDtyz6RLDatUjxfwstj/wrP6KFn+ZuhR7kLNZmLpzDMZtIXk9vtjN1dOTua3exlTIVz2Hu3Rx8NLgatN9k7U0kLWrCaUQo5fJTqwVjMblfZekodD2OjKaOMdLKtieADJy1nnAjKaMNlq+oyQd6htzj9oPrRKO+CG2N28j07q3PlbDR2dnPIbm3E3Qm0hxs5BUwJs/doY3Yv40P2mwwPiVQ3ulIMUZd8aOgwYtXqtmpVo+u6rUclKkV5WSkhFB8H3clh6Lhigo2DwKaGHLbon4yV0+9ut0te/lvv/MUKRzlPceNmv2xG0I+Qw6Wx0r8cM74G1KesT8dhvCktCzVNS0PZaZ5Xk0Ebz/yFHupSaNFRTUQ5SCKasSMSuSRDVXeiHbiuMa31vXd6VvHnkXHKIYcvs02nlN2mYX03lvxdi59Qf2DDtFfZssp1Q5EPoyZIO0GEGJFIHCnRVOMoq6qsaAc5rJx6RJ+leUljz8TWm+yDVw8mooqzT23+udReb7L7ScbR+aezs1vPcT/H7Atq41FFTBRbPyepGzPhL7BvfZ88FO1xb4J7y/2GfnDBxPSL+DwbTAZvjue62PE/r/VM853pPzcCepBzdHA4HA7/AAAA//8DAL7u70zYBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054850_dcc554cb89e74159855b8fda6d16c235.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054850_dcc554cb89e74159855b8fda6d16c235.trn new file mode 100644 index 0000000..03c8086 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054850_dcc554cb89e74159855b8fda6d16c235.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACoxUy27jOBD8FYFnUaFI6mVgDxknwQbZjI3Ys7vYGx/NmIhMGhSVTBDk3weU5YkzmMPeCLIfVdXVfENO7AEt0OXhcP0MLg4oR9FOV5TQGpMOl82WVAveLipS1C1rSMn/Qzmyd/CKFqjhSpWqA8ygBsw1qbBkRmGtoStJqQmteKopHge0eEPCFhqerYLCD39DGKx3aIH+sU77l9Rb2EL1ftRF8D3cuiEKpxKYq+vN3Xa1xjdN/fX6y5dj5ABDKlBYjRZId61SLWW4aWiFuQCFOyMEFoJpoYWpu648plkXITjRF4N++sCgfXQQ1YIWlBUE0w6950iLKBJsKQbYvh4Skkmmq3SfT9fTcfGGniGgBc1Pgh7LXajeXuwHOdpeX0QRHiGaIPbw4sMTPIse5egQ/AFCtDDps9pkH5BKUpCC1pQQlKN7oXbWQXZ7la36RFiaRhNKKO5EW2POJMMtowxzQknDRKvqMmG8g+CgP6t6b1Xwgzcxm2XPPvVZehetG/04ZLcuwmMQ8Zh3I/oBUI7Wo+ztsHsAoV+3/mFMb27sE5flGAK4mK1F3GV/imGXSOhGV4oC6JLJhkgDVavbqlWNruu2NopXirCyUpwrZqTuhJQdU5RTIzk0NcrRaoyHMZ70/34GYhvsfg/6A8F20njdi2h82N9qcNEam0ZziphM1fcTq2yuuewtuPhJZLRAdck174jGvJQC88Z0WAATWFZ1x1vJdA3J2kvvjH0cf+pEjNGcmapta9nJkgA1TctJYyTRyjDV6UpCQxvStNB2ihBZ8bKVnSIayorrxC54Par4qxUYYShHD6NLG5rdJtov1uHvNf9QZB189Mr3aWC2h83rEGH/u6kt/f7gBxsTfzOP9tsA996l1/kPmDWbky99PAuGtAjZtHtJFg2c4k7VDHNtGiwp0biuW97UXDDQHcrRlVdPELLkMGHdNJSTqVab7DKonY2g4hhS638nVsd53px25kOQ4uv1dukDXB4O+Xz7x3NXJAevNtnJAJ/+lm9Dit75IbGIYTzz0QZ6c4J15qaj8bIH0DaAitPT9pg4a/Q7h12GaI1QcUhr8JdXkzFmp80hv/Y7G8DP7GPzsyHMppgr8XaqM/2AkxX+1wf4/v7+/gMAAP//AwCxdSWE9QUAAA== \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054856_09e56a2b38574bdb8e196ea189c58142.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054856_09e56a2b38574bdb8e196ea189c58142.trn new file mode 100644 index 0000000..ac3ed9b --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054856_09e56a2b38574bdb8e196ea189c58142.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTTU/cMBD9K9Gc4+DYjvNxoyxVEWpBsGqr3ib2pFgEZ+U4fAjtf6+cXUTprRfLGvnNvPfm+RU8PhB0cLrbnT+SjzPkEN1aElxoxltW1ltedarpKl00Uopa6l+Qg7ukF+igVsaUpiUmSRNTllesl4Nh1lJb8tJyUanUE3/P0L0CusLSozNUTPN3CrObPHTww3k7PaXZ6AozTostwjTShZ8jepPIbM5vL7dX1+xzrb+df/p0eDnTnBoUzkIHtm2MaYRkdS0qppAMawdEhigtWhx025YHmPORgsexmO39Owc7RU/RdKIQsuBMtLDPwWLERLvHmbYvu8RktWmT6vlaXq/dKzxSgE7kb4Ye2p2Y0Z08zP3iRntyOCPO90npLkw7CtHR6ssqdRwxuslnx0lnoyMfIYer2+x6xDhM4eGDWbcH/Rf/IX+bpp8/k1ki2bNp8RE6UAJy+IrmznnKLjbQgS6VVS23TJU9MlUPLUOSyPpKt6rppdWUtno2+ej8Mi1zduEj/Q4rf+jgM44zHZifBnPnIpm4hCTqp07A6zDZxcTs3f6SF7yQXCbQEndLzG7IukAmUpK3Dcux3z8QoQXnicoSAvmYXWO8y77gfJce2NpWRhDZUvY17weqGttUjamt1o0ejKoMl2VllDJy6G2Lfd9KI5QYekW1hhwobTtbA9YS15wImUbNmdKVYNhzYkZz5FXbN7ZMmXj3MbsaE64fassFF6zFRjMle8kaKSRTXPBaYmP0inuz5Lh81UAOlxQ8jX9J/upMmOZpiNkxBdkHE24Wnz5vtibiyXn2vLq9mcw9hSxtC51POT0uaL/f7/8AAAD//wMAd4cViwMEAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054856_3e9580a6a36741b390d50bd290250e42.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054856_3e9580a6a36741b390d50bd290250e42.trn new file mode 100644 index 0000000..54605b1 --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054856_3e9580a6a36741b390d50bd290250e42.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRTXW/bIBT9KxbPwcWAMfitbVotqrpGbbRNe8Nw3aA6EGHcD1X57xNOqq5725t1xTn3fFy/I693gFp0vt9fPYNPI1qg5OYRJVRgonDVbEjdctnWopSMM0bVb7RA7gbeUIsabkxlFGAGAjC3pMYd6w22FlRFKktozTOnfhxR+460Ky08OwNlGH9AHF3wqEU/nbfhJe/WrjRDmGwZwwArPybtTRazvHq42dyt8XUjvl9dXBxfjjBmgtJZ1CKrpDGSMtw0tMZcg8Gq1xprzay2uhdKVUeY8wmi10M52qdPDTYkD8m0tKSsJJgqdFggq5POsjs9wuZtn5XMMS3zfDGP58/2HT1DRC1dfAR6pDszgzszYbfT3p71zrtxixZoH8MeYnIwRzK7HAadXPDFacnl4MAntEB3D8V60KkPcfclp4ej9dV/OL/VZus8FKslapGouOWKWMyrTmPe9AprYBp3tVBcdswKyLVdBp+cn8I0Fiuf4DHOKlGLrvUwwlHfeTRbl8CkKWbpv0QGwqtLl8HmQd69jsFOJhWfcVekJCUjLHNMaT+l4h6si2ASZE+bOJ3o/4FQQQnJyqYYwadirdO2+KbHbX5gG1sbCmAr1jWk66GWVtbSNFYIKXrDa0NYVRvODes7q3TXKWYop33HoRFZd263mA+qMY1QnQbMOasxZ12HOwUWV5KQCqSESvdfYi3uhozr+sYSSihWWoqMY1gyyjAnlDRMSyOqfDsfkZwa5xIt0A1ED8Nflm+diWEMfSpO1RdfQriffP5Zi/kMXpzHr3P4y2CeIBa5PO18vstTX4fD4fAHAAD//wMA/WXCnPMDAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/20260917054856_5d9eff7293784d3c9fe7fbec6ab2a85b.trn b/Distribution/.dotnet/TelemetryStorageService/20260917054856_5d9eff7293784d3c9fe7fbec6ab2a85b.trn new file mode 100644 index 0000000..17e624d --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/20260917054856_5d9eff7293784d3c9fe7fbec6ab2a85b.trn @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRUy27kIBD8FYvz4GDA2PiWpzaKsok2o+xqbzzaCYoDI8B5KJp/X+GZKDun1V4QancX1VUlfyCvngEN6HizOX8BnxNaoeyWEiVUYCJx061JO/B+aEXdU0lb2v1GK+Su4B0NqOPGNEYCZiAAc0tarNlosLUgG9JYQlteMNVDQsMHUq628OIM1CHdQ0wueDSgn87b8FreVq42U5htHcMElz5l5U0hc3Z+d7W+ucUXnfh+fnKy60yQCkDtLBqQlb0xPWW462iLuQKD5agUVopZZdUopGx2Y85niF5NdbJPXxxsyB6yGWhNWU0wlWi7QlZlVWhrlWD9vilMFpnOSn21lJfr8IFeIKKBrj4F3cEdmckdPSc9u8ke7c6s0lNazlGZHOI7WqFNDBuI2cGi0XFK8Kyn97VKTxe7nnJN529g5gz2NMw+owExgVZo0WiaVHbBV3uKp5MDn5ePOTqfnPkXVEG6uatuJ5XHEJ8PLLnbqXz5HyJfK/PoPFSXZwW74ZZLYjFvtMK8GyVWwBTWrZC818wKKAk5DT47P4c5VZc+w0NcVkIDulBTgh2/42geXQaT51j2/CXK4G0Mdja5+rKyITWpGWFlaM6bOVc/wLoIJkNZYh3nPd794QgVlJBCZY4RfK5uVX6svqn0WBpsZ1tDAWzDdEf0CG1v+7Y3nRWiF6PhrSGsaQ3nho3aSqW1ZIZyOmoOXREYSnKqJaySso522mA7tgJzYhusjBW4oVJT23R2pPRAx+pmKnN67CyhhGKpeoE50wz3jDLMCSUdU70RTcnlpyT7PPAerdAVRA/TXytfOxNDCmOu9l5XByL8mH35EVSL76/O47dF7bNgniBWxS3lfMn83qDtdrv9AwAA//8DAJ9uh65PBAAA \ No newline at end of file diff --git a/Distribution/.dotnet/TelemetryStorageService/7b4fdabac24445e18bb7e730fceaf989 b/Distribution/.dotnet/TelemetryStorageService/7b4fdabac24445e18bb7e730fceaf989 new file mode 100644 index 0000000..5dbb49f --- /dev/null +++ b/Distribution/.dotnet/TelemetryStorageService/7b4fdabac24445e18bb7e730fceaf989 @@ -0,0 +1,5 @@ +https://dc.services.visualstudio.com/v2/track +Content-Type:application/x-json-stream +Content-Encoding:gzip + +H4sIAAAAAAAACpRVTW/jNhD9KwKvlbQSKZGSgD1kHWcbLPKB2OgWvQ3JYcxGIQ2KyjYN/N8LyknX2UUPvdjSSDPz5r031Atx8IhkIGf7/foJXZxITqJdQrSivKj6ohbbqh2abmh52bGu5XX/B8mJ/YLPZCCiUapWPRYMORaNrtpCMqMKrbGvq1pXtG1STbifyPBCwJYan6zC0k+/YZisd2QgX63T/lvqDbZUo591GfyIl26K4FQCc77efNne3BYXgl+vP306vjnhlAqUVpOB6L5TqqOsEIK2RQOoit4AFABMgwbD+74+plkXMTgYy0k/fMegfXQY1UBLysqqoD055ERDhARbwoTb531CstB0nuL5El4uhxfyhIEMNH8j9Fjugxrth8dJznbUH5ZfkpN98HsM0eLCyDLkOEK03mWvPVajRRdJTj6llM2sFE4TGcgFjBO+hdfu3jq8CPCI33x4uD72La/XW5KT2+D/RBVvIe7IQJhRnTZS1dD00kjUPa9awB5MI5vOaM1qZRStTcWFkLQxrNNSAuei1VJSSnJys8luR4jGh8d3gm2OGlz+Dwk2Z6u1Azmi/nGkLYR7jGQgLW8lMtNRLjlo6FlnakDWayUZb7GTQncoBKMMVKuqrla1qFvoRdsKzmjqcjltIjgNo3e4/gvVnAgmA9mGOfW7ArWzDrPLczIQXje66StdNLWEohGmLwAZFLLlfdNJpjkmE1+AHeeAK4h470Ny//X8GZNOK++idbOfp+zSRbwPi5wn491ssrOgdjaiinNIQv3OU8nb4PWsYvbdh3VVViWrWEqa436O2R1qG1DFha9X+DebH1Mop1WVoMwhoItZkj77Faakf62FbhVF1DWTopIG2053baeE5rzjRjWtqljdqqZRzEjdg5Q9U7ShRjYoOMkJJttny6Y1XS8qo6DoIFHGelOAkrLg0vTQiKpjlXjHcHYzpjxphK5oRYseOl40TLKiY5QVTUUrwaBTvIb35j4ZsSt5WTclE91CzRtvrwvTdCQn6xB8WPk5nWLD6d2lMz57yVb+cW9HDNnHLM+upqXPZ3QYYDwNrZ9gnI/reBp9s9C77AD73RLYwvSwXGz0wx1OfnzCMC2Ba4wbfXy2uCX7mNV5tqSvdqhen0C0T7j1flQ7sMceK6/xzMH4PNljpTv42x/Bf92b5f9s2l8vFfPsJu6WybIDyckXDA7HE4dcWRX85E3MXjc3e+eZE8rP7bQf4fkn5n9BwSpTa5mk/Y7+50W+m136gGTLifDNuuKvxejnXj1gyNKigHXprPw342oeo93uAoJGfeU1/lj0kJNHhGkO+Lh8opZT02FYYJzPx2W7dFd2HO2Eyjs9kYFz3pSM0/YV7n++JxpaVqzmh8Ph8A8AAAD//wMADw4oQRAHAAA= \ No newline at end of file diff --git a/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/10.0.303.1/microsoft.net.workloads.workloadset.json b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/10.0.303.1/microsoft.net.workloads.workloadset.json new file mode 100644 index 0000000..8e0f001 --- /dev/null +++ b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/10.0.303.1/microsoft.net.workloads.workloadset.json @@ -0,0 +1,18 @@ +{ + "Microsoft.NET.Workload.Emscripten.Current": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Emscripten.net6": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Emscripten.net7": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Emscripten.net8": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Emscripten.net9": "10.0.111/10.0.100", + "Microsoft.NET.Sdk.Android": "36.1.69/10.0.100", + "Microsoft.NET.Sdk.iOS": "26.5.10315/10.0.100", + "Microsoft.NET.Sdk.MacCatalyst": "26.5.10315/10.0.100", + "Microsoft.NET.Sdk.macOS": "26.5.10315/10.0.100", + "Microsoft.NET.Sdk.Maui": "10.0.20/10.0.100", + "Microsoft.NET.Sdk.tvOS": "26.5.10315/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.Current": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.net6": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.net7": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.net8": "10.0.111/10.0.100", + "Microsoft.NET.Workload.Mono.ToolChain.net9": "10.0.111/10.0.100" +} diff --git a/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/AdvertisedManifestFeatureBand.txt b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/AdvertisedManifestFeatureBand.txt new file mode 100644 index 0000000..d43750c --- /dev/null +++ b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/AdvertisedManifestFeatureBand.txt @@ -0,0 +1 @@ +10.0.300 \ No newline at end of file diff --git a/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/workloadVersion.txt b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/workloadVersion.txt new file mode 100644 index 0000000..bc93d3c --- /dev/null +++ b/Distribution/.dotnet/sdk-advertising/10.0.300/microsoft.net.workloads/workloadVersion.txt @@ -0,0 +1 @@ +10.0.303.1 \ No newline at end of file diff --git a/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs index a12b129..a312656 100644 --- a/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs +++ b/Distribution/Migrations/20260917034841_RefactorSalesToShopPOAndInvoice.cs @@ -13,41 +13,16 @@ namespace Distribution.Migrations /// protected override void Up(MigrationBuilder migrationBuilder) { - migrationBuilder.DropForeignKey( - name: "FK_DeliveryRuns_Routes_FK_RouteId", - table: "DeliveryRuns"); + DropForeignKeyIfExists(migrationBuilder, "DeliveryRuns", "FK_DeliveryRuns_Routes_FK_RouteId"); + DropForeignKeyIfExists(migrationBuilder, "DeliveryRuns", "FK_DeliveryRuns_Warehouses_FK_SourceWarehouseId"); - migrationBuilder.DropForeignKey( - name: "FK_DeliveryRuns_Warehouses_FK_SourceWarehouseId", - table: "DeliveryRuns"); - - migrationBuilder.DropForeignKey( - name: "FK_DeliveryTasks_Orders_FK_OrderId", - table: "DeliveryTasks"); - - migrationBuilder.DropForeignKey( - name: "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId", - table: "LoadingSheetItems"); - - migrationBuilder.DropForeignKey( - name: "FK_LoadingSheets_Warehouses_FK_SourceWarehouseId", - table: "LoadingSheets"); - - migrationBuilder.DropForeignKey( - name: "FK_Payments_Sales_FK_SaleId", - table: "Payments"); - - migrationBuilder.DropForeignKey( - name: "FK_Payments_Stores_FK_StoreId", - table: "Payments"); - - migrationBuilder.DropForeignKey( - name: "FK_SaleReturns_Orders_FK_OrderId", - table: "SaleReturns"); - - migrationBuilder.DropForeignKey( - name: "FK_SchemeRedemptions_Orders_FK_OrderId", - table: "SchemeRedemptions"); + DropForeignKeyIfExists(migrationBuilder, "DeliveryTasks", "FK_DeliveryTasks_Orders_FK_OrderId"); + DropForeignKeyIfExists(migrationBuilder, "LoadingSheetItems", "FK_LoadingSheetItems_LoadingSheets_FK_LoadingSheetId"); + DropForeignKeyIfExists(migrationBuilder, "LoadingSheets", "FK_LoadingSheets_Warehouses_FK_SourceWarehouseId"); + DropForeignKeyIfExists(migrationBuilder, "Payments", "FK_Payments_Sales_FK_SaleId"); + DropForeignKeyIfExists(migrationBuilder, "Payments", "FK_Payments_Stores_FK_StoreId"); + DropForeignKeyIfExists(migrationBuilder, "SaleReturns", "FK_SaleReturns_Orders_FK_OrderId"); + DropForeignKeyIfExists(migrationBuilder, "SchemeRedemptions", "FK_SchemeRedemptions_Orders_FK_OrderId"); migrationBuilder.DropTable( name: "OrderItems"); @@ -58,57 +33,20 @@ namespace Distribution.Migrations migrationBuilder.DropTable( name: "Sales"); - migrationBuilder.DropIndex( - name: "IX_Payments_FK_SaleId", - table: "Payments"); + DropIndexIfExists(migrationBuilder, "Payments", "IX_Payments_FK_SaleId"); + DropIndexIfExists(migrationBuilder, "LoadingSheets", "IX_LoadingSheets_FK_SourceWarehouseId"); + DropIndexIfExists(migrationBuilder, "DeliveryRuns", "IX_DeliveryRuns_FK_RouteId"); + DropIndexIfExists(migrationBuilder, "DeliveryRuns", "IX_DeliveryRuns_FK_SourceWarehouseId"); - migrationBuilder.DropIndex( - name: "IX_LoadingSheets_FK_SourceWarehouseId", - table: "LoadingSheets"); - - migrationBuilder.DropIndex( - name: "IX_DeliveryRuns_FK_RouteId", - table: "DeliveryRuns"); - - migrationBuilder.DropIndex( - name: "IX_DeliveryRuns_FK_SourceWarehouseId", - table: "DeliveryRuns"); - - migrationBuilder.DropColumn( - name: "FK_SaleId", - table: "Payments"); - - migrationBuilder.DropColumn( - name: "DispatchConfirmedAt", - table: "LoadingSheets"); - - migrationBuilder.DropColumn( - name: "DispatchConfirmedBy", - table: "LoadingSheets"); - - migrationBuilder.DropColumn( - name: "QuantityReceived", - table: "LoadingSheetItems"); - - migrationBuilder.DropColumn( - name: "QuantityResolved", - table: "LoadingSheetItems"); - - migrationBuilder.DropColumn( - name: "ActivatedAt", - table: "DeliveryRuns"); - - migrationBuilder.DropColumn( - name: "FK_RouteId", - table: "DeliveryRuns"); - - migrationBuilder.DropColumn( - name: "FK_SourceWarehouseId", - table: "DeliveryRuns"); - - migrationBuilder.DropColumn( - name: "RideType", - table: "DeliveryRuns"); + DropColumnIfExists(migrationBuilder, "Payments", "FK_SaleId"); + DropColumnIfExists(migrationBuilder, "LoadingSheets", "DispatchConfirmedAt"); + DropColumnIfExists(migrationBuilder, "LoadingSheets", "DispatchConfirmedBy"); + DropColumnIfExists(migrationBuilder, "LoadingSheetItems", "QuantityReceived"); + DropColumnIfExists(migrationBuilder, "LoadingSheetItems", "QuantityResolved"); + DropColumnIfExists(migrationBuilder, "DeliveryRuns", "ActivatedAt"); + DropColumnIfExists(migrationBuilder, "DeliveryRuns", "FK_RouteId"); + DropColumnIfExists(migrationBuilder, "DeliveryRuns", "FK_SourceWarehouseId"); + DropColumnIfExists(migrationBuilder, "DeliveryRuns", "RideType"); migrationBuilder.RenameColumn( name: "FK_OrderId", @@ -957,5 +895,66 @@ namespace Distribution.Migrations principalColumn: "Id", onDelete: ReferentialAction.Restrict); } + + private static void DropForeignKeyIfExists(MigrationBuilder migrationBuilder, string tableName, string constraintName) + { + migrationBuilder.Sql($""" + SET @sql = IF( + EXISTS( + SELECT 1 + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS + WHERE CONSTRAINT_SCHEMA = DATABASE() + AND TABLE_NAME = '{tableName}' + AND CONSTRAINT_NAME = '{constraintName}' + AND CONSTRAINT_TYPE = 'FOREIGN KEY' + ), + 'ALTER TABLE `{tableName}` DROP FOREIGN KEY `{constraintName}`', + 'SELECT 1' + ); + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + """); + } + + private static void DropIndexIfExists(MigrationBuilder migrationBuilder, string tableName, string indexName) + { + migrationBuilder.Sql($""" + SET @sql = IF( + EXISTS( + SELECT 1 + FROM INFORMATION_SCHEMA.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = '{tableName}' + AND INDEX_NAME = '{indexName}' + ), + 'DROP INDEX `{indexName}` ON `{tableName}`', + 'SELECT 1' + ); + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + """); + } + + private static void DropColumnIfExists(MigrationBuilder migrationBuilder, string tableName, string columnName) + { + migrationBuilder.Sql($""" + SET @sql = IF( + EXISTS( + SELECT 1 + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = '{tableName}' + AND COLUMN_NAME = '{columnName}' + ), + 'ALTER TABLE `{tableName}` DROP COLUMN `{columnName}`', + 'SELECT 1' + ); + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + """); + } } } diff --git a/Distribution/appsettings.json b/Distribution/appsettings.json index 8efc9f8..d63b6f9 100644 --- a/Distribution/appsettings.json +++ b/Distribution/appsettings.json @@ -1,7 +1,7 @@ { "Urls": "http://localhost:5089", "ConnectionStrings": { - "DefaultConnection": "Server=187.127.102.190;Port=3306;Database=distribution_db;User=kalana;Password=kalana@hexdive" + "DefaultConnection": "Server=187.127.102.190;Port=3306;Database=distribution;User=kalana;Password=kalana@hexdive" }, "Logging": { "LogLevel": { diff --git a/Distribution/docs/refactor_docs/refactor_plan.md b/Distribution/docs/refactor_docs/refactor_plan.md index b688a38..e648038 100644 --- a/Distribution/docs/refactor_docs/refactor_plan.md +++ b/Distribution/docs/refactor_docs/refactor_plan.md @@ -684,15 +684,33 @@ appsettings.Development.json --- -## Open Items (must resolve before coding the relevant phase) +## Open Items + +### Resolved during implementation + +| # | Item | Resolution | +|---|---|---| +| 2 | Cascade when Confirmed ShopPO is cancelled and Invoice already exists | Cancel is rejected (400) if a linked Invoice exists. Invoice must be voided separately before the ShopPO can be cancelled. No automatic cascade. | +| 3 | Cascade when Confirmed ShopPO is cancelled and it's in a LoadingSheet | Cancel is rejected (400) if the ShopPO appears in any Planned LoadingSheet. Operator must remove it from the sheet first. | +| 4 | `FinalizeInvoiceRequest` payload — free issues field shape | Deferred to a later pass. v1 `POST /api/invoices/{id}/finalize` takes no body and locks the invoice as-is. | +| 5 | Who can confirm a ShopPO? | No role restriction in v1 — any user can confirm. Gating deferred until the auth layer is implemented. | + +### Still open | # | Item | Blocks | |---|---|---| -| 1 | Who holds `loading.confirm` permission? | Phase 9 — ConfirmAsync auth guard | -| 2 | Cascade when Confirmed ShopPO is cancelled and Invoice already exists | Phase 7 — CancelAsync | -| 3 | Cascade when Confirmed ShopPO is cancelled and it's in a LoadingSheet | Phase 7 — CancelAsync | -| 4 | `FinalizeInvoiceRequest` payload — free issues field shape | Phase 6 — FinalizeAsync | -| 5 | Who can confirm a ShopPO? (agent, office, either?) | Phase 7 — ConfirmAsync permission | +| 1 | Who holds `loading.confirm` permission? | Permission seeding (`loading.populate`, `loading.confirm`) — explicitly noted as **Pending** in the API reference. Must decide role before seeding. | + +### New items — identified during frontend refactor (2026-09-17) + +| # | Item | Area | +|---|---|---| +| 6 | `order-return-edit-dialog.tsx` — file not verified; client imports it but it was not reviewed during the refactor pass. Needs to be checked for old `orderId`/`OrderResponse` references. | Returns | +| 7 | `sales-visits/` components — any components in this section that interact with sales/orders need auditing against the new ShopPO/Invoice types. | Sales Visits | +| 8 | SysConfig management page not built — the backend has a `SysConfig` model and the `InvoiceCreationMode` config key is read by `ShopPOController`. A UI to view and toggle system config is missing. | Config | +| 9 | InvoiceCreationMode (ModeA vs ModeB) UI branching — the ShopPO confirm button calls `confirm` or `confirmAndCreateInvoice` depending on mode, but the mode is not currently read from the backend. The UI should fetch `GET /api/sys-config` and gate the action accordingly. | Sales / Invoice | +| 10 | Loading Sheet item population UI — `PUT /api/loading-sheets/{id}/items` exists in the API layer but no UI for populating/editing items on a Planned sheet has been built. | Dispatch | +| 11 | `PaymentMethod` enum is missing `Cheque` — per `invoice_collection.md`, the final design includes `Cash`, `Cheque`, `Credit`. The frontend only has `Cash` and `Credit`. Cheque-specific fields (`ChequeNumber`, `ChequeDate`) and `EntryMode` (`RealTime`, `DayEndManual`) are also unimplemented. | Payments | --- diff --git a/Distribution/docs/refactor_frontend_api_reference.md b/Distribution/docs/refactor_frontend_api_reference.md new file mode 100644 index 0000000..e7c1042 --- /dev/null +++ b/Distribution/docs/refactor_frontend_api_reference.md @@ -0,0 +1,978 @@ +# Frontend API Reference — ERP Distribution (Post-Refactor) + +> Last updated: 2026-09-17 +> Base URL: `https:///api` +> All responses are JSON. Enum fields are serialized as **strings** (e.g. `"Pending"`, `"ModeB"`). +> All `Guid` fields are UUID v4 strings. All `DateTime` fields are ISO 8601. + +--- + +## Table of Contents + +1. [Pagination](#pagination) +2. [Enums Reference](#enums-reference) +3. [ShopPO](#shoppo) +4. [Invoice](#invoice) +5. [Payment](#payment) +6. [Ride (DeliveryRun)](#ride-deliveryrun) +7. [Loading Sheet](#loading-sheet) +8. [Delivery Tasks](#delivery-tasks) +9. [Returns](#returns) +10. [Schemes](#schemes) +11. [System Config](#system-config) +12. [Key Relationships & Flows](#key-relationships--flows) + +--- + +## Pagination + +All list endpoints return a `PagedResponse`: + +```json +{ + "page": 1, + "pageSize": 20, + "total": 84, + "items": [ /* T[] */ ] +} +``` + +Default page size is `20`. Pass `?page=2&pageSize=50` to paginate. + +--- + +## Enums Reference + +| Enum | Values | +|------|--------| +| `ShopPOStatus` | `Pending`, `PartiallyFulfilled`, `Fulfilled`, `Cancelled` | +| `InvoiceStatus` | `Draft`, `Printed`, `Finalized` | +| `PaymentStatus` | `Pending`, `PartiallyPaid`, `Paid` | +| `PaymentMethod` | `Cash`, `Credit` | +| `RideStatus` | `Open`, `Cancelled`, `Closed` | +| `LoadingSheetStatus` | `Planned`, `Confirmed` | +| `DeliveryTaskStatus` | `Pending`, `Delivered`, `PartiallyDelivered`, `Failed` | +| `ReturnMode` | `CreditDeduction`, `ItemExchange` | +| `ReturnReasonCode` | `Expired`, `Damaged`, `OrderError`, `Other` | +| `CancelRequestType` | `VehicleBreakdown`, `DriverUnavailable`, `RouteIssue`, `Other` | +| `InvoiceCreationMode` | `ModeA`, `ModeB` | +| `SchemeRuleType` | `SlabDiscount`, `FlatPercent`, `BuyXGetY`, `FreeBundle` | + +--- + +## ShopPO + +A ShopPO is a shop-facing purchase order raised by a sales agent on behalf of a store. + +### Status Flow + +``` +Pending → PartiallyFulfilled → Fulfilled + ↘ Cancelled +``` + +### `GET /api/shop-pos` + +List all ShopPOs with optional filters. + +**Query params:** + +| Param | Type | Description | +|-------|------|-------------| +| `agentId` | `Guid?` | Filter by the agent who raised the PO | +| `routeId` | `Guid?` | Filter by the store's route | +| `shopId` | `Guid?` | Filter by store | +| `confirmed` | `bool?` | `true` = confirmed only, `false` = unconfirmed only | +| `page` | `int` | Default `1` | +| `pageSize` | `int` | Default `20` | + +**Response:** `PagedResponse` + +```json +{ + "page": 1, + "pageSize": 20, + "total": 12, + "items": [ + { + "id": "uuid", + "storeId": "uuid", + "storeName": "Colombo Mart", + "raisedById": "uuid", + "invoiceId": "uuid | null", + "totalAmount": 15000.00, + "status": "Pending", + "confirmedAt": "2026-09-17T10:00:00 | null", + "confirmedBy": "uuid | null", + "fulfilledAt": "2026-09-17T14:00:00 | null", + "items": [ + { + "id": "uuid", + "itemId": "uuid", + "itemName": "Milo 400g", + "quantity": 10, + "quantityFulfilled": 0, + "unitPrice": 850.00, + "isActive": true + } + ], + "isActive": true, + "createdAt": "2026-09-17T08:00:00" + } + ] +} +``` + +### `GET /api/shop-pos/{id}` + +**Response:** `ShopPOResponse` (same shape as above, single object) or `404`. + +--- + +## Invoice + +An Invoice is the billing document generated from a confirmed ShopPO. There is at most one Invoice per ShopPO. + +**InvoiceCreationMode** (system config) controls whether the invoice is: +- **ModeA** — auto-created when the ShopPO is confirmed +- **ModeB** — created as a separate explicit step (default) + +### Status Flow + +``` +Draft → Printed → Finalized +``` + +Once Finalized, the invoice is locked. Payments can be collected at any status. + +### `GET /api/invoices` + +**Query params:** + +| Param | Type | Description | +|-------|------|-------------| +| `agentId` | `Guid?` | Agent who raised the ShopPO | +| `routeId` | `Guid?` | Store's route | +| `shopId` | `Guid?` | Store | +| `status` | `InvoiceStatus?` | `Draft`, `Printed`, `Finalized` | +| `page` | `int` | Default `1` | +| `pageSize` | `int` | Default `20` | + +**Response:** `PagedResponse` + +```json +{ + "page": 1, + "pageSize": 20, + "total": 5, + "items": [ + { + "id": "uuid", + "shopPOId": "uuid", + "storeName": "Colombo Mart", + "status": "Draft", + "paymentStatus": "Pending", + "createdBy": "uuid", + "printedAt": null, + "printedBy": null, + "finalizedAt": null, + "finalizedBy": null, + "totalAmount": 15000.00, + "isActive": true, + "createdAt": "2026-09-17T08:30:00" + } + ] +} +``` + +### `GET /api/invoices/{id}` + +**Response:** `InvoiceResponse` (single) or `404`. + +> **Note:** The detail response from the repository also loads `Payments`. The current `InvoiceResponse` DTO does not yet expose payments — use `GET /api/invoices/{id}/payments` for that. + +--- + +## Payment + +Payments are collected against an Invoice. Multiple payments can be made on one invoice (e.g. partial cash collection). + +### `GET /api/invoices/{invoiceId}/payments` + +Returns all payments for the invoice. + +**Response:** `PaymentResponse[]` + +```json +[ + { + "id": "uuid", + "invoiceId": "uuid", + "amount": 5000.00, + "method": "Cash", + "collectedAt": "2026-09-17T15:00:00", + "collectedBy": "uuid", + "createdAt": "2026-09-17T15:00:00" + } +] +``` + +Returns `404` if the invoice does not exist. + +### `POST /api/invoices/{invoiceId}/payments` + +Record a payment against an invoice. + +**Request body:** + +```json +{ + "amount": 5000.00, + "method": "Cash", + "collectedByUserId": "uuid | null" +} +``` + +| Field | Type | Required | Notes | +|-------|------|----------|-------| +| `amount` | `decimal` | Yes | Must be > 0 | +| `method` | `PaymentMethod` | Yes | `Cash` or `Credit` | +| `collectedByUserId` | `Guid?` | No | Defaults to authenticated user | + +**Response:** `PaymentResponse` or `404` if invoice not found, `400` on business rule violation. + +--- + +## Ride (DeliveryRun) + +A Ride represents a vehicle dispatch for a day. The driver moves along a route making deliveries. + +### Status Flow + +``` +Open → Closed + ↘ Cancelled +``` + +### `GET /api/rides` + +**Query params:** + +| Param | Type | Description | +|-------|------|-------------| +| `status` | `RideStatus?` | `Open`, `Cancelled`, `Closed` | +| `driverProfileId` | `Guid?` | Filter by driver | +| `vehicleId` | `Guid?` | Filter by vehicle | +| `page` | `int` | Default `1` | +| `pageSize` | `int` | Default `20` | + +**Response:** `PagedResponse` + +```json +{ + "items": [ + { + "id": "uuid", + "status": "Open", + "vehicleId": "uuid", + "vehicleNumberPlate": "WP CAB 1234", + "driverProfileId": "uuid", + "driverFullName": "Kamal Perera", + "meterstart": 12450, + "meterend": 0, + "startedAt": null, + "closedAt": null, + "createdAt": "2026-09-17T06:00:00" + } + ] +} +``` + +### `GET /api/rides/{id}` + +**Response:** `RideResponse` or `404`. + +### `POST /api/rides` + +Create a new ride. + +**Request body:** + +```json +{ + "vehicleId": "uuid", + "driverProfileId": "uuid", + "meterstart": 12450 +} +``` + +**Response:** `201 Created` with `RideResponse`. `400` on validation error. + +### `PUT /api/rides/{id}/driver` + +Re-assign the driver on an Open ride. + +**Request body:** + +```json +{ + "driverProfileId": "uuid" +} +``` + +**Response:** `RideResponse`. `404` if ride not found. `400` if ride is not Open. + +### `POST /api/rides/{id}/close` + +Close a ride and record the ending odometer. + +**Request body:** + +```json +{ + "meterend": 12890 +} +``` + +**Response:** `RideResponse`. `400` if ride is not Open. + +### `POST /api/rides/{id}/cancel` + +Cancel a ride. + +**Request body:** + +```json +{ + "typeCode": "VehicleBreakdown", + "reason": "Engine overheating" +} +``` + +| Field | Type | Notes | +|-------|------|-------| +| `typeCode` | `CancelRequestType` | `VehicleBreakdown`, `DriverUnavailable`, `RouteIssue`, `Other` | +| `reason` | `string` | Free text reason | + +**Response:** `RideResponse`. `400` if ride is not Open. + +--- + +## Loading Sheet + +A Loading Sheet records the items loaded onto a vehicle before a ride. It belongs to a Ride. + +### Status Flow + +``` +Planned → Confirmed +``` + +Items can only be edited while the sheet is `Planned`. Confirming the sheet commits stock movements (Warehouse → Vehicle). + +### `GET /api/loading-sheets` + +**Query params:** + +| Param | Type | Description | +|-------|------|-------------| +| `rideId` | `Guid?` | Filter by ride | +| `status` | `LoadingSheetStatus?` | `Planned`, `Confirmed` | +| `page` | `int` | Default `1` | +| `pageSize` | `int` | Default `20` | + +**Response:** `PagedResponse` + +```json +{ + "items": [ + { + "id": "uuid", + "fK_RideId": "uuid", + "status": "Planned", + "populatedBy": "uuid", + "populatedAt": "2026-09-17T07:00:00", + "confirmedAt": null, + "confirmedBy": null, + "createdAt": "2026-09-17T07:00:00", + "items": [ + { + "id": "uuid", + "fK_ItemId": "uuid", + "itemName": "Milo 400g", + "fK_WarehouseId": "uuid", + "warehouseName": "Colombo Warehouse", + "quantityDispatched": 24.0, + "fK_ShopPOItemId": "uuid | null" + } + ], + "orders": [ + { "shopPOId": "uuid" } + ] + } + ] +} +``` + +### `GET /api/loading-sheets/{id}` + +**Response:** `LoadingSheetResponse` or `404`. + +### `POST /api/loading-sheets` + +Create a new loading sheet for a ride. The ride must exist. Only one `Planned` sheet per ride is allowed. + +**Request body:** + +```json +{ + "fK_RideId": "uuid" +} +``` + +**Response:** `201 Created` with `LoadingSheetResponse`. `400` if ride already has a planned sheet. + +### `PUT /api/loading-sheets/{id}/items` + +Replace all items on a `Planned` loading sheet. This is a full replace — any items not included are removed. + +**Request body:** + +```json +{ + "items": [ + { + "fK_ItemId": "uuid", + "fK_WarehouseId": "uuid", + "quantity": 24.0, + "fK_ShopPOItemId": "uuid | null" + } + ] +} +``` + +| Field | Type | Required | Notes | +|-------|------|----------|-------| +| `fK_ItemId` | `Guid` | Yes | The item being loaded | +| `fK_WarehouseId` | `Guid` | Yes | Source warehouse for this item | +| `quantity` | `decimal` | Yes | Units to load | +| `fK_ShopPOItemId` | `Guid?` | No | Links the load line to a specific ShopPO line item | + +**Response:** `LoadingSheetResponse`. `400` if sheet is not `Planned`. + +### `POST /api/loading-sheets/{id}/confirm` + +Confirm the loading sheet. Commits stock: moves each item from its specified warehouse to the vehicle. Sheet becomes `Confirmed` and can no longer be edited. + +**Request body:** _(none)_ + +**Response:** `LoadingSheetResponse`. `400` if already confirmed. + +--- + +## Delivery Tasks + +Delivery Tasks are the per-stop delivery jobs attached to a Ride. Each task maps to one ShopPO. + +> **Note:** Auto-generation of delivery tasks from route/ShopPO assignments is deferred and not yet implemented. Tasks must be created manually or via a future dispatch endpoint. + +### Status Flow + +``` +Pending → Delivered + ↘ PartiallyDelivered + ↘ Failed +``` + +### `GET /api/rides/{rideId}/tasks` + +List all delivery tasks for a ride, ordered by `Sequence`. + +**Response:** `DeliveryTaskResponse[]` + +```json +[ + { + "id": "uuid", + "fK_RideId": "uuid", + "fK_ShopPOId": "uuid", + "storeId": "uuid", + "storeName": "Galle Mart", + "sequence": 1, + "status": "Pending", + "customerConfirmed": false, + "confirmedAt": null, + "note": null, + "items": [ + { + "itemId": "uuid", + "itemName": "Milo 400g", + "quantity": 10, + "quantityFulfilled": 0, + "unitPrice": 850.00 + } + ], + "createdAt": "2026-09-17T08:00:00" + } +] +``` + +### `GET /api/delivery-tasks/{id}` + +**Response:** `DeliveryTaskResponse` or `404`. + +### `PUT /api/delivery-tasks/{id}/quantities` + +Set the fulfilled quantity for each item in the task. Call this before confirming. + +**Request body:** + +```json +{ + "items": [ + { "itemId": "uuid", "quantityFulfilled": 8 } + ] +} +``` + +**Response:** `DeliveryTaskResponse`. `400` if task is already closed. + +### `POST /api/delivery-tasks/{id}/confirm` + +Mark the task as Delivered or PartiallyDelivered based on quantities set. Updates ShopPO fulfillment, creates stock movement (Vehicle → External), and records payment if applicable. + +**Request body:** _(none)_ + +**Response:** `DeliveryTaskResponse`. `400` if task is not `Pending`. + +### `POST /api/delivery-tasks/{id}/fail` + +Mark the task as Failed with a reason note. + +**Request body:** + +```json +{ + "note": "Store was closed" +} +``` + +**Response:** `DeliveryTaskResponse`. `400` if task is not `Pending`. + +--- + +## Returns + +Returns are recorded against a ShopPO during the same store visit. Effects (credit deduction or item exchange) are applied immediately — no approval step. + +> **Note:** The Create endpoint (`POST /api/shop-pos/{id}/returns`) is currently stubbed (`501 Not Implemented`) while the return flow is being redesigned. `GET` and `PATCH` endpoints are fully operational. + +### `GET /api/returns` + +List all returns. + +**Response:** `SaleReturnResponse[]` + +```json +[ + { + "id": "uuid", + "shopPOId": "uuid", + "mode": "CreditDeduction", + "totalCreditAmount": 1700.00, + "orderTotalAmountAfter": 13300.00, + "isActive": true, + "createdAt": "2026-09-17T11:00:00", + "items": [ + { + "id": "uuid", + "itemId": "uuid", + "sku": "MILO400", + "itemName": "Milo 400g", + "quantity": 2.0, + "reasonCode": "Damaged", + "unitPrice": 850.00 + } + ] + } +] +``` + +### `GET /api/returns/{id}` + +**Response:** `SaleReturnResponse` or `404`. + +### `GET /api/shop-pos/{id}/returns` + +List all returns for a specific ShopPO. + +**Response:** `SaleReturnResponse[]` + +### `POST /api/shop-pos/{id}/returns` + +> **501 Not Implemented** — return flow under redesign. + +**Request body (for future reference):** + +```json +{ + "mode": "CreditDeduction", + "items": [ + { "itemId": "uuid", "quantity": 2.0, "reasonCode": "Damaged" } + ], + "createdByUserId": "uuid" +} +``` + +| `mode` | Effect | +|--------|--------| +| `CreditDeduction` | `totalCreditAmount` is netted off the ShopPO's `TotalAmount` | +| `ItemExchange` | Items are swapped; no monetary credit applied | + +### `PATCH /api/returns/{id}/reasons` + +Update the reason code on individual return line items. Only reason codes can be edited post-creation. + +**Request body:** + +```json +{ + "items": [ + { "itemId": "uuid", "reasonCode": "Expired" } + ] +} +``` + +**Response:** `SaleReturnResponse`. `409` if return is no longer active. + +--- + +## Schemes + +Schemes are promotional rules applied to ShopPOs (formerly Orders). + +### Scheme Rule Types + +| Type | Description | +|------|-------------| +| `SlabDiscount` | Tiered % discount based on order amount. Config: `SlabDiscountConfig` | +| `FlatPercent` | Flat % discount on order total. Config: `FlatPercentConfig` | +| `BuyXGetY` | Buy N of trigger item → get free payout item | +| `FreeBundle` | Buy a bundle of items → get a free payout item | + +### `GET /api/schemes` + +List all schemes (paginated). + +**Response:** `PagedResponse` + +```json +{ + "items": [ + { + "id": "uuid", + "name": "Q3 Volume Boost", + "ruleType": "SlabDiscount", + "ruleConfig": "{\"Tiers\":[{\"MinOrderAmount\":10000,\"DiscountPercent\":5}]}", + "triggerItemId": null, + "triggerItemName": null, + "triggerQty": null, + "freeItemId": null, + "freeItemName": null, + "freeQty": null, + "bundleComponents": [], + "regionId": "uuid | null", + "regionName": "Western Province | null", + "eligibleSegment": null, + "dateRangeFrom": "2026-07-01T00:00:00", + "dateRangeTo": "2026-09-30T00:00:00", + "agentLimitExempt": false, + "baselineExpectedSales": 500000.00, + "isActive": true, + "createdAt": "2026-06-15T09:00:00" + } + ] +} +``` + +### `GET /api/schemes/{id}` + +**Response:** `SchemeResponse` or `404`. + +### `POST /api/schemes` + +Create a scheme. For discount-only schemes (`SlabDiscount`, `FlatPercent`), free-goods fields can be omitted. For `BuyXGetY` / `FreeBundle`, you can supply the free-goods config inline here or set it later via `PUT .../free-goods-rule`. + +**Request body:** + +```json +{ + "name": "Q3 Volume Boost", + "ruleType": "SlabDiscount", + "ruleConfig": "{\"Tiers\":[{\"MinOrderAmount\":10000,\"DiscountPercent\":5}]}", + "regionId": null, + "eligibleSegment": null, + "dateRangeFrom": "2026-07-01T00:00:00", + "dateRangeTo": "2026-09-30T00:00:00", + "agentLimitExempt": false, + "baselineExpectedSales": 500000.00 +} +``` + +#### `ruleConfig` shapes + +**SlabDiscount:** +```json +{ "Tiers": [ { "MinOrderAmount": 10000, "DiscountPercent": 5 }, { "MinOrderAmount": 20000, "DiscountPercent": 8 } ] } +``` + +**FlatPercent:** +```json +{ "DiscountPercent": 3.5 } +``` + +**BuyXGetY / FreeBundle:** `ruleConfig` is `null` — the payout is set via `PUT .../free-goods-rule`. + +### `PUT /api/schemes/{id}` + +Update scheme metadata. Cannot change `ruleType`. + +### `DELETE /api/schemes/{id}` + +Soft-delete (sets `IsActive = false`). + +### `PUT /api/schemes/{id}/free-goods-rule` + +Set the free-goods payout for `BuyXGetY` or `FreeBundle` schemes. + +**Request body:** + +```json +{ + "triggerItemId": "uuid | null", + "triggerQty": 6, + "freeItemId": "uuid", + "freeQty": 1.0 +} +``` + +- `BuyXGetY`: `triggerItemId` + `triggerQty` required (what store must buy). +- `FreeBundle`: `triggerItemId` / `triggerQty` ignored — trigger is the bundle components. + +### `PUT /api/schemes/{id}/bundle-components/{itemId}` + +Add or update a component in a `FreeBundle` scheme. + +**Request body:** + +```json +{ "qty": 4 } +``` + +### `DELETE /api/schemes/{id}/bundle-components/{itemId}` + +Remove a bundle component. + +### `GET /api/shop-pos/{shopPOId}/scheme-eligibility` + +Check which active schemes the ShopPO qualifies for. + +**Response:** `SchemeEligibilityResponse[]` + +```json +[ + { + "schemeId": "uuid", + "schemeName": "Q3 Volume Boost", + "ruleType": "SlabDiscount", + "eligible": true, + "reason": null, + "discountAmount": 750.00, + "freeItemId": null, + "freeQty": null + } +] +``` + +### `POST /api/shop-pos/{shopPOId}/apply-scheme` + +Apply a scheme to the ShopPO (create a redemption record and apply discount/free goods). + +**Request body:** + +```json +{ "schemeId": "uuid" } +``` + +**Response:** `SchemeRedemptionResponse` + +```json +{ + "id": "uuid", + "schemeId": "uuid", + "shopPOId": "uuid", + "discountAmount": 750.00, + "freeItemId": null, + "freeItemName": null, + "freeQty": null, + "freeItemCostValue": null, + "redeemedAt": "2026-09-17T09:30:00" +} +``` + +### `GET /api/schemes/{id}/spend` + +**Response:** `SchemeSpendResponse` + +```json +{ + "schemeId": "uuid", + "totalDiscountSpend": 45000.00, + "totalFreeGoodsCostSpend": 12000.00, + "totalSpend": 57000.00, + "redemptionCount": 38 +} +``` + +### `GET /api/schemes/{id}/roi` + +**Response:** `SchemeROIResponse` + +```json +{ + "schemeId": "uuid", + "baselineExpectedSales": 500000.00, + "actualSales": 620000.00, + "incrementalSales": 120000.00, + "totalSpend": 57000.00, + "roi": 1.105 +} +``` + +--- + +## System Config + +Key-value store for system-wide configuration. All keys and values are strings. Only known keys have typed endpoints with validation. + +### `GET /api/sys-config` + +Return all config entries. + +**Response:** `SysConfigResponse[]` + +```json +[ + { + "key": "InvoiceCreationMode", + "value": "ModeB", + "updatedAt": "2026-09-17T00:00:00", + "updatedBy": null + } +] +``` + +### `GET /api/sys-config/invoice-creation-mode` + +**Response:** + +```json +{ "mode": "ModeB" } +``` + +### `PUT /api/sys-config/invoice-creation-mode` + +**Request body:** + +```json +{ "mode": "ModeA" } +``` + +| Value | Behaviour | +|-------|-----------| +| `ModeA` | Invoice is auto-created when a ShopPO is confirmed | +| `ModeB` | Invoice must be created as a separate explicit step (default) | + +**Response:** `SysConfigResponse`. `400` if value is not a valid `InvoiceCreationMode`. + +### `GET /api/sys-config/{key}` + +Generic getter by key string. `404` if key not set. + +### `PUT /api/sys-config/{key}` + +Generic raw string setter. Requires admin-level auth. + +**Request body:** + +```json +{ "value": "SomeValue" } +``` + +**Response:** `SysConfigResponse`. `400` if value fails validation for a known key. + +--- + +## Key Relationships & Flows + +### Core Entity Chain + +``` +Store ──< ShopPO ──< ShopPOItem + │ + └──► Invoice ──< Payment + │ + └──► SaleReturn ──< SaleReturnItem + │ + └──► SchemeRedemption + +Ride (DeliveryRun) ──► LoadingSheet ──< LoadingSheetItem + └──< DeliveryTask ──► ShopPO +``` + +### ShopPO → Invoice Dependency + +- `ShopPO.invoiceId` is `null` until an invoice is created. +- In **ModeA**, the invoice is created automatically when the ShopPO is confirmed. +- In **ModeB**, the invoice must be created via a dedicated endpoint (not yet exposed — planned). +- An invoice can only exist for a confirmed ShopPO. + +### Payment → Invoice Dependency + +- Payments are always attached to an **Invoice**, never directly to a ShopPO. +- `Invoice.paymentStatus` is computed: + - `Pending` — no payments + - `PartiallyPaid` — payments collected but total < invoice amount + - `Paid` — fully settled + +### Loading Sheet → Stock + +- Confirming a loading sheet deducts each item from its **source warehouse** (`fK_WarehouseId` per line) and credits the **vehicle** stock location. +- Each loading sheet line can optionally link to a `fK_ShopPOItemId` for traceability. + +### Delivery Task → ShopPO Fulfillment + +- Confirming a delivery task updates `ShopPOItem.quantityFulfilled` and transitions the ShopPO status: + - All items fully fulfilled → `Fulfilled` + - Some items partially fulfilled → `PartiallyFulfilled` + +### Returns → ShopPO + +- Returns always reference a `shopPOId`. +- `CreditDeduction` mode: `SaleReturn.totalCreditAmount` is netted off `ShopPO.totalAmount` immediately. +- `ItemExchange` mode: no monetary impact; items are swapped in stock. +- Only the `reasonCode` on each return line can be edited after creation. + +--- + +## What Is Not Yet Implemented + +| Feature | Status | Notes | +|---------|--------|-------| +| ShopPO confirm endpoint | Pending | `PUT /api/shop-pos/{id}/confirm` — triggers InvoiceCreationMode check | +| Invoice create (ModeB) | Pending | `POST /api/invoices` with `{ shopPOId }` | +| Invoice print | Pending | `POST /api/invoices/{id}/print` | +| Invoice finalize | Pending | `POST /api/invoices/{id}/finalize` | +| Delivery task auto-generation | Deferred | Route-based dispatch not yet implemented | +| Returns create | Redesign | `POST /api/shop-pos/{id}/returns` returns `501` | +| Permission seeding | Pending | `loading.populate`, `loading.confirm` scopes | diff --git a/distribution_fe/app/(dashboard)/operations/deliveries/_components/delivery-tasks-client.tsx b/distribution_fe/app/(dashboard)/operations/deliveries/_components/delivery-tasks-client.tsx index 64014af..648742d 100644 --- a/distribution_fe/app/(dashboard)/operations/deliveries/_components/delivery-tasks-client.tsx +++ b/distribution_fe/app/(dashboard)/operations/deliveries/_components/delivery-tasks-client.tsx @@ -51,7 +51,7 @@ export function DeliveryTasksClient() { const fetchRides = useCallback(async () => { try { - const res = await ridesApi.list({ page: 1, pageSize: 200, rideType: 'Delivery' }) + const res = await ridesApi.list({ page: 1, pageSize: 200 }) const items = getPaginatedItems(res) setRides(items) setSelectedRideId((current) => current || items[0]?.id || '') @@ -188,7 +188,7 @@ export function DeliveryTasksClient() { 0}>Select a ride... {rides.map((ride) => ( - {ride.routeName} - {ride.vehicleNumberPlate} + {ride.vehicleNumberPlate} — {ride.driverFullName} ))} diff --git a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-create-dialog.tsx b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-create-dialog.tsx new file mode 100644 index 0000000..b0031bc --- /dev/null +++ b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-create-dialog.tsx @@ -0,0 +1,113 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useForm, zodResolver, z } from '@/lib/form' +import { FormField } from '@/components/shared/form-field' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from '@/components/ui/dialog' +import { FieldGroup } from '@/components/ui/field' +import { toast } from '@/components/ui/toast' +import { loadingSheets as loadingSheetsApi, rides as ridesApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { RideResponse } from '@/types/api' + +const schema = z.object({ + fK_RideId: z.string().min(1, 'Ride is required'), +}) + +type FormValues = z.infer + +interface LoadingSheetCreateDialogProps { + open: boolean + onClose: () => void + onSuccess: () => void +} + +export function LoadingSheetCreateDialog({ open, onClose, onSuccess }: LoadingSheetCreateDialogProps) { + const [ridesList, setRidesList] = useState([]) + + const form = useForm({ + resolver: zodResolver(schema), + defaultValues: { fK_RideId: '' }, + }) + + useEffect(() => { + if (!open) return + form.reset({ fK_RideId: '' }) + ridesApi.list({ status: 'Open', pageSize: 200 }) + .then((res) => setRidesList(getPaginatedItems(res))) + .catch((err) => toast.add({ title: 'Failed to load rides', description: getApiError(err), type: 'error' })) + }, [open]) + + async function onSubmit(values: FormValues) { + try { + await loadingSheetsApi.create(values) + toast.add({ title: 'Loading sheet created', type: 'success' }) + onSuccess() + onClose() + } catch (err) { + toast.add({ title: 'Failed to create loading sheet', description: getApiError(err), type: 'error' }) + } + } + + return ( + !v && onClose()}> + + + New Loading Sheet + + Create a loading sheet for an open ride. Only one planned sheet per ride is allowed. + + + +
+ + ( + + )} + /> + + + + + + +
+
+
+ ) +} diff --git a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-view-sheet.tsx b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-view-sheet.tsx index 8ab855d..227f6ad 100644 --- a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheet-view-sheet.tsx @@ -11,11 +11,8 @@ import { Separator } from '@/components/ui/separator' import type { LoadingSheetResponse, LoadingSheetStatus } from '@/types/api' const LS_STATUS_VARIANT: Record = { - Pending: 'secondary', - DispatchConfirmed: 'default', - ReceiptConfirmed: 'default', - DiscrepancyFlagged: 'destructive', - Resolved: 'secondary', + Planned: 'secondary', + Confirmed: 'default', } const fmtDateTime = (v: string | null) => @@ -25,6 +22,8 @@ const fmtDateTime = (v: string | null) => }) : '—' +const truncId = (id: string) => id.substring(0, 8) + interface LoadingSheetViewSheetProps { open: boolean onClose: () => void @@ -51,13 +50,12 @@ export function LoadingSheetViewSheet({ open, onClose, sheet }: LoadingSheetView
- {sheet.id.substring(0, 8)}} /> - + {truncId(sheet.id)}} /> + {truncId(sheet.fK_RideId)}} /> {sheet.status}} /> - - - - + + + 0 ? sheet.orders.map(o => truncId(o.shopPOId)).join(', ') : '—'} />
@@ -70,15 +68,14 @@ export function LoadingSheetViewSheet({ open, onClose, sheet }: LoadingSheetView Item - Dispatched - Received - Resolved + Warehouse + Qty {sheet.items.length === 0 ? ( - + No items on this sheet. @@ -86,9 +83,8 @@ export function LoadingSheetViewSheet({ open, onClose, sheet }: LoadingSheetView sheet.items.map((item) => ( {item.itemName} + {item.warehouseName} {item.quantityDispatched} - {item.quantityReceived} - {item.quantityResolved} )) )} diff --git a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheets-client.tsx b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheets-client.tsx index 36bde8a..25acbc0 100644 --- a/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheets-client.tsx +++ b/distribution_fe/app/(dashboard)/operations/loading/_components/loading-sheets-client.tsx @@ -1,14 +1,19 @@ 'use client' import { useState, useEffect, useCallback, useMemo } from 'react' +import { HugeiconsIcon } from '@hugeicons/react' +import { Add01Icon } from '@hugeicons/core-free-icons' + import { DataTable } from '@/components/shared/data-table' import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' +import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/toast' import { loadingSheets as loadingSheetsApi, getApiError, getPaginatedItems } from '@/lib/api/index' import type { LoadingSheetResponse, LoadingSheetStatus } from '@/types/api' import { LoadingSheetViewSheet } from './loading-sheet-view-sheet' +import { LoadingSheetCreateDialog } from './loading-sheet-create-dialog' const fmtDate = (v: string) => new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) @@ -16,11 +21,8 @@ const fmtDate = (v: string) => const truncId = (id: string) => id.substring(0, 8) const LS_STATUS_VARIANT: Record = { - Pending: 'secondary', - DispatchConfirmed: 'default', - ReceiptConfirmed: 'default', - DiscrepancyFlagged: 'destructive', - Resolved: 'secondary', + Planned: 'secondary', + Confirmed: 'default', } export function LoadingSheetsClient() { @@ -30,6 +32,7 @@ export function LoadingSheetsClient() { const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(20) + const [createOpen, setCreateOpen] = useState(false) const [viewOpen, setViewOpen] = useState(false) const [selectedSheet, setSelectedSheet] = useState(null) @@ -55,23 +58,13 @@ export function LoadingSheetsClient() { setViewOpen(true) } - async function handleConfirmDispatch(row: LoadingSheetResponse) { + async function handleConfirm(row: LoadingSheetResponse) { try { - await loadingSheetsApi.confirmDispatch(row.id) - toast.add({ title: 'Dispatch confirmed', type: 'success' }) + await loadingSheetsApi.confirm(row.id) + toast.add({ title: 'Loading sheet confirmed — stock committed to vehicle', type: 'success' }) fetchData(page, pageSize) } catch (err) { - toast.add({ title: 'Failed to confirm dispatch', description: getApiError(err), type: 'error' }) - } - } - - async function handleConfirmReceipt(row: LoadingSheetResponse) { - try { - await loadingSheetsApi.confirmReceipt(row.id, []) - toast.add({ title: 'Receipt confirmed', type: 'success' }) - fetchData(page, pageSize) - } catch (err) { - toast.add({ title: 'Failed to confirm receipt', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to confirm loading sheet', description: getApiError(err), type: 'error' }) } } @@ -92,33 +85,45 @@ export function LoadingSheetsClient() { ), }, { - key: 'warehouseName', - title: 'Warehouse', - fields: [{ key: 'warehouseName', primary: true }], - minWidth: 180, + key: 'rideId', + title: 'Ride', + fields: ['fK_RideId'], + width: 140, + cellRender: (row) => ( + {truncId(row.fK_RideId)} + ), }, { key: 'status', title: 'Status', fields: ['status'], - width: 180, + width: 140, cellRender: (row) => ( {row.status} ), }, + { + key: 'orders', + title: 'POs', + fields: ['orders'], + width: 80, + cellRender: (row) => ( + {row.orders.length} + ), + }, { key: 'itemCount', title: 'Items', fields: ['items'], - width: 120, + width: 80, cellRender: (row) => ( - {row.items.length} items + {row.items.length} ), }, { - key: 'createdAt', - title: 'Created', - fields: [{ key: 'createdAt', transform: (v) => fmtDate(v as string) }], + key: 'populatedAt', + title: 'Populated', + fields: [{ key: 'populatedAt', transform: (v) => fmtDate(v as string) }], width: 140, }, ], @@ -131,15 +136,9 @@ export function LoadingSheetsClient() { }, { action: 'confirm', - label: 'Confirm dispatch', - onClick: handleConfirmDispatch, - visible: (target) => target.status === 'Pending', - }, - { - action: 'confirm', - label: 'Confirm receipt', - onClick: handleConfirmReceipt, - visible: (target) => target.status === 'DispatchConfirmed', + label: 'Confirm & commit stock', + onClick: handleConfirm, + visible: (target) => target.status === 'Planned', }, ], }, @@ -151,9 +150,13 @@ export function LoadingSheetsClient() {

Loading Sheets

- Track goods loaded onto a vehicle before dispatch + Items loaded onto a vehicle before a delivery run

+ + setCreateOpen(false)} + onSuccess={() => fetchData(page, pageSize)} + /> + setViewOpen(false)} diff --git a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-cancel-dialog.tsx b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-cancel-dialog.tsx index 8bfcf52..2a536ee 100644 --- a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-cancel-dialog.tsx +++ b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-cancel-dialog.tsx @@ -57,12 +57,12 @@ export function RideCancelDialog({ open, onClose, onSuccess, ride }: RideCancelD async function onSubmit(values: FormValues) { try { - await ridesApi.cancelRequests.raise(ride!.id, values) - toast.add({ title: 'Cancel request raised', type: 'success' }) + await ridesApi.cancel(ride!.id, values) + toast.add({ title: 'Ride cancelled', type: 'success' }) onSuccess() onClose() } catch (err) { - toast.add({ title: 'Failed to raise cancel request', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to cancel ride', description: getApiError(err), type: 'error' }) } } @@ -72,7 +72,7 @@ export function RideCancelDialog({ open, onClose, onSuccess, ride }: RideCancelD Cancel Ride - Raises a cancel request for this ride, subject to supervisor approval. + Cancelling this ride is immediate and cannot be undone. @@ -122,7 +122,7 @@ export function RideCancelDialog({ open, onClose, onSuccess, ride }: RideCancelD Back diff --git a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-edit-driver-sheet.tsx b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-edit-driver-sheet.tsx index 59c1d4f..6c17d8f 100644 --- a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-edit-driver-sheet.tsx +++ b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-edit-driver-sheet.tsx @@ -72,7 +72,7 @@ export function RideEditDriverSheet({ open, onClose, onSuccess, ride }: RideEdit Edit Ride Driver - Reassign the driver for this ride. Only available while the ride is in Draft status. + Reassign the driver for this ride. Only available while the ride is Open. diff --git a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-sheet.tsx b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-sheet.tsx index 840f79c..bb5412b 100644 --- a/distribution_fe/app/(dashboard)/operations/rides/_components/ride-sheet.tsx +++ b/distribution_fe/app/(dashboard)/operations/rides/_components/ride-sheet.tsx @@ -26,19 +26,14 @@ import { rides as ridesApi, vehicles as vehiclesApi, drivers as driversApi, - routes as routesApi, - warehouses as warehousesApi, getApiError, getPaginatedItems, } from '@/lib/api/index' -import type { VehicleResponse, DriverProfileResponse, RouteResponse, WarehouseResponse } from '@/types/api' +import type { VehicleResponse, DriverProfileResponse } from '@/types/api' const schema = z.object({ - rideType: z.enum(['Delivery', 'Sale']), vehicleId: z.string().min(1, 'Vehicle is required'), driverProfileId: z.string().min(1, 'Driver is required'), - routeId: z.string().min(1, 'Route is required'), - sourceWarehouseId: z.string().min(1, 'Warehouse is required'), meterstart: z.number().min(0, 'Meter start must be 0 or more'), }) @@ -50,21 +45,15 @@ interface RideSheetProps { onSuccess: () => void } - export function RideSheet({ open, onClose, onSuccess }: RideSheetProps) { const [vehiclesList, setVehiclesList] = useState([]) const [driversList, setDriversList] = useState([]) - const [routesList, setRoutesList] = useState([]) - const [warehousesList, setWarehousesList] = useState([]) const form = useForm({ resolver: zodResolver(schema), defaultValues: { - rideType: 'Delivery', vehicleId: '', driverProfileId: '', - routeId: '', - sourceWarehouseId: '', meterstart: 0, }, }) @@ -73,26 +62,18 @@ export function RideSheet({ open, onClose, onSuccess }: RideSheetProps) { if (!open) return form.reset({ - rideType: 'Delivery', vehicleId: '', driverProfileId: '', - routeId: '', - sourceWarehouseId: '', meterstart: 0, }) - // available=true tells backend to exclude vehicles already on an open ride Promise.all([ vehiclesApi.list({ available: true, isActive: true, pageSize: 200 }), driversApi.list({ pageSize: 200 }), - routesApi.list({ pageSize: 200 }), - warehousesApi.list({ pageSize: 200 }), ]) - .then(([v, d, r, w]) => { + .then(([v, d]) => { setVehiclesList(getPaginatedItems(v)) setDriversList(getPaginatedItems(d)) - setRoutesList(getPaginatedItems(r)) - setWarehousesList(getPaginatedItems(w)) }) .catch((err) => { toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' }) @@ -115,30 +96,11 @@ export function RideSheet({ open, onClose, onSuccess }: RideSheetProps) { Create Ride - Start a new delivery or sales run. + Start a new delivery run for a driver and vehicle.
- ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> - = { - Draft: 'secondary', - Open: 'secondary', - Active: 'default', - CancelRequested: 'destructive', + Open: 'default', Cancelled: 'destructive', Closed: 'secondary', } -const RIDE_TYPE_VARIANT: Record = { - Delivery: 'default', - Sale: 'secondary', -} - const fmtDateTime = (v: string | null) => v ? new Date(v).toLocaleString('en-GB', { @@ -58,14 +50,10 @@ export function RideViewSheet({ open, onClose, ride }: RideViewSheetProps) {
- - - {ride.rideType}} /> {ride.status}} /> - - + + -
diff --git a/distribution_fe/app/(dashboard)/operations/rides/_components/rides-client.tsx b/distribution_fe/app/(dashboard)/operations/rides/_components/rides-client.tsx index 8e58ea2..0fe1f35 100644 --- a/distribution_fe/app/(dashboard)/operations/rides/_components/rides-client.tsx +++ b/distribution_fe/app/(dashboard)/operations/rides/_components/rides-client.tsx @@ -10,7 +10,7 @@ import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/toast' import { rides as ridesApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { RideResponse, RideStatus, RideType } from '@/types/api' +import type { RideResponse, RideStatus } from '@/types/api' import { RideSheet } from './ride-sheet' import { RideViewSheet } from './ride-view-sheet' @@ -22,19 +22,11 @@ const fmtDate = (v: string) => new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) const RIDE_STATUS_VARIANT: Record = { - Draft: 'secondary', - Open: 'secondary', - Active: 'default', - CancelRequested: 'destructive', + Open: 'default', Cancelled: 'destructive', Closed: 'secondary', } -const RIDE_TYPE_VARIANT: Record = { - Delivery: 'default', - Sale: 'secondary', -} - export function RidesClient() { const [data, setData] = useState([]) const [loading, setLoading] = useState(true) @@ -81,16 +73,6 @@ export function RidesClient() { setCancelOpen(true) } - async function handleActivate(row: RideResponse) { - try { - await ridesApi.activate(row.id) - toast.add({ title: 'Ride activated', type: 'success' }) - fetchData(page, pageSize) - } catch (err) { - toast.add({ title: 'Failed to activate ride', description: getApiError(err), type: 'error' }) - } - } - function handleClose(row: RideResponse) { setSelectedRide(row) setCloseOpen(true) @@ -115,30 +97,29 @@ export function RidesClient() { ), }, - { - key: 'routeName', - title: 'Route', - fields: [{ key: 'routeName', primary: true }], - minWidth: 160, - }, - { - key: 'rideType', - title: 'Type', - fields: ['rideType'], - width: 120, - cellRender: (row) => ( - {row.rideType} - ), - }, { key: 'status', title: 'Status', fields: ['status'], - width: 160, + width: 140, cellRender: (row) => ( {row.status} ), }, + { + key: 'meter', + title: 'Meter', + fields: ['meterstart', 'meterend'], + width: 160, + cellRender: (row) => ( +
+

{row.meterstart} km

+ {row.meterend ? ( +

→ {row.meterend} km

+ ) : null} +
+ ), + }, { key: 'createdAt', title: 'Created', @@ -157,25 +138,19 @@ export function RidesClient() { action: 'edit', label: 'Edit driver', onClick: handleEditDriver, - visible: (target) => target.status === 'Draft', - }, - { - action: 'activate', - label: 'Activate ride', - onClick: handleActivate, visible: (target) => target.status === 'Open', }, { action: 'close', label: 'Close ride', onClick: handleClose, - visible: (target) => target.status === 'Active', + visible: (target) => target.status === 'Open', }, { action: 'cancel', label: 'Cancel ride', onClick: handleCancel, - visible: (target) => target.status === 'Active', + visible: (target) => target.status === 'Open', }, ], }, @@ -192,7 +167,7 @@ export function RidesClient() { diff --git a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-dialog.tsx b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-dialog.tsx index 05bfb64..b1693bd 100644 --- a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-dialog.tsx +++ b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-dialog.tsx @@ -27,14 +27,13 @@ import { HugeiconsIcon } from '@hugeicons/react' import { Add01Icon, Delete02Icon } from '@hugeicons/core-free-icons' import { saleReturns as saleReturnsApi, - orders as ordersApi, - stores as storesApi, + shopPos as shopPosApi, items as itemsApi, users as usersApi, getApiError, getPaginatedItems, } from '@/lib/api/index' -import type { OrderResponse, ItemSummaryResponse, UserResponse, ReturnReasonCode } from '@/types/api' +import type { ShopPOResponse, ItemSummaryResponse, UserResponse, ReturnReasonCode } from '@/types/api' const REASON_CODES: ReturnReasonCode[] = ['Expired', 'Damaged', 'OrderError', 'Other'] @@ -45,7 +44,7 @@ const returnItemSchema = z.object({ }) const schema = z.object({ - orderId: z.string().min(1, 'Order is required'), + shopPOId: z.string().min(1, 'Shop PO is required'), mode: z.enum(['CreditDeduction', 'ItemExchange']), createdByUserId: z.string().min(1, 'Created by is required'), items: z.array(returnItemSchema).min(1, 'At least one item is required'), @@ -64,58 +63,55 @@ function defaultItem() { } export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialogProps) { - const [ordersList, setOrdersList] = useState([]) - const [storeNameById, setStoreNameById] = useState>(new Map()) + const [shopPOList, setShopPOList] = useState([]) const [itemsList, setItemsList] = useState([]) const [usersList, setUsersList] = useState([]) - const [selectedOrder, setSelectedOrder] = useState(null) + const [selectedPO, setSelectedPO] = useState(null) const form = useForm({ resolver: zodResolver(schema), - defaultValues: { orderId: '', mode: 'CreditDeduction', createdByUserId: '', items: [defaultItem()] }, + defaultValues: { shopPOId: '', mode: 'CreditDeduction', createdByUserId: '', items: [defaultItem()] }, }) const { fields, append, remove } = useFieldArray({ control: form.control, name: 'items' }) const itemsById = useMemo(() => new Map(itemsList.map((i) => [i.id, i])), [itemsList]) - const eligibleOrders = useMemo( - () => ordersList.filter((o) => o.status !== 'Cancelled' && o.status !== 'Fulfilled'), - [ordersList] + const eligiblePOs = useMemo( + () => shopPOList.filter((o) => o.status !== 'Cancelled' && o.confirmedAt), + [shopPOList] ) useEffect(() => { if (!open) return - form.reset({ orderId: '', mode: 'CreditDeduction', createdByUserId: '', items: [defaultItem()] }) - setSelectedOrder(null) + form.reset({ shopPOId: '', mode: 'CreditDeduction', createdByUserId: '', items: [defaultItem()] }) + setSelectedPO(null) Promise.all([ - ordersApi.list(), - storesApi.list({ pageSize: 200 }), + shopPosApi.list({ pageSize: 200 }), itemsApi.list({ pageSize: 200 }), usersApi.list({ pageSize: 200 }), ]) - .then(([orderList, storeList, itemsRes, usersRes]) => { - setOrdersList(orderList) - setStoreNameById(new Map(getPaginatedItems(storeList).map((s) => [s.id, s.storeName]))) + .then(([posRes, itemsRes, usersRes]) => { + setShopPOList(getPaginatedItems(posRes)) setItemsList(getPaginatedItems(itemsRes)) setUsersList(getPaginatedItems(usersRes)) }) .catch((err) => toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' })) }, [open]) - function handleOrderChange(orderId: string | null) { - form.setValue('orderId', orderId ?? '', { shouldValidate: true }) - const order = orderId ? ordersList.find((o) => o.id === orderId) ?? null : null - setSelectedOrder(order) + function handlePOChange(shopPOId: string | null) { + form.setValue('shopPOId', shopPOId ?? '', { shouldValidate: true }) + const po = shopPOId ? shopPOList.find((o) => o.id === shopPOId) ?? null : null + setSelectedPO(po) } async function onSubmit(values: FormValues) { try { - await saleReturnsApi.create(values.orderId, { + await saleReturnsApi.create(values.shopPOId, { mode: values.mode, items: values.items, createdByUserId: values.createdByUserId, }) - toast.add({ title: 'Order return recorded', type: 'success' }) + toast.add({ title: 'Return recorded', type: 'success' }) onSuccess() onClose() } catch (err) { @@ -123,14 +119,15 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo } } + const activeItems = selectedPO?.items.filter((i) => i.isActive) ?? [] + return ( { if (!v) onClose() }}> Record Order Return - Record items a store returned against an open order. Only items the store has previously - ordered can be returned. + Record items a store returned against a confirmed Shop PO. @@ -138,19 +135,19 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo ( - - + - Select order... - {eligibleOrders.map((o) => ( + Select Shop PO... + {eligiblePOs.map((o) => ( - {storeNameById.get(o.storeId) ?? o.storeId.slice(0, 8)} — {o.id.slice(0, 8).toUpperCase()} ({o.status}) + {o.storeName} — {o.id.slice(0, 8).toUpperCase()} ({o.status}) ))} @@ -200,7 +197,7 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo - {selectedOrder && ( + {selectedPO && (

Items to Return

@@ -223,11 +220,11 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo Select item... - {selectedOrder.items.map((oi) => { + {activeItems.map((oi) => { const item = itemsById.get(oi.itemId) return ( - {item?.name ?? oi.itemId.slice(0, 8)} {item ? `— ${item.sku}` : ''} + {oi.itemName}{item ? ` — ${item.sku}` : ''} ) })} @@ -282,7 +279,7 @@ export function OrderReturnDialog({ open, onClose, onSuccess }: OrderReturnDialo - diff --git a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-view-sheet.tsx b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-view-sheet.tsx index 4ba1660..8997cc3 100644 --- a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-return-view-sheet.tsx @@ -49,7 +49,7 @@ export function OrderReturnViewSheet({ open, onClose, ret, storeName }: OrderRet
{storeName && } - {ret.orderId}} /> + {ret.shopPOId}} /> {MODE_LABEL[ret.mode]}} /> diff --git a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-returns-client.tsx b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-returns-client.tsx index d11ff3d..5d28ec0 100644 --- a/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-returns-client.tsx +++ b/distribution_fe/app/(dashboard)/returns-claims/order-returns/_components/order-returns-client.tsx @@ -9,7 +9,7 @@ import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/toast' -import { saleReturns as saleReturnsApi, orders as ordersApi, stores as storesApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import { saleReturns as saleReturnsApi, shopPos as shopPosApi, stores as storesApi, getApiError, getPaginatedItems } from '@/lib/api/index' import type { SaleReturnResponse, ReturnMode } from '@/types/api' import { OrderReturnViewSheet } from './order-return-view-sheet' import { OrderReturnDialog } from './order-return-dialog' @@ -49,13 +49,13 @@ export function OrderReturnsClient() { const fetchData = useCallback(async () => { setLoading(true) try { - const [returns, orderList, storeList] = await Promise.all([ + const [returns, shopPOList, storeList] = await Promise.all([ saleReturnsApi.list(), - ordersApi.list(), + shopPosApi.list({ pageSize: 200 }), storesApi.list({ pageSize: 200 }), ]) const storeNameById = new Map(getPaginatedItems(storeList).map((s) => [s.id, s.storeName])) - const map = new Map(orderList.map((o) => [o.id, storeNameById.get(o.storeId) ?? '—'])) + const map = new Map(getPaginatedItems(shopPOList).map((o) => [o.id, storeNameById.get(o.storeId) ?? o.storeName])) setStoreNameByOrderId(map) setData(returns) } catch (err) { @@ -78,10 +78,10 @@ export function OrderReturnsClient() { { key: 'store', title: 'Store', - fields: ['orderId'], + fields: ['shopPOId'], minWidth: 200, cellRender: (row) => ( - {storeNameByOrderId.get(row.orderId) ?? '—'} + {storeNameByOrderId.get(row.shopPOId) ?? '—'} ), }, { @@ -163,7 +163,7 @@ export function OrderReturnsClient() { open={viewOpen} onClose={() => setViewOpen(false)} ret={viewing} - storeName={viewing ? storeNameByOrderId.get(viewing.orderId) : undefined} + storeName={viewing ? storeNameByOrderId.get(viewing.shopPOId) : undefined} /> = { - Pending: 'secondary', - Completed: 'default', - Cancelled: 'destructive', -} - -const PAYMENT_STATUS_VARIANT: Record = { - Pending: 'secondary', - PartiallyPaid: 'secondary', - Paid: 'default', -} - -const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` -const truncId = (id: string) => id.substring(0, 8) - -const fmtDateTime = (v: string | null) => - v - ? new Date(v).toLocaleString('en-GB', { - day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', - }) - : '—' - -interface SaleViewSheetProps { - open: boolean - onClose: () => void - sale: SaleResponse | null -} - -function Row({ label, value }: { label: string; value: React.ReactNode }) { - return ( -
- {label} - {value} -
- ) -} - -export function SaleViewSheet({ open, onClose, sale }: SaleViewSheetProps) { - if (!sale) return null - - return ( - !v && onClose()}> - - - Sale Details - - -
- {truncId(sale.id)}} /> - {truncId(sale.storeId)}} /> - {sale.status}} /> - {sale.paymentStatus}} /> - - - - - - -
- - - -
-

Items ({sale.items.length})

-
- - - - - - - - - - - {sale.items.length === 0 ? ( - - - - ) : ( - sale.items.map((item) => ( - - - - - - - )) - )} - -
ItemQuantityFulfilledUnit Price
- No items on this sale. -
{truncId(item.itemId)}{item.quantity}{item.quantityFulfilled}{fmtAmount(item.unitPrice)}
-
-
-
-
- ) -} +// Replaced by shop-po-view-sheet.tsx +export {} diff --git a/distribution_fe/app/(dashboard)/sales/_components/sales-client.tsx b/distribution_fe/app/(dashboard)/sales/_components/sales-client.tsx index 4f9c997..bb02cd2 100644 --- a/distribution_fe/app/(dashboard)/sales/_components/sales-client.tsx +++ b/distribution_fe/app/(dashboard)/sales/_components/sales-client.tsx @@ -1,7 +1,6 @@ 'use client' import { useState, useEffect, useCallback, useMemo } from 'react' -import { useRouter } from 'next/navigation' import { HugeiconsIcon } from '@hugeicons/react' import { Add01Icon } from '@hugeicons/core-free-icons' @@ -10,10 +9,11 @@ import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/toast' -import { sales as salesApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { SaleResponse, SaleStatus, PaymentStatus } from '@/types/api' +import { shopPos as shopPosApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { ShopPOResponse, ShopPOStatus } from '@/types/api' -import { SaleViewSheet } from './sale-view-sheet' +import { ShopPOViewSheet } from './shop-po-view-sheet' +import { ShopPOCreateSheet } from './shop-po-create-sheet' const fmtDate = (v: string) => new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) @@ -21,36 +21,31 @@ const fmtDate = (v: string) => const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) -const SALE_STATUS_VARIANT: Record = { +const PO_STATUS_VARIANT: Record = { Pending: 'secondary', - Completed: 'default', + PartiallyFulfilled: 'secondary', + Fulfilled: 'default', Cancelled: 'destructive', } -const PAYMENT_STATUS_VARIANT: Record = { - Pending: 'secondary', - PartiallyPaid: 'secondary', - Paid: 'default', -} - export function SalesClient() { - const router = useRouter() - const [data, setData] = useState([]) + const [data, setData] = useState([]) const [loading, setLoading] = useState(true) const [total, setTotal] = useState(0) const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(20) const [viewOpen, setViewOpen] = useState(false) - const [selectedSale, setSelectedSale] = useState(null) + const [createOpen, setCreateOpen] = useState(false) + const [selectedPO, setSelectedPO] = useState(null) const fetchData = useCallback(async (p: number, ps: number) => { setLoading(true) try { - const res = await salesApi.list({ page: p, pageSize: ps }) + const res = await shopPosApi.list({ page: p, pageSize: ps }) setData(getPaginatedItems(res)) setTotal(res.total) } catch (err) { - toast.add({ title: 'Failed to load sales', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to load Shop POs', description: getApiError(err), type: 'error' }) } finally { setLoading(false) } @@ -60,45 +55,52 @@ export function SalesClient() { fetchData(page, pageSize) }, [fetchData, page, pageSize]) - function handleView(row: SaleResponse) { - setSelectedSale(row) + function handleView(row: ShopPOResponse) { + setSelectedPO(row) setViewOpen(true) } - async function handleCancel(row: SaleResponse) { + async function handleConfirm(row: ShopPOResponse) { try { - await salesApi.cancel(row.id) - toast.add({ title: 'Sale cancelled', type: 'success' }) + await shopPosApi.confirm(row.id) + toast.add({ title: 'Shop PO confirmed', type: 'success' }) fetchData(page, pageSize) } catch (err) { - toast.add({ title: 'Failed to cancel sale', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to confirm Shop PO', description: getApiError(err), type: 'error' }) } } - const tableConfig = useMemo>(() => ({ + async function handleCancel(row: ShopPOResponse) { + try { + await shopPosApi.cancel(row.id) + toast.add({ title: 'Shop PO cancelled', type: 'success' }) + fetchData(page, pageSize) + } catch (err) { + toast.add({ title: 'Failed to cancel Shop PO', description: getApiError(err), type: 'error' }) + } + } + + const tableConfig = useMemo>(() => ({ rowKey: 'id', serverSide: true, stickyHeader: true, - emptyMessage: 'No sales found.', + emptyMessage: 'No Shop POs found.', pagination: { enabled: true, pageSize, pageSizeOptions: [10, 20, 50] }, columns: [ { key: 'id', - title: 'Sale ID', + title: 'PO ID', fields: ['id'], - width: 140, + width: 120, cellRender: (row) => ( {truncId(row.id)} ), }, { - key: 'storeId', - title: 'Store ID', - fields: ['storeId'], - width: 140, - cellRender: (row) => ( - {truncId(row.storeId)} - ), + key: 'store', + title: 'Store', + fields: [{ key: 'storeName', primary: true }], + minWidth: 180, }, { key: 'totalAmount', @@ -113,25 +115,21 @@ export function SalesClient() { key: 'status', title: 'Status', fields: ['status'], - width: 140, - cellRender: (row) => ( - {row.status} - ), - }, - { - key: 'paymentStatus', - title: 'Payment', - fields: ['paymentStatus'], width: 160, cellRender: (row) => ( - {row.paymentStatus} + {row.status} ), }, { - key: 'saleDate', - title: 'Sale Date', - fields: [{ key: 'saleDate', transform: (v) => fmtDate(v as string) }], - width: 140, + key: 'confirmed', + title: 'Confirmed', + fields: ['confirmedAt'], + width: 120, + cellRender: (row) => ( + + {row.confirmedAt ? fmtDate(row.confirmedAt) : 'Unconfirmed'} + + ), }, { key: 'createdAt', @@ -144,14 +142,20 @@ export function SalesClient() { actions: () => [ { action: 'view', - label: 'View sale', + label: 'View PO', onClick: handleView, }, + { + action: 'confirm', + label: 'Confirm PO', + onClick: handleConfirm, + visible: (target) => !target.confirmedAt && target.status !== 'Cancelled', + }, { action: 'cancel', - label: 'Cancel sale', + label: 'Cancel PO', onClick: handleCancel, - visible: (target) => target.status !== 'Cancelled', + visible: (target) => target.status !== 'Cancelled' && target.status !== 'Fulfilled', }, ], }, @@ -161,14 +165,14 @@ export function SalesClient() { <>
-

Sales

+

Shop POs

- Sales transactions recorded against stores + Purchase orders raised by agents on behalf of stores

-
@@ -183,10 +187,16 @@ export function SalesClient() { }} /> - setCreateOpen(false)} + onSuccess={() => fetchData(page, pageSize)} + /> + + setViewOpen(false)} - sale={selectedSale} + po={selectedPO} /> ) diff --git a/distribution_fe/app/(dashboard)/sales/_components/shop-po-create-sheet.tsx b/distribution_fe/app/(dashboard)/sales/_components/shop-po-create-sheet.tsx new file mode 100644 index 0000000..0fdad1d --- /dev/null +++ b/distribution_fe/app/(dashboard)/sales/_components/shop-po-create-sheet.tsx @@ -0,0 +1,217 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useForm, zodResolver, z } from '@/lib/form' +import { FormField } from '@/components/shared/form-field' +import { Input } from '@/components/ui/input' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from '@/components/ui/dialog' +import { FieldGroup } from '@/components/ui/field' +import { toast } from '@/components/ui/toast' +import { shopPos as shopPosApi, stores as storesApi, items as itemsApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { StoreResponse, ItemSummaryResponse } from '@/types/api' + +const itemLineSchema = z.object({ + itemId: z.string().min(1, 'Item required'), + quantity: z.number().int().min(1, 'Min 1'), + unitPrice: z.number().min(0, 'Price must be 0 or more'), +}) + +const schema = z.object({ + storeId: z.string().min(1, 'Store is required'), + items: z.array(itemLineSchema).min(1, 'At least one item is required'), +}) + +type FormValues = z.infer + +interface ShopPOCreateSheetProps { + open: boolean + onClose: () => void + onSuccess: () => void +} + +const emptyLine = { itemId: '', quantity: 1, unitPrice: 0 } + +export function ShopPOCreateSheet({ open, onClose, onSuccess }: ShopPOCreateSheetProps) { + const [storesList, setStoresList] = useState([]) + const [itemsList, setItemsList] = useState([]) + + const form = useForm({ + resolver: zodResolver(schema), + defaultValues: { storeId: '', items: [emptyLine] }, + }) + + const watchedItems = form.watch('items') + + useEffect(() => { + if (!open) return + form.reset({ storeId: '', items: [emptyLine] }) + Promise.all([ + storesApi.list({ pageSize: 200 }), + itemsApi.list({ pageSize: 200 }), + ]) + .then(([s, i]) => { + setStoresList(getPaginatedItems(s)) + setItemsList(getPaginatedItems(i)) + }) + .catch((err) => toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' })) + }, [open]) + + function addLine() { + form.setValue('items', [...watchedItems, emptyLine]) + } + + function removeLine(idx: number) { + form.setValue('items', watchedItems.filter((_, i) => i !== idx)) + } + + async function onSubmit(values: FormValues) { + try { + await shopPosApi.create(values) + toast.add({ title: 'Shop PO created', type: 'success' }) + onSuccess() + onClose() + } catch (err) { + toast.add({ title: 'Failed to create Shop PO', description: getApiError(err), type: 'error' }) + } + } + + return ( + !v && onClose()}> + + + New Shop PO + Raise a purchase order on behalf of a store. + + + + + ( + + )} + /> + + +
+
+

Line Items

+ +
+ +
+ {watchedItems.map((_, idx) => ( +
+ ( + + )} + /> + ( + field.onChange(Number(e.target.value))} + onBlur={field.onBlur} + aria-invalid={invalid} + /> + )} + /> + ( + field.onChange(Number(e.target.value))} + onBlur={field.onBlur} + aria-invalid={invalid} + /> + )} + /> +
+ +
+
+ ))} +
+
+ + + + + + +
+
+ ) +} diff --git a/distribution_fe/app/(dashboard)/sales/_components/shop-po-view-sheet.tsx b/distribution_fe/app/(dashboard)/sales/_components/shop-po-view-sheet.tsx new file mode 100644 index 0000000..911233c --- /dev/null +++ b/distribution_fe/app/(dashboard)/sales/_components/shop-po-view-sheet.tsx @@ -0,0 +1,106 @@ +'use client' + +import { Badge } from '@/components/ui/badge' +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' +import { Separator } from '@/components/ui/separator' +import type { ShopPOResponse, ShopPOStatus } from '@/types/api' + +const PO_STATUS_VARIANT: Record = { + Pending: 'secondary', + PartiallyFulfilled: 'secondary', + Fulfilled: 'default', + Cancelled: 'destructive', +} + +const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` +const truncId = (id: string) => id.substring(0, 8) + +const fmtDateTime = (v: string | null) => + v + ? new Date(v).toLocaleString('en-GB', { + day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', + }) + : '—' + +interface ShopPOViewSheetProps { + open: boolean + onClose: () => void + po: ShopPOResponse | null +} + +function Row({ label, value }: { label: string; value: React.ReactNode }) { + return ( +
+ {label} + {value} +
+ ) +} + +export function ShopPOViewSheet({ open, onClose, po }: ShopPOViewSheetProps) { + if (!po) return null + + return ( + !v && onClose()}> + + + Shop PO Details + + +
+ {truncId(po.id)}} /> + + {po.status}} /> + + {truncId(po.invoiceId)} : 'No invoice yet'} /> + + + +
+ + + +
+

Line Items ({po.items.filter(i => i.isActive).length})

+
+ + + + + + + + + + + + {po.items.filter(i => i.isActive).length === 0 ? ( + + + + ) : ( + po.items.filter(i => i.isActive).map((item) => ( + + + + + + + + )) + )} + +
ItemQtyFulfilledUnit PriceLine Total
+ No items on this PO. +
{item.itemName}{item.quantity}{item.quantityFulfilled}{fmtAmount(item.unitPrice)}{fmtAmount(item.quantity * item.unitPrice)}
+
+
+
+
+ ) +} diff --git a/distribution_fe/app/(dashboard)/sales/new/page.tsx b/distribution_fe/app/(dashboard)/sales/new/page.tsx index 6d04845..d384969 100644 --- a/distribution_fe/app/(dashboard)/sales/new/page.tsx +++ b/distribution_fe/app/(dashboard)/sales/new/page.tsx @@ -15,24 +15,21 @@ import { SelectTrigger, SelectValue, } from '@/components/ui/select' -import { Checkbox } from '@/components/ui/checkbox' import { Button } from '@/components/ui/button' import { FieldGroup } from '@/components/ui/field' import { Separator } from '@/components/ui/separator' import { toast } from '@/components/ui/toast' import { - sales as salesApi, + shopPos as shopPosApi, stores as storesApi, - rides as ridesApi, items as itemsApi, - users as usersApi, priceLists as priceListsApi, getApiError, getPaginatedItems, } from '@/lib/api/index' -import type { ItemSummaryResponse, RideResponse, StoreResponse, UserResponse } from '@/types/api' +import type { ItemSummaryResponse, StoreResponse } from '@/types/api' -const saleItemSchema = z.object({ +const lineItemSchema = z.object({ itemId: z.string().min(1, 'Item is required'), quantity: z.number().min(1, 'Quantity must be at least 1'), unitPrice: z.number().min(0.01, 'Unit price must be greater than 0'), @@ -40,11 +37,7 @@ const saleItemSchema = z.object({ const schema = z.object({ storeId: z.string().min(1, 'Store is required'), - saleDate: z.string().min(1, 'Sale date is required'), - createdByUserId: z.string().min(1, 'Created by is required'), - rideId: z.string(), - fulfillImmediately: z.boolean(), - items: z.array(saleItemSchema).min(1, 'At least one item is required'), + items: z.array(lineItemSchema).min(1, 'At least one item is required'), }) type FormValues = z.infer @@ -53,61 +46,46 @@ function createDefaultItem() { return { itemId: '', quantity: 1, unitPrice: 0 } } -function todayIso() { - return new Date().toISOString().slice(0, 10) -} - const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` -export default function NewSalePage() { +export default function NewShopPOPage() { const router = useRouter() const [storesList, setStoresList] = useState([]) - const [ridesList, setRidesList] = useState([]) const [itemsList, setItemsList] = useState([]) - const [usersList, setUsersList] = useState([]) + const [priceMinByIndex, setPriceMinByIndex] = useState>({}) + const [priceRetailByIndex, setPriceRetailByIndex] = useState>({}) const form = useForm({ resolver: zodResolver(schema), - defaultValues: { - storeId: '', - saleDate: todayIso(), - createdByUserId: '', - rideId: '', - fulfillImmediately: false, - items: [createDefaultItem()], - }, - }) - - const { fields, append, remove } = useFieldArray({ - control: form.control, - name: 'items', + defaultValues: { storeId: '', items: [createDefaultItem()] }, }) + const { fields, append, remove } = useFieldArray({ control: form.control, name: 'items' }) const watchedItems = useWatch({ control: form.control, name: 'items' }) const watchedStoreId = useWatch({ control: form.control, name: 'storeId' }) - const watchedSaleDate = useWatch({ control: form.control, name: 'saleDate' }) + const itemsById = useMemo( () => new Map(itemsList.map((item) => [item.id, item])), [itemsList] ) + const totalAmount = useMemo( - () => watchedItems.reduce((sum, item) => sum + (Number(item.quantity) || 0) * (Number(item.unitPrice) || 0), 0), + () => watchedItems.reduce((sum, line) => sum + (Number(line.quantity) || 0) * (Number(line.unitPrice) || 0), 0), [watchedItems] ) - const [priceMinByIndex, setPriceMinByIndex] = useState>({}) - const [priceRetailByIndex, setPriceRetailByIndex] = useState>({}) async function resolveAndSetPrice(index: number, itemId: string) { const item = itemsById.get(itemId) - if (watchedStoreId && watchedSaleDate) { + const today = new Date().toISOString().slice(0, 10) + if (watchedStoreId) { try { - const resolution = await priceListsApi.resolve({ itemId, storeId: watchedStoreId, saleDate: watchedSaleDate }) + const resolution = await priceListsApi.resolve({ itemId, storeId: watchedStoreId, saleDate: today }) form.setValue(`items.${index}.unitPrice`, resolution.price, { shouldValidate: true }) setPriceMinByIndex((prev) => ({ ...prev, [index]: resolution.minPrice })) setPriceRetailByIndex((prev) => ({ ...prev, [index]: resolution.retailPrice })) return } catch { - // No resolvable price for this store/date (e.g. store/item not found) — fall back below. + // No resolvable price for this store — fall back to item default. } } if (item) { @@ -117,28 +95,22 @@ export default function NewSalePage() { } } - // Re-resolve every already-selected line's price whenever the store or sale date changes, - // since the applicable price list is scoped by the store's region and the sale date. useEffect(() => { - if (!watchedStoreId || !watchedSaleDate) return + if (!watchedStoreId) return watchedItems.forEach((line, index) => { if (line.itemId) resolveAndSetPrice(index, line.itemId) }) // eslint-disable-next-line react-hooks/exhaustive-deps - }, [watchedStoreId, watchedSaleDate]) + }, [watchedStoreId]) useEffect(() => { Promise.all([ storesApi.list({ pageSize: 200 }), - ridesApi.list({ pageSize: 200, rideType: 'Sale' }), itemsApi.list({ pageSize: 200 }), - usersApi.list({ pageSize: 200 }), ]) - .then(([stores, rides, items, usersRes]) => { + .then(([stores, items]) => { setStoresList(getPaginatedItems(stores)) - setRidesList(getPaginatedItems(rides)) setItemsList(getPaginatedItems(items)) - setUsersList(getPaginatedItems(usersRes)) }) .catch((err) => { toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' }) @@ -147,18 +119,14 @@ export default function NewSalePage() { async function onSubmit(values: FormValues) { try { - await salesApi.create({ + await shopPosApi.create({ storeId: values.storeId, - saleDate: values.saleDate, - rideId: values.rideId || null, - fulfillImmediately: values.fulfillImmediately, items: values.items, - createdByUserId: values.createdByUserId, }) - toast.add({ title: 'Sale created', type: 'success' }) + toast.add({ title: 'Shop PO created', type: 'success' }) router.push('/sales') } catch (err) { - toast.add({ title: 'Failed to create sale', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to create Shop PO', description: getApiError(err), type: 'error' }) } } @@ -170,116 +138,34 @@ export default function NewSalePage() { Back
-

Create Sale

-

Record a sale for a store with one or more items.

+

Create Shop PO

+

Record a purchase order for a store.

-

Sale Details

+

Order Details

-
- ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> - - ( - - )} - /> -
- ( - + )} />
@@ -313,7 +199,9 @@ export default function NewSalePage() { {fields.map((fieldItem, index) => { const selectedItem = itemsById.get(watchedItems[index]?.itemId ?? '') - const lineTotal = (Number(watchedItems[index]?.quantity) || 0) * (Number(watchedItems[index]?.unitPrice) || 0) + const lineTotal = + (Number(watchedItems[index]?.quantity) || 0) * + (Number(watchedItems[index]?.unitPrice) || 0) return ( @@ -336,7 +224,7 @@ export default function NewSalePage() { Select item... {itemsList.map((item) => ( - {item.name} - {item.sku} + {item.name} — {item.sku} ))} @@ -356,9 +244,6 @@ export default function NewSalePage() { name={`items.${index}.quantity`} render={({ field, invalid }) => ( ( {priceMinByIndex[index] != null && (

- Negotiable down to {fmtAmount(priceMinByIndex[index]!)} + Min: {fmtAmount(priceMinByIndex[index]!)}

)} {priceRetailByIndex[index] != null && (

- Retail price: {fmtAmount(priceRetailByIndex[index]!)} + Retail: {fmtAmount(priceRetailByIndex[index]!)}

)} @@ -426,9 +308,9 @@ export default function NewSalePage() {
-

Sale Summary

+

Order Summary

- {watchedItems.length} item{watchedItems.length === 1 ? '' : 's'} on this sale. + {watchedItems.length} item{watchedItems.length === 1 ? '' : 's'} on this order.

@@ -440,7 +322,7 @@ export default function NewSalePage() {
- - - - -
- ) -} +// Retained for compatibility — invoice status transitions are now handled inline via table row actions. +export {} diff --git a/distribution_fe/app/(dashboard)/sales/orders/_components/order-view-sheet.tsx b/distribution_fe/app/(dashboard)/sales/orders/_components/order-view-sheet.tsx index ab2a68d..3a82da6 100644 --- a/distribution_fe/app/(dashboard)/sales/orders/_components/order-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/sales/orders/_components/order-view-sheet.tsx @@ -7,14 +7,18 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog' -import { Separator } from '@/components/ui/separator' -import type { OrderResponse, OrderStatus } from '@/types/api' +import type { InvoiceResponse, InvoiceStatus, PaymentStatus } from '@/types/api' -const ORDER_STATUS_VARIANT: Record = { +const INVOICE_STATUS_VARIANT: Record = { + Draft: 'secondary', + Printed: 'secondary', + Finalized: 'default', +} + +const PAYMENT_STATUS_VARIANT: Record = { Pending: 'secondary', - PartiallyFulfilled: 'secondary', - Fulfilled: 'default', - Cancelled: 'destructive', + PartiallyPaid: 'secondary', + Paid: 'default', } const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` @@ -30,8 +34,7 @@ const fmtDateTime = (v: string | null) => interface OrderViewSheetProps { open: boolean onClose: () => void - order: OrderResponse | null - storeName?: string + invoice: InvoiceResponse | null } function Row({ label, value }: { label: string; value: React.ReactNode }) { @@ -43,61 +46,26 @@ function Row({ label, value }: { label: string; value: React.ReactNode }) { ) } -export function OrderViewSheet({ open, onClose, order, storeName }: OrderViewSheetProps) { - if (!order) return null +export function OrderViewSheet({ open, onClose, invoice }: OrderViewSheetProps) { + if (!invoice) return null return ( !v && onClose()}> - + - Order Details + Invoice Details
- {truncId(order.id)}} /> - {truncId(order.saleId)}} /> - {truncId(order.storeId)}} /> - {order.status}} /> - - - - -
- - - -
-

Items ({order.items.length})

-
- - - - - - - - - - - {order.items.length === 0 ? ( - - - - ) : ( - order.items.map((item) => ( - - - - - - - )) - )} - -
ItemQuantityFulfilledUnit Price
- No items on this order. -
{truncId(item.itemId)}{item.quantity}{item.quantityFulfilled}{fmtAmount(item.unitPrice)}
-
+ {truncId(invoice.id)}} /> + {truncId(invoice.shopPOId)}} /> + + {invoice.status}} /> + {invoice.paymentStatus}} /> + + + +
diff --git a/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx b/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx index 6499008..980a219 100644 --- a/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx +++ b/distribution_fe/app/(dashboard)/sales/orders/_components/orders-client.tsx @@ -6,11 +6,10 @@ import { DataTable } from '@/components/shared/data-table' import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' import { toast } from '@/components/ui/toast' -import { orders as ordersApi, stores as storesApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { OrderResponse, OrderStatus, StoreResponse } from '@/types/api' +import { invoices as invoicesApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { InvoiceResponse, InvoiceStatus, PaymentStatus } from '@/types/api' import { OrderViewSheet } from './order-view-sheet' -import { OrderEditStatusDialog } from './order-edit-status-dialog' const fmtDate = (v: string) => new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) @@ -18,78 +17,80 @@ const fmtDate = (v: string) => const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) -const ORDER_STATUS_VARIANT: Record = { +const INVOICE_STATUS_VARIANT: Record = { + Draft: 'secondary', + Printed: 'secondary', + Finalized: 'default', +} + +const PAYMENT_STATUS_VARIANT: Record = { Pending: 'secondary', - PartiallyFulfilled: 'secondary', - Fulfilled: 'default', - Cancelled: 'destructive', + PartiallyPaid: 'secondary', + Paid: 'default', } export function OrdersClient() { - const [data, setData] = useState([]) + const [data, setData] = useState([]) const [loading, setLoading] = useState(true) const [total, setTotal] = useState(0) + const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(20) const [viewOpen, setViewOpen] = useState(false) - const [editOpen, setEditOpen] = useState(false) - const [selectedOrder, setSelectedOrder] = useState(null) - const [storesList, setStoresList] = useState([]) + const [selectedInvoice, setSelectedInvoice] = useState(null) - const storesById = useMemo( - () => new Map(storesList.map((s) => [s.id, s.storeName])), - [storesList] - ) - - const fetchData = useCallback(async () => { + const fetchData = useCallback(async (p: number, ps: number) => { setLoading(true) try { - const items = await ordersApi.list() - setData(items) - setTotal(items.length) + const res = await invoicesApi.list({ page: p, pageSize: ps }) + setData(getPaginatedItems(res)) + setTotal(res.total) } catch (err) { - toast.add({ title: 'Failed to load orders', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to load invoices', description: getApiError(err), type: 'error' }) } finally { setLoading(false) } }, []) useEffect(() => { - fetchData() - storesApi.list({ pageSize: 200 }) - .then((res) => setStoresList(getPaginatedItems(res))) - .catch((err) => toast.add({ title: 'Failed to load stores', description: getApiError(err), type: 'error' })) - }, [fetchData]) + fetchData(page, pageSize) + }, [fetchData, page, pageSize]) - function handleView(row: OrderResponse) { - setSelectedOrder(row) + function handleView(row: InvoiceResponse) { + setSelectedInvoice(row) setViewOpen(true) } - function handleEdit(row: OrderResponse) { - setSelectedOrder(row) - setEditOpen(true) - } - - async function handleDelete(row: OrderResponse) { + async function handlePrint(row: InvoiceResponse) { try { - await ordersApi.delete(row.id) - toast.add({ title: 'Order cancelled', type: 'success' }) - fetchData() + await invoicesApi.print(row.id) + toast.add({ title: 'Invoice marked as printed', type: 'success' }) + fetchData(page, pageSize) } catch (err) { - toast.add({ title: 'Failed to cancel order', description: getApiError(err), type: 'error' }) + toast.add({ title: 'Failed to print invoice', description: getApiError(err), type: 'error' }) } } - const tableConfig = useMemo>(() => ({ + async function handleFinalize(row: InvoiceResponse) { + try { + await invoicesApi.finalize(row.id) + toast.add({ title: 'Invoice finalized', type: 'success' }) + fetchData(page, pageSize) + } catch (err) { + toast.add({ title: 'Failed to finalize invoice', description: getApiError(err), type: 'error' }) + } + } + + const tableConfig = useMemo>(() => ({ rowKey: 'id', + serverSide: true, stickyHeader: true, - emptyMessage: 'No orders found.', + emptyMessage: 'No invoices found.', pagination: { enabled: true, pageSize, pageSizeOptions: [10, 20, 50] }, columns: [ { key: 'id', - title: 'Order ID', + title: 'Invoice ID', fields: ['id'], width: 140, cellRender: (row) => ( @@ -97,22 +98,10 @@ export function OrdersClient() { ), }, { - key: 'saleId', - title: 'Sale ID', - fields: ['saleId'], - width: 140, - cellRender: (row) => ( - {truncId(row.saleId)} - ), - }, - { - key: 'storeId', + key: 'store', title: 'Store', - fields: ['storeId'], - minWidth: 160, - cellRender: (row) => ( - {storesById.get(row.storeId) ?? truncId(row.storeId)} - ), + fields: [{ key: 'storeName', primary: true }], + minWidth: 180, }, { key: 'totalAmount', @@ -127,16 +116,19 @@ export function OrdersClient() { key: 'status', title: 'Status', fields: ['status'], - width: 180, + width: 140, cellRender: (row) => ( - {row.status} + {row.status} ), }, { - key: 'orderDate', - title: 'Order Date', - fields: [{ key: 'orderDate', transform: (v) => fmtDate(v as string) }], - width: 140, + key: 'paymentStatus', + title: 'Payment', + fields: ['paymentStatus'], + width: 150, + cellRender: (row) => ( + {row.paymentStatus} + ), }, { key: 'createdAt', @@ -149,32 +141,32 @@ export function OrdersClient() { actions: () => [ { action: 'view', - label: 'View order', + label: 'View invoice', onClick: handleView, }, { - action: 'edit', - label: 'Edit status', - onClick: handleEdit, - visible: (target) => target.status !== 'Cancelled', + action: 'print', + label: 'Mark as printed', + onClick: handlePrint, + visible: (target) => target.status === 'Draft', }, { - action: 'cancel', - label: 'Delete order', - onClick: handleDelete, - visible: (target) => target.status !== 'Cancelled', + action: 'finalize', + label: 'Finalize invoice', + onClick: handleFinalize, + visible: (target) => target.status === 'Printed', }, ], }, - }), [pageSize, storesById]) + }), [pageSize]) return ( <>
-

Orders

+

Invoices

- Fulfillment status of store orders + Billing documents generated from confirmed Shop POs

@@ -185,6 +177,7 @@ export function OrdersClient() { loading={loading} totalCount={total} onServerSideChange={({ page: p }) => { + setPage(p.page) setPageSize(p.pageSize) }} /> @@ -192,15 +185,7 @@ export function OrdersClient() { setViewOpen(false)} - order={selectedOrder} - storeName={selectedOrder ? storesById.get(selectedOrder.storeId) : undefined} - /> - - setEditOpen(false)} - onSuccess={fetchData} - order={selectedOrder} + invoice={selectedInvoice} /> ) diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx index 28e945f..1d47c16 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx @@ -1,6 +1,6 @@ 'use client' -import { useEffect, useState } from 'react' +import { useEffect } from 'react' import { useForm, zodResolver, z } from '@/lib/form' import { FormField } from '@/components/shared/form-field' import { Input } from '@/components/ui/input' @@ -22,14 +22,13 @@ import { } from '@/components/ui/dialog' import { FieldGroup } from '@/components/ui/field' import { toast } from '@/components/ui/toast' -import { payments as paymentsApi, sales as salesApi, users as usersApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { SaleResponse, UserResponse } from '@/types/api' +import { payments as paymentsApi, getApiError } from '@/lib/api/index' +import type { InvoiceResponse } from '@/types/api' const schema = z.object({ - saleId: z.string().min(1, 'Sale is required'), + invoiceId: z.string().min(1, 'Invoice is required'), amount: z.number().min(0.01, 'Amount must be greater than 0'), method: z.enum(['Cash', 'Credit']), - collectedByUserId: z.string().min(1, 'Collected by is required'), }) type FormValues = z.infer @@ -38,51 +37,31 @@ interface PaymentSheetProps { open: boolean onClose: () => void onSuccess: () => void + invoices: InvoiceResponse[] } const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) -export function PaymentSheet({ open, onClose, onSuccess }: PaymentSheetProps) { - const [salesList, setSalesList] = useState([]) - const [usersList, setUsersList] = useState([]) - +export function PaymentSheet({ open, onClose, onSuccess, invoices }: PaymentSheetProps) { const form = useForm({ resolver: zodResolver(schema), defaultValues: { - saleId: '', + invoiceId: '', amount: 0, method: 'Cash', - collectedByUserId: '', }, }) useEffect(() => { if (!open) return - - form.reset({ - saleId: '', - amount: 0, - method: 'Cash', - collectedByUserId: '', - }) - - Promise.all([ - salesApi.list({ pageSize: 200 }), - usersApi.list({ pageSize: 200 }), - ]) - .then(([salesRes, usersRes]) => { - setSalesList(getPaginatedItems(salesRes).filter((s) => s.status !== 'Cancelled')) - setUsersList(getPaginatedItems(usersRes)) - }) - .catch((err) => { - toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' }) - }) + form.reset({ invoiceId: '', amount: 0, method: 'Cash' }) }, [open]) async function onSubmit(values: FormValues) { + const { invoiceId, ...rest } = values try { - await paymentsApi.create(values) + await paymentsApi.create(invoiceId, rest) toast.add({ title: 'Payment recorded', type: 'success' }) onSuccess() onClose() @@ -91,31 +70,33 @@ export function PaymentSheet({ open, onClose, onSuccess }: PaymentSheetProps) { } } + const pendingInvoices = invoices.filter((inv) => inv.paymentStatus !== 'Paid') + return ( !v && onClose()}> Record Payment - Record a cash or credit payment against a sale. + Record a cash or credit payment against an invoice.
( + )} /> - - ( - - )} - /> diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx index 1468570..2aa4a01 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx @@ -26,8 +26,7 @@ interface PaymentViewSheetProps { open: boolean onClose: () => void payment: PaymentResponse | null - storeName?: string - collectedByName?: string + invoiceName?: string } function Row({ label, value }: { label: string; value: React.ReactNode }) { @@ -39,7 +38,7 @@ function Row({ label, value }: { label: string; value: React.ReactNode }) { ) } -export function PaymentViewSheet({ open, onClose, payment, storeName, collectedByName }: PaymentViewSheetProps) { +export function PaymentViewSheet({ open, onClose, payment, invoiceName }: PaymentViewSheetProps) { if (!payment) return null return ( @@ -51,12 +50,11 @@ export function PaymentViewSheet({ open, onClose, payment, storeName, collectedB
{truncId(payment.id)}} /> - {truncId(payment.saleId)}} /> - {truncId(payment.storeId)}} /> + {truncId(payment.invoiceId)}} /> {payment.method}} /> - {truncId(payment.collectedBy)}} /> + {truncId(payment.collectedBy)}} />
diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx index 8327b16..cf1ed72 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx @@ -8,9 +8,10 @@ import { DataTable } from '@/components/shared/data-table' import type { TableConfig } from '@/components/shared/data-table' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' import { toast } from '@/components/ui/toast' -import { payments as paymentsApi, stores as storesApi, users as usersApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { PaymentResponse, PaymentMethod, StoreResponse, UserResponse } from '@/types/api' +import { invoices as invoicesApi, payments as paymentsApi, getApiError, getPaginatedItems } from '@/lib/api/index' +import type { PaymentResponse, PaymentMethod, InvoiceResponse } from '@/types/api' import { PaymentSheet } from './payment-sheet' import { PaymentViewSheet } from './payment-view-sheet' @@ -27,33 +28,39 @@ const PAYMENT_METHOD_VARIANT: Record = { } export function PaymentsClient() { + const [invoicesList, setInvoicesList] = useState([]) + const [selectedInvoiceId, setSelectedInvoiceId] = useState('') const [data, setData] = useState([]) - const [loading, setLoading] = useState(true) + const [loading, setLoading] = useState(false) const [total, setTotal] = useState(0) - const [page, setPage] = useState(1) - const [pageSize, setPageSize] = useState(20) + const [pageSize] = useState(20) const [sheetOpen, setSheetOpen] = useState(false) const [viewOpen, setViewOpen] = useState(false) const [selectedPayment, setSelectedPayment] = useState(null) - const [storesList, setStoresList] = useState([]) - const [usersList, setUsersList] = useState([]) - const storeNameById = useMemo( - () => new Map(storesList.map((s) => [s.id, s.storeName])), - [storesList] - ) - const userNameById = useMemo( - () => new Map(usersList.map((u) => [u.id, u.fullName])), - [usersList] + const invoiceNameById = useMemo( + () => new Map(invoicesList.map((inv) => [inv.id, `${inv.storeName} — ${truncId(inv.id)}`])), + [invoicesList] ) - const fetchData = useCallback(async (p: number, ps: number) => { + useEffect(() => { + invoicesApi.list({ pageSize: 200 }) + .then((res) => setInvoicesList(getPaginatedItems(res))) + .catch((err) => toast.add({ title: 'Failed to load invoices', description: getApiError(err), type: 'error' })) + }, []) + + const fetchData = useCallback(async (invoiceId: string) => { + if (!invoiceId) { + setData([]) + setTotal(0) + return + } setLoading(true) try { - const res = await paymentsApi.list({ page: p, pageSize: ps }) - setData(getPaginatedItems(res)) - setTotal(res.total) + const items = await paymentsApi.listByInvoice(invoiceId) + setData(items) + setTotal(items.length) } catch (err) { toast.add({ title: 'Failed to load payments', description: getApiError(err), type: 'error' }) } finally { @@ -62,17 +69,8 @@ export function PaymentsClient() { }, []) useEffect(() => { - fetchData(page, pageSize) - }, [fetchData, page, pageSize]) - - useEffect(() => { - storesApi.list({ pageSize: 200 }) - .then((res) => setStoresList(getPaginatedItems(res))) - .catch((err) => toast.add({ title: 'Failed to load stores', description: getApiError(err), type: 'error' })) - usersApi.list({ pageSize: 200 }) - .then((res) => setUsersList(getPaginatedItems(res))) - .catch((err) => toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' })) - }, []) + fetchData(selectedInvoiceId) + }, [fetchData, selectedInvoiceId]) function handleView(row: PaymentResponse) { setSelectedPayment(row) @@ -81,9 +79,8 @@ export function PaymentsClient() { const tableConfig = useMemo>(() => ({ rowKey: 'id', - serverSide: true, stickyHeader: true, - emptyMessage: 'No payments found.', + emptyMessage: selectedInvoiceId ? 'No payments found for this invoice.' : 'Enter an invoice ID to view its payments.', pagination: { enabled: true, pageSize, pageSizeOptions: [10, 20, 50] }, columns: [ { @@ -96,12 +93,12 @@ export function PaymentsClient() { ), }, { - key: 'storeId', - title: 'Store', - fields: ['storeId'], - minWidth: 160, + key: 'invoiceId', + title: 'Invoice', + fields: ['invoiceId'], + minWidth: 180, cellRender: (row) => ( - {storeNameById.get(row.storeId) ?? truncId(row.storeId)} + {invoiceNameById.get(row.invoiceId) ?? truncId(row.invoiceId)} ), }, { @@ -128,15 +125,6 @@ export function PaymentsClient() { fields: [{ key: 'collectedAt', transform: (v) => fmtDate(v as string) }], width: 140, }, - { - key: 'collectedBy', - title: 'Collected By', - fields: ['collectedBy'], - minWidth: 160, - cellRender: (row) => ( - {userNameById.get(row.collectedBy) ?? truncId(row.collectedBy)} - ), - }, ], rowActions: { actions: () => [ @@ -147,7 +135,7 @@ export function PaymentsClient() { }, ], }, - }), [pageSize, storeNameById, userNameById]) + }), [pageSize, invoiceNameById]) return ( <> @@ -155,7 +143,7 @@ export function PaymentsClient() {

Payments

- Cash and credit payments collected from stores + Cash and credit payments collected against invoices

+
+ setSelectedInvoiceId(e.target.value.trim())} + /> + {selectedInvoiceId && ( + + )} +
+ { - setPage(p.page) - setPageSize(p.pageSize) - }} /> setSheetOpen(false)} - onSuccess={() => fetchData(page, pageSize)} + onSuccess={() => fetchData(selectedInvoiceId)} + invoices={invoicesList} /> setViewOpen(false)} payment={selectedPayment} - storeName={selectedPayment ? storeNameById.get(selectedPayment.storeId) : undefined} - collectedByName={selectedPayment ? userNameById.get(selectedPayment.collectedBy) : undefined} + invoiceName={selectedPayment ? invoiceNameById.get(selectedPayment.invoiceId) : undefined} /> ) diff --git a/distribution_fe/app/(dashboard)/stores/_components/store-sheet.tsx b/distribution_fe/app/(dashboard)/stores/_components/store-sheet.tsx index 467aeaf..420b278 100644 --- a/distribution_fe/app/(dashboard)/stores/_components/store-sheet.tsx +++ b/distribution_fe/app/(dashboard)/stores/_components/store-sheet.tsx @@ -50,7 +50,7 @@ type FormValues = z.infer interface StoreSheetProps { open: boolean onClose: () => void - store: StoreResponse + store: StoreResponse | null onSuccess: () => void } @@ -81,7 +81,7 @@ export function StoreSheet({ open, onClose, store, onSuccess }: StoreSheetProps) toast.add({ title: 'Failed to load routes', description: getApiError(err), type: 'error' }) ) - form.reset({ + if (store) form.reset({ storeName: store.storeName, ownerName: store.ownerName, storeAddress: store.storeAddress, @@ -97,7 +97,7 @@ export function StoreSheet({ open, onClose, store, onSuccess }: StoreSheetProps) async function onSubmit(values: FormValues) { try { - await storesApi.update(store.id, { + await storesApi.update(store!.id, { ...values, segment: values.segment || undefined, }) diff --git a/distribution_fe/components/shared/data-table/types.ts b/distribution_fe/components/shared/data-table/types.ts index 47cac6c..e7e6708 100644 --- a/distribution_fe/components/shared/data-table/types.ts +++ b/distribution_fe/components/shared/data-table/types.ts @@ -10,7 +10,9 @@ export type RowActionKind = | 'deactivate' | 'confirm' | 'close' - | 'cancel'; + | 'cancel' + | 'print' + | 'finalize'; export interface BadgeConfig { colorMap?: Record; diff --git a/distribution_fe/components/shared/row-actions.tsx b/distribution_fe/components/shared/row-actions.tsx index 01037d9..05b6487 100644 --- a/distribution_fe/components/shared/row-actions.tsx +++ b/distribution_fe/components/shared/row-actions.tsx @@ -5,9 +5,11 @@ import { HugeiconsIcon } from "@hugeicons/react" import { Cancel01Icon, CheckmarkCircle02Icon, + CheckmarkSquare01Icon, Delete02Icon, EyeIcon, PencilEdit01Icon, + PrinterIcon, } from "@hugeicons/core-free-icons" import { Button } from "@/components/ui/button" @@ -20,6 +22,8 @@ const ACTION_ICONS = { confirm: CheckmarkCircle02Icon, deactivate: Cancel01Icon, edit: PencilEdit01Icon, + finalize: CheckmarkSquare01Icon, + print: PrinterIcon, view: EyeIcon, } as const diff --git a/distribution_fe/config/nav.ts b/distribution_fe/config/nav.ts index 315219c..fa863d2 100644 --- a/distribution_fe/config/nav.ts +++ b/distribution_fe/config/nav.ts @@ -60,12 +60,12 @@ export const NAV_GROUPS: NavGroup[] = [ ], }, { - title: 'Sales & Orders', + title: 'Shop POs & Invoices', icon: DollarSquareIcon, items: [ - { title: 'Sales', href: '/sales', icon: DollarSquareIcon, description: 'Sales transactions recorded against stores', permission: 'orders.view' }, - { title: 'Orders', href: '/sales/orders', icon: ClipboardListIcon, description: 'Fulfillment status of store orders', permission: 'orders.view' }, - { title: 'Payments', href: '/sales/payments', icon: BankIcon, description: 'Cash and credit payments collected from stores', permission: 'orders.view' }, + { title: 'Shop POs', href: '/sales', icon: ClipboardListIcon, description: 'Purchase orders raised by sales agents on behalf of stores', permission: 'orders.view' }, + { title: 'Invoices', href: '/sales/orders', icon: DollarSquareIcon, description: 'Billing documents generated from confirmed Shop POs', permission: 'orders.view' }, + { title: 'Payments', href: '/sales/payments', icon: BankIcon, description: 'Cash and credit payments collected against invoices', permission: 'orders.view' }, ], }, { @@ -161,6 +161,6 @@ export const BOTTOM_NAV_CANDIDATES: NavItem[] = [ { title: 'Stores', href: '/stores', icon: Store01Icon, permission: 'stores.view' }, { title: 'Rides', href: '/operations/rides', icon: TruckIcon, permission: 'rides.view' }, { title: 'Loading', href: '/operations/loading', icon: DeliveryBox01Icon, permission: 'loading.view' }, - { title: 'Sales', href: '/sales', icon: DollarSquareIcon, permission: 'orders.view' }, + { title: 'Shop POs', href: '/sales', icon: ClipboardListIcon, permission: 'orders.view' }, { title: 'Items', href: '/catalogue/items', icon: Package01Icon, permission: 'items.view' }, ] diff --git a/distribution_fe/lib/api/index.ts b/distribution_fe/lib/api/index.ts index 8b6a06b..65c81eb 100644 --- a/distribution_fe/lib/api/index.ts +++ b/distribution_fe/lib/api/index.ts @@ -8,7 +8,7 @@ export { drivers, compliance } from './drivers' export { purchaseOrders, grn, purchaseReturns } from './procurement' export { rides, loadingSheets, deliveryTasks } from './operations' export { stock } from './stock' -export { sales, orders, payments } from './sales' +export { shopPos, invoices, payments } from './sales' export { saleReturns, claims, supplierClaims } from './returns-claims' export { getPaginatedItems } from './paginated' diff --git a/distribution_fe/lib/api/operations.ts b/distribution_fe/lib/api/operations.ts index 00d6a62..7abd22f 100644 --- a/distribution_fe/lib/api/operations.ts +++ b/distribution_fe/lib/api/operations.ts @@ -2,10 +2,8 @@ import { api } from '@/lib/api' import type { PaginatedResponse, RideResponse, - CancelRequestResponse, LoadingSheetResponse, DeliveryTaskResponse, - RideType, RideStatus, CancelRequestType, LoadingSheetStatus, @@ -16,22 +14,18 @@ import type { PageParams } from './master' // ─── Rides ──────────────────────────────────────────────────────────────────── export interface RideBody { - rideType: RideType vehicleId: string driverProfileId: string - routeId: string - sourceWarehouseId: string meterstart: number } export interface RideListParams extends PageParams { status?: RideStatus - rideType?: RideType driverProfileId?: string vehicleId?: string } -export interface CancelRequestBody { +export interface CancelRideBody { typeCode: CancelRequestType reason: string } @@ -49,43 +43,24 @@ export const rides = { assignDriver: (id: string, driverProfileId: string) => api.put(`/rides/${id}/driver`, { driverProfileId }).then(r => r.data), - activate: (id: string) => - api.patch(`/rides/${id}/activate`).then(r => r.data), - close: (id: string, meterend: number) => - api.patch(`/rides/${id}/close`, { meterend }).then(r => r.data), + api.post(`/rides/${id}/close`, { meterend }).then(r => r.data), - cancelRequests: { - getForRide: (rideId: string) => - api.get(`/rides/${rideId}/cancel-request`).then(r => r.data), - - raise: (rideId: string, body: CancelRequestBody) => - api.post(`/rides/${rideId}/cancel-request`, body).then(r => r.data), - - approve: (requestId: string) => - api.post(`/rides/cancel-requests/${requestId}/approve`).then(r => r.data), - - reject: (requestId: string) => - api.post(`/rides/cancel-requests/${requestId}/reject`).then(r => r.data), - }, + cancel: (id: string, body: CancelRideBody) => + api.post(`/rides/${id}/cancel`, body).then(r => r.data), } // ─── Loading Sheets ─────────────────────────────────────────────────────────── -export interface LoadingSheetItemBody { - itemId: string - quantityDispatched: number +export interface LoadingSheetCreateBody { + fK_RideId: string } -export interface LoadingSheetBody { - rideId: string - sourceWarehouseId: string - items: LoadingSheetItemBody[] -} - -export interface LoadingSheetReceiptItemBody { - itemId: string - quantityReceived: number +export interface LoadingSheetItemInput { + fK_ItemId: string + fK_WarehouseId: string + quantity: number + fK_ShopPOItemId?: string | null } export interface LoadingSheetListParams extends PageParams { @@ -100,17 +75,14 @@ export const loadingSheets = { get: (id: string) => api.get(`/loading-sheets/${id}`).then(r => r.data), - create: (body: LoadingSheetBody) => + create: (body: LoadingSheetCreateBody) => api.post('/loading-sheets', body).then(r => r.data), - confirmDispatch: (id: string) => - api.patch(`/loading-sheets/${id}/dispatch`).then(r => r.data), + updateItems: (id: string, items: LoadingSheetItemInput[]) => + api.put(`/loading-sheets/${id}/items`, { items }).then(r => r.data), - confirmReceipt: (id: string, items: LoadingSheetReceiptItemBody[]) => - api.patch(`/loading-sheets/${id}/receipt`, { items }).then(r => r.data), - - resolve: (id: string) => - api.patch(`/loading-sheets/${id}/resolve`).then(r => r.data), + confirm: (id: string) => + api.post(`/loading-sheets/${id}/confirm`).then(r => r.data), } // ─── Delivery Tasks ─────────────────────────────────────────────────────────── @@ -121,11 +93,8 @@ export interface DeliveryTaskItemQuantity { } export const deliveryTasks = { - generate: (rideId: string) => - api.post(`/rides/${rideId}/tasks/generate`).then(r => r.data), - listByRide: (rideId: string) => - api.get(`/rides/${rideId}/delivery-tasks`).then(r => r.data), + api.get(`/rides/${rideId}/tasks`).then(r => r.data), get: (id: string) => api.get(`/delivery-tasks/${id}`).then(r => r.data), diff --git a/distribution_fe/lib/api/returns-claims.ts b/distribution_fe/lib/api/returns-claims.ts index f7cea52..bd558af 100644 --- a/distribution_fe/lib/api/returns-claims.ts +++ b/distribution_fe/lib/api/returns-claims.ts @@ -35,11 +35,11 @@ export const saleReturns = { get: (id: string) => api.get(`/returns/${id}`).then(r => r.data), - listByOrder: (orderId: string) => - api.get(`/orders/${orderId}/returns`).then(r => r.data), + listByShopPO: (shopPOId: string) => + api.get(`/shop-pos/${shopPOId}/returns`).then(r => r.data), - create: (orderId: string, body: SaleReturnBody) => - api.post(`/orders/${orderId}/returns`, body).then(r => r.data), + create: (shopPOId: string, body: SaleReturnBody) => + api.post(`/shop-pos/${shopPOId}/returns`, body).then(r => r.data), updateReasons: (id: string, body: UpdateSaleReturnReasonsBody) => api.patch(`/returns/${id}/reasons`, body).then(r => r.data), diff --git a/distribution_fe/lib/api/sales.ts b/distribution_fe/lib/api/sales.ts index 026e920..7d0c280 100644 --- a/distribution_fe/lib/api/sales.ts +++ b/distribution_fe/lib/api/sales.ts @@ -1,101 +1,99 @@ import { api } from '@/lib/api' import type { PaginatedResponse, - SaleResponse, - OrderResponse, - OrderStatus, + ShopPOResponse, + InvoiceResponse, + InvoiceStatus, PaymentResponse, - SaleStatus, - PaymentStatus, PaymentMethod, + ShopPOStatus, } from '@/types/api' import type { PageParams } from './master' -// ─── Sales ──────────────────────────────────────────────────────────────────── +// ─── Shop POs ───────────────────────────────────────────────────────────────── -export interface SaleItemBody { +export interface ShopPOItemBody { itemId: string quantity: number - unitPrice: number + unitPrice?: number | null } -export interface SaleBody { +export interface CreateShopPOBody { storeId: string - saleDate: string - rideId?: string | null - fulfillImmediately?: boolean - items: SaleItemBody[] - // TEMPORARY: required while auth doesn't resolve a logged-in user server-side — see testbug.md #28. - createdByUserId: string + items: ShopPOItemBody[] } -export interface SaleListParams extends PageParams { - storeId?: string - status?: SaleStatus - paymentStatus?: PaymentStatus - rideId?: string - from?: string - to?: string +export interface UpdateShopPOItemsBody { + items: ShopPOItemBody[] } -export const sales = { - list: (params?: SaleListParams) => - api.get>('/sales', { params }).then(r => r.data), +export interface ShopPOListParams extends PageParams { + agentId?: string + routeId?: string + shopId?: string + confirmed?: boolean + status?: ShopPOStatus +} + +export const shopPos = { + list: (params?: ShopPOListParams) => + api.get>('/shop-pos', { params }).then(r => r.data), get: (id: string) => - api.get(`/sales/${id}`).then(r => r.data), + api.get(`/shop-pos/${id}`).then(r => r.data), - create: (body: SaleBody) => - api.post('/sales', body).then(r => r.data), + create: (body: CreateShopPOBody) => + api.post('/shop-pos', body).then(r => r.data), + + updateItems: (id: string, body: UpdateShopPOItemsBody) => + api.put(`/shop-pos/${id}/items`, body).then(r => r.data), + + confirm: (id: string) => + api.post(`/shop-pos/${id}/confirm`).then(r => r.data), + + confirmAndCreateInvoice: (id: string) => + api.post(`/shop-pos/${id}/confirm-and-create-invoice`).then(r => r.data), cancel: (id: string) => - api.patch(`/sales/${id}/cancel`).then(r => r.data), + api.post(`/shop-pos/${id}/cancel`).then(r => r.data), } -// ─── Orders ─────────────────────────────────────────────────────────────────── -// GET /orders takes no query params and returns a plain array — no server-side -// filtering/pagination exists on the backend, unlike Sales/Payments. +// ─── Invoices ───────────────────────────────────────────────────────────────── -export const orders = { - list: () => - api.get('/orders').then(r => r.data), +export interface InvoiceListParams extends PageParams { + agentId?: string + routeId?: string + shopId?: string + status?: InvoiceStatus +} + +export const invoices = { + list: (params?: InvoiceListParams) => + api.get>('/invoices', { params }).then(r => r.data), get: (id: string) => - api.get(`/orders/${id}`).then(r => r.data), + api.get(`/invoices/${id}`).then(r => r.data), - update: (id: string, status: OrderStatus) => - api.put(`/orders/${id}`, { status }).then(r => r.data), + print: (id: string) => + api.post(`/invoices/${id}/print`).then(r => r.data), - delete: (id: string) => - api.delete(`/orders/${id}`), + finalize: (id: string) => + api.post(`/invoices/${id}/finalize`).then(r => r.data), } // ─── Payments ───────────────────────────────────────────────────────────────── export interface PaymentBody { - saleId: string amount: number method: PaymentMethod - // TEMPORARY: required while auth doesn't resolve a logged-in user server-side — see testbug.md #28. - collectedByUserId: string -} - -export interface PaymentListParams extends PageParams { - storeId?: string - saleId?: string - method?: PaymentMethod - from?: string - to?: string + collectedByUserId?: string | null } export const payments = { - list: (params?: PaymentListParams) => - api.get>('/payments', { params }).then(r => r.data), + listByInvoice: (invoiceId: string) => + api.get(`/invoices/${invoiceId}/payments`).then(r => r.data), - get: (id: string) => - api.get(`/payments/${id}`).then(r => r.data), - - create: (body: PaymentBody) => - api.post('/payments', body).then(r => r.data), + create: (invoiceId: string, body: PaymentBody) => + api.post(`/invoices/${invoiceId}/payments`, body).then(r => r.data), } diff --git a/distribution_fe/types/api.ts b/distribution_fe/types/api.ts index 5f00b9e..d8f799a 100644 --- a/distribution_fe/types/api.ts +++ b/distribution_fe/types/api.ts @@ -5,19 +5,15 @@ export type LocationType = 'Warehouse' | 'Vehicle' | 'External' export type MovementType = | 'Sale' | 'CustomerReturn' | 'Transfer' | 'Damage' | 'Adjustment' | 'Load' | 'PurchaseReceipt' | 'PurchaseReturn' -export type LoadingSheetStatus = - | 'Pending' | 'DispatchConfirmed' | 'ReceiptConfirmed' - | 'DiscrepancyFlagged' | 'Resolved' -export type RideType = 'Delivery' | 'Sale' -export type RideStatus = - | 'Draft' | 'Open' | 'Active' | 'CancelRequested' | 'Cancelled' | 'Closed' +export type LoadingSheetStatus = 'Planned' | 'Confirmed' +export type RideStatus = 'Open' | 'Cancelled' | 'Closed' export type CancelRequestType = | 'VehicleBreakdown' | 'DriverUnavailable' | 'RouteIssue' | 'Other' -export type CancelRequestStatus = 'Pending' | 'Approved' | 'Rejected' export type PurchaseOrderStatus = | 'Issued' | 'PartiallyReceived' | 'Received' | 'Closed' | 'Cancelled' -export type SaleStatus = 'Pending' | 'Completed' | 'Cancelled' -export type OrderStatus = 'Pending' | 'PartiallyFulfilled' | 'Fulfilled' | 'Cancelled' +export type ShopPOStatus = 'Pending' | 'PartiallyFulfilled' | 'Fulfilled' | 'Cancelled' +export type InvoiceStatus = 'Draft' | 'Printed' | 'Finalized' +export type InvoiceCreationMode = 'ModeA' | 'ModeB' export type PaymentStatus = 'Pending' | 'PartiallyPaid' | 'Paid' export type PaymentMethod = 'Cash' | 'Credit' export type DeliveryTaskStatus = 'Pending' | 'Delivered' | 'PartiallyDelivered' | 'Failed' @@ -457,7 +453,7 @@ export interface SaleReturnItemResponse { export interface SaleReturnResponse { id: string - orderId: string + shopPOId: string mode: ReturnMode totalCreditAmount: number orderTotalAmountAfter: number @@ -555,59 +551,45 @@ export interface DriverComplianceConfigResponse { export interface RideResponse { id: string - rideType: RideType status: RideStatus vehicleId: string vehicleNumberPlate: string driverProfileId: string driverFullName: string - routeId: string - routeName: string - sourceWarehouseId: string - sourceWarehouseName: string meterstart: number meterend: number startedAt: string | null - activatedAt: string | null closedAt: string | null createdAt: string } -export interface CancelRequestResponse { - id: string - rideId: string - typeCode: CancelRequestType - reason: string - requestedBy: string - requestedAt: string - status: CancelRequestStatus - approvedBy: string | null - approvedAt: string | null -} - // ─── Loading Sheets ─────────────────────────────────────────────────────────── export interface LoadingSheetItemResponse { id: string fK_ItemId: string itemName: string + fK_WarehouseId: string + warehouseName: string quantityDispatched: number - quantityReceived: number - quantityResolved: number + fK_ShopPOItemId: string | null +} + +export interface LoadingSheetOrderRef { + shopPOId: string } export interface LoadingSheetResponse { id: string fK_RideId: string - fK_SourceWarehouseId: string - warehouseName: string status: LoadingSheetStatus - dispatchConfirmedAt: string | null - dispatchConfirmedBy: string | null - receiptConfirmedAt: string | null - receiptConfirmedBy: string | null + populatedBy: string + populatedAt: string + confirmedAt: string | null + confirmedBy: string | null createdAt: string items: LoadingSheetItemResponse[] + orders: LoadingSheetOrderRef[] } // ─── Delivery Tasks ─────────────────────────────────────────────────────────── @@ -623,7 +605,7 @@ export interface DeliveryTaskItemResponse { export interface DeliveryTaskResponse { id: string fK_RideId: string - fK_OrderId: string + fK_ShopPOId: string storeId: string storeName: string sequence: number @@ -635,58 +617,53 @@ export interface DeliveryTaskResponse { createdAt: string } -// ─── Sales / Orders / Payments ──────────────────────────────────────────────── +// ─── ShopPO / Invoice / Payment ─────────────────────────────────────────────── -export interface SaleItemResponse { +export interface ShopPOItemResponse { + id: string itemId: string + itemName: string quantity: number quantityFulfilled: number unitPrice: number + isActive: boolean } -export interface SaleResponse { +export interface ShopPOResponse { id: string - saleDate: string storeId: string - createdByUserId: string - rideId: string | null + storeName: string + raisedById: string + invoiceId: string | null totalAmount: number - status: SaleStatus - paymentStatus: PaymentStatus - fulfillImmediately: boolean - completedAt: string | null - orderId: string - orderStatus: OrderStatus - orderFulfilledAt: string | null - items: SaleItemResponse[] + status: ShopPOStatus + confirmedAt: string | null + confirmedBy: string | null + fulfilledAt: string | null + items: ShopPOItemResponse[] isActive: boolean createdAt: string } -export interface OrderItemResponse { - itemId: string - quantity: number - quantityFulfilled: number - unitPrice: number -} - -export interface OrderResponse { +export interface InvoiceResponse { id: string - saleId: string - orderDate: string - storeId: string + shopPOId: string + storeName: string + status: InvoiceStatus + paymentStatus: PaymentStatus + createdBy: string + printedAt: string | null + printedBy: string | null + finalizedAt: string | null + finalizedBy: string | null totalAmount: number - status: OrderStatus - fulfilledAt: string | null - items: OrderItemResponse[] isActive: boolean createdAt: string } export interface PaymentResponse { id: string - saleId: string - storeId: string + invoiceId: string amount: number method: PaymentMethod collectedAt: string @@ -694,6 +671,13 @@ export interface PaymentResponse { createdAt: string } +export interface SysConfigResponse { + key: string + value: string + updatedAt: string + updatedBy: string | null +} + // ─── API Error ──────────────────────────────────────────────────────────────── export interface ApiError { From e2cec66d6b35b91e0e1f924c13dfc31aaafe8ca7 Mon Sep 17 00:00:00 2001 From: DeepnaPooja Date: Thu, 17 Sep 2026 14:37:56 +0530 Subject: [PATCH 03/11] remove the ride cancel request --- Distribution/Data/AppDBContext.cs | 1 - .../Data/Seed/OperationsExtrasSeed.cs | 17 - .../Ride/IRideCancelRequestRepository.cs | 14 - .../Ride/RideCancelRequestRepository.cs | 39 - ...090213_RemoveRideCancelRequest.Designer.cs | 3992 +++++++++++++++++ .../20260917090213_RemoveRideCancelRequest.cs | 59 + .../Migrations/AppDBContextModelSnapshot.cs | 63 - Distribution/Models/Enums.cs | 2 - Distribution/Models/RideCancelRequest.cs | 23 - 9 files changed, 4051 insertions(+), 159 deletions(-) delete mode 100644 Distribution/Features/Ride/IRideCancelRequestRepository.cs delete mode 100644 Distribution/Features/Ride/RideCancelRequestRepository.cs create mode 100644 Distribution/Migrations/20260917090213_RemoveRideCancelRequest.Designer.cs create mode 100644 Distribution/Migrations/20260917090213_RemoveRideCancelRequest.cs delete mode 100644 Distribution/Models/RideCancelRequest.cs diff --git a/Distribution/Data/AppDBContext.cs b/Distribution/Data/AppDBContext.cs index d7130b8..0393a15 100644 --- a/Distribution/Data/AppDBContext.cs +++ b/Distribution/Data/AppDBContext.cs @@ -37,7 +37,6 @@ public class AppDBContext(DbContextOptions options) : DbContext(op public DbSet Suppliers { get; set; } public DbSet DriverProfiles { get; set; } public DbSet DriverComplianceConfigs { get; set; } - public DbSet RideCancelRequests { get; set; } public DbSet Schemes { get; set; } public DbSet SchemeRedemptions { get; set; } public DbSet SchemeBundleComponents { get; set; } diff --git a/Distribution/Data/Seed/OperationsExtrasSeed.cs b/Distribution/Data/Seed/OperationsExtrasSeed.cs index 6ff35a8..db3f318 100644 --- a/Distribution/Data/Seed/OperationsExtrasSeed.cs +++ b/Distribution/Data/Seed/OperationsExtrasSeed.cs @@ -32,8 +32,6 @@ public static class OperationsExtrasSeed private static readonly Guid DriverComplianceConfig1Id = new("64000000-0000-0000-0000-000000000001"); - private static readonly Guid RideCancelRequest1Id = new("65000000-0000-0000-0000-000000000001"); - private static readonly Guid RouteVisitLog1Id = new("66000000-0000-0000-0000-000000000001"); private static readonly Guid RouteVisitLog2Id = new("66000000-0000-0000-0000-000000000002"); @@ -95,21 +93,6 @@ public static class OperationsExtrasSeed new DriverComplianceConfig { Id = DriverComplianceConfig1Id, EnforceLicenseExpiry = true, EnforceMedicalClearance = true, UpdatedAt = new DateTime(2026, 8, 20), UpdatedBy = MasterDataSeed.Supervisor1UserId } ); - modelBuilder.Entity().HasData( - new RideCancelRequest - { - Id = RideCancelRequest1Id, - FK_RideId = OperationsDataSeed.ActiveDeliveryRunId, - TypeCode = CancelRequestType.VehicleBreakdown, - Reason = "Reported minor engine issue, resolved after inspection", - RequestedBy = MasterDataSeed.Driver2UserId, - RequestedAt = new DateTime(2026, 8, 30, 9, 10, 0), - Status = CancelRequestStatus.Rejected, - ApprovedBy = MasterDataSeed.Supervisor1UserId, - ApprovedAt = new DateTime(2026, 8, 30, 9, 15, 0) - } - ); - modelBuilder.Entity().HasData( new RouteVisitLog { Id = RouteVisitLog1Id, FK_RouteId = MasterDataSeed.ColomboRouteId, FK_StoreId = MasterDataSeed.FortStoreId, FK_UserId = MasterDataSeed.SalesRep1UserId, CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0), CheckInLatitude = 6.9344m, CheckInLongitude = 79.8428m, IsDeviationFlagged = false, CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0), CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, new RouteVisitLog { Id = RouteVisitLog2Id, FK_RouteId = MasterDataSeed.ColomboRouteId, FK_StoreId = MasterDataSeed.DehiwalaStoreId, FK_UserId = MasterDataSeed.SalesRep1UserId, CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0), CheckInLatitude = 6.9000m, CheckInLongitude = 79.8654m, IsDeviationFlagged = true, CheckOutAt = null, CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0), IsActive = true } diff --git a/Distribution/Features/Ride/IRideCancelRequestRepository.cs b/Distribution/Features/Ride/IRideCancelRequestRepository.cs deleted file mode 100644 index bcd140b..0000000 --- a/Distribution/Features/Ride/IRideCancelRequestRepository.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Distribution.Models; - -namespace Distribution.Features.Ride; - -public interface IRideCancelRequestRepository -{ - Task GetByIdAsync(Guid id); - Task GetByRideIdAsync(Guid rideId); - Task GetPendingByRideIdAsync(Guid rideId); - Task> GetAllAsync(CancelRequestStatus? status, int page, int pageSize); - Task GetCountAsync(CancelRequestStatus? status); - Task AddAsync(RideCancelRequest request); - void Update(RideCancelRequest request); -} diff --git a/Distribution/Features/Ride/RideCancelRequestRepository.cs b/Distribution/Features/Ride/RideCancelRequestRepository.cs deleted file mode 100644 index c9bf85e..0000000 --- a/Distribution/Features/Ride/RideCancelRequestRepository.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Distribution.Data; -using Distribution.Models; -using Microsoft.EntityFrameworkCore; - -namespace Distribution.Features.Ride; - -public class RideCancelRequestRepository(AppDBContext context) : IRideCancelRequestRepository -{ - public async Task GetByIdAsync(Guid id) => - await context.RideCancelRequests.FirstOrDefaultAsync(r => r.Id == id); - - public async Task GetByRideIdAsync(Guid rideId) => - await context.RideCancelRequests - .Where(r => r.FK_RideId == rideId) - .OrderByDescending(r => r.RequestedAt) - .FirstOrDefaultAsync(); - - public async Task GetPendingByRideIdAsync(Guid rideId) => - await context.RideCancelRequests - .FirstOrDefaultAsync(r => r.FK_RideId == rideId && r.Status == CancelRequestStatus.Pending); - - public async Task> GetAllAsync(CancelRequestStatus? status, int page, int pageSize) => - await context.RideCancelRequests - .Where(r => status == null || r.Status == status) - .OrderByDescending(r => r.RequestedAt) - .Skip((page - 1) * pageSize) - .Take(pageSize) - .ToListAsync(); - - public async Task GetCountAsync(CancelRequestStatus? status) => - await context.RideCancelRequests - .CountAsync(r => status == null || r.Status == status); - - public async Task AddAsync(RideCancelRequest request) => - await context.RideCancelRequests.AddAsync(request); - - public void Update(RideCancelRequest request) => - context.RideCancelRequests.Update(request); -} diff --git a/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.Designer.cs b/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.Designer.cs new file mode 100644 index 0000000..6d83405 --- /dev/null +++ b/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.Designer.cs @@ -0,0 +1,3992 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917090213_RemoveRideCancelRequest")] + partial class RemoveRideCancelRequest + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.cs b/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.cs new file mode 100644 index 0000000..54a5100 --- /dev/null +++ b/Distribution/Migrations/20260917090213_RemoveRideCancelRequest.cs @@ -0,0 +1,59 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Distribution.Migrations +{ + /// + public partial class RemoveRideCancelRequest : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "RideCancelRequests"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "RideCancelRequests", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + FK_RideId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ApprovedAt = table.Column(type: "datetime(6)", nullable: true), + ApprovedBy = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Reason = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + RequestedAt = table.Column(type: "datetime(6)", nullable: false), + RequestedBy = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Status = table.Column(type: "int", nullable: false), + TypeCode = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RideCancelRequests", x => x.Id); + table.ForeignKey( + name: "FK_RideCancelRequests_DeliveryRuns_FK_RideId", + column: x => x.FK_RideId, + principalTable: "DeliveryRuns", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.InsertData( + table: "RideCancelRequests", + columns: new[] { "Id", "ApprovedAt", "ApprovedBy", "FK_RideId", "Reason", "RequestedAt", "RequestedBy", "Status", "TypeCode" }, + values: new object[] { new Guid("65000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 30, 9, 15, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new Guid("31000000-0000-0000-0000-000000000002"), "Reported minor engine issue, resolved after inspection", new DateTime(2026, 8, 30, 9, 10, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000005"), 2, 0 }); + + migrationBuilder.CreateIndex( + name: "IX_RideCancelRequests_FK_RideId", + table: "RideCancelRequests", + column: "FK_RideId"); + } + } +} diff --git a/Distribution/Migrations/AppDBContextModelSnapshot.cs b/Distribution/Migrations/AppDBContextModelSnapshot.cs index e0d3129..cc0afa2 100644 --- a/Distribution/Migrations/AppDBContextModelSnapshot.cs +++ b/Distribution/Migrations/AppDBContextModelSnapshot.cs @@ -1407,58 +1407,6 @@ namespace Distribution.Migrations }); }); - modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("char(36)"); - - b.Property("ApprovedAt") - .HasColumnType("datetime(6)"); - - b.Property("ApprovedBy") - .HasColumnType("char(36)"); - - b.Property("FK_RideId") - .HasColumnType("char(36)"); - - b.Property("Reason") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RequestedAt") - .HasColumnType("datetime(6)"); - - b.Property("RequestedBy") - .HasColumnType("char(36)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("TypeCode") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("FK_RideId"); - - b.ToTable("RideCancelRequests"); - - b.HasData( - new - { - Id = new Guid("65000000-0000-0000-0000-000000000001"), - ApprovedAt = new DateTime(2026, 8, 30, 9, 15, 0, 0, DateTimeKind.Unspecified), - ApprovedBy = new Guid("29000000-0000-0000-0000-000000000001"), - FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), - Reason = "Reported minor engine issue, resolved after inspection", - RequestedAt = new DateTime(2026, 8, 30, 9, 10, 0, 0, DateTimeKind.Unspecified), - RequestedBy = new Guid("29000000-0000-0000-0000-000000000005"), - Status = 2, - TypeCode = 0 - }); - }); - modelBuilder.Entity("Distribution.Models.Role", b => { b.Property("Id") @@ -3553,17 +3501,6 @@ namespace Distribution.Migrations b.Navigation("Region"); }); - modelBuilder.Entity("Distribution.Models.RideCancelRequest", b => - { - b.HasOne("Distribution.Models.DeliveryRun", "Ride") - .WithMany() - .HasForeignKey("FK_RideId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Ride"); - }); - modelBuilder.Entity("Distribution.Models.RolePermission", b => { b.HasOne("Distribution.Models.Permission", "Permission") diff --git a/Distribution/Models/Enums.cs b/Distribution/Models/Enums.cs index e8621d2..b183fcc 100644 --- a/Distribution/Models/Enums.cs +++ b/Distribution/Models/Enums.cs @@ -14,8 +14,6 @@ namespace Distribution.Models public enum CancelRequestType { VehicleBreakdown, DriverUnavailable, RouteIssue, Other } - public enum CancelRequestStatus { Pending, Approved, Rejected } - public enum PurchaseOrderStatus { Issued, PartiallyReceived, Received, Closed, Cancelled } public enum ShopPOStatus { Pending, PartiallyFulfilled, Fulfilled, Cancelled } diff --git a/Distribution/Models/RideCancelRequest.cs b/Distribution/Models/RideCancelRequest.cs deleted file mode 100644 index 0692c83..0000000 --- a/Distribution/Models/RideCancelRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; - -namespace Distribution.Models -{ - public class RideCancelRequest - { - public Guid Id { get; set; } = Guid.NewGuid(); - - public Guid FK_RideId { get; set; } - [ForeignKey("FK_RideId")] - public DeliveryRun Ride { get; set; } - - public CancelRequestType TypeCode { get; set; } - public string Reason { get; set; } - - public Guid RequestedBy { get; set; } - public DateTime RequestedAt { get; set; } = DateTime.Now; - - public CancelRequestStatus Status { get; set; } = CancelRequestStatus.Pending; - public Guid? ApprovedBy { get; set; } - public DateTime? ApprovedAt { get; set; } - } -} From e132e29c820aea93fbc59830b39e9e2c19c3b718 Mon Sep 17 00:00:00 2001 From: DeepnaPooja Date: Fri, 18 Sep 2026 11:43:43 +0530 Subject: [PATCH 04/11] Add cheque and entry mode details to payments --- Distribution/Features/Payment/PaymentDTOs.cs | 7 +++++++ .../Features/Payment/PaymentService.cs | 19 ++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Distribution/Features/Payment/PaymentDTOs.cs b/Distribution/Features/Payment/PaymentDTOs.cs index 20b886f..1a9eb55 100644 --- a/Distribution/Features/Payment/PaymentDTOs.cs +++ b/Distribution/Features/Payment/PaymentDTOs.cs @@ -5,6 +5,9 @@ namespace Distribution.Features.Payment; public record CreatePaymentRequest( decimal Amount, PaymentMethod Method, + EntryMode EntryMode = EntryMode.RealTime, + string? ChequeNumber = null, + DateTime? ChequeDate = null, Guid? CollectedByUserId = null); public record PaymentResponse( @@ -12,6 +15,10 @@ public record PaymentResponse( Guid InvoiceId, decimal Amount, PaymentMethod Method, + EntryMode EntryMode, + string? ChequeNumber, + DateTime? ChequeDate, DateTime CollectedAt, Guid CollectedBy, + Guid? RecordedBy, DateTime CreatedAt); diff --git a/Distribution/Features/Payment/PaymentService.cs b/Distribution/Features/Payment/PaymentService.cs index 43a9e5d..f20e7b0 100644 --- a/Distribution/Features/Payment/PaymentService.cs +++ b/Distribution/Features/Payment/PaymentService.cs @@ -12,7 +12,8 @@ public class PaymentService( ICurrentUserService currentUser) { private static PaymentResponse ToResponse(Models.Payment p) => - new(p.Id, p.FK_InvoiceId, p.Amount, p.Method, p.CollectedAt, p.CollectedBy, p.CreatedAt); + new(p.Id, p.FK_InvoiceId, p.Amount, p.Method, p.EntryMode, p.ChequeNumber, p.ChequeDate, + p.CollectedAt, p.CollectedBy, p.RecordedBy, p.CreatedAt); public async Task?> GetByInvoiceIdAsync(Guid invoiceId) { @@ -30,16 +31,28 @@ public class PaymentService( if (invoice.Status == InvoiceStatus.Finalized) throw new InvalidOperationException("Cannot record a payment against a finalized invoice"); - var userId = currentUser.UserId ?? request.CollectedByUserId + if (request.Method == PaymentMethod.Cheque && + (string.IsNullOrWhiteSpace(request.ChequeNumber) || request.ChequeDate is null)) + throw new InvalidOperationException("ChequeNumber and ChequeDate are required when Method is Cheque"); + + var recorderId = currentUser.UserId ?? request.CollectedByUserId ?? throw new InvalidOperationException("CollectedByUserId is required while auth is unavailable"); + var collectedBy = request.CollectedByUserId ?? recorderId; + var recordedBy = request.EntryMode == EntryMode.DayEndManual && collectedBy != recorderId + ? recorderId + : (Guid?)null; var payment = new Models.Payment { FK_InvoiceId = invoiceId, Amount = request.Amount, Method = request.Method, + EntryMode = request.EntryMode, + ChequeNumber = request.Method == PaymentMethod.Cheque ? request.ChequeNumber : null, + ChequeDate = request.Method == PaymentMethod.Cheque ? request.ChequeDate : null, CollectedAt = DateTime.Now, - CollectedBy = userId + CollectedBy = collectedBy, + RecordedBy = recordedBy }; await uow.BeginAsync(ct); From 63e7ddba8272063cab93f074cb335d22f5c7e8f6 Mon Sep 17 00:00:00 2001 From: DeepnaPooja Date: Fri, 18 Sep 2026 11:45:30 +0530 Subject: [PATCH 05/11] Add payment cheque fields and seed invoice payments --- Distribution/Data/Seed/CommerceSeed.cs | 8 +- Distribution/Data/Seed/OperationsDataSeed.cs | 35 +- ...5_AddPaymentChequeAndEntryMode.Designer.cs | 4005 ++++++++++++++++ ...0917094455_AddPaymentChequeAndEntryMode.cs | 69 + ...05_SeedInvoice2AndMorePayments.Designer.cs | 4082 +++++++++++++++++ ...60917104905_SeedInvoice2AndMorePayments.cs | 76 + .../Migrations/AppDBContextModelSnapshot.cs | 90 + 7 files changed, 8363 insertions(+), 2 deletions(-) create mode 100644 Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.Designer.cs create mode 100644 Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.cs create mode 100644 Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.Designer.cs create mode 100644 Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.cs diff --git a/Distribution/Data/Seed/CommerceSeed.cs b/Distribution/Data/Seed/CommerceSeed.cs index b3bc233..9b2d64c 100644 --- a/Distribution/Data/Seed/CommerceSeed.cs +++ b/Distribution/Data/Seed/CommerceSeed.cs @@ -16,6 +16,9 @@ public static class CommerceSeed private static readonly Guid SchemeRedemption1Id = new("50000000-0000-0000-0000-000000000001"); private static readonly Guid Payment1Id = new("47000000-0000-0000-0000-000000000001"); + private static readonly Guid Payment2Id = new("47000000-0000-0000-0000-000000000002"); + private static readonly Guid Payment3Id = new("47000000-0000-0000-0000-000000000003"); + private static readonly Guid Payment4Id = new("47000000-0000-0000-0000-000000000004"); private static readonly Guid SaleReturn1Id = new("51000000-0000-0000-0000-000000000001"); private static readonly Guid SaleReturnItem1Id = new("52000000-0000-0000-0000-000000000001"); @@ -84,7 +87,10 @@ public static class CommerceSeed ); modelBuilder.Entity().HasData( - new Payment { Id = Payment1Id, FK_InvoiceId = OperationsDataSeed.Invoice1Id, Amount = 3000m, Method = PaymentMethod.Cash, CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0), CollectedBy = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0), IsActive = true } + new Payment { Id = Payment1Id, FK_InvoiceId = OperationsDataSeed.Invoice1Id, Amount = 3000m, Method = PaymentMethod.Cash, EntryMode = EntryMode.RealTime, CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0), CollectedBy = MasterDataSeed.SalesRep1UserId, CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0), IsActive = true }, + new Payment { Id = Payment2Id, FK_InvoiceId = OperationsDataSeed.Invoice2Id, Amount = 1000m, Method = PaymentMethod.Cash, EntryMode = EntryMode.RealTime, CollectedAt = new DateTime(2026, 8, 31, 9, 20, 0), CollectedBy = MasterDataSeed.SalesRep2UserId, CreatedAt = new DateTime(2026, 8, 31, 9, 20, 0), IsActive = true }, + new Payment { Id = Payment3Id, FK_InvoiceId = OperationsDataSeed.Invoice2Id, Amount = 800m, Method = PaymentMethod.Cheque, EntryMode = EntryMode.DayEndManual, ChequeNumber = "000456", ChequeDate = new DateTime(2026, 8, 31), CollectedAt = new DateTime(2026, 8, 31, 11, 0, 0), CollectedBy = MasterDataSeed.SalesRep2UserId, RecordedBy = MasterDataSeed.Supervisor1UserId, CreatedAt = new DateTime(2026, 8, 31, 18, 0, 0), IsActive = true }, + new Payment { Id = Payment4Id, FK_InvoiceId = OperationsDataSeed.Invoice2Id, Amount = 300m, Method = PaymentMethod.Credit, EntryMode = EntryMode.RealTime, CollectedAt = new DateTime(2026, 8, 31, 11, 5, 0), CollectedBy = MasterDataSeed.SalesRep2UserId, CreatedAt = new DateTime(2026, 8, 31, 11, 5, 0), IsActive = true } ); modelBuilder.Entity().HasData( diff --git a/Distribution/Data/Seed/OperationsDataSeed.cs b/Distribution/Data/Seed/OperationsDataSeed.cs index a0953d2..f063b2f 100644 --- a/Distribution/Data/Seed/OperationsDataSeed.cs +++ b/Distribution/Data/Seed/OperationsDataSeed.cs @@ -13,12 +13,15 @@ public static class OperationsDataSeed internal static readonly Guid ShopPO1Id = new("33000000-0000-0000-0000-000000000001"); internal static readonly Guid ShopPO2Id = new("33000000-0000-0000-0000-000000000002"); + internal static readonly Guid ShopPO3Id = new("33000000-0000-0000-0000-000000000003"); internal static readonly Guid ShopPOItem1Id = new("34000000-0000-0000-0000-000000000001"); internal static readonly Guid ShopPOItem2Id = new("34000000-0000-0000-0000-000000000002"); internal static readonly Guid ShopPOItem3Id = new("34000000-0000-0000-0000-000000000003"); + internal static readonly Guid ShopPOItem4Id = new("34000000-0000-0000-0000-000000000004"); internal static readonly Guid Invoice1Id = new("34500000-0000-0000-0000-000000000001"); + internal static readonly Guid Invoice2Id = new("34500000-0000-0000-0000-000000000002"); internal static readonly Guid LoadingSheet1Id = new("35000000-0000-0000-0000-000000000001"); @@ -86,13 +89,28 @@ public static class OperationsDataSeed FulfilledAt = null, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true + }, + new ShopPO + { + Id = ShopPO3Id, + FK_StoreId = MasterDataSeed.KandyStoreId, + RaisedById = MasterDataSeed.SalesRep2UserId, + InvoiceId = Invoice2Id, + TotalAmount = 2400m, + Status = ShopPOStatus.Fulfilled, + ConfirmedAt = new DateTime(2026, 8, 31, 8, 30, 0), + ConfirmedBy = MasterDataSeed.Supervisor1UserId, + FulfilledAt = new DateTime(2026, 8, 31, 13, 0, 0), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0), + IsActive = true } ); modelBuilder.Entity().HasData( new ShopPOItem { Id = ShopPOItem1Id, FK_ShopPOId = ShopPO1Id, FK_ItemId = MasterDataSeed.Coke500ItemId, Quantity = 30, QuantityFulfilled = 30, UnitPrice = 60m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, new ShopPOItem { Id = ShopPOItem2Id, FK_ShopPOId = ShopPO1Id, FK_ItemId = MasterDataSeed.LaysClassicItemId, Quantity = 24, QuantityFulfilled = 24, UnitPrice = 50m, CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0), IsActive = true }, - new ShopPOItem { Id = ShopPOItem3Id, FK_ShopPOId = ShopPO2Id, FK_ItemId = MasterDataSeed.Coke1500ItemId, Quantity = 10, QuantityFulfilled = 0, UnitPrice = 120m, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true } + new ShopPOItem { Id = ShopPOItem3Id, FK_ShopPOId = ShopPO2Id, FK_ItemId = MasterDataSeed.Coke1500ItemId, Quantity = 10, QuantityFulfilled = 0, UnitPrice = 120m, CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0), IsActive = true }, + new ShopPOItem { Id = ShopPOItem4Id, FK_ShopPOId = ShopPO3Id, FK_ItemId = MasterDataSeed.Coke1500ItemId, Quantity = 20, QuantityFulfilled = 20, UnitPrice = 120m, CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0), IsActive = true } ); modelBuilder.Entity().HasData( @@ -110,6 +128,21 @@ public static class OperationsDataSeed TotalAmount = 3000m, CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0), IsActive = true + }, + new Invoice + { + Id = Invoice2Id, + FK_ShopPOId = ShopPO3Id, + Status = InvoiceStatus.Printed, + PaymentStatus = PaymentStatus.PartiallyPaid, + CreatedBy = MasterDataSeed.SalesRep2UserId, + PrintedAt = new DateTime(2026, 8, 31, 9, 15, 0), + PrintedBy = MasterDataSeed.SalesRep2UserId, + FinalizedAt = null, + FinalizedBy = null, + TotalAmount = 2400m, + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0), + IsActive = true } ); diff --git a/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.Designer.cs b/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.Designer.cs new file mode 100644 index 0000000..6427823 --- /dev/null +++ b/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.Designer.cs @@ -0,0 +1,4005 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917094455_AddPaymentChequeAndEntryMode")] + partial class AddPaymentChequeAndEntryMode + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("ChequeDate") + .HasColumnType("datetime(6)"); + + b.Property("ChequeNumber") + .HasColumnType("longtext"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EntryMode") + .HasColumnType("int"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.Property("RecordedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.cs b/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.cs new file mode 100644 index 0000000..618dd61 --- /dev/null +++ b/Distribution/Migrations/20260917094455_AddPaymentChequeAndEntryMode.cs @@ -0,0 +1,69 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Distribution.Migrations +{ + /// + public partial class AddPaymentChequeAndEntryMode : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ChequeDate", + table: "Payments", + type: "datetime(6)", + nullable: true); + + migrationBuilder.AddColumn( + name: "ChequeNumber", + table: "Payments", + type: "longtext", + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "EntryMode", + table: "Payments", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "RecordedBy", + table: "Payments", + type: "char(36)", + nullable: true, + collation: "ascii_general_ci"); + + migrationBuilder.UpdateData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000001"), + columns: new[] { "ChequeDate", "ChequeNumber", "EntryMode", "RecordedBy" }, + values: new object[] { null, null, 0, null }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ChequeDate", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "ChequeNumber", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "EntryMode", + table: "Payments"); + + migrationBuilder.DropColumn( + name: "RecordedBy", + table: "Payments"); + } + } +} diff --git a/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.Designer.cs b/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.Designer.cs new file mode 100644 index 0000000..2fd6275 --- /dev/null +++ b/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.Designer.cs @@ -0,0 +1,4082 @@ +// +using System; +using Distribution.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Distribution.Migrations +{ + [DbContext(typeof(AppDBContext))] + [Migration("20260917104905_SeedInvoice2AndMorePayments")] + partial class SeedInvoice2AndMorePayments + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("Distribution.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Brands"); + + b.HasData( + new + { + Id = new Guid("21000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Coca-Cola" + }, + new + { + Id = new Guid("21000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Lays" + }); + }); + + modelBuilder.Entity("Distribution.Models.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowCustomerReturn") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Beverages" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + AllowCustomerReturn = false, + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snacks" + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("SettledAt") + .HasColumnType("datetime(6)"); + + b.Property("SettledByUserId") + .HasColumnType("char(36)"); + + b.Property("SettlementAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("SettledByUserId"); + + b.ToTable("Claims"); + + b.HasData( + new + { + Id = new Guid("53000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 27, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "Distributor margin claim for Q3 promotional shortfall", + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + IsActive = true, + SettledAt = new DateTime(2026, 8, 28, 0, 0, 0, 0, DateTimeKind.Unspecified), + SettledByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + SettlementAmount = 15000m, + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssuedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("CreditNotes"); + + b.HasData( + new + { + Id = new Guid("54000000-0000-0000-0000-000000000001"), + Amount = 300m, + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + IssuedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ClosedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_DriverProfileId") + .HasColumnType("char(36)"); + + b.Property("FK_VehicleId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Meterend") + .HasColumnType("int"); + + b.Property("Meterstart") + .HasColumnType("int"); + + b.Property("StartedAt") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_DriverProfileId"); + + b.HasIndex("FK_VehicleId"); + + b.ToTable("DeliveryRuns"); + + b.HasData( + new + { + Id = new Guid("31000000-0000-0000-0000-000000000001"), + ClosedAt = new DateTime(2026, 8, 25, 14, 0, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000001"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000001"), + IsActive = true, + Meterend = 10550, + Meterstart = 10500, + StartedAt = new DateTime(2026, 8, 25, 8, 0, 0, 0, DateTimeKind.Unspecified), + Status = 2 + }, + new + { + Id = new Guid("31000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 8, 45, 0, 0, DateTimeKind.Unspecified), + FK_DriverProfileId = new Guid("30000000-0000-0000-0000-000000000002"), + FK_VehicleId = new Guid("28000000-0000-0000-0000-000000000002"), + IsActive = true, + Meterend = 0, + Meterstart = 20300, + StartedAt = new DateTime(2026, 8, 30, 9, 0, 0, 0, DateTimeKind.Unspecified), + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CustomerConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("Sequence") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("DeliveryTasks"); + + b.HasData( + new + { + Id = new Guid("37000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 30, 10, 5, 0, 0, DateTimeKind.Unspecified), + CustomerConfirmed = false, + FK_RideId = new Guid("31000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Sequence = 1, + Status = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverComplianceConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("EnforceLicenseExpiry") + .HasColumnType("tinyint(1)"); + + b.Property("EnforceMedicalClearance") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("DriverComplianceConfigs"); + + b.HasData( + new + { + Id = new Guid("64000000-0000-0000-0000-000000000001"), + EnforceLicenseExpiry = true, + EnforceMedicalClearance = true, + UpdatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + UpdatedBy = new Guid("29000000-0000-0000-0000-000000000001") + }); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LicenseExpiry") + .HasColumnType("datetime(6)"); + + b.Property("LicenseNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("MedicalClearanceExpiry") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_UserId") + .IsUnique(); + + b.ToTable("DriverProfiles"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000004"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 6, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B1234567", + MedicalClearanceExpiry = new DateTime(2027, 1, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000005"), + IsActive = true, + LicenseExpiry = new DateTime(2027, 9, 30, 0, 0, 0, 0, DateTimeKind.Unspecified), + LicenseNumber = "B7654321", + MedicalClearanceExpiry = new DateTime(2027, 3, 31, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("FK_ReceivedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("ReceivedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("GoodsReceipts"); + + b.HasData( + new + { + Id = new Guid("43000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + FK_ReceivedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + ReceivedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AcceptedQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderItemId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RejectedQuantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderItemId"); + + b.ToTable("GoodsReceiptItems"); + + b.HasData( + new + { + Id = new Guid("44000000-0000-0000-0000-000000000001"), + AcceptedQuantity = 200, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000001"), + IsActive = true, + RejectedQuantity = 0 + }, + new + { + Id = new Guid("44000000-0000-0000-0000-000000000002"), + AcceptedQuantity = 98, + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderItemId = new Guid("42000000-0000-0000-0000-000000000002"), + IsActive = true, + RejectedQuantity = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FinalizedAt") + .HasColumnType("datetime(6)"); + + b.Property("FinalizedBy") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PaymentStatus") + .HasColumnType("int"); + + b.Property("PrintedAt") + .HasColumnType("datetime(6)"); + + b.Property("PrintedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("Invoices"); + + b.HasData( + new + { + Id = new Guid("34500000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FinalizedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FinalizedBy = new Guid("29000000-0000-0000-0000-000000000001"), + IsActive = true, + PaymentStatus = 2, + PrintedAt = new DateTime(2026, 8, 25, 8, 45, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("34500000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000003"), + IsActive = true, + PaymentStatus = 1, + PrintedAt = new DateTime(2026, 8, 31, 9, 15, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 1, + TotalAmount = 2400m + }); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CostPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("ExternalErpItemId") + .HasColumnType("int"); + + b.Property("FK_BaseUomId") + .HasColumnType("char(36)"); + + b.Property("FK_BrandId") + .HasColumnType("char(36)"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("FK_SubCategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("LastSyncedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SalePrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Sku") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SyncSource") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_BaseUomId"); + + b.HasIndex("FK_BrandId"); + + b.HasIndex("FK_CategoryId"); + + b.HasIndex("FK_SubCategoryId"); + + b.ToTable("Items"); + + b.HasData( + new + { + Id = new Guid("23000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 500ml bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 500ml", + SalePrice = 60m, + Sku = "BEV-COKE-500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Coca-Cola 1.5L bottle", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000001"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Coca-Cola 1.5L", + SalePrice = 120m, + Sku = "BEV-COKE-1500", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Classic Salted 52g pack", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Classic 52g", + SalePrice = 50m, + Sku = "SNK-LAYS-52", + SyncSource = 0 + }, + new + { + Id = new Guid("23000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Description = "Lays Family Pack 150g", + FK_BaseUomId = new Guid("22000000-0000-0000-0000-000000000001"), + FK_BrandId = new Guid("21000000-0000-0000-0000-000000000002"), + FK_CategoryId = new Guid("20000000-0000-0000-0000-000000000002"), + IsActive = true, + Name = "Lays Family Pack 150g", + SalePrice = 150m, + Sku = "SNK-LAYS-FAM", + SyncSource = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RideId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PopulatedAt") + .HasColumnType("datetime(6)"); + + b.Property("PopulatedBy") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_RideId"); + + b.ToTable("LoadingSheets"); + + b.HasData( + new + { + Id = new Guid("35000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 7, 45, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_RideId = new Guid("31000000-0000-0000-0000-000000000001"), + IsActive = true, + PopulatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + PopulatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOItemId") + .HasColumnType("char(36)"); + + b.Property("FK_WarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("QuantityDispatched") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_LoadingSheetId"); + + b.HasIndex("FK_ShopPOItemId"); + + b.HasIndex("FK_WarehouseId"); + + b.ToTable("LoadingSheetItems"); + + b.HasData( + new + { + Id = new Guid("36000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 50m + }, + new + { + Id = new Guid("36000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_LoadingSheetId = new Guid("35000000-0000-0000-0000-000000000001"), + FK_WarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + QuantityDispatched = 30m + }); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.Property("FK_LoadingSheetId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.HasKey("FK_LoadingSheetId", "FK_ShopPOId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("LoadingSheetOrders"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("ChequeDate") + .HasColumnType("datetime(6)"); + + b.Property("ChequeNumber") + .HasColumnType("longtext"); + + b.Property("CollectedAt") + .HasColumnType("datetime(6)"); + + b.Property("CollectedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EntryMode") + .HasColumnType("int"); + + b.Property("FK_InvoiceId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.Property("RecordedBy") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("FK_InvoiceId"); + + b.ToTable("Payments"); + + b.HasData( + new + { + Id = new Guid("47000000-0000-0000-0000-000000000001"), + Amount = 3000m, + CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + Method = 0 + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000002"), + Amount = 1000m, + CollectedAt = new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 0 + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000003"), + Amount = 800m, + ChequeDate = new DateTime(2026, 8, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + ChequeNumber = "000456", + CollectedAt = new DateTime(2026, 8, 31, 11, 0, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 18, 0, 0, 0, DateTimeKind.Unspecified), + EntryMode = 1, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 1, + RecordedBy = new Guid("29000000-0000-0000-0000-000000000001") + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000004"), + Amount = 300m, + CollectedAt = new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveFrom") + .HasColumnType("datetime(6)"); + + b.Property("EffectiveTo") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("PriceLists"); + + b.HasData( + new + { + Id = new Guid("39000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveFrom = new DateTime(2026, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + EffectiveTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Name = "Western Province Price List" + }); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgencyMarginPercent") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PriceListId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("MinPrice") + .HasColumnType("decimal(65,30)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.Property("RetailPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PriceListId", "FK_ItemId") + .IsUnique(); + + b.ToTable("PriceListItems"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 55m, + Price = 60m + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PriceListId = new Guid("39000000-0000-0000-0000-000000000001"), + IsActive = true, + MinPrice = 45m, + Price = 50m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelReason") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_SupplierId"); + + b.ToTable("PurchaseOrders"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000001"), + IsActive = true, + Status = 2 + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_SupplierId = new Guid("38000000-0000-0000-0000-000000000002"), + IsActive = true, + Status = 2 + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CancelledQuantity") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsCancelled") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("ReceivedQuantity") + .HasColumnType("int"); + + b.Property("UnitCost") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseOrderItems"); + + b.HasData( + new + { + Id = new Guid("42000000-0000-0000-0000-000000000001"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 200, + ReceivedQuantity = 200, + UnitCost = 40m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000002"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + IsCancelled = false, + Quantity = 100, + ReceivedQuantity = 98, + UnitCost = 80m + }, + new + { + Id = new Guid("42000000-0000-0000-0000-000000000003"), + CancelledQuantity = 0, + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + IsCancelled = false, + Quantity = 150, + ReceivedQuantity = 150, + UnitCost = 35m + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.ToTable("PurchaseReturns"); + + b.HasData( + new + { + Id = new Guid("45000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000002"), + IsActive = true, + Reason = "Damaged in transit" + }); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_PurchaseReturnId"); + + b.ToTable("PurchaseReturnItems"); + + b.HasData( + new + { + Id = new Guid("46000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_PurchaseReturnId = new Guid("45000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 10 + }); + }); + + modelBuilder.Entity("Distribution.Models.Region", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Regions"); + + b.HasData( + new + { + Id = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Western Province" + }, + new + { + Id = new Guid("24000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Central Province" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_AgencyUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_AgencyUserId"); + + b.HasIndex("FK_RegionId", "FK_AgencyUserId") + .IsUnique(); + + b.ToTable("RegionAgencyMaps"); + + b.HasData( + new + { + Id = new Guid("57000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_AgencyUserId = new Guid("70000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("BudgetAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalBudgets"); + + b.HasData( + new + { + Id = new Guid("58000000-0000-0000-0000-000000000001"), + BudgetAmount = 200000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08" + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Period") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TargetValue") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId", "Period") + .IsUnique(); + + b.ToTable("RegionalTargets"); + + b.HasData( + new + { + Id = new Guid("59000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Period = "2026-08", + TargetValue = 500000m + }); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RuleConfig") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RegionId") + .IsUnique(); + + b.ToTable("RegionalTaxRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + RuleConfig = "{\"rate\": 0.15}" + }); + }); + + modelBuilder.Entity("Distribution.Models.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 10, + Name = "SalesRep" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 20, + Name = "Supervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 30, + Name = "AreaManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 40, + Name = "AreaSupervisor" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 50, + Name = "RegionalManager" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Level = 60, + Name = "RegionalAgency" + }); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FK_PermissionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_RoleId", "FK_PermissionId"); + + b.HasIndex("FK_PermissionId"); + + b.ToTable("RolePermissions"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("EndPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_OwnerUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("decimal(65,30)"); + + b.Property("RouteName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartPoint") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_OwnerUserId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("Routes"); + + b.HasData( + new + { + Id = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Dehiwala", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 18.5m, + RouteName = "Colombo City Route", + StartPoint = "Colombo Fort" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Negombo", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + IsActive = true, + Length = 32.0m, + RouteName = "Negombo Coastal Route", + StartPoint = "Wattala" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Peradeniya", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 12.0m, + RouteName = "Kandy Town Route", + StartPoint = "Kandy Lake" + }, + new + { + Id = new Guid("25000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + EndPoint = "Matale", + FK_OwnerUserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + IsActive = true, + Length = 26.0m, + RouteName = "Matale Route", + StartPoint = "Kandy" + }); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CheckInAt") + .HasColumnType("datetime(6)"); + + b.Property("CheckInLatitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckInLongitude") + .HasColumnType("decimal(65,30)"); + + b.Property("CheckOutAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeviationFlagged") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.HasIndex("FK_StoreId"); + + b.HasIndex("FK_UserId"); + + b.ToTable("RouteVisitLogs"); + + b.HasData( + new + { + Id = new Guid("66000000-0000-0000-0000-000000000001"), + CheckInAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9344m, + CheckInLongitude = 79.8428m, + CheckOutAt = new DateTime(2026, 8, 25, 9, 25, 0, 0, DateTimeKind.Unspecified), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = false + }, + new + { + Id = new Guid("66000000-0000-0000-0000-000000000002"), + CheckInAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + CheckInLatitude = 6.9000m, + CheckInLongitude = 79.8654m, + CreatedAt = new DateTime(2026, 8, 25, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000002"), + FK_UserId = new Guid("29000000-0000-0000-0000-000000000002"), + IsActive = true, + IsDeviationFlagged = true + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedByUserId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Mode") + .HasColumnType("int"); + + b.Property("TotalCreditAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedByUserId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SaleReturns"); + + b.HasData( + new + { + Id = new Guid("51000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedByUserId = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Mode = 0, + TotalCreditAmount = 300m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SaleReturnId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SaleReturnId"); + + b.ToTable("SaleReturnItems"); + + b.HasData( + new + { + Id = new Guid("52000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 26, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SaleReturnId = new Guid("51000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 5m, + ReasonCode = 1, + UnitPrice = 60m + }); + }); + + modelBuilder.Entity("Distribution.Models.SaleRoute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("SaleRoutes"); + + b.HasData( + new + { + Id = new Guid("69000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }, + new + { + Id = new Guid("69000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AgentLimitExempt") + .HasColumnType("tinyint(1)"); + + b.Property("BaselineExpectedSales") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeFrom") + .HasColumnType("datetime(6)"); + + b.Property("DateRangeTo") + .HasColumnType("datetime(6)"); + + b.Property("EligibleSegment") + .HasColumnType("longtext"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("FK_TriggerItemId") + .HasColumnType("char(36)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegionId") + .HasColumnType("char(36)"); + + b.Property("RuleConfig") + .HasColumnType("longtext"); + + b.Property("RuleType") + .HasColumnType("int"); + + b.Property("TriggerQty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_TriggerItemId"); + + b.HasIndex("RegionId"); + + b.ToTable("Schemes"); + + b.HasData( + new + { + Id = new Guid("48000000-0000-0000-0000-000000000001"), + AgentLimitExempt = false, + BaselineExpectedSales = 500000m, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + FK_TriggerItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FreeQty = 1m, + IsActive = true, + Name = "Buy 10 Coke Get 1 Free", + RuleType = 0, + TriggerQty = 10 + }, + new + { + Id = new Guid("48000000-0000-0000-0000-000000000002"), + AgentLimitExempt = false, + CreatedAt = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeFrom = new DateTime(2026, 8, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + DateRangeTo = new DateTime(2026, 12, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000004"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000002"), + FreeQty = 1m, + IsActive = true, + Name = "Snack Combo Bundle", + RuleType = 3 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("Qty") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SchemeId", "FK_ItemId") + .IsUnique(); + + b.ToTable("SchemeBundleComponents"); + + b.HasData( + new + { + Id = new Guid("49000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000002"), + Qty = 5 + }); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DiscountAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_FreeItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SchemeId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("FieldInvoiceId") + .HasColumnType("char(36)"); + + b.Property("FreeItemCostValue") + .HasColumnType("decimal(65,30)"); + + b.Property("FreeQty") + .HasColumnType("decimal(65,30)"); + + b.Property("RedeemedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FreeItemId"); + + b.HasIndex("FK_SchemeId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("SchemeRedemptions"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + DiscountAmount = 0m, + FK_FreeItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_SchemeId = new Guid("48000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + FreeItemCostValue = 40m, + FreeQty = 1m, + RedeemedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConfirmedAt") + .HasColumnType("datetime(6)"); + + b.Property("ConfirmedBy") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FulfilledAt") + .HasColumnType("datetime(6)"); + + b.Property("InvoiceId") + .HasColumnType("char(36)") + .HasColumnName("InvoiceId"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedById") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("TotalAmount") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("ShopPOs"); + + b.HasData( + new + { + Id = new Guid("33000000-0000-0000-0000-000000000001"), + ConfirmedAt = new DateTime(2026, 8, 25, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FulfilledAt = new DateTime(2026, 8, 25, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000002"), + Status = 2, + TotalAmount = 3000m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 0, + TotalAmount = 1200m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000003"), + ConfirmedAt = new DateTime(2026, 8, 31, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + FulfilledAt = new DateTime(2026, 8, 31, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 2, + TotalAmount = 2400m + }); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ShopPOId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("QuantityFulfilled") + .HasColumnType("int"); + + b.Property("UnitPrice") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ShopPOId"); + + b.ToTable("ShopPOItems"); + + b.HasData( + new + { + Id = new Guid("34000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 30, + QuantityFulfilled = 30, + UnitPrice = 60m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000001"), + IsActive = true, + Quantity = 24, + QuantityFulfilled = 24, + UnitPrice = 50m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 30, 10, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000002"), + IsActive = true, + Quantity = 10, + QuantityFulfilled = 0, + UnitPrice = 120m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000003"), + IsActive = true, + Quantity = 20, + QuantityFulfilled = 20, + UnitPrice = 120m + }); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("LocationId") + .HasColumnType("char(36)"); + + b.Property("LocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId", "LocationId") + .IsUnique(); + + b.ToTable("StockBalances"); + + b.HasData( + new + { + Id = new Guid("61000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 150m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000003"), + LocationId = new Guid("27000000-0000-0000-0000-000000000001"), + LocationType = 0, + Quantity = 90m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("61000000-0000-0000-0000-000000000003"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + LocationId = new Guid("28000000-0000-0000-0000-000000000001"), + LocationType = 1, + Quantity = 20m, + UpdatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FromLocationId") + .HasColumnType("char(36)"); + + b.Property("FromLocationType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.Property("ReasonCode") + .HasColumnType("longtext"); + + b.Property("ReferenceId") + .HasColumnType("char(36)"); + + b.Property("ToLocationId") + .HasColumnType("char(36)"); + + b.Property("ToLocationType") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.ToTable("StockMovements"); + + b.HasData( + new + { + Id = new Guid("62000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + FromLocationType = 2, + Quantity = 200m, + ReferenceId = new Guid("43000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + ToLocationType = 0, + Type = 6 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 25, 7, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("27000000-0000-0000-0000-000000000001"), + FromLocationType = 0, + Quantity = 50m, + ReferenceId = new Guid("35000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + ToLocationType = 1, + Type = 5 + }, + new + { + Id = new Guid("62000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000002"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FromLocationId = new Guid("28000000-0000-0000-0000-000000000001"), + FromLocationType = 1, + Quantity = 30m, + ReferenceId = new Guid("32000000-0000-0000-0000-000000000001"), + ToLocationId = new Guid("00000000-0000-0000-0000-000000000000"), + ToLocationType = 2, + Type = 0 + }); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreditAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreditLimit") + .HasColumnType("decimal(65,30)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("KycStatus") + .HasColumnType("int"); + + b.Property("Latitude") + .HasColumnType("decimal(65,30)"); + + b.Property("Longitude") + .HasColumnType("decimal(65,30)"); + + b.Property("OneTimeAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("OutstandingBalance") + .HasColumnType("decimal(65,30)"); + + b.Property("OwnerName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Segment") + .HasColumnType("longtext"); + + b.Property("StoreAddress") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StoreName") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("Stores"); + + b.HasData( + new + { + Id = new Guid("26000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 50000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.9344m, + Longitude = 79.8428m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Saman Kumara", + Segment = "Gold", + StoreAddress = "12 York Street, Colombo Fort", + StoreName = "Fort Mini Mart" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 30000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + IsActive = true, + KycStatus = 1, + Latitude = 6.8508m, + Longitude = 79.8654m, + OneTimeAmount = 0m, + OutstandingBalance = 5000m, + OwnerName = "Nadeesha Silva", + Segment = "Silver", + StoreAddress = "45 Galle Road, Dehiwala", + StoreName = "Dehiwala Grocery" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 40000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 6.9890m, + Longitude = 79.8912m, + OneTimeAmount = 0m, + OutstandingBalance = 1200m, + OwnerName = "Ruwan Gunasekara", + Segment = "Gold", + StoreAddress = "88 Negombo Road, Wattala", + StoreName = "Wattala Supermarket" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 25000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000002"), + IsActive = true, + KycStatus = 0, + Latitude = 7.2094m, + Longitude = 79.8380m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Chamari Peiris", + StoreAddress = "5 Beach Road, Negombo", + StoreName = "Negombo Beach Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 35000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000003"), + IsActive = true, + KycStatus = 1, + Latitude = 7.2906m, + Longitude = 80.6337m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Dinesh Wickramasinghe", + Segment = "Key Account", + StoreAddress = "3 Lake Road, Kandy", + StoreName = "Kandy Lake View Store" + }, + new + { + Id = new Guid("26000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + CreditAmount = 0m, + CreditLimit = 20000m, + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000004"), + IsActive = true, + KycStatus = 0, + Latitude = 7.4675m, + Longitude = 80.6234m, + OneTimeAmount = 0m, + OutstandingBalance = 0m, + OwnerName = "Ishara Bandara", + StoreAddress = "20 Main Street, Matale", + StoreName = "Matale Central Store" + }); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DocumentType") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("FileReference") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("UploadedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("StoreKycDocuments"); + + b.HasData( + new + { + Id = new Guid("63000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "Business Registration", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000001"), + FileReference = "seed/kyc/fort-mini-mart-brc.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 10, 0, 0, 0, 0, DateTimeKind.Unspecified) + }, + new + { + Id = new Guid("63000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified), + DocumentType = "NIC", + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000003"), + FileReference = "seed/kyc/wattala-owner-nic.pdf", + IsActive = true, + UploadedAt = new DateTime(2026, 8, 12, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("FK_CategoryId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_CategoryId"); + + b.ToTable("SubCategories"); + }); + + modelBuilder.Entity("Distribution.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ContactInfo") + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PerformanceScore") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + + b.HasData( + new + { + Id = new Guid("38000000-0000-0000-0000-000000000001"), + ContactInfo = "+94 11 234 5678", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Ceylon Beverages Ltd", + PerformanceScore = 4.2m + }, + new + { + Id = new Guid("38000000-0000-0000-0000-000000000002"), + ContactInfo = "+94 11 876 5432", + CreatedAt = new DateTime(2026, 8, 14, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Snack Foods (Pvt) Ltd" + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("EvidenceUrl") + .HasColumnType("longtext"); + + b.Property("FK_GoodsReceiptId") + .HasColumnType("char(36)"); + + b.Property("FK_PurchaseOrderId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("RaisedByUserId") + .HasColumnType("char(36)"); + + b.Property("ResolutionAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("ResolutionNotes") + .HasColumnType("longtext"); + + b.Property("ResolutionType") + .HasColumnType("int"); + + b.Property("ResolvedAt") + .HasColumnType("datetime(6)"); + + b.Property("ResolvedByUserId") + .HasColumnType("char(36)"); + + b.Property("Status") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("FK_GoodsReceiptId"); + + b.HasIndex("FK_PurchaseOrderId"); + + b.HasIndex("RaisedByUserId"); + + b.HasIndex("ResolvedByUserId"); + + b.ToTable("SupplierClaims"); + + b.HasData( + new + { + Id = new Guid("55000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + Details = "2 units of Coke 1.5L received damaged", + FK_GoodsReceiptId = new Guid("43000000-0000-0000-0000-000000000001"), + FK_PurchaseOrderId = new Guid("41000000-0000-0000-0000-000000000001"), + IsActive = true, + RaisedByUserId = new Guid("29000000-0000-0000-0000-000000000001"), + ResolutionAmount = 160m, + ResolutionNotes = "Credited against next invoice", + ResolutionType = 1, + ResolvedAt = new DateTime(2026, 8, 16, 0, 0, 0, 0, DateTimeKind.Unspecified), + ResolvedByUserId = new Guid("29000000-0000-0000-0000-000000000006"), + Status = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_SupplierClaimId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IssueType") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_SupplierClaimId"); + + b.ToTable("SupplierClaimItems"); + + b.HasData( + new + { + Id = new Guid("56000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 15, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_SupplierClaimId = new Guid("55000000-0000-0000-0000-000000000001"), + IsActive = true, + IssueType = 0, + Quantity = 2m + }); + }); + + modelBuilder.Entity("Distribution.Models.SysConfig", b => + { + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("UpdatedBy") + .HasColumnType("char(36)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Key"); + + b.ToTable("SysConfigs"); + + b.HasData( + new + { + Key = "InvoiceCreationMode", + UpdatedAt = new DateTime(2026, 9, 17, 0, 0, 0, 0, DateTimeKind.Unspecified), + Value = "ModeB" + }); + }); + + modelBuilder.Entity("Distribution.Models.Uom", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExternalErpId") + .HasColumnType("int"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Uoms"); + + b.HasData( + new + { + Id = new Guid("22000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Piece" + }, + new + { + Id = new Guid("67000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Name = "Case" + }); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("FK_FromUomId") + .HasColumnType("char(36)"); + + b.Property("FK_ItemId") + .HasColumnType("char(36)"); + + b.Property("FK_ToUomId") + .HasColumnType("char(36)"); + + b.Property("Factor") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.HasIndex("FK_FromUomId"); + + b.HasIndex("FK_ItemId"); + + b.HasIndex("FK_ToUomId"); + + b.ToTable("UomConversions"); + + b.HasData( + new + { + Id = new Guid("67000000-0000-0000-0000-000000000002"), + FK_FromUomId = new Guid("67000000-0000-0000-0000-000000000001"), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000001"), + FK_ToUomId = new Guid("22000000-0000-0000-0000-000000000001"), + Factor = 24m + }); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FK_ReportsToUserId") + .HasColumnType("char(36)"); + + b.Property("FK_RoleId") + .HasColumnType("char(36)"); + + b.Property("FullName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("FK_ReportsToUserId"); + + b.HasIndex("FK_RoleId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), + FullName = "Sunil Fernando", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "sunil.fernando" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Nimal Perera", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "nimal.perera" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Kamal Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "kamal.silva" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Ruwan Jayasuriya", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "ruwan.jayasuriya" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_ReportsToUserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), + FullName = "Priyantha Kumara", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priyantha.kumara" + }, + new + { + Id = new Guid("29000000-0000-0000-0000-000000000006"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), + FullName = "Priya Rajapaksa", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "priya.rajapaksa" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), + FullName = "Channa De Silva", + IsActive = true, + PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==", + Username = "channa.desilva" + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RegionId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RegionId"); + + b.HasIndex("FK_RegionId"); + + b.ToTable("UserRegionScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000006"), + FK_RegionId = new Guid("24000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000001"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_RouteId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_RouteId"); + + b.HasIndex("FK_RouteId"); + + b.ToTable("UserRouteScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000001"), + FK_RouteId = new Guid("25000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000002"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.Property("FK_UserId") + .HasColumnType("char(36)"); + + b.Property("FK_StoreId") + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.HasKey("FK_UserId", "FK_StoreId"); + + b.HasIndex("FK_StoreId"); + + b.ToTable("UserStoreScopes"); + + b.HasData( + new + { + FK_UserId = new Guid("29000000-0000-0000-0000-000000000003"), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + Id = new Guid("68000000-0000-0000-0000-000000000003"), + IsActive = true + }); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DefaultWarehouseId") + .HasColumnType("char(36)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("NumberPlate") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RegNumber") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DefaultWarehouseId"); + + b.ToTable("Vehicles"); + + b.HasData( + new + { + Id = new Guid("28000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000001"), + IsActive = true, + NumberPlate = "CAB-1234", + RegNumber = "WP-CAB-1234", + Type = 2 + }, + new + { + Id = new Guid("28000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + DefaultWarehouseId = new Guid("27000000-0000-0000-0000-000000000002"), + IsActive = true, + NumberPlate = "KY-5678", + RegNumber = "CP-KY-5678", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("Location") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("VehicleId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("VehicleId"); + + b.ToTable("Warehouses"); + + b.HasData( + new + { + Id = new Guid("27000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Peliyagoda, Colombo", + Name = "Colombo Distribution Center", + Type = 0 + }, + new + { + Id = new Guid("27000000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 20, 0, 0, 0, 0, DateTimeKind.Unspecified), + IsActive = true, + Location = "Katugastota, Kandy", + Name = "Kandy Fulfillment Center", + Type = 1 + }); + }); + + modelBuilder.Entity("Distribution.Models.Claim", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "SettledByUser") + .WithMany() + .HasForeignKey("SettledByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("AgencyUser"); + + b.Navigation("SettledByUser"); + }); + + modelBuilder.Entity("Distribution.Models.CreditNote", b => + { + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany() + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryRun", b => + { + b.HasOne("Distribution.Models.DriverProfile", "DriverProfile") + .WithMany() + .HasForeignKey("FK_DriverProfileId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("FK_VehicleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DriverProfile"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.DeliveryTask", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.DriverProfile", b => + { + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceiptItem", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany("Items") + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrderItem", "PurchaseOrderItem") + .WithMany() + .HasForeignKey("FK_PurchaseOrderItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrderItem"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.HasOne("Distribution.Models.Uom", "BaseUom") + .WithMany() + .HasForeignKey("FK_BaseUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Brand", "Brand") + .WithMany() + .HasForeignKey("FK_BrandId"); + + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.SubCategory", "SubCategory") + .WithMany() + .HasForeignKey("FK_SubCategoryId"); + + b.Navigation("BaseUom"); + + b.Navigation("Brand"); + + b.Navigation("Category"); + + b.Navigation("SubCategory"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.HasOne("Distribution.Models.DeliveryRun", "Ride") + .WithMany() + .HasForeignKey("FK_RideId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Ride"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Items") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPOItem", "ShopPOItem") + .WithMany() + .HasForeignKey("FK_ShopPOItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Distribution.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("FK_WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPOItem"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheetOrder", b => + { + b.HasOne("Distribution.Models.LoadingSheet", "LoadingSheet") + .WithMany("Orders") + .HasForeignKey("FK_LoadingSheetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("LoadingSheet"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.Payment", b => + { + b.HasOne("Distribution.Models.Invoice", "Invoice") + .WithMany("Payments") + .HasForeignKey("FK_InvoiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Invoice"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.PriceListItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.PriceList", "PriceList") + .WithMany("Items") + .HasForeignKey("FK_PriceListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PriceList"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.HasOne("Distribution.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("FK_SupplierId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrderItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("Items") + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.PurchaseReturn", "PurchaseReturn") + .WithMany("Items") + .HasForeignKey("FK_PurchaseReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("PurchaseReturn"); + }); + + modelBuilder.Entity("Distribution.Models.RegionAgencyMap", b => + { + b.HasOne("Distribution.Models.User", "AgencyUser") + .WithMany() + .HasForeignKey("FK_AgencyUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgencyUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalBudget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTarget", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RegionalTaxRule", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RolePermission", b => + { + b.HasOne("Distribution.Models.Permission", "Permission") + .WithMany() + .HasForeignKey("FK_PermissionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Permission"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.Route", b => + { + b.HasOne("Distribution.Models.User", "OwnerUser") + .WithMany() + .HasForeignKey("FK_OwnerUserId"); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OwnerUser"); + + b.Navigation("Region"); + }); + + modelBuilder.Entity("Distribution.Models.RouteVisitLog", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.HasOne("Distribution.Models.User", "CreatedByUser") + .WithMany() + .HasForeignKey("CreatedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByUser"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturnItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SaleReturn", "SaleReturn") + .WithMany("Items") + .HasForeignKey("FK_SaleReturnId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SaleReturn"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Item", "TriggerItem") + .WithMany() + .HasForeignKey("FK_TriggerItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("RegionId"); + + b.Navigation("FreeItem"); + + b.Navigation("Region"); + + b.Navigation("TriggerItem"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeBundleComponent", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("BundleComponents") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Scheme"); + }); + + modelBuilder.Entity("Distribution.Models.SchemeRedemption", b => + { + b.HasOne("Distribution.Models.Item", "FreeItem") + .WithMany() + .HasForeignKey("FK_FreeItemId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Scheme", "Scheme") + .WithMany("Redemptions") + .HasForeignKey("FK_SchemeId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany() + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("FreeItem"); + + b.Navigation("Scheme"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPOItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.ShopPO", "ShopPO") + .WithMany("Items") + .HasForeignKey("FK_ShopPOId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("ShopPO"); + }); + + modelBuilder.Entity("Distribution.Models.StockBalance", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.StockMovement", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Distribution.Models.Store", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + }); + + modelBuilder.Entity("Distribution.Models.StoreKycDocument", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + }); + + modelBuilder.Entity("Distribution.Models.SubCategory", b => + { + b.HasOne("Distribution.Models.Category", "Category") + .WithMany() + .HasForeignKey("FK_CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.HasOne("Distribution.Models.GoodsReceipt", "GoodsReceipt") + .WithMany() + .HasForeignKey("FK_GoodsReceiptId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.PurchaseOrder", "PurchaseOrder") + .WithMany() + .HasForeignKey("FK_PurchaseOrderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "RaisedByUser") + .WithMany() + .HasForeignKey("RaisedByUserId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "ResolvedByUser") + .WithMany() + .HasForeignKey("ResolvedByUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("GoodsReceipt"); + + b.Navigation("PurchaseOrder"); + + b.Navigation("RaisedByUser"); + + b.Navigation("ResolvedByUser"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaimItem", b => + { + b.HasOne("Distribution.Models.Item", "Item") + .WithMany() + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Distribution.Models.SupplierClaim", "SupplierClaim") + .WithMany("Items") + .HasForeignKey("FK_SupplierClaimId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("SupplierClaim"); + }); + + modelBuilder.Entity("Distribution.Models.UomConversion", b => + { + b.HasOne("Distribution.Models.Uom", "FromUom") + .WithMany() + .HasForeignKey("FK_FromUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Item", "Item") + .WithMany("Conversions") + .HasForeignKey("FK_ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.Uom", "ToUom") + .WithMany() + .HasForeignKey("FK_ToUomId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUom"); + + b.Navigation("Item"); + + b.Navigation("ToUom"); + }); + + modelBuilder.Entity("Distribution.Models.User", b => + { + b.HasOne("Distribution.Models.User", "ReportsTo") + .WithMany() + .HasForeignKey("FK_ReportsToUserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Distribution.Models.Role", "Role") + .WithMany() + .HasForeignKey("FK_RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ReportsTo"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Distribution.Models.UserRegionScope", b => + { + b.HasOne("Distribution.Models.Region", "Region") + .WithMany() + .HasForeignKey("FK_RegionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Region"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserRouteScope", b => + { + b.HasOne("Distribution.Models.Route", "Route") + .WithMany() + .HasForeignKey("FK_RouteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Route"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.UserStoreScope", b => + { + b.HasOne("Distribution.Models.Store", "Store") + .WithMany() + .HasForeignKey("FK_StoreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Distribution.Models.User", "User") + .WithMany() + .HasForeignKey("FK_UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Store"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Distribution.Models.Vehicle", b => + { + b.HasOne("Distribution.Models.Warehouse", null) + .WithMany() + .HasForeignKey("DefaultWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Distribution.Models.Warehouse", b => + { + b.HasOne("Distribution.Models.Vehicle", "Vehicle") + .WithMany() + .HasForeignKey("VehicleId"); + + b.Navigation("Vehicle"); + }); + + modelBuilder.Entity("Distribution.Models.GoodsReceipt", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Invoice", b => + { + b.Navigation("Payments"); + }); + + modelBuilder.Entity("Distribution.Models.Item", b => + { + b.Navigation("Conversions"); + }); + + modelBuilder.Entity("Distribution.Models.LoadingSheet", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + }); + + modelBuilder.Entity("Distribution.Models.PriceList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseOrder", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.PurchaseReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SaleReturn", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.Scheme", b => + { + b.Navigation("BundleComponents"); + + b.Navigation("Redemptions"); + }); + + modelBuilder.Entity("Distribution.Models.ShopPO", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Distribution.Models.SupplierClaim", b => + { + b.Navigation("Items"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.cs b/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.cs new file mode 100644 index 0000000..30be6b0 --- /dev/null +++ b/Distribution/Migrations/20260917104905_SeedInvoice2AndMorePayments.cs @@ -0,0 +1,76 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Distribution.Migrations +{ + /// + public partial class SeedInvoice2AndMorePayments : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertData( + table: "ShopPOs", + columns: new[] { "Id", "ConfirmedAt", "ConfirmedBy", "CreatedAt", "FK_StoreId", "FulfilledAt", "InvoiceId", "IsActive", "RaisedById", "Status", "TotalAmount" }, + values: new object[] { new Guid("33000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 31, 8, 30, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("26000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 31, 13, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34500000-0000-0000-0000-000000000002"), true, new Guid("29000000-0000-0000-0000-000000000003"), 2, 2400m }); + + migrationBuilder.InsertData( + table: "Invoices", + columns: new[] { "Id", "CreatedAt", "CreatedBy", "FK_ShopPOId", "FinalizedAt", "FinalizedBy", "IsActive", "PaymentStatus", "PrintedAt", "PrintedBy", "Status", "TotalAmount" }, + values: new object[] { new Guid("34500000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new Guid("33000000-0000-0000-0000-000000000003"), null, null, true, 1, new DateTime(2026, 8, 31, 9, 15, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), 1, 2400m }); + + migrationBuilder.InsertData( + table: "ShopPOItems", + columns: new[] { "Id", "CreatedAt", "FK_ItemId", "FK_ShopPOId", "IsActive", "Quantity", "QuantityFulfilled", "UnitPrice" }, + values: new object[] { new Guid("34000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23000000-0000-0000-0000-000000000002"), new Guid("33000000-0000-0000-0000-000000000003"), true, 20, 20, 120m }); + + migrationBuilder.InsertData( + table: "Payments", + columns: new[] { "Id", "Amount", "ChequeDate", "ChequeNumber", "CollectedAt", "CollectedBy", "CreatedAt", "EntryMode", "FK_InvoiceId", "IsActive", "Method", "RecordedBy" }, + values: new object[,] + { + { new Guid("47000000-0000-0000-0000-000000000002"), 1000m, null, null, new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), 0, new Guid("34500000-0000-0000-0000-000000000002"), true, 0, null }, + { new Guid("47000000-0000-0000-0000-000000000003"), 800m, new DateTime(2026, 8, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), "000456", new DateTime(2026, 8, 31, 11, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 31, 18, 0, 0, 0, DateTimeKind.Unspecified), 1, new Guid("34500000-0000-0000-0000-000000000002"), true, 1, new Guid("29000000-0000-0000-0000-000000000001") }, + { new Guid("47000000-0000-0000-0000-000000000004"), 300m, null, null, new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), new Guid("29000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), 0, new Guid("34500000-0000-0000-0000-000000000002"), true, 2, null } + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000002")); + + migrationBuilder.DeleteData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000003")); + + migrationBuilder.DeleteData( + table: "Payments", + keyColumn: "Id", + keyValue: new Guid("47000000-0000-0000-0000-000000000004")); + + migrationBuilder.DeleteData( + table: "ShopPOItems", + keyColumn: "Id", + keyValue: new Guid("34000000-0000-0000-0000-000000000004")); + + migrationBuilder.DeleteData( + table: "Invoices", + keyColumn: "Id", + keyValue: new Guid("34500000-0000-0000-0000-000000000002")); + + migrationBuilder.DeleteData( + table: "ShopPOs", + keyColumn: "Id", + keyValue: new Guid("33000000-0000-0000-0000-000000000003")); + } + } +} diff --git a/Distribution/Migrations/AppDBContextModelSnapshot.cs b/Distribution/Migrations/AppDBContextModelSnapshot.cs index cc0afa2..8f517d0 100644 --- a/Distribution/Migrations/AppDBContextModelSnapshot.cs +++ b/Distribution/Migrations/AppDBContextModelSnapshot.cs @@ -572,6 +572,19 @@ namespace Distribution.Migrations PrintedBy = new Guid("29000000-0000-0000-0000-000000000002"), Status = 2, TotalAmount = 3000m + }, + new + { + Id = new Guid("34500000-0000-0000-0000-000000000002"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + CreatedBy = new Guid("29000000-0000-0000-0000-000000000003"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000003"), + IsActive = true, + PaymentStatus = 1, + PrintedAt = new DateTime(2026, 8, 31, 9, 15, 0, 0, DateTimeKind.Unspecified), + PrintedBy = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 1, + TotalAmount = 2400m }); }); @@ -833,6 +846,12 @@ namespace Distribution.Migrations b.Property("Amount") .HasColumnType("decimal(65,30)"); + b.Property("ChequeDate") + .HasColumnType("datetime(6)"); + + b.Property("ChequeNumber") + .HasColumnType("longtext"); + b.Property("CollectedAt") .HasColumnType("datetime(6)"); @@ -842,6 +861,9 @@ namespace Distribution.Migrations b.Property("CreatedAt") .HasColumnType("datetime(6)"); + b.Property("EntryMode") + .HasColumnType("int"); + b.Property("FK_InvoiceId") .HasColumnType("char(36)"); @@ -851,6 +873,9 @@ namespace Distribution.Migrations b.Property("Method") .HasColumnType("int"); + b.Property("RecordedBy") + .HasColumnType("char(36)"); + b.HasKey("Id"); b.HasIndex("FK_InvoiceId"); @@ -865,9 +890,49 @@ namespace Distribution.Migrations CollectedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), CollectedBy = new Guid("29000000-0000-0000-0000-000000000002"), CreatedAt = new DateTime(2026, 8, 25, 9, 30, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000001"), IsActive = true, Method = 0 + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000002"), + Amount = 1000m, + CollectedAt = new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 9, 20, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 0 + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000003"), + Amount = 800m, + ChequeDate = new DateTime(2026, 8, 31, 0, 0, 0, 0, DateTimeKind.Unspecified), + ChequeNumber = "000456", + CollectedAt = new DateTime(2026, 8, 31, 11, 0, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 18, 0, 0, 0, DateTimeKind.Unspecified), + EntryMode = 1, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 1, + RecordedBy = new Guid("29000000-0000-0000-0000-000000000001") + }, + new + { + Id = new Guid("47000000-0000-0000-0000-000000000004"), + Amount = 300m, + CollectedAt = new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), + CollectedBy = new Guid("29000000-0000-0000-0000-000000000003"), + CreatedAt = new DateTime(2026, 8, 31, 11, 5, 0, 0, DateTimeKind.Unspecified), + EntryMode = 0, + FK_InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + Method = 2 }); }); @@ -2052,6 +2117,20 @@ namespace Distribution.Migrations RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), Status = 0, TotalAmount = 1200m + }, + new + { + Id = new Guid("33000000-0000-0000-0000-000000000003"), + ConfirmedAt = new DateTime(2026, 8, 31, 8, 30, 0, 0, DateTimeKind.Unspecified), + ConfirmedBy = new Guid("29000000-0000-0000-0000-000000000001"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_StoreId = new Guid("26000000-0000-0000-0000-000000000005"), + FulfilledAt = new DateTime(2026, 8, 31, 13, 0, 0, 0, DateTimeKind.Unspecified), + InvoiceId = new Guid("34500000-0000-0000-0000-000000000002"), + IsActive = true, + RaisedById = new Guid("29000000-0000-0000-0000-000000000003"), + Status = 2, + TotalAmount = 2400m }); }); @@ -2123,6 +2202,17 @@ namespace Distribution.Migrations Quantity = 10, QuantityFulfilled = 0, UnitPrice = 120m + }, + new + { + Id = new Guid("34000000-0000-0000-0000-000000000004"), + CreatedAt = new DateTime(2026, 8, 31, 9, 0, 0, 0, DateTimeKind.Unspecified), + FK_ItemId = new Guid("23000000-0000-0000-0000-000000000002"), + FK_ShopPOId = new Guid("33000000-0000-0000-0000-000000000003"), + IsActive = true, + Quantity = 20, + QuantityFulfilled = 20, + UnitPrice = 120m }); }); From 1f6d63a0b3b15699a6d365086ce72fff4eea0f5e Mon Sep 17 00:00:00 2001 From: DeepnaPooja Date: Fri, 18 Sep 2026 11:47:34 +0530 Subject: [PATCH 06/11] Add cheque to payment UI --- .../docs/refactor_docs/ride_lifecycle.md | 34 +++++- .../payments/_components/payment-sheet.tsx | 108 ++++++++++++++++-- .../_components/payment-view-sheet.tsx | 23 +++- .../payments/_components/payments-client.tsx | 21 +++- 4 files changed, 168 insertions(+), 18 deletions(-) diff --git a/Distribution/docs/refactor_docs/ride_lifecycle.md b/Distribution/docs/refactor_docs/ride_lifecycle.md index be99cba..7f64e1d 100644 --- a/Distribution/docs/refactor_docs/ride_lifecycle.md +++ b/Distribution/docs/refactor_docs/ride_lifecycle.md @@ -1,11 +1,36 @@ # [Refactor] Ride Lifecycle — Route-Free, Type-Free Rides -**Status**: Proposed (design only — no code changes yet) +**Status**: Mostly implemented — see [Implementation Status](#implementation-status-2026-09-17) **Refactors**: [../03_ride_lifecycle.md](../03_ride_lifecycle.md) (kept as-is, this is the target design) **Depends On**: 02 — Stock Ledger --- +## Implementation Status (2026-09-17) + +**Done**, verified against `Models/DeliveryRun.cs`, `Features/Ride/*`: +- `RideStatus` collapsed to `Open`/`Cancelled`/`Closed` — no Draft/Active stage anywhere. +- `FK_RouteId`, `RideType`, `ActivatedAt`, `FK_SourceWarehouseId` are all gone from `DeliveryRun`. +- `POST /api/rides` creates directly into `Open` with `StartedAt` set; no `/open`/`/activate` routes. +- `POST /api/rides/{id}/cancel` cancels an `Open` ride directly — no approval step, no + `CancelRequested` stage. +- Driver compliance check (`CheckDriverComplianceAsync`) and the "vehicle can't have two Open rides" + guard are both wired into `RideService.CreateAsync`. +- Dead `RideCancelRequest` model/repository/table removed (2026-09-17) — see Migration Notes. + +**Not done / diverges from this doc:** +1. **`GET /api/rides/breakdown-assist/{rideId}`** — not implemented at all (no route in + `RideController.cs`), not even the trimmed "vehicle stock levels only" version this doc describes. +2. **Impact item 1 (delivery task generation) confirmed still broken, honestly**: + `DeliveryTaskService.GenerateAsync` is a one-line `throw new NotImplementedException("... route- + based dispatch not yet implemented.")` — matches this doc's prediction exactly, not yet designed. +3. **Impact item 4 (stock reconciliation at Close/Cancel without a source warehouse)** — still + unaddressed; `CloseAsync`/`CancelAsync` do not touch `StockBalance` at all. +4. **Impact item 2 (loading sheet auto-population)** — resolved differently than either this doc or + `loading_event.md` predicted; see that document's own Implementation Status section. + +--- + ## Goal Ride should not require a `Route`, should not carry a `RideType`, should not be gated by a warehouse's `Type`, and should not even pin down a source warehouse on the ride record itself. Per direction from the business owner, the ride record carries only what a real dispatch needs to track — **"a ride only carries vehicle, driver assign, and meter reading from start to end."** Everything route-shaped (which stores get visited, which orders/items travel on this trip) and everything warehouse-shaped (where stock loads from/returns to) moves out of the Ride entity's responsibility entirely; neither is replaced by another matching mechanism here. @@ -215,9 +240,10 @@ Not part of this docs-only pass, but captured for the eventual implementation st `DeliveryRun`/`Ride` and their Fluent/EF configuration. `Status` stays, re-typed to the narrowed `RideStatus` (`Open`/`Cancelled`/`Closed`). Add `CancelTypeCode`, `CancelReason`, `CancelledAt` columns to `DeliveryRun`. -- Drop the `RideCancelRequest` table, its Fluent/EF configuration, and - `RideCancelRequestRepository`/`IRideCancelRequestRepository` — the request/approve/reject flow is - gone. +- ~~Drop the `RideCancelRequest` table, its Fluent/EF configuration, and + `RideCancelRequestRepository`/`IRideCancelRequestRepository`~~ — **Done (2026-09-17)**: model, + repository, `DbSet`, and seed data removed; `CancelRequestStatus` enum removed as unused; + migration `RemoveRideCancelRequest` applied, dropping the table. - Remove `RouteId`, `RideType`, and `SourceWarehouseId`/`SourceWarehouseName` from `CreateRideRequest`, `RideResponse`, and `BreakdownAssistRideResponse` in `RideDTOs.cs`. Remove the open-orders list from `BreakdownAssistResponse`. Remove the `RaiseCancelRequest`/cancel-request diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx index 1d47c16..0878203 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-sheet.tsx @@ -11,6 +11,7 @@ import { SelectTrigger, SelectValue, } from '@/components/ui/select' +import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group' import { Button } from '@/components/ui/button' import { Dialog, @@ -25,11 +26,23 @@ import { toast } from '@/components/ui/toast' import { payments as paymentsApi, getApiError } from '@/lib/api/index' import type { InvoiceResponse } from '@/types/api' -const schema = z.object({ - invoiceId: z.string().min(1, 'Invoice is required'), - amount: z.number().min(0.01, 'Amount must be greater than 0'), - method: z.enum(['Cash', 'Credit']), -}) +const schema = z + .object({ + invoiceId: z.string().min(1, 'Invoice is required'), + amount: z.number().min(0.01, 'Amount must be greater than 0'), + method: z.enum(['Cash', 'Cheque', 'Credit']), + entryMode: z.enum(['RealTime', 'DayEndManual']), + chequeNumber: z.string().optional(), + chequeDate: z.string().optional(), + }) + .refine((data) => data.method !== 'Cheque' || !!data.chequeNumber, { + message: 'Cheque number is required for cheque payments', + path: ['chequeNumber'], + }) + .refine((data) => data.method !== 'Cheque' || !!data.chequeDate, { + message: 'Cheque date is required for cheque payments', + path: ['chequeDate'], + }) type FormValues = z.infer @@ -50,18 +63,35 @@ export function PaymentSheet({ open, onClose, onSuccess, invoices }: PaymentShee invoiceId: '', amount: 0, method: 'Cash', + entryMode: 'RealTime', + chequeNumber: '', + chequeDate: '', }, }) + const method = form.watch('method') + useEffect(() => { if (!open) return - form.reset({ invoiceId: '', amount: 0, method: 'Cash' }) + form.reset({ + invoiceId: '', + amount: 0, + method: 'Cash', + entryMode: 'RealTime', + chequeNumber: '', + chequeDate: '', + }) }, [open]) async function onSubmit(values: FormValues) { - const { invoiceId, ...rest } = values + const { invoiceId, method, chequeNumber, chequeDate, ...rest } = values try { - await paymentsApi.create(invoiceId, rest) + await paymentsApi.create(invoiceId, { + ...rest, + method, + chequeNumber: method === 'Cheque' ? chequeNumber : undefined, + chequeDate: method === 'Cheque' ? chequeDate : undefined, + }) toast.add({ title: 'Payment recorded', type: 'success' }) onSuccess() onClose() @@ -77,7 +107,7 @@ export function PaymentSheet({ open, onClose, onSuccess, invoices }: PaymentShee Record Payment - Record a cash or credit payment against an invoice. + Record a cash, cheque, or credit payment against an invoice. @@ -137,11 +167,71 @@ export function PaymentSheet({ open, onClose, onSuccess, invoices }: PaymentShee Cash + Cheque Credit )} /> + + {method === 'Cheque' && ( + <> + ( + + )} + /> + + ( + + )} + /> + + )} + + ( + value[0] && field.onChange(value[0])} + > + Real-time + Day-end entry + + )} + /> diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx index 2aa4a01..bc00bd1 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payment-view-sheet.tsx @@ -7,13 +7,19 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog' -import type { PaymentResponse, PaymentMethod } from '@/types/api' +import type { PaymentResponse, PaymentMethod, EntryMode } from '@/types/api' -const PAYMENT_METHOD_VARIANT: Record = { +const PAYMENT_METHOD_VARIANT: Record = { Cash: 'default', + Cheque: 'outline', Credit: 'secondary', } +const ENTRY_MODE_LABEL: Record = { + RealTime: 'Real-time', + DayEndManual: 'Day-end entry', +} + const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) @@ -22,6 +28,9 @@ const fmtDateTime = (v: string) => day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit', }) +const fmtDate = (v: string) => + new Date(v).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) + interface PaymentViewSheetProps { open: boolean onClose: () => void @@ -53,8 +62,18 @@ export function PaymentViewSheet({ open, onClose, payment, invoiceName }: Paymen {truncId(payment.invoiceId)}} /> {payment.method}} /> + {payment.method === 'Cheque' && ( + <> + + + + )} + {ENTRY_MODE_LABEL[payment.entryMode]}} /> {truncId(payment.collectedBy)}} /> + {payment.recordedBy && ( + {truncId(payment.recordedBy)}} /> + )} diff --git a/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx b/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx index cf1ed72..daef14a 100644 --- a/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx +++ b/distribution_fe/app/(dashboard)/sales/payments/_components/payments-client.tsx @@ -11,7 +11,7 @@ import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { toast } from '@/components/ui/toast' import { invoices as invoicesApi, payments as paymentsApi, getApiError, getPaginatedItems } from '@/lib/api/index' -import type { PaymentResponse, PaymentMethod, InvoiceResponse } from '@/types/api' +import type { PaymentResponse, PaymentMethod, EntryMode, InvoiceResponse } from '@/types/api' import { PaymentSheet } from './payment-sheet' import { PaymentViewSheet } from './payment-view-sheet' @@ -22,11 +22,17 @@ const fmtDate = (v: string) => const fmtAmount = (n: number) => `Rs. ${n.toLocaleString()}` const truncId = (id: string) => id.substring(0, 8) -const PAYMENT_METHOD_VARIANT: Record = { +const PAYMENT_METHOD_VARIANT: Record = { Cash: 'default', + Cheque: 'outline', Credit: 'secondary', } +const ENTRY_MODE_LABEL: Record = { + RealTime: 'Real-time', + DayEndManual: 'Day-end entry', +} + export function PaymentsClient() { const [invoicesList, setInvoicesList] = useState([]) const [selectedInvoiceId, setSelectedInvoiceId] = useState('') @@ -119,6 +125,15 @@ export function PaymentsClient() { {row.method} ), }, + { + key: 'entryMode', + title: 'Entry Mode', + fields: ['entryMode'], + width: 130, + cellRender: (row) => ( + {ENTRY_MODE_LABEL[row.entryMode]} + ), + }, { key: 'collectedAt', title: 'Collected At', @@ -143,7 +158,7 @@ export function PaymentsClient() {

Payments

- Cash and credit payments collected against invoices + Cash, cheque, and credit payments collected against invoices