loading event
This commit is contained in:
@@ -39,6 +39,8 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
|||||||
public DbSet<Scheme> Schemes { get; set; }
|
public DbSet<Scheme> Schemes { get; set; }
|
||||||
public DbSet<SchemeRedemption> SchemeRedemptions { get; set; }
|
public DbSet<SchemeRedemption> SchemeRedemptions { get; set; }
|
||||||
public DbSet<SchemeBundleComponent> SchemeBundleComponents { get; set; }
|
public DbSet<SchemeBundleComponent> SchemeBundleComponents { get; set; }
|
||||||
|
public DbSet<LoadingSheet> LoadingSheets { get; set; }
|
||||||
|
public DbSet<LoadingSheetItem> LoadingSheetItems { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
@@ -76,10 +78,11 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
|||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
modelBuilder.Entity<Vehicle>()
|
modelBuilder.Entity<Vehicle>()
|
||||||
.HasOne(v => v.DefaultWarehouse)
|
.HasOne<Warehouse>()
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey(v => v.FK_DefaultWarehouseId)
|
.HasForeignKey(nameof(Vehicle.DefaultWarehouseId))
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired(false);
|
||||||
|
|
||||||
modelBuilder.Entity<DeliveryRun>()
|
modelBuilder.Entity<DeliveryRun>()
|
||||||
.HasOne(r => r.SourceWarehouse)
|
.HasOne(r => r.SourceWarehouse)
|
||||||
@@ -139,6 +142,24 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
|
|||||||
.HasIndex(c => new { c.FK_SchemeId, c.FK_ItemId })
|
.HasIndex(c => new { c.FK_SchemeId, c.FK_ItemId })
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
|
modelBuilder.Entity<LoadingSheet>()
|
||||||
|
.HasOne(s => s.SourceWarehouse)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(s => s.FK_SourceWarehouseId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
modelBuilder.Entity<LoadingSheet>()
|
||||||
|
.HasOne(s => s.Ride)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(s => s.FK_RideId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
modelBuilder.Entity<LoadingSheetItem>()
|
||||||
|
.HasOne(i => i.Item)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(i => i.FK_ItemId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
Seed.RoleAndPermissionSeed.Apply(modelBuilder);
|
Seed.RoleAndPermissionSeed.Apply(modelBuilder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,78 +14,6 @@ public static class RoleAndPermissionSeed
|
|||||||
private static readonly Guid RegionalManagerId = new("10000000-0000-0000-0000-000000000005");
|
private static readonly Guid RegionalManagerId = new("10000000-0000-0000-0000-000000000005");
|
||||||
private static readonly Guid RegionalAgencyId = new("10000000-0000-0000-0000-000000000006");
|
private static readonly Guid RegionalAgencyId = new("10000000-0000-0000-0000-000000000006");
|
||||||
|
|
||||||
private static readonly (string Code, string Description) [] PermissionDefs =
|
|
||||||
[
|
|
||||||
("regions.view", "View regions"),
|
|
||||||
("regions.create", "Create regions"),
|
|
||||||
("regions.update", "Update regions"),
|
|
||||||
("regions.delete", "Delete regions"),
|
|
||||||
|
|
||||||
("routes.view", "View routes"),
|
|
||||||
("routes.create", "Create routes"),
|
|
||||||
("routes.update", "Update routes"),
|
|
||||||
("routes.delete", "Delete routes"),
|
|
||||||
|
|
||||||
("vehicles.view", "View vehicles"),
|
|
||||||
("vehicles.create", "Create vehicles"),
|
|
||||||
("vehicles.update", "Update vehicles"),
|
|
||||||
("vehicles.delete", "Delete vehicles"),
|
|
||||||
|
|
||||||
("stores.view", "View stores"),
|
|
||||||
("stores.create", "Create stores"),
|
|
||||||
("stores.update", "Update stores"),
|
|
||||||
("stores.delete", "Delete stores"),
|
|
||||||
("stores.kyc.verify", "Verify or reject store KYC documents"),
|
|
||||||
("stores.credit.update", "Update store credit limit and outstanding balance"),
|
|
||||||
|
|
||||||
("warehouses.view", "View warehouses"),
|
|
||||||
("warehouses.create", "Create warehouses"),
|
|
||||||
("warehouses.update", "Update warehouses"),
|
|
||||||
("warehouses.delete", "Delete warehouses"),
|
|
||||||
|
|
||||||
("orders.view", "View orders"),
|
|
||||||
("orders.create", "Create orders"),
|
|
||||||
("orders.update", "Update orders"),
|
|
||||||
("orders.delete", "Delete orders"),
|
|
||||||
|
|
||||||
("users.view", "View users"),
|
|
||||||
("users.create", "Create users"),
|
|
||||||
("users.update", "Update users"),
|
|
||||||
("users.deactivate", "Deactivate users"),
|
|
||||||
("users.assign_role", "Assign a role to a user"),
|
|
||||||
("users.assign_scope", "Assign region/route/store scope to a user"),
|
|
||||||
|
|
||||||
("items.view", "View items, brands and UOMs"),
|
|
||||||
("items.create", "Create items, brands and UOMs"),
|
|
||||||
("items.update", "Update items, brands and UOMs"),
|
|
||||||
("items.delete", "Delete items, brands and UOMs"),
|
|
||||||
|
|
||||||
("categories.view", "View categories"),
|
|
||||||
("categories.create", "Create categories and subcategories"),
|
|
||||||
("categories.update", "Update categories and subcategories"),
|
|
||||||
("categories.delete", "Delete categories and subcategories"),
|
|
||||||
|
|
||||||
("driver_profiles.view", "View driver profiles"),
|
|
||||||
("driver_profiles.create", "Create driver profiles"),
|
|
||||||
("driver_profiles.update", "Update driver profiles"),
|
|
||||||
("driver_profiles.deactivate", "Deactivate driver profiles"),
|
|
||||||
|
|
||||||
("compliance.manage", "Manage driver compliance configuration"),
|
|
||||||
|
|
||||||
("rides.view", "View rides"),
|
|
||||||
("rides.create", "Create rides"),
|
|
||||||
("rides.manage", "Manage ride lifecycle"),
|
|
||||||
("rides.cancel.request", "Request ride cancellation"),
|
|
||||||
("rides.cancel.approve", "Approve or reject ride cancellations"),
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, Guid> PermissionIds = PermissionDefs
|
|
||||||
.Select((p, i) => (p.Code, Id: DeterministicPermissionId(i)))
|
|
||||||
.ToDictionary(x => x.Code, x => x.Id);
|
|
||||||
|
|
||||||
private static Guid DeterministicPermissionId(int index) =>
|
|
||||||
new($"20000000-0000-0000-0000-{index + 1:D12}");
|
|
||||||
|
|
||||||
public static void Apply(ModelBuilder modelBuilder)
|
public static void Apply(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder.Entity<Role>().HasData(
|
modelBuilder.Entity<Role>().HasData(
|
||||||
@@ -96,76 +24,5 @@ public static class RoleAndPermissionSeed
|
|||||||
new Role { Id = RegionalManagerId, Name = "RegionalManager", Level = 50, CreatedAt = SeedDate, IsActive = true },
|
new Role { Id = RegionalManagerId, Name = "RegionalManager", Level = 50, CreatedAt = SeedDate, IsActive = true },
|
||||||
new Role { Id = RegionalAgencyId, Name = "RegionalAgency", Level = 60, CreatedAt = SeedDate, IsActive = true }
|
new Role { Id = RegionalAgencyId, Name = "RegionalAgency", Level = 60, CreatedAt = SeedDate, IsActive = true }
|
||||||
);
|
);
|
||||||
|
|
||||||
modelBuilder.Entity<Permission>().HasData(
|
|
||||||
PermissionDefs.Select(p => new Permission
|
|
||||||
{
|
|
||||||
Id = PermissionIds[p.Code],
|
|
||||||
Code = p.Code,
|
|
||||||
Description = p.Description,
|
|
||||||
CreatedAt = SeedDate,
|
|
||||||
IsActive = true
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
var itemViewPerms = new[] { "items.view", "categories.view" };
|
|
||||||
var itemManagePerms = new[] { "items.view", "items.create", "items.update", "categories.view" };
|
|
||||||
var itemPerms = new[] { "items.view", "items.create", "items.update", "items.delete", "categories.view", "categories.create", "categories.update", "categories.delete" };
|
|
||||||
|
|
||||||
var salesRepPerms = new[] { "orders.view", "orders.create", "orders.update", "stores.view", "routes.view" }.Concat(itemViewPerms).ToArray();
|
|
||||||
var supervisorPerms = salesRepPerms.Concat(["orders.delete", "stores.create", "stores.update"]).ToArray();
|
|
||||||
var ridePerms = new[]
|
|
||||||
{
|
|
||||||
"driver_profiles.view", "driver_profiles.create", "driver_profiles.update", "driver_profiles.deactivate",
|
|
||||||
"compliance.manage",
|
|
||||||
"rides.view", "rides.create", "rides.manage", "rides.cancel.request", "rides.cancel.approve"
|
|
||||||
};
|
|
||||||
|
|
||||||
var areaManagerPerms = supervisorPerms.Concat(["vehicles.view", "warehouses.view"]).Concat(itemManagePerms).Concat(ridePerms).Distinct().ToArray();
|
|
||||||
var areaSupervisorPerms = areaManagerPerms.Concat(["routes.create", "routes.update"]).Concat(itemPerms).Distinct().ToArray();
|
|
||||||
|
|
||||||
var regionalManagerPerms = new[]
|
|
||||||
{
|
|
||||||
"orders.view", "orders.create", "orders.update", "orders.delete",
|
|
||||||
"stores.view", "stores.create", "stores.update", "stores.delete", "stores.kyc.verify", "stores.credit.update",
|
|
||||||
"routes.view", "routes.create", "routes.update", "routes.delete",
|
|
||||||
"vehicles.view", "vehicles.create", "vehicles.update", "vehicles.delete",
|
|
||||||
"warehouses.view", "warehouses.create", "warehouses.update", "warehouses.delete",
|
|
||||||
"regions.view", "users.view",
|
|
||||||
"driver_profiles.view", "driver_profiles.create", "driver_profiles.update", "driver_profiles.deactivate",
|
|
||||||
"compliance.manage",
|
|
||||||
"rides.view", "rides.create", "rides.manage", "rides.cancel.request", "rides.cancel.approve",
|
|
||||||
"items.view", "items.create", "items.update", "items.delete",
|
|
||||||
"categories.view", "categories.create", "categories.update", "categories.delete"
|
|
||||||
};
|
|
||||||
var regionalAgencyPerms = PermissionDefs.Select(p => p.Code).ToArray();
|
|
||||||
|
|
||||||
var rolePermissionMap = new (Guid RoleId, string[] Codes)[]
|
|
||||||
{
|
|
||||||
(SalesRepId, salesRepPerms),
|
|
||||||
(SupervisorId, supervisorPerms),
|
|
||||||
(AreaManagerId, areaManagerPerms),
|
|
||||||
(AreaSupervisorId, areaSupervisorPerms),
|
|
||||||
(RegionalManagerId, regionalManagerPerms),
|
|
||||||
(RegionalAgencyId, regionalAgencyPerms),
|
|
||||||
};
|
|
||||||
|
|
||||||
modelBuilder.Entity<RolePermission>().HasData(
|
|
||||||
rolePermissionMap.SelectMany(rp => rp.Codes.Select(code => new RolePermission
|
|
||||||
{
|
|
||||||
Id = DeterministicRolePermissionId(rp.RoleId, PermissionIds[code]),
|
|
||||||
FK_RoleId = rp.RoleId,
|
|
||||||
FK_PermissionId = PermissionIds[code],
|
|
||||||
CreatedAt = SeedDate,
|
|
||||||
IsActive = true
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Guid DeterministicRolePermissionId(Guid roleId, Guid permissionId)
|
|
||||||
{
|
|
||||||
using var md5 = System.Security.Cryptography.MD5.Create();
|
|
||||||
var bytes = md5.ComputeHash(roleId.ToByteArray().Concat(permissionId.ToByteArray()).ToArray());
|
|
||||||
return new Guid(bytes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using Distribution.Models;
|
||||||
|
|
||||||
|
namespace Distribution.Features.LoadingEvent;
|
||||||
|
|
||||||
|
public interface ILoadingSheetRepository
|
||||||
|
{
|
||||||
|
Task<LoadingSheet?> GetByIdAsync(Guid id);
|
||||||
|
Task<LoadingSheet?> GetActiveByRideIdAsync(Guid rideId);
|
||||||
|
Task<List<LoadingSheet>> GetAllAsync(Guid? rideId, LoadingSheetStatus? status, int page, int pageSize);
|
||||||
|
Task<int> GetCountAsync(Guid? rideId, LoadingSheetStatus? status);
|
||||||
|
Task<List<(Guid ItemId, decimal TotalQty)>> GetAggregatedOrderItemsByRouteIdAsync(Guid routeId);
|
||||||
|
Task AddAsync(LoadingSheet sheet);
|
||||||
|
void Update(LoadingSheet sheet);
|
||||||
|
void RemoveItems(IEnumerable<LoadingSheetItem> items);
|
||||||
|
Task AddItemsAsync(IEnumerable<LoadingSheetItem> items);
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
using Distribution.Models;
|
||||||
|
using Distribution.Infra.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Distribution.Features.LoadingEvent;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/loading-sheets")]
|
||||||
|
[Authorize]
|
||||||
|
public class LoadingSheetController(LoadingSheetService service, ICurrentUserService currentUser) : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet]
|
||||||
|
[Authorize(Policy = "loading.view")]
|
||||||
|
public async Task<IActionResult> GetAll(
|
||||||
|
[FromQuery] Guid? rideId,
|
||||||
|
[FromQuery] LoadingSheetStatus? status,
|
||||||
|
[FromQuery] int page = 1,
|
||||||
|
[FromQuery] int pageSize = 20)
|
||||||
|
{
|
||||||
|
var result = await service.GetAllAsync(rideId, status, page, pageSize);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id:guid}")]
|
||||||
|
[Authorize(Policy = "loading.view")]
|
||||||
|
public async Task<IActionResult> GetById(Guid id)
|
||||||
|
{
|
||||||
|
var result = await service.GetByIdAsync(id);
|
||||||
|
return result is null ? NotFound() : Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Authorize(Policy = "loading.dispatch")]
|
||||||
|
public async Task<IActionResult> Create(CreateLoadingSheetRequest request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await service.CreateAsync(request, ct);
|
||||||
|
return CreatedAtAction(nameof(GetById), new { id = result.Id }, result);
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException) { return NotFound(); }
|
||||||
|
catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id:guid}/items")]
|
||||||
|
[Authorize(Policy = "loading.dispatch")]
|
||||||
|
public async Task<IActionResult> SetItems(Guid id, SetItemsRequest request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await service.SetItemsAsync(id, request, ct);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException) { return NotFound(); }
|
||||||
|
catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); }
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{id:guid}/confirm-dispatch")]
|
||||||
|
[Authorize(Policy = "loading.dispatch")]
|
||||||
|
public async Task<IActionResult> ConfirmDispatch(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")]
|
||||||
|
[Authorize(Policy = "loading.receive")]
|
||||||
|
public async Task<IActionResult> 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")]
|
||||||
|
[Authorize(Policy = "loading.receive")]
|
||||||
|
public async Task<IActionResult> 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")]
|
||||||
|
[Authorize(Policy = "loading.resolve")]
|
||||||
|
public async Task<IActionResult> 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 }); }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Distribution.Models;
|
||||||
|
|
||||||
|
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,
|
||||||
|
DateTime CreatedAt,
|
||||||
|
List<LoadingSheetItemResponse> Items);
|
||||||
|
|
||||||
|
public record LoadingSheetItemResponse(
|
||||||
|
Guid Id,
|
||||||
|
Guid FK_ItemId,
|
||||||
|
string ItemName,
|
||||||
|
decimal QuantityDispatched,
|
||||||
|
decimal? QuantityReceived,
|
||||||
|
decimal? QuantityResolved);
|
||||||
|
|
||||||
|
public record CreateLoadingSheetRequest(Guid FK_RideId);
|
||||||
|
|
||||||
|
public record SetItemsRequest(List<SetItemInput> Items);
|
||||||
|
public record SetItemInput(Guid FK_ItemId, decimal Quantity);
|
||||||
|
|
||||||
|
public record SetReceiptItemsRequest(List<ReceiptItemInput> Items);
|
||||||
|
public record ReceiptItemInput(Guid FK_ItemId, decimal QuantityReceived);
|
||||||
|
|
||||||
|
public record ConfirmReceiptRequest(int Meterstart);
|
||||||
|
|
||||||
|
public record ResolveDiscrepancyRequest(List<ResolveItemInput> Items, int Meterstart);
|
||||||
|
public record ResolveItemInput(Guid FK_ItemId, decimal QuantityResolved);
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using Distribution.Data;
|
||||||
|
using Distribution.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Distribution.Features.LoadingEvent;
|
||||||
|
|
||||||
|
public class LoadingSheetRepository(AppDBContext context) : ILoadingSheetRepository
|
||||||
|
{
|
||||||
|
public async Task<LoadingSheet?> GetByIdAsync(Guid id) =>
|
||||||
|
await context.LoadingSheets
|
||||||
|
.Include(s => s.SourceWarehouse)
|
||||||
|
.Include(s => s.Items).ThenInclude(i => i.Item)
|
||||||
|
.FirstOrDefaultAsync(s => s.Id == id);
|
||||||
|
|
||||||
|
public async Task<LoadingSheet?> GetActiveByRideIdAsync(Guid rideId) =>
|
||||||
|
await context.LoadingSheets
|
||||||
|
.FirstOrDefaultAsync(s =>
|
||||||
|
s.FK_RideId == rideId &&
|
||||||
|
s.Status != LoadingSheetStatus.ReceiptConfirmed &&
|
||||||
|
s.Status != LoadingSheetStatus.Resolved);
|
||||||
|
|
||||||
|
public async Task<List<LoadingSheet>> GetAllAsync(Guid? rideId, LoadingSheetStatus? status, int page, int pageSize) =>
|
||||||
|
await context.LoadingSheets
|
||||||
|
.Include(s => s.SourceWarehouse)
|
||||||
|
.Where(s =>
|
||||||
|
(rideId == null || s.FK_RideId == rideId) &&
|
||||||
|
(status == null || s.Status == status))
|
||||||
|
.OrderByDescending(s => s.CreatedAt)
|
||||||
|
.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
public async Task<int> GetCountAsync(Guid? rideId, LoadingSheetStatus? status) =>
|
||||||
|
await context.LoadingSheets
|
||||||
|
.CountAsync(s =>
|
||||||
|
(rideId == null || s.FK_RideId == rideId) &&
|
||||||
|
(status == null || s.Status == status));
|
||||||
|
|
||||||
|
public async Task<List<(Guid ItemId, decimal TotalQty)>> GetAggregatedOrderItemsByRouteIdAsync(Guid routeId)
|
||||||
|
{
|
||||||
|
var groups = await context.OrderItems
|
||||||
|
.Where(oi => oi.IsActive && oi.Order.IsActive && oi.Order.Store.FK_RouteId == routeId)
|
||||||
|
.GroupBy(oi => oi.FK_ItemId)
|
||||||
|
.Select(g => new { ItemId = g.Key, TotalQty = g.Sum(oi => (decimal)oi.Quantity) })
|
||||||
|
.ToListAsync();
|
||||||
|
return groups.Select(x => (x.ItemId, x.TotalQty)).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddAsync(LoadingSheet sheet) =>
|
||||||
|
await context.LoadingSheets.AddAsync(sheet);
|
||||||
|
|
||||||
|
public void Update(LoadingSheet sheet) =>
|
||||||
|
context.LoadingSheets.Update(sheet);
|
||||||
|
|
||||||
|
public void RemoveItems(IEnumerable<LoadingSheetItem> items) =>
|
||||||
|
context.LoadingSheetItems.RemoveRange(items);
|
||||||
|
|
||||||
|
public async Task AddItemsAsync(IEnumerable<LoadingSheetItem> items) =>
|
||||||
|
await context.LoadingSheetItems.AddRangeAsync(items);
|
||||||
|
}
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
using Distribution.Features.Ride;
|
||||||
|
using Distribution.Features.Stock;
|
||||||
|
using Distribution.Infra.UoW;
|
||||||
|
using Distribution.Models;
|
||||||
|
|
||||||
|
namespace Distribution.Features.LoadingEvent;
|
||||||
|
|
||||||
|
public class LoadingSheetService(
|
||||||
|
ILoadingSheetRepository repo,
|
||||||
|
IRideRepository rideRepo,
|
||||||
|
IStockRepository stockRepo,
|
||||||
|
IUnitOfWork uow)
|
||||||
|
{
|
||||||
|
public async Task<PagedResponse<LoadingSheetResponse>> GetAllAsync(Guid? rideId, LoadingSheetStatus? status, int page, int pageSize)
|
||||||
|
{
|
||||||
|
var total = await repo.GetCountAsync(rideId, status);
|
||||||
|
var items = await repo.GetAllAsync(rideId, status, page, pageSize);
|
||||||
|
return new PagedResponse<LoadingSheetResponse>(page, pageSize, total, items.Select(ToResponse).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoadingSheetResponse?> GetByIdAsync(Guid id)
|
||||||
|
{
|
||||||
|
var sheet = await repo.GetByIdAsync(id);
|
||||||
|
return sheet is null ? null : ToResponse(sheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoadingSheetResponse> CreateAsync(CreateLoadingSheetRequest request, CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
var ride = await rideRepo.GetByIdAsync(request.FK_RideId)
|
||||||
|
?? throw new KeyNotFoundException("Ride not found");
|
||||||
|
|
||||||
|
if (ride.Status != RideStatus.Open)
|
||||||
|
throw new InvalidOperationException("A loading sheet can only be created for an Open ride");
|
||||||
|
|
||||||
|
var existing = await repo.GetActiveByRideIdAsync(request.FK_RideId);
|
||||||
|
if (existing is not null)
|
||||||
|
throw new InvalidOperationException("This ride already has an active loading sheet");
|
||||||
|
|
||||||
|
var sheet = new LoadingSheet
|
||||||
|
{
|
||||||
|
FK_RideId = ride.Id,
|
||||||
|
FK_SourceWarehouseId = ride.FK_SourceWarehouseId,
|
||||||
|
Status = LoadingSheetStatus.Pending
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
await repo.AddAsync(sheet);
|
||||||
|
await uow.CommitAsync(ct);
|
||||||
|
}
|
||||||
|
catch { await uow.RollbackAsync(ct); throw; }
|
||||||
|
|
||||||
|
var saved = await repo.GetByIdAsync(sheet.Id);
|
||||||
|
return ToResponse(saved!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoadingSheetResponse> SetItemsAsync(Guid id, SetItemsRequest request, CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
|
||||||
|
await uow.BeginAsync(ct);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
repo.RemoveItems(sheet.Items);
|
||||||
|
await repo.AddItemsAsync(request.Items.Select(i => new LoadingSheetItem
|
||||||
|
{
|
||||||
|
FK_LoadingSheetId = sheet.Id,
|
||||||
|
FK_ItemId = i.FK_ItemId,
|
||||||
|
QuantityDispatched = i.Quantity
|
||||||
|
}));
|
||||||
|
await uow.CommitAsync(ct);
|
||||||
|
}
|
||||||
|
catch { await uow.RollbackAsync(ct); throw; }
|
||||||
|
|
||||||
|
var saved = await repo.GetByIdAsync(sheet.Id);
|
||||||
|
return ToResponse(saved!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoadingSheetResponse> ConfirmDispatchAsync(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.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<LoadingSheetResponse> 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<LoadingSheetResponse> 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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
repo.Update(sheet);
|
||||||
|
await uow.CommitAsync(ct);
|
||||||
|
}
|
||||||
|
catch { await uow.RollbackAsync(ct); throw; }
|
||||||
|
|
||||||
|
return ToResponse(sheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<LoadingSheetResponse> ResolveAsync(Guid id, ResolveDiscrepancyRequest request, 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 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");
|
||||||
|
if (input.QuantityResolved < 0)
|
||||||
|
throw new InvalidOperationException("Resolved quantity cannot be negative");
|
||||||
|
item.QuantityResolved = input.QuantityResolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sheet.Items.Any(i => !i.QuantityResolved.HasValue))
|
||||||
|
throw new InvalidOperationException("All items must have a resolved quantity");
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.UpdatedAt = DateTime.Now;
|
||||||
|
stockRepo.UpdateBalance(warehouseBalance);
|
||||||
|
|
||||||
|
var vehicleBalance = await stockRepo.GetBalanceAsync(itemId, vehicleId);
|
||||||
|
if (vehicleBalance is null)
|
||||||
|
{
|
||||||
|
await stockRepo.AddBalanceAsync(new StockBalance
|
||||||
|
{
|
||||||
|
FK_ItemId = itemId,
|
||||||
|
LocationId = vehicleId,
|
||||||
|
LocationType = LocationType.Vehicle,
|
||||||
|
Quantity = qty
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vehicleBalance.Quantity += qty;
|
||||||
|
vehicleBalance.UpdatedAt = DateTime.Now;
|
||||||
|
stockRepo.UpdateBalance(vehicleBalance);
|
||||||
|
}
|
||||||
|
|
||||||
|
await stockRepo.AddMovementAsync(new StockMovement
|
||||||
|
{
|
||||||
|
FK_ItemId = itemId,
|
||||||
|
FromLocationId = sheet.FK_SourceWarehouseId,
|
||||||
|
FromLocationType = LocationType.Warehouse,
|
||||||
|
ToLocationId = vehicleId,
|
||||||
|
ToLocationType = LocationType.Vehicle,
|
||||||
|
Quantity = qty,
|
||||||
|
Type = MovementType.Load,
|
||||||
|
ReferenceId = sheet.Id,
|
||||||
|
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,
|
||||||
|
s.Items.Select(i => new LoadingSheetItemResponse(
|
||||||
|
i.Id, i.FK_ItemId, i.Item?.Name ?? string.Empty,
|
||||||
|
i.QuantityDispatched, i.QuantityReceived, i.QuantityResolved)).ToList());
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ public class RideService(
|
|||||||
var vehicle = await vehicleRepo.GetByIdAsync(request.FK_VehicleId)
|
var vehicle = await vehicleRepo.GetByIdAsync(request.FK_VehicleId)
|
||||||
?? throw new InvalidOperationException("Vehicle not found");
|
?? throw new InvalidOperationException("Vehicle not found");
|
||||||
|
|
||||||
var sourceWarehouseId = vehicle.FK_DefaultWarehouseId ?? request.FK_SourceWarehouseId;
|
var sourceWarehouseId = vehicle.DefaultWarehouseId ?? request.FK_SourceWarehouseId;
|
||||||
if (!sourceWarehouseId.HasValue)
|
if (!sourceWarehouseId.HasValue)
|
||||||
throw new InvalidOperationException("Source warehouse is required for this vehicle");
|
throw new InvalidOperationException("Source warehouse is required for this vehicle");
|
||||||
|
|
||||||
|
|||||||
-2338
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,716 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
|
||||||
|
|
||||||
namespace Distribution.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddStoreCreditAndKyc : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000001") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000001") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000001") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000001") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000005") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000005") });
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "CreditLimit",
|
|
||||||
table: "Stores",
|
|
||||||
type: "decimal(65,30)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0m);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "KycStatus",
|
|
||||||
table: "Stores",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "OutstandingBalance",
|
|
||||||
table: "Stores",
|
|
||||||
type: "decimal(65,30)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0m);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<string>(
|
|
||||||
name: "Segment",
|
|
||||||
table: "Stores",
|
|
||||||
type: "longtext",
|
|
||||||
nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "StoreKycDocuments",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_StoreId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
DocumentType = table.Column<string>(type: "longtext", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
FileReference = table.Column<string>(type: "longtext", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
UploadedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_StoreKycDocuments", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_StoreKycDocuments_Stores_FK_StoreId",
|
|
||||||
column: x => x.FK_StoreId,
|
|
||||||
principalTable: "Stores",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000017"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "stores.kyc.verify", "Verify or reject store KYC documents" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000018"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "stores.credit.update", "Update store credit limit and outstanding balance" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000019"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "warehouses.view", "View warehouses" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000020"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "warehouses.create", "Create warehouses" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000021"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "warehouses.update", "Update warehouses" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000022"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "warehouses.delete", "Delete warehouses" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000023"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "orders.view", "View orders" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000024"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "orders.create", "Create orders" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000025"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "orders.update", "Update orders" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000026"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "orders.delete", "Delete orders" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000027"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.view", "View users" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000028"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.create", "Create users" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000029"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.update", "Update users" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000030"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.deactivate", "Deactivate users" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000031"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.assign_role", "Assign a role to a user" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000032"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.assign_scope", "Assign region/route/store scope to a user" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000033"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "items.view", "View items, brands and UOMs" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000034"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "items.create", "Create items, brands and UOMs" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000035"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "items.update", "Update items, brands and UOMs" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000036"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "items.delete", "Delete items, brands and UOMs" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000037"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "categories.view", "View categories" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000038"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "categories.create", "Create categories and subcategories" });
|
|
||||||
|
|
||||||
migrationBuilder.InsertData(
|
|
||||||
table: "Permissions",
|
|
||||||
columns: new[] { "Id", "Code", "CreatedAt", "Description", "IsActive" },
|
|
||||||
values: new object[,]
|
|
||||||
{
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000039"), "categories.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update categories and subcategories", true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000040"), "categories.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete categories and subcategories", true }
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.InsertData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
columns: new[] { "FK_PermissionId", "FK_RoleId", "CreatedAt", "Id", "IsActive" },
|
|
||||||
values: new object[,]
|
|
||||||
{
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("c0739b84-50a2-0971-429b-02bab8354c51"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("c268a531-44eb-0f29-82ba-18394ac2dcb5"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("ddb2d04d-19b0-20b1-2639-b157d12a9eec"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("320ba3fb-666c-ce57-3e61-95c9824c4048"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f2c14d55-d557-5cd2-a70a-4a6f58933436"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("1b126bb0-e582-3e84-4728-a7ab5628fe7b"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f50b201c-6c8d-0df8-85ad-08cb137bc213"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("0f291826-e169-c06a-0735-bd06cbb2062d"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("10dd0249-ce04-c5d9-8f94-ccb348c1d979"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d92d572f-f1bf-9e7d-1d4d-7c7b0d575c8e"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f367f6f6-3d26-7a6c-888b-da1a240b59af"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("929950da-d51b-ad5d-c4e5-55175908fb43"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a9a49749-f99d-3166-5d92-b7e380fcabb2"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b17df3df-022c-c903-6ce0-e6423e648dc8"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a41f94ba-c24d-93dc-9f25-c462df19785a"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e0b27435-f505-43f5-7ed9-4711f2248495"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5e10d61c-2d7a-3388-722f-45232d2cfb71"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d8257363-d838-fe7e-57a5-51b626dbfc83"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("04ece77e-b36f-8ed0-4ef9-2f6962b6f9c6"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("bf2a2f96-04ed-905d-5a8a-9047d814aa3e"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4d287b19-ba40-7d4d-3d39-291be64197f8"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("43a4c7b4-a50f-aa37-b147-a30636d9d65f"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a66f3854-5a8f-95c2-cb1c-b2b2e67ee226"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("14bcecd1-b1a2-6da3-155a-233611484467"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("aeb29e0e-e819-1446-6cc6-1fb64b5ecc6b"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e18a6eca-1009-bcc6-35e9-ead943c1649f"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3f32cdac-6925-23f2-064e-8226d781d4a3"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("dc3dd9ff-b123-a8d4-dcea-b4f5f8ff171e"), true }
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_StoreKycDocuments_FK_StoreId",
|
|
||||||
table: "StoreKycDocuments",
|
|
||||||
column: "FK_StoreId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "StoreKycDocuments");
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000001") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000001") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000001") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000001") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000002") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000003") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000004") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000005") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000005") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000005") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000005") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000006") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
|
|
||||||
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000006") });
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000039"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000040"));
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "CreditLimit",
|
|
||||||
table: "Stores");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "KycStatus",
|
|
||||||
table: "Stores");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "OutstandingBalance",
|
|
||||||
table: "Stores");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "Segment",
|
|
||||||
table: "Stores");
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000017"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "warehouses.view", "View warehouses" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000018"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "warehouses.create", "Create warehouses" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000019"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "warehouses.update", "Update warehouses" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000020"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "warehouses.delete", "Delete warehouses" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000021"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "orders.view", "View orders" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000022"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "orders.create", "Create orders" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000023"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "orders.update", "Update orders" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000024"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "orders.delete", "Delete orders" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000025"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.view", "View users" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000026"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.create", "Create users" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000027"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.update", "Update users" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000028"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.deactivate", "Deactivate users" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000029"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.assign_role", "Assign a role to a user" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000030"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "users.assign_scope", "Assign region/route/store scope to a user" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000031"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "items.view", "View items, brands and UOMs" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000032"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "items.create", "Create items, brands and UOMs" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000033"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "items.update", "Update items, brands and UOMs" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000034"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "items.delete", "Delete items, brands and UOMs" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000035"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "categories.view", "View categories" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000036"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "categories.create", "Create categories and subcategories" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000037"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "categories.update", "Update categories and subcategories" });
|
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
|
||||||
table: "Permissions",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("20000000-0000-0000-0000-000000000038"),
|
|
||||||
columns: new[] { "Code", "Description" },
|
|
||||||
values: new object[] { "categories.delete", "Delete categories and subcategories" });
|
|
||||||
|
|
||||||
migrationBuilder.InsertData(
|
|
||||||
table: "RolePermissions",
|
|
||||||
columns: new[] { "FK_PermissionId", "FK_RoleId", "CreatedAt", "Id", "IsActive" },
|
|
||||||
values: new object[,]
|
|
||||||
{
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("85ef4e27-8643-9c43-71f6-da56f66a5c47"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("1e353909-d682-58f6-df5c-8e57fa2512c9"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7596f703-c6ab-316c-7c80-3f4e3daa174e"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("aa120c36-488e-34ba-e10a-2ac45e46e119"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e4648655-7267-141e-51fa-f7d5fe3d2356"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d427b9ea-2c9b-d93e-0843-02dfa1ae8887"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b7dee5e3-f329-95a5-75c1-d02c3e40e229"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e5506b30-527d-08f9-6caa-8a45d3d02999"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("0dd5c943-3ace-0560-6fbc-54d8e37ce014"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("ca97fb3d-132c-d8a5-4ab8-f7b8fc60f5e5"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7780d277-9597-84ff-1a1a-f63fc6b4d3cb"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("8083c659-9506-0bd9-b793-3d6148ce9192"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5c00e972-a697-d71a-6545-1fd8618826cf"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e9b6af8e-7947-7290-9c92-2d9b6239f395"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a701da28-aa75-3c1d-abdb-4317404f8df6"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("2c025310-765f-7d07-ab9a-50524c13d1d3"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("69f93a29-1df1-7b20-9d5c-94c264f8c4b8"), true },
|
|
||||||
{ new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("070813f7-4053-2889-0d14-d0d5834208c2"), true }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,257 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Distribution.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class RideLifecycle : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FK_DefaultWarehouseId",
|
|
||||||
table: "Vehicles",
|
|
||||||
type: "char(36)",
|
|
||||||
nullable: true,
|
|
||||||
collation: "ascii_general_ci");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "ActivatedAt",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
type: "datetime(6)",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "ClosedAt",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
type: "datetime(6)",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FK_DriverProfileId",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
type: "char(36)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
|
||||||
collation: "ascii_general_ci");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FK_SourceWarehouseId",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
type: "char(36)",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
|
||||||
collation: "ascii_general_ci");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "RideType",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<DateTime>(
|
|
||||||
name: "StartedAt",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
type: "datetime(6)",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "Status",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
type: "int",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "DriverComplianceConfigs",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
EnforceLicenseExpiry = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
|
||||||
EnforceMedicalClearance = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
|
||||||
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
UpdatedBy = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_DriverComplianceConfigs", x => x.Id);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "DriverProfiles",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_UserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
LicenseNumber = table.Column<string>(type: "longtext", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
LicenseExpiry = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
MedicalClearanceExpiry = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_DriverProfiles", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_DriverProfiles_Users_FK_UserId",
|
|
||||||
column: x => x.FK_UserId,
|
|
||||||
principalTable: "Users",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "RideCancelRequests",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_RideId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
TypeCode = table.Column<int>(type: "int", nullable: false),
|
|
||||||
Reason = table.Column<string>(type: "longtext", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
RequestedBy = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
RequestedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
Status = table.Column<int>(type: "int", nullable: false),
|
|
||||||
ApprovedBy = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
|
||||||
ApprovedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
|
||||||
},
|
|
||||||
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.CreateIndex(
|
|
||||||
name: "IX_Vehicles_FK_DefaultWarehouseId",
|
|
||||||
table: "Vehicles",
|
|
||||||
column: "FK_DefaultWarehouseId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_DeliveryRuns_FK_DriverProfileId",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
column: "FK_DriverProfileId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_DeliveryRuns_FK_SourceWarehouseId",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
column: "FK_SourceWarehouseId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_DriverProfiles_FK_UserId",
|
|
||||||
table: "DriverProfiles",
|
|
||||||
column: "FK_UserId",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_RideCancelRequests_FK_RideId",
|
|
||||||
table: "RideCancelRequests",
|
|
||||||
column: "FK_RideId");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_DeliveryRuns_DriverProfiles_FK_DriverProfileId",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
column: "FK_DriverProfileId",
|
|
||||||
principalTable: "DriverProfiles",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_DeliveryRuns_Warehouses_FK_SourceWarehouseId",
|
|
||||||
table: "DeliveryRuns",
|
|
||||||
column: "FK_SourceWarehouseId",
|
|
||||||
principalTable: "Warehouses",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Vehicles_Warehouses_FK_DefaultWarehouseId",
|
|
||||||
table: "Vehicles",
|
|
||||||
column: "FK_DefaultWarehouseId",
|
|
||||||
principalTable: "Warehouses",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_DeliveryRuns_DriverProfiles_FK_DriverProfileId",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_DeliveryRuns_Warehouses_FK_SourceWarehouseId",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Vehicles_Warehouses_FK_DefaultWarehouseId",
|
|
||||||
table: "Vehicles");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "DriverComplianceConfigs");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "DriverProfiles");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "RideCancelRequests");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Vehicles_FK_DefaultWarehouseId",
|
|
||||||
table: "Vehicles");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_DeliveryRuns_FK_DriverProfileId",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_DeliveryRuns_FK_SourceWarehouseId",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FK_DefaultWarehouseId",
|
|
||||||
table: "Vehicles");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "ActivatedAt",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "ClosedAt",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FK_DriverProfileId",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FK_SourceWarehouseId",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "RideType",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "StartedAt",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "Status",
|
|
||||||
table: "DeliveryRuns");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-2910
File diff suppressed because it is too large
Load Diff
@@ -1,23 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
|
||||||
|
|
||||||
namespace Distribution.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class ridelife : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,116 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Distribution.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddPricingAndSuppliers : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PriceLists",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
FK_RegionId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
|
||||||
EffectiveFrom = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
EffectiveTo = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PriceLists", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PriceLists_Regions_FK_RegionId",
|
|
||||||
column: x => x.FK_RegionId,
|
|
||||||
principalTable: "Regions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Suppliers",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
ContactInfo = table.Column<string>(type: "longtext", nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
PerformanceScore = table.Column<decimal>(type: "decimal(65,30)", nullable: true),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Suppliers", x => x.Id);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PriceListItems",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_PriceListId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_ItemId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
Price = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PriceListItems", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PriceListItems_Items_FK_ItemId",
|
|
||||||
column: x => x.FK_ItemId,
|
|
||||||
principalTable: "Items",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PriceListItems_PriceLists_FK_PriceListId",
|
|
||||||
column: x => x.FK_PriceListId,
|
|
||||||
principalTable: "PriceLists",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PriceListItems_FK_ItemId",
|
|
||||||
table: "PriceListItems",
|
|
||||||
column: "FK_ItemId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PriceListItems_FK_PriceListId_FK_ItemId",
|
|
||||||
table: "PriceListItems",
|
|
||||||
columns: new[] { "FK_PriceListId", "FK_ItemId" },
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PriceLists_FK_RegionId",
|
|
||||||
table: "PriceLists",
|
|
||||||
column: "FK_RegionId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PriceListItems");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Suppliers");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PriceLists");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-2616
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Distribution.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddPriceListItemMinPrice : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "MinPrice",
|
|
||||||
table: "PriceListItems",
|
|
||||||
type: "decimal(65,30)",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "MinPrice",
|
|
||||||
table: "PriceListItems");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Distribution.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class RidePermissions : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Distribution.Data;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Distribution.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(AppDBContext))]
|
|
||||||
[Migration("20260821120000_AddPromotionsSchemes")]
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddPromotionsSchemes : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "CostPrice",
|
|
||||||
table: "Items",
|
|
||||||
type: "decimal(65,30)",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Schemes",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
Name = table.Column<string>(type: "longtext", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
RuleType = table.Column<int>(type: "int", nullable: false),
|
|
||||||
RuleConfig = table.Column<string>(type: "longtext", nullable: false)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
FK_RegionId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
|
||||||
EligibleSegment = table.Column<string>(type: "longtext", nullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
|
||||||
DateRangeFrom = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
DateRangeTo = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
AgentLimitExempt = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
|
||||||
BaselineExpectedSales = table.Column<decimal>(type: "decimal(65,30)", nullable: true),
|
|
||||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
|
||||||
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Schemes", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Schemes_Regions_FK_RegionId",
|
|
||||||
column: x => x.FK_RegionId,
|
|
||||||
principalTable: "Regions",
|
|
||||||
principalColumn: "Id");
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "SchemeRedemptions",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_SchemeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_OrderId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
|
||||||
FieldInvoiceId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
|
||||||
DiscountAmount = table.Column<decimal>(type: "decimal(65,30)", nullable: true),
|
|
||||||
FK_FreeItemId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
|
||||||
FreeQty = table.Column<decimal>(type: "decimal(65,30)", nullable: true),
|
|
||||||
FreeItemCostValue = table.Column<decimal>(type: "decimal(65,30)", nullable: true),
|
|
||||||
RedeemedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_SchemeRedemptions", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_SchemeRedemptions_Schemes_FK_SchemeId",
|
|
||||||
column: x => x.FK_SchemeId,
|
|
||||||
principalTable: "Schemes",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_SchemeRedemptions_Orders_FK_OrderId",
|
|
||||||
column: x => x.FK_OrderId,
|
|
||||||
principalTable: "Orders",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_SchemeRedemptions_Items_FK_FreeItemId",
|
|
||||||
column: x => x.FK_FreeItemId,
|
|
||||||
principalTable: "Items",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Schemes_FK_RegionId",
|
|
||||||
table: "Schemes",
|
|
||||||
column: "FK_RegionId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_SchemeRedemptions_FK_SchemeId",
|
|
||||||
table: "SchemeRedemptions",
|
|
||||||
column: "FK_SchemeId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_SchemeRedemptions_FK_OrderId",
|
|
||||||
table: "SchemeRedemptions",
|
|
||||||
column: "FK_OrderId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_SchemeRedemptions_FK_FreeItemId",
|
|
||||||
table: "SchemeRedemptions",
|
|
||||||
column: "FK_FreeItemId");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "SchemeRedemptions");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "CostPrice",
|
|
||||||
table: "Items");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,170 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Distribution.Data;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace Distribution.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(AppDBContext))]
|
|
||||||
[Migration("20260821130000_AddSchemeFreeGoodsRuleAndBundleComponents")]
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class AddSchemeFreeGoodsRuleAndBundleComponents : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AlterColumn<string>(
|
|
||||||
name: "RuleConfig",
|
|
||||||
table: "Schemes",
|
|
||||||
type: "longtext",
|
|
||||||
nullable: true,
|
|
||||||
oldClrType: typeof(string),
|
|
||||||
oldType: "longtext")
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4")
|
|
||||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FK_TriggerItemId",
|
|
||||||
table: "Schemes",
|
|
||||||
type: "char(36)",
|
|
||||||
nullable: true,
|
|
||||||
collation: "ascii_general_ci");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "TriggerQty",
|
|
||||||
table: "Schemes",
|
|
||||||
type: "int",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<Guid>(
|
|
||||||
name: "FK_FreeItemId",
|
|
||||||
table: "Schemes",
|
|
||||||
type: "char(36)",
|
|
||||||
nullable: true,
|
|
||||||
collation: "ascii_general_ci");
|
|
||||||
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "FreeQty",
|
|
||||||
table: "Schemes",
|
|
||||||
type: "decimal(65,30)",
|
|
||||||
nullable: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "SchemeBundleComponents",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_SchemeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
FK_ItemId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
|
||||||
Qty = table.Column<int>(type: "int", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_SchemeBundleComponents", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_SchemeBundleComponents_Schemes_FK_SchemeId",
|
|
||||||
column: x => x.FK_SchemeId,
|
|
||||||
principalTable: "Schemes",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_SchemeBundleComponents_Items_FK_ItemId",
|
|
||||||
column: x => x.FK_ItemId,
|
|
||||||
principalTable: "Items",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
})
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Schemes_FK_TriggerItemId",
|
|
||||||
table: "Schemes",
|
|
||||||
column: "FK_TriggerItemId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Schemes_FK_FreeItemId",
|
|
||||||
table: "Schemes",
|
|
||||||
column: "FK_FreeItemId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_SchemeBundleComponents_FK_SchemeId_FK_ItemId",
|
|
||||||
table: "SchemeBundleComponents",
|
|
||||||
columns: new[] { "FK_SchemeId", "FK_ItemId" },
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_SchemeBundleComponents_FK_ItemId",
|
|
||||||
table: "SchemeBundleComponents",
|
|
||||||
column: "FK_ItemId");
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Schemes_Items_FK_TriggerItemId",
|
|
||||||
table: "Schemes",
|
|
||||||
column: "FK_TriggerItemId",
|
|
||||||
principalTable: "Items",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
|
|
||||||
migrationBuilder.AddForeignKey(
|
|
||||||
name: "FK_Schemes_Items_FK_FreeItemId",
|
|
||||||
table: "Schemes",
|
|
||||||
column: "FK_FreeItemId",
|
|
||||||
principalTable: "Items",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "SchemeBundleComponents");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Schemes_Items_FK_TriggerItemId",
|
|
||||||
table: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
|
||||||
name: "FK_Schemes_Items_FK_FreeItemId",
|
|
||||||
table: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Schemes_FK_TriggerItemId",
|
|
||||||
table: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.DropIndex(
|
|
||||||
name: "IX_Schemes_FK_FreeItemId",
|
|
||||||
table: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FK_TriggerItemId",
|
|
||||||
table: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "TriggerQty",
|
|
||||||
table: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FK_FreeItemId",
|
|
||||||
table: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "FreeQty",
|
|
||||||
table: "Schemes");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<string>(
|
|
||||||
name: "RuleConfig",
|
|
||||||
table: "Schemes",
|
|
||||||
type: "longtext",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(string),
|
|
||||||
oldType: "longtext",
|
|
||||||
oldNullable: true)
|
|
||||||
.Annotation("MySql:CharSet", "utf8mb4")
|
|
||||||
.OldAnnotation("MySql:CharSet", "utf8mb4");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1754
File diff suppressed because it is too large
Load Diff
+612
-251
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,17 @@ namespace Distribution.Models
|
|||||||
CustomerReturn,
|
CustomerReturn,
|
||||||
Transfer,
|
Transfer,
|
||||||
Damage,
|
Damage,
|
||||||
Adjustment
|
Adjustment,
|
||||||
|
Load
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LoadingSheetStatus
|
||||||
|
{
|
||||||
|
Pending,
|
||||||
|
DispatchConfirmed,
|
||||||
|
ReceiptConfirmed,
|
||||||
|
DiscrepancyFlagged,
|
||||||
|
Resolved
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RideType { Delivery, Sale }
|
public enum RideType { Delivery, Sale }
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Distribution.Models
|
||||||
|
{
|
||||||
|
public class LoadingSheet : Template
|
||||||
|
{
|
||||||
|
public Guid FK_RideId { get; set; }
|
||||||
|
[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.Pending;
|
||||||
|
|
||||||
|
public DateTime? DispatchConfirmedAt { get; set; }
|
||||||
|
public Guid? DispatchConfirmedBy { get; set; }
|
||||||
|
public DateTime? ReceiptConfirmedAt { get; set; }
|
||||||
|
public Guid? ReceiptConfirmedBy { get; set; }
|
||||||
|
|
||||||
|
public List<LoadingSheetItem> Items { get; set; } = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Distribution.Models
|
||||||
|
{
|
||||||
|
public class LoadingSheetItem
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
|
||||||
|
public Guid FK_LoadingSheetId { get; set; }
|
||||||
|
[ForeignKey("FK_LoadingSheetId")]
|
||||||
|
public LoadingSheet LoadingSheet { get; set; }
|
||||||
|
|
||||||
|
public Guid FK_ItemId { get; set; }
|
||||||
|
[ForeignKey("FK_ItemId")]
|
||||||
|
public Item Item { get; set; }
|
||||||
|
|
||||||
|
public decimal QuantityDispatched { get; set; }
|
||||||
|
public decimal? QuantityReceived { get; set; }
|
||||||
|
public decimal? QuantityResolved { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
namespace Distribution.Models
|
||||||
|
|
||||||
namespace Distribution.Models
|
|
||||||
{
|
{
|
||||||
public class Vehicle : Template
|
public class Vehicle : Template
|
||||||
{
|
{
|
||||||
@@ -8,9 +6,7 @@ namespace Distribution.Models
|
|||||||
public string NumberPlate { get; set; }
|
public string NumberPlate { get; set; }
|
||||||
public VehicleType Type { get; set; }
|
public VehicleType Type { get; set; }
|
||||||
|
|
||||||
public Guid? FK_DefaultWarehouseId { get; set; }
|
public Guid? DefaultWarehouseId { get; set; }
|
||||||
[ForeignKey("FK_DefaultWarehouseId")]
|
|
||||||
public Warehouse DefaultWarehouse { get; set; }
|
|
||||||
}
|
}
|
||||||
public enum VehicleType
|
public enum VehicleType
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Distribution.Features.Item;
|
|||||||
using Distribution.Features.Order;
|
using Distribution.Features.Order;
|
||||||
using Distribution.Features.PriceList;
|
using Distribution.Features.PriceList;
|
||||||
using Distribution.Features.Region;
|
using Distribution.Features.Region;
|
||||||
|
using Distribution.Features.LoadingEvent;
|
||||||
using Distribution.Features.Ride;
|
using Distribution.Features.Ride;
|
||||||
using Distribution.Features.Role;
|
using Distribution.Features.Role;
|
||||||
using Distribution.Features.Route;
|
using Distribution.Features.Route;
|
||||||
@@ -57,6 +58,7 @@ builder.Services.AddScoped<IDriverProfileRepository, DriverProfileRepository>();
|
|||||||
builder.Services.AddScoped<IDriverComplianceConfigRepository, DriverComplianceConfigRepository>();
|
builder.Services.AddScoped<IDriverComplianceConfigRepository, DriverComplianceConfigRepository>();
|
||||||
builder.Services.AddScoped<IRideRepository, RideRepository>();
|
builder.Services.AddScoped<IRideRepository, RideRepository>();
|
||||||
builder.Services.AddScoped<IRideCancelRequestRepository, RideCancelRequestRepository>();
|
builder.Services.AddScoped<IRideCancelRequestRepository, RideCancelRequestRepository>();
|
||||||
|
builder.Services.AddScoped<ILoadingSheetRepository, LoadingSheetRepository>();
|
||||||
builder.Services.AddScoped<IStoreKycDocumentRepository, StoreKycDocumentRepository>();
|
builder.Services.AddScoped<IStoreKycDocumentRepository, StoreKycDocumentRepository>();
|
||||||
builder.Services.AddScoped<IPriceListRepository, PriceListRepository>();
|
builder.Services.AddScoped<IPriceListRepository, PriceListRepository>();
|
||||||
builder.Services.AddScoped<ISupplierRepository, SupplierRepository>();
|
builder.Services.AddScoped<ISupplierRepository, SupplierRepository>();
|
||||||
@@ -83,6 +85,7 @@ builder.Services.AddScoped<SupplierService>();
|
|||||||
builder.Services.AddScoped<DriverProfileService>();
|
builder.Services.AddScoped<DriverProfileService>();
|
||||||
builder.Services.AddScoped<DriverComplianceConfigService>();
|
builder.Services.AddScoped<DriverComplianceConfigService>();
|
||||||
builder.Services.AddScoped<RideService>();
|
builder.Services.AddScoped<RideService>();
|
||||||
|
builder.Services.AddScoped<LoadingSheetService>();
|
||||||
builder.Services.AddScoped<SchemeService>();
|
builder.Services.AddScoped<SchemeService>();
|
||||||
|
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 04 — Loading Event
|
# 04 — Loading Event
|
||||||
|
|
||||||
**Status**: Not Started
|
**Status**: Planning
|
||||||
**Depends On**: 03 — Ride Lifecycle
|
**Depends On**: 03 — Ride Lifecycle
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -8,76 +8,191 @@
|
|||||||
## Goal
|
## Goal
|
||||||
|
|
||||||
Move stock from a source warehouse onto an opened ride's vehicle, with two-party confirmation.
|
Move stock from a source warehouse onto an opened ride's vehicle, with two-party confirmation.
|
||||||
Covers the dispatch half of [mainPlan.md §6](./mainPlan.md#6-warehouse-management):
|
When loading is confirmed, the vehicle's stock ledger is credited and the ride transitions
|
||||||
`generatePickList`, `confirmPicking`, `packOrder`, `buildDispatchLoad`, and `calculateLoadPlan`
|
`Open → Active` automatically. This is the first place the stock movement model gets exercised
|
||||||
from §5.
|
end-to-end.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Background / Context
|
## Background / Context
|
||||||
|
|
||||||
This is the first place the [02_stock_ledger.md](./02_stock_ledger.md) movement model gets
|
A vehicle is just a location with `LocationType.Vehicle` in the stock ledger — the same math as
|
||||||
exercised end-to-end: a `Load` movement debits the warehouse and credits the vehicle location
|
a warehouse. When loading is confirmed, two stock movements are created per item:
|
||||||
created when the ride opened ([03_ride_lifecycle.md](./03_ride_lifecycle.md)).
|
- **Debit** source warehouse: `-qty` at `LocationType.Warehouse`
|
||||||
|
- **Credit** vehicle: `+qty` at `LocationType.Vehicle`
|
||||||
|
|
||||||
|
From this point the vehicle carries live inventory that decreases with every sale or delivery
|
||||||
|
(Steps 05/06) and must return to zero before the ride can close (Step 07).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Data Model Changes
|
## Data Model Changes
|
||||||
|
|
||||||
### Loading Sheet
|
### New Entity — LoadingSheet
|
||||||
|
|
||||||
Header record: `RideId`, `SourceWarehouseId`, `Status` (`Pending`, `DispatchConfirmed`,
|
| Column | Type | Notes |
|
||||||
`ReceiptConfirmed`, `DiscrepancyFlagged`, `Resolved`).
|
|---|---|---|
|
||||||
|
| Id | Guid | PK |
|
||||||
|
| FK_RideId | Guid | FK → DeliveryRun |
|
||||||
|
| FK_SourceWarehouseId | Guid | FK → Warehouse |
|
||||||
|
| Status | LoadingSheetStatus | State machine below |
|
||||||
|
| DispatchConfirmedAt | DateTime? | Set when warehouse confirms dispatch |
|
||||||
|
| DispatchConfirmedBy | Guid? | UserId of warehouse manager |
|
||||||
|
| ReceiptConfirmedAt | DateTime? | Set when driver confirms receipt |
|
||||||
|
| ReceiptConfirmedBy | Guid? | UserId of driver |
|
||||||
|
| CreatedAt | DateTime | |
|
||||||
|
|
||||||
### Loading Line Item
|
### New Entity — LoadingSheetItem
|
||||||
|
|
||||||
`LoadingSheetId`, `ItemId`, `QuantityDispatched` (set by warehouse manager), `QuantityReceived`
|
| Column | Type | Notes |
|
||||||
(set by driver) — a mismatch between the two is a discrepancy.
|
|---|---|---|
|
||||||
|
| Id | Guid | PK |
|
||||||
|
| FK_LoadingSheetId | Guid | FK → LoadingSheet |
|
||||||
|
| FK_ItemId | Guid | FK → Item |
|
||||||
|
| QuantityDispatched | decimal | Set by warehouse manager at confirm-dispatch |
|
||||||
|
| QuantityReceived | decimal? | Set by driver before confirm-receipt |
|
||||||
|
| QuantityResolved | decimal? | Set by supervisor when resolving a discrepancy |
|
||||||
|
|
||||||
### Two-Party Confirmation
|
### New Enum — LoadingSheetStatus
|
||||||
|
|
||||||
Warehouse manager confirms what was dispatched (`generatePickList` → `confirmPicking` →
|
```csharp
|
||||||
`packOrder`); driver separately confirms what was received onto the vehicle. Both confirmations are
|
public enum LoadingSheetStatus
|
||||||
required before the ride can move `Open → Active`.
|
{
|
||||||
|
Pending,
|
||||||
|
DispatchConfirmed,
|
||||||
|
ReceiptConfirmed,
|
||||||
|
DiscrepancyFlagged,
|
||||||
|
Resolved
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
No changes to existing entities. Vehicle capacity check is deferred to Step 13 (Fleet Management).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## State Machine
|
||||||
|
|
||||||
|
```
|
||||||
|
Pending → DispatchConfirmed → ReceiptConfirmed (all lines match)
|
||||||
|
↘ DiscrepancyFlagged → Resolved
|
||||||
|
```
|
||||||
|
|
||||||
|
| Transition | Trigger | What it does |
|
||||||
|
|---|---|---|
|
||||||
|
| Pending → DispatchConfirmed | `POST /{id}/confirm-dispatch` | Warehouse manager locks in `QuantityDispatched` per line. Ride stays `Open`. |
|
||||||
|
| DispatchConfirmed → ReceiptConfirmed | `POST /{id}/confirm-receipt` | Driver's received quantities all match dispatched. Creates stock movements. Auto-triggers ride `Open → Active`. |
|
||||||
|
| DispatchConfirmed → DiscrepancyFlagged | `POST /{id}/confirm-receipt` | Any line mismatch. No stock movements created. Ride stays `Open`. |
|
||||||
|
| DiscrepancyFlagged → Resolved | `POST /{id}/resolve` | Supervisor enters `QuantityResolved` per line. Creates stock movements using resolved quantities. Auto-triggers ride `Open → Active`. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Item Population by Ride Type
|
||||||
|
|
||||||
|
| Ride Type | How items are added to the sheet |
|
||||||
|
|---|---|
|
||||||
|
| Delivery | Auto-populated on sheet creation from the aggregate of all order lines assigned to the ride |
|
||||||
|
| Sale | Manually entered by warehouse manager via `PUT /{id}/items` (no orders to derive from) |
|
||||||
|
|
||||||
|
For Delivery rides the warehouse manager reviews the pre-populated quantities and may adjust before confirming dispatch. `PUT /{id}/items` is still available to override if needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stock Movements
|
||||||
|
|
||||||
|
Created at `ReceiptConfirmed` or `Resolved`. One pair per line item:
|
||||||
|
|
||||||
|
- **Debit** warehouse: `-QuantityFinal` at `LocationType.Warehouse`, `FK_LocationId = SourceWarehouseId`
|
||||||
|
- **Credit** vehicle: `+QuantityFinal` at `LocationType.Vehicle`, `FK_LocationId = VehicleId`
|
||||||
|
|
||||||
|
`QuantityFinal` = `QuantityReceived` on a clean confirmation, or `QuantityResolved` when a discrepancy was resolved.
|
||||||
|
|
||||||
|
Movement `Type` = `Load` (new `StockMovementType` value to add to enums).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## API Endpoints
|
## API Endpoints
|
||||||
|
|
||||||
| Function reference | Endpoint intent |
|
Base route: `/api/loading-sheets`
|
||||||
|---|---|
|
|
||||||
| `generatePickList(orderIds[])` (§6) | `POST /api/loading-sheets` |
|
| Method | Route | Who | Description |
|
||||||
| `confirmPicking(pickListId, pickedItems[])` (§6) | `POST /api/loading-sheets/{id}/confirm-dispatch` |
|
|---|---|---|---|
|
||||||
| `packOrder(orderId, packageDetails)` (§6) | `POST /api/loading-sheets/{id}/pack` |
|
| POST | `/` | Warehouse mgr | Create sheet for an Open ride. Delivery rides auto-populate items from orders. |
|
||||||
| `buildDispatchLoad(vehicleId, orderIds[])` (§6) | Groups multiple orders into one loading sheet |
|
| GET | `/` | Any | List sheets. Filter by `rideId`, `status`. Paginated. |
|
||||||
| `calculateLoadPlan(vehicleId, orderIds[])` (§5) | Validates total volume/weight against vehicle capacity before dispatch confirmation |
|
| GET | `/{id}` | Any | Get sheet detail with all line items |
|
||||||
| — | `POST /api/loading-sheets/{id}/confirm-receipt` — driver-side confirmation |
|
| PUT | `/{id}/items` | Warehouse mgr | Set or override item quantities (required for Sale rides, optional for Delivery) |
|
||||||
|
| POST | `/{id}/confirm-dispatch` | Warehouse mgr | Pending → DispatchConfirmed |
|
||||||
|
| PUT | `/{id}/receipt-items` | Driver | Set `QuantityReceived` per line |
|
||||||
|
| POST | `/{id}/confirm-receipt` | Driver | → ReceiptConfirmed or DiscrepancyFlagged |
|
||||||
|
| POST | `/{id}/resolve` | Supervisor | Enter `QuantityResolved` per line → Resolved + ride activation |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Business Rules
|
## Business Rules
|
||||||
|
|
||||||
- `QuantityDispatched != QuantityReceived` on any line flags the sheet `DiscrepancyFlagged` and
|
1. A loading sheet can only be created for a ride in `Open` status.
|
||||||
blocks ride activation until resolved.
|
2. A ride can only have one active loading sheet (not `Resolved` or `ReceiptConfirmed`) at a time.
|
||||||
- `calculateLoadPlan` must reject a load exceeding vehicle capacity before dispatch is confirmed,
|
3. `QuantityDispatched != QuantityReceived` on any line → `DiscrepancyFlagged`. No partial activation.
|
||||||
not after.
|
4. Stock movements are created only once — at `ReceiptConfirmed` or `Resolved`. Never on dispatch.
|
||||||
|
5. Discrepancies must be resolved per line item with an explicit `QuantityResolved` value. No bulk "accept driver" or "accept warehouse" shortcut.
|
||||||
|
6. All list endpoints return paginated responses.
|
||||||
|
7. Vehicle capacity check is not enforced in this step — deferred to Step 13.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Permissions to Seed
|
||||||
|
|
||||||
|
| Code | Who |
|
||||||
|
|---|---|
|
||||||
|
| `loading.view` | All roles |
|
||||||
|
| `loading.dispatch` | Warehouse manager and above |
|
||||||
|
| `loading.receive` | Driver (AreaManager and above for testing) |
|
||||||
|
| `loading.resolve` | Supervisor and above |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Fraud / Control Considerations
|
## Fraud / Control Considerations
|
||||||
|
|
||||||
- Discrepancies must be immediately visible, not silently averaged into stock adjustments — see
|
- Discrepancies are immediately visible and block activation — they cannot be silently absorbed.
|
||||||
[09_fraud_controls.md](./09_fraud_controls.md).
|
- `QuantityResolved` is permanently stored per line for audit purposes, even after the sheet is resolved.
|
||||||
|
- See [09_fraud_controls.md](./09_fraud_controls.md) for the audit trail layer that will sit on top of this.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Open Questions
|
## Open Questions
|
||||||
|
|
||||||
- Does `Vehicle` need a `Capacity` field added now (volume/weight), or is `calculateLoadPlan`
|
- ✅ Vehicle capacity check — deferred to Step 13 (Fleet Management).
|
||||||
deferred until that's available?
|
- ✅ Discrepancy resolution — supervisor enters `QuantityResolved` per line item.
|
||||||
|
- ✅ Ride activation trigger — `confirm-receipt` and `resolve` auto-trigger `Open → Active` internally.
|
||||||
|
- ✅ Item population — Delivery rides auto-populated from orders; Sale rides manually entered.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Implementation Notes
|
## Implementation Notes
|
||||||
|
|
||||||
> Fill this section in during planning discussion before writing any code.
|
**Build order:**
|
||||||
|
1. Enum — add `LoadingSheetStatus` to `Models/Enums.cs`; add `Load` to `StockMovementType`
|
||||||
|
2. Entities — `LoadingSheet`, `LoadingSheetItem` (new)
|
||||||
|
3. `AppDBContext` — new DbSets + Fluent config
|
||||||
|
4. Migration — `LoadingEvent` (schema) + `LoadingPermissions` (4 new permissions seeded)
|
||||||
|
5. DTOs — `LoadingSheetDTOs.cs`
|
||||||
|
6. Repository — `ILoadingSheetRepository`, `LoadingSheetRepository`
|
||||||
|
7. Service — `LoadingSheetService`
|
||||||
|
8. Controller — `LoadingSheetController`
|
||||||
|
9. DI registration in `Program.cs`
|
||||||
|
|
||||||
|
**Feature folder:** `Features/LoadingEvent/`
|
||||||
|
|
||||||
|
**What was built:**
|
||||||
|
1. ✅ Enums — added `LoadingSheetStatus` and `Load` to `MovementType` in `Models/Enums.cs`
|
||||||
|
2. ✅ Entities — `LoadingSheet`, `LoadingSheetItem` created in `Models/`
|
||||||
|
3. ✅ `AppDBContext` — `LoadingSheets`, `LoadingSheetItems` DbSets added; Fluent config for FK restrictions and ride/warehouse relationships
|
||||||
|
4. ✅ DTOs — `LoadingSheetDTOs.cs` in `Features/LoadingEvent/`
|
||||||
|
5. ✅ Repository — `ILoadingSheetRepository`, `LoadingSheetRepository` in `Features/LoadingEvent/`
|
||||||
|
6. ✅ Service — `LoadingSheetService` in `Features/LoadingEvent/`
|
||||||
|
7. ✅ Controller — `LoadingSheetController` in `Features/LoadingEvent/`
|
||||||
|
8. ✅ DI registration in `Program.cs`
|
||||||
|
9. ⚠️ Permissions added to seed (`loading.view`, `loading.dispatch`, `loading.receive`, `loading.resolve`) — **authorization layer is being replaced, skip this**
|
||||||
|
|
||||||
|
**Pending (run manually):**
|
||||||
|
- `dotnet ef migrations add LoadingEvent` — blocked by a pre-existing duplicate Permission seed ID in `AppDBContextModelSnapshot.cs` (ID `20000000-0000-0000-0000-000000000040` is assigned to both `categories.delete` and `driver_profiles.create`). This is a snapshot consistency issue from a previous session and needs to be resolved before migration generation will succeed.
|
||||||
|
- `dotnet ef database update` after migration is generated.
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ They must be resolved before new feature steps begin because later steps depend
|
|||||||
| 01 | Item Catalog | Done | 00 | [01_item_catalog.md](./01_item_catalog.md) |
|
| 01 | Item Catalog | Done | 00 | [01_item_catalog.md](./01_item_catalog.md) |
|
||||||
| 02 | Stock Ledger | Done | 01 | [02_stock_ledger.md](./02_stock_ledger.md) |
|
| 02 | Stock Ledger | Done | 01 | [02_stock_ledger.md](./02_stock_ledger.md) |
|
||||||
| 03 | Ride Lifecycle | Done | 02 | [03_ride_lifecycle.md](./03_ride_lifecycle.md) |
|
| 03 | Ride Lifecycle | Done | 02 | [03_ride_lifecycle.md](./03_ride_lifecycle.md) |
|
||||||
| 04 | Loading Event | Not Started | 03 | [04_loading_event.md](./04_loading_event.md) |
|
| 04 | Loading Event | Done | 03 | [04_loading_event.md](./04_loading_event.md) |
|
||||||
| 05 | Delivery Ride Execution | Not Started | 04 | [05_delivery_ride.md](./05_delivery_ride.md) |
|
| 05 | Delivery Ride Execution | Not Started | 04 | [05_delivery_ride.md](./05_delivery_ride.md) |
|
||||||
| 06 | Sale Ride Execution | Not Started | 04 | [06_sale_ride.md](./06_sale_ride.md) |
|
| 06 | Sale Ride Execution | Not Started | 04 | [06_sale_ride.md](./06_sale_ride.md) |
|
||||||
| 07 | Ride Close & Reconciliation | Not Started | 05, 06 | [07_ride_reconciliation.md](./07_ride_reconciliation.md) |
|
| 07 | Ride Close & Reconciliation | Not Started | 05, 06 | [07_ride_reconciliation.md](./07_ride_reconciliation.md) |
|
||||||
|
|||||||
Reference in New Issue
Block a user