stock_ledger completed need to test

This commit is contained in:
Kalana B. Thilakarathna
2026-08-20 09:42:33 +05:30
parent aa7ea37ab6
commit f95fda3806
37 changed files with 1976 additions and 5805 deletions
+6
View File
@@ -27,6 +27,8 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
public DbSet<UserRegionScope> UserRegionScopes { get; set; }
public DbSet<UserRouteScope> UserRouteScopes { get; set; }
public DbSet<UserStoreScope> UserStoreScopes { get; set; }
public DbSet<StockBalance> StockBalances { get; set; }
public DbSet<StockMovement> StockMovements { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
@@ -51,6 +53,10 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
.HasForeignKey(u => u.FK_ReportsToUserId)
.OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<StockBalance>()
.HasIndex(sb => new { sb.FK_ItemId, sb.LocationId })
.IsUnique();
Seed.RoleAndPermissionSeed.Apply(modelBuilder);
}
}
@@ -0,0 +1,19 @@
using Distribution.Models;
namespace Distribution.Features.Stock;
public interface IStockRepository
{
// Balance
Task<StockBalance?> GetBalanceAsync(Guid itemId, Guid locationId);
Task<List<StockBalance>> GetBalancesAsync(Guid? locationId, LocationType? locationType, Guid? itemId, int page, int pageSize);
Task<int> GetBalancesCountAsync(Guid? locationId, LocationType? locationType, Guid? itemId);
Task<List<StockBalance>> GetBalancesByItemAsync(Guid itemId);
Task AddBalanceAsync(StockBalance balance);
void UpdateBalance(StockBalance balance);
// Movements
Task AddMovementAsync(StockMovement movement);
Task<List<StockMovement>> GetMovementsAsync(Guid? locationId, Guid? itemId, MovementType? type, DateTime? from, DateTime? to, int page, int pageSize);
Task<int> GetMovementsCountAsync(Guid? locationId, Guid? itemId, MovementType? type, DateTime? from, DateTime? to);
}
@@ -0,0 +1,98 @@
using Distribution.Infra.Authorization;
using Distribution.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Stock;
[ApiController]
[Route("api/stock")]
[Authorize]
public class StockController(StockService service, ICurrentUserService currentUser) : ControllerBase
{
// ── Query ──────────────────────────────────────────────────────────────
[HttpGet("balances")]
public async Task<IActionResult> GetBalances(
[FromQuery] Guid? locationId,
[FromQuery] LocationType? locationType,
[FromQuery] Guid? itemId,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 20)
{
var result = await service.GetBalancesAsync(locationId, locationType, itemId, page, pageSize);
return Ok(result);
}
[HttpGet("balances/{itemId}/total")]
public async Task<IActionResult> GetItemTotal(Guid itemId)
{
var result = await service.GetItemTotalAsync(itemId);
if (result is null) return NotFound();
return Ok(result);
}
[HttpGet("movements")]
public async Task<IActionResult> GetMovements(
[FromQuery] Guid? locationId,
[FromQuery] Guid? itemId,
[FromQuery] MovementType? type,
[FromQuery] DateTime? from,
[FromQuery] DateTime? to,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 20)
{
var result = await service.GetMovementsAsync(locationId, itemId, type, from, to, page, pageSize);
return Ok(result);
}
// ── Write ──────────────────────────────────────────────────────────────
[HttpPost("transfer")]
public async Task<IActionResult> Transfer(TransferRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
try
{
var result = await service.TransferAsync(request, currentUser.UserId.Value, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
[HttpPost("damage")]
public async Task<IActionResult> RecordDamage(DamageRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
try
{
var result = await service.RecordDamageAsync(request, currentUser.UserId.Value, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
[HttpPost("customer-return")]
public async Task<IActionResult> RecordCustomerReturn(CustomerReturnRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
try
{
var result = await service.RecordCustomerReturnAsync(request, currentUser.UserId.Value, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
[HttpPost("adjustment")]
public async Task<IActionResult> Adjust(AdjustmentRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
try
{
var result = await service.AdjustAsync(request, currentUser.UserId.Value, ct);
return Ok(result);
}
catch (InvalidOperationException ex) { return BadRequest(ex.Message); }
}
}
+67
View File
@@ -0,0 +1,67 @@
using Distribution.Models;
namespace Distribution.Features.Stock;
// Shared pagination wrapper
public record PagedResponse<T>(int Page, int PageSize, int Total, List<T> Items);
// Balance
public record StockBalanceResponse(
Guid ItemId,
string ItemName,
Guid LocationId,
LocationType LocationType,
decimal Quantity,
DateTime UpdatedAt);
public record StockTotalResponse(
Guid ItemId,
string ItemName,
decimal TotalQuantity,
List<StockBalanceResponse> Breakdown);
// Movement
public record StockMovementResponse(
Guid Id,
Guid ItemId,
string ItemName,
Guid? FromLocationId,
LocationType? FromLocationType,
Guid? ToLocationId,
LocationType? ToLocationType,
decimal Quantity,
MovementType Type,
string? ReasonCode,
Guid? ReferenceId,
DateTime CreatedAt,
Guid CreatedBy);
// Write requests
public record TransferRequest(
Guid ItemId,
Guid FromLocationId,
LocationType FromLocationType,
Guid ToLocationId,
LocationType ToLocationType,
decimal Quantity,
Guid? ReferenceId);
public record DamageRequest(
Guid ItemId,
Guid LocationId,
LocationType LocationType,
decimal Quantity,
string ReasonCode);
public record CustomerReturnRequest(
Guid ItemId,
Guid VehicleId,
decimal Quantity,
Guid? ReferenceId);
public record AdjustmentRequest(
Guid ItemId,
Guid LocationId,
LocationType LocationType,
decimal Quantity,
string ReasonCode);
@@ -0,0 +1,70 @@
using Distribution.Data;
using Distribution.Models;
using Microsoft.EntityFrameworkCore;
namespace Distribution.Features.Stock;
public class StockRepository(AppDBContext db) : IStockRepository
{
public Task<StockBalance?> GetBalanceAsync(Guid itemId, Guid locationId) =>
db.StockBalances
.Include(b => b.Item)
.FirstOrDefaultAsync(b => b.FK_ItemId == itemId && b.LocationId == locationId);
public Task<List<StockBalance>> GetBalancesAsync(Guid? locationId, LocationType? locationType, Guid? itemId, int page, int pageSize)
{
var query = db.StockBalances.Include(b => b.Item).AsQueryable();
if (locationId.HasValue) query = query.Where(b => b.LocationId == locationId.Value);
if (locationType.HasValue) query = query.Where(b => b.LocationType == locationType.Value);
if (itemId.HasValue) query = query.Where(b => b.FK_ItemId == itemId.Value);
return query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();
}
public Task<int> GetBalancesCountAsync(Guid? locationId, LocationType? locationType, Guid? itemId)
{
var query = db.StockBalances.AsQueryable();
if (locationId.HasValue) query = query.Where(b => b.LocationId == locationId.Value);
if (locationType.HasValue) query = query.Where(b => b.LocationType == locationType.Value);
if (itemId.HasValue) query = query.Where(b => b.FK_ItemId == itemId.Value);
return query.CountAsync();
}
public Task<List<StockBalance>> GetBalancesByItemAsync(Guid itemId) =>
db.StockBalances
.Include(b => b.Item)
.Where(b => b.FK_ItemId == itemId)
.ToListAsync();
public async Task AddBalanceAsync(StockBalance balance) =>
await db.StockBalances.AddAsync(balance);
public void UpdateBalance(StockBalance balance) =>
db.StockBalances.Update(balance);
public async Task AddMovementAsync(StockMovement movement) =>
await db.StockMovements.AddAsync(movement);
public Task<List<StockMovement>> GetMovementsAsync(Guid? locationId, Guid? itemId, MovementType? type, DateTime? from, DateTime? to, int page, int pageSize)
{
var query = db.StockMovements.Include(m => m.Item).AsQueryable();
if (locationId.HasValue)
query = query.Where(m => m.FromLocationId == locationId.Value || m.ToLocationId == locationId.Value);
if (itemId.HasValue) query = query.Where(m => m.FK_ItemId == itemId.Value);
if (type.HasValue) query = query.Where(m => m.Type == type.Value);
if (from.HasValue) query = query.Where(m => m.CreatedAt >= from.Value);
if (to.HasValue) query = query.Where(m => m.CreatedAt <= to.Value);
return query.OrderByDescending(m => m.CreatedAt).Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();
}
public Task<int> GetMovementsCountAsync(Guid? locationId, Guid? itemId, MovementType? type, DateTime? from, DateTime? to)
{
var query = db.StockMovements.AsQueryable();
if (locationId.HasValue)
query = query.Where(m => m.FromLocationId == locationId.Value || m.ToLocationId == locationId.Value);
if (itemId.HasValue) query = query.Where(m => m.FK_ItemId == itemId.Value);
if (type.HasValue) query = query.Where(m => m.Type == type.Value);
if (from.HasValue) query = query.Where(m => m.CreatedAt >= from.Value);
if (to.HasValue) query = query.Where(m => m.CreatedAt <= to.Value);
return query.CountAsync();
}
}
+228
View File
@@ -0,0 +1,228 @@
using Distribution.Features.Category;
using Distribution.Features.Item;
using Distribution.Infra.UoW;
using Distribution.Models;
namespace Distribution.Features.Stock;
public class StockService(IStockRepository repo, IItemRepository itemRepo, ICategoryRepository categoryRepo, IUnitOfWork uow)
{
private static StockBalanceResponse MapBalance(StockBalance b) =>
new(b.FK_ItemId, b.Item.Name, b.LocationId, b.LocationType, b.Quantity, b.UpdatedAt);
private static StockMovementResponse MapMovement(StockMovement m) =>
new(m.Id, m.FK_ItemId, m.Item.Name, m.FromLocationId, m.FromLocationType,
m.ToLocationId, m.ToLocationType, m.Quantity, m.Type, m.ReasonCode,
m.ReferenceId, m.CreatedAt, m.CreatedBy);
// ── Queries ────────────────────────────────────────────────────────────
public async Task<PagedResponse<StockBalanceResponse>> GetBalancesAsync(
Guid? locationId, LocationType? locationType, Guid? itemId, int page, int pageSize)
{
var items = await repo.GetBalancesAsync(locationId, locationType, itemId, page, pageSize);
var total = await repo.GetBalancesCountAsync(locationId, locationType, itemId);
return new PagedResponse<StockBalanceResponse>(page, pageSize, total, items.Select(MapBalance).ToList());
}
public async Task<StockTotalResponse?> GetItemTotalAsync(Guid itemId)
{
var item = await itemRepo.GetByIdAsync(itemId);
if (item is null || !item.IsActive) return null;
var balances = await repo.GetBalancesByItemAsync(itemId);
var total = balances.Sum(b => b.Quantity);
return new StockTotalResponse(itemId, item.Name, total, balances.Select(MapBalance).ToList());
}
public async Task<PagedResponse<StockMovementResponse>> GetMovementsAsync(
Guid? locationId, Guid? itemId, MovementType? type, DateTime? from, DateTime? to, int page, int pageSize)
{
var items = await repo.GetMovementsAsync(locationId, itemId, type, from, to, page, pageSize);
var total = await repo.GetMovementsCountAsync(locationId, itemId, type, from, to);
return new PagedResponse<StockMovementResponse>(page, pageSize, total, items.Select(MapMovement).ToList());
}
// ── Writes ─────────────────────────────────────────────────────────────
public async Task<StockMovementResponse> TransferAsync(TransferRequest request, Guid userId, CancellationToken ct = default)
{
await EnsureStockAsync(request.ItemId, request.FromLocationId, request.Quantity);
var movement = new StockMovement
{
FK_ItemId = request.ItemId,
FromLocationId = request.FromLocationId,
FromLocationType = request.FromLocationType,
ToLocationId = request.ToLocationId,
ToLocationType = request.ToLocationType,
Quantity = request.Quantity,
Type = MovementType.Transfer,
ReferenceId = request.ReferenceId,
CreatedBy = userId
};
await uow.BeginAsync(ct);
try
{
await ApplyTransferAsync(request.ItemId, request.FromLocationId, request.ToLocationId, request.ToLocationType, request.Quantity);
await repo.AddMovementAsync(movement);
await uow.CommitAsync(ct);
}
catch { await uow.RollbackAsync(ct); throw; }
return MapMovement(movement);
}
public async Task<StockMovementResponse> RecordDamageAsync(DamageRequest request, Guid userId, CancellationToken ct = default)
{
await EnsureStockAsync(request.ItemId, request.LocationId, request.Quantity);
var movement = new StockMovement
{
FK_ItemId = request.ItemId,
FromLocationId = request.LocationId,
FromLocationType = request.LocationType,
Quantity = request.Quantity,
Type = MovementType.Damage,
ReasonCode = request.ReasonCode,
CreatedBy = userId
};
await uow.BeginAsync(ct);
try
{
await DebitBalanceAsync(request.ItemId, request.LocationId, request.Quantity);
await repo.AddMovementAsync(movement);
await uow.CommitAsync(ct);
}
catch { await uow.RollbackAsync(ct); throw; }
return MapMovement(movement);
}
public async Task<StockMovementResponse> RecordCustomerReturnAsync(CustomerReturnRequest request, Guid userId, CancellationToken ct = default)
{
var item = await itemRepo.GetByIdAsync(request.ItemId)
?? throw new InvalidOperationException("Item not found.");
var category = await categoryRepo.GetByIdAsync(item.FK_CategoryId)
?? throw new InvalidOperationException("Category not found.");
if (!category.AllowCustomerReturn)
throw new InvalidOperationException($"Customer returns are not allowed for category '{category.Name}'.");
var movement = new StockMovement
{
FK_ItemId = request.ItemId,
ToLocationId = request.VehicleId,
ToLocationType = LocationType.Vehicle,
Quantity = request.Quantity,
Type = MovementType.CustomerReturn,
ReferenceId = request.ReferenceId,
CreatedBy = userId
};
await uow.BeginAsync(ct);
try
{
await CreditBalanceAsync(request.ItemId, request.VehicleId, LocationType.Vehicle, request.Quantity);
await repo.AddMovementAsync(movement);
await uow.CommitAsync(ct);
}
catch { await uow.RollbackAsync(ct); throw; }
return MapMovement(movement);
}
public async Task<StockMovementResponse> AdjustAsync(AdjustmentRequest request, Guid userId, CancellationToken ct = default)
{
var balance = await repo.GetBalanceAsync(request.ItemId, request.LocationId);
if (balance is not null && balance.Quantity + request.Quantity < 0)
throw new InvalidOperationException("Adjustment would result in negative stock.");
var movement = new StockMovement
{
FK_ItemId = request.ItemId,
FromLocationId = request.Quantity < 0 ? request.LocationId : null,
FromLocationType = request.Quantity < 0 ? request.LocationType : null,
ToLocationId = request.Quantity > 0 ? request.LocationId : null,
ToLocationType = request.Quantity > 0 ? request.LocationType : null,
Quantity = Math.Abs(request.Quantity),
Type = MovementType.Adjustment,
ReasonCode = request.ReasonCode,
CreatedBy = userId
};
await uow.BeginAsync(ct);
try
{
if (balance is null)
{
await repo.AddBalanceAsync(new StockBalance
{
FK_ItemId = request.ItemId,
LocationId = request.LocationId,
LocationType = request.LocationType,
Quantity = request.Quantity
});
}
else
{
balance.Quantity += request.Quantity;
balance.UpdatedAt = DateTime.Now;
repo.UpdateBalance(balance);
}
await repo.AddMovementAsync(movement);
await uow.CommitAsync(ct);
}
catch { await uow.RollbackAsync(ct); throw; }
return MapMovement(movement);
}
// ── Helpers ────────────────────────────────────────────────────────────
private async Task EnsureStockAsync(Guid itemId, Guid locationId, decimal quantity)
{
var balance = await repo.GetBalanceAsync(itemId, locationId);
if (balance is null || balance.Quantity < quantity)
throw new InvalidOperationException("Insufficient stock at the specified location.");
}
private async Task DebitBalanceAsync(Guid itemId, Guid locationId, decimal quantity)
{
var balance = await repo.GetBalanceAsync(itemId, locationId)
?? throw new InvalidOperationException("No stock balance found.");
balance.Quantity -= quantity;
balance.UpdatedAt = DateTime.Now;
repo.UpdateBalance(balance);
}
private async Task CreditBalanceAsync(Guid itemId, Guid locationId, LocationType locationType, decimal quantity)
{
var balance = await repo.GetBalanceAsync(itemId, locationId);
if (balance is null)
{
await repo.AddBalanceAsync(new StockBalance
{
FK_ItemId = itemId,
LocationId = locationId,
LocationType = locationType,
Quantity = quantity
});
}
else
{
balance.Quantity += quantity;
balance.UpdatedAt = DateTime.Now;
repo.UpdateBalance(balance);
}
}
private async Task ApplyTransferAsync(Guid itemId, Guid fromLocationId, Guid toLocationId, LocationType toLocationType, decimal quantity)
{
await DebitBalanceAsync(itemId, fromLocationId, quantity);
await CreditBalanceAsync(itemId, toLocationId, toLocationType, quantity);
}
}
@@ -1,362 +0,0 @@
// <auto-generated />
using System;
using Distribution.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Distribution.Migrations
{
[DbContext(typeof(AppDBContext))]
[Migration("20260818065939_initialDbCreate")]
partial class initialDbCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Distribution.Models.DeliveryRun", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid>("FK_RouteId")
.HasColumnType("char(36)");
b.Property<Guid>("FK_VehicleId")
.HasColumnType("char(36)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<int>("Meterend")
.HasColumnType("int");
b.Property<int>("Meterstart")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("FK_RouteId");
b.HasIndex("FK_VehicleId");
b.ToTable("DeliveryRuns");
});
modelBuilder.Entity("Distribution.Models.Item", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.HasKey("Id");
b.ToTable("Items");
});
modelBuilder.Entity("Distribution.Models.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid>("FK_StoreId")
.HasColumnType("char(36)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("OrderDate")
.HasColumnType("datetime(6)");
b.Property<decimal>("TotalAmount")
.HasColumnType("decimal(18,2)");
b.HasKey("Id");
b.HasIndex("FK_StoreId");
b.ToTable("Orders");
});
modelBuilder.Entity("Distribution.Models.OrderItem", b =>
{
b.Property<Guid>("FK_OrderId")
.HasColumnType("char(36)");
b.Property<Guid>("FK_ItemId")
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid>("Id")
.HasColumnType("char(36)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<int>("Quantity")
.HasColumnType("int");
b.HasKey("FK_OrderId", "FK_ItemId");
b.HasIndex("FK_ItemId");
b.ToTable("OrderItems");
});
modelBuilder.Entity("Distribution.Models.Region", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("Regions");
});
modelBuilder.Entity("Distribution.Models.Route", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("EndPoint")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<decimal>("Length")
.HasColumnType("decimal(18,2)");
b.Property<string>("RouteName")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("StartPoint")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("Routes");
});
modelBuilder.Entity("Distribution.Models.SaleRoute", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.HasKey("Id");
b.ToTable("SaleRoutes");
});
modelBuilder.Entity("Distribution.Models.Store", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<decimal>("CreditAmount")
.HasColumnType("decimal(18,2)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<decimal>("Latitude")
.HasColumnType("decimal(18,2)");
b.Property<decimal>("Longitude")
.HasColumnType("decimal(18,2)");
b.Property<decimal>("OneTimeAmount")
.HasColumnType("decimal(18,2)");
b.Property<string>("OwnerName")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("StoreAddress")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("StoreName")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("Stores");
});
modelBuilder.Entity("Distribution.Models.Vehicle", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<string>("NumberPlate")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("RegNumber")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Vehicles");
});
modelBuilder.Entity("Distribution.Models.Warehouse", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<string>("Location")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("Type")
.HasColumnType("int");
b.Property<Guid?>("VehicleId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("VehicleId");
b.ToTable("Warehouses");
});
modelBuilder.Entity("Distribution.Models.DeliveryRun", b =>
{
b.HasOne("Distribution.Models.Route", "Route")
.WithMany()
.HasForeignKey("FK_RouteId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Distribution.Models.Vehicle", "Vehicle")
.WithMany()
.HasForeignKey("FK_VehicleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Route");
b.Navigation("Vehicle");
});
modelBuilder.Entity("Distribution.Models.Order", b =>
{
b.HasOne("Distribution.Models.Store", "Store")
.WithMany()
.HasForeignKey("FK_StoreId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Store");
});
modelBuilder.Entity("Distribution.Models.OrderItem", b =>
{
b.HasOne("Distribution.Models.Item", "Item")
.WithMany()
.HasForeignKey("FK_ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Distribution.Models.Order", "Order")
.WithMany()
.HasForeignKey("FK_OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Item");
b.Navigation("Order");
});
modelBuilder.Entity("Distribution.Models.Warehouse", b =>
{
b.HasOne("Distribution.Models.Vehicle", "Vehicle")
.WithMany()
.HasForeignKey("VehicleId");
b.Navigation("Vehicle");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,281 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class initialDbCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Items",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", 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_Items", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Regions",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "longtext", 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_Regions", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Routes",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
RouteName = table.Column<string>(type: "longtext", nullable: false),
StartPoint = table.Column<string>(type: "longtext", nullable: false),
EndPoint = table.Column<string>(type: "longtext", nullable: false),
Length = table.Column<decimal>(type: "decimal(18,2)", 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_Routes", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "SaleRoutes",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", 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_SaleRoutes", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Stores",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
OwnerName = table.Column<string>(type: "longtext", nullable: false),
StoreName = table.Column<string>(type: "longtext", nullable: false),
StoreAddress = table.Column<string>(type: "longtext", nullable: false),
Latitude = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
Longitude = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
OneTimeAmount = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
CreditAmount = table.Column<decimal>(type: "decimal(18,2)", 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_Stores", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Vehicles",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
RegNumber = table.Column<string>(type: "longtext", nullable: false),
NumberPlate = table.Column<string>(type: "longtext", nullable: false),
Type = table.Column<int>(type: "int", 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_Vehicles", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Orders",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
OrderDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
FK_StoreId = table.Column<Guid>(type: "char(36)", nullable: false),
TotalAmount = table.Column<decimal>(type: "decimal(18,2)", 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_Orders", x => x.Id);
table.ForeignKey(
name: "FK_Orders_Stores_FK_StoreId",
column: x => x.FK_StoreId,
principalTable: "Stores",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "DeliveryRuns",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
FK_VehicleId = table.Column<Guid>(type: "char(36)", nullable: false),
Meterstart = table.Column<int>(type: "int", nullable: false),
Meterend = table.Column<int>(type: "int", nullable: false),
FK_RouteId = table.Column<Guid>(type: "char(36)", 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_DeliveryRuns", x => x.Id);
table.ForeignKey(
name: "FK_DeliveryRuns_Routes_FK_RouteId",
column: x => x.FK_RouteId,
principalTable: "Routes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DeliveryRuns_Vehicles_FK_VehicleId",
column: x => x.FK_VehicleId,
principalTable: "Vehicles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Warehouses",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "longtext", nullable: false),
Location = table.Column<string>(type: "longtext", nullable: false),
Type = table.Column<int>(type: "int", nullable: false),
VehicleId = table.Column<Guid>(type: "char(36)", 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_Warehouses", x => x.Id);
table.ForeignKey(
name: "FK_Warehouses_Vehicles_VehicleId",
column: x => x.VehicleId,
principalTable: "Vehicles",
principalColumn: "Id");
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "OrderItems",
columns: table => new
{
FK_OrderId = table.Column<Guid>(type: "char(36)", nullable: false),
FK_ItemId = table.Column<Guid>(type: "char(36)", nullable: false),
Quantity = table.Column<int>(type: "int", nullable: false),
Id = table.Column<Guid>(type: "char(36)", 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_OrderItems", x => new { x.FK_OrderId, x.FK_ItemId });
table.ForeignKey(
name: "FK_OrderItems_Items_FK_ItemId",
column: x => x.FK_ItemId,
principalTable: "Items",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_OrderItems_Orders_FK_OrderId",
column: x => x.FK_OrderId,
principalTable: "Orders",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_DeliveryRuns_FK_RouteId",
table: "DeliveryRuns",
column: "FK_RouteId");
migrationBuilder.CreateIndex(
name: "IX_DeliveryRuns_FK_VehicleId",
table: "DeliveryRuns",
column: "FK_VehicleId");
migrationBuilder.CreateIndex(
name: "IX_OrderItems_FK_ItemId",
table: "OrderItems",
column: "FK_ItemId");
migrationBuilder.CreateIndex(
name: "IX_Orders_FK_StoreId",
table: "Orders",
column: "FK_StoreId");
migrationBuilder.CreateIndex(
name: "IX_Warehouses_VehicleId",
table: "Warehouses",
column: "VehicleId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "DeliveryRuns");
migrationBuilder.DropTable(
name: "OrderItems");
migrationBuilder.DropTable(
name: "Regions");
migrationBuilder.DropTable(
name: "SaleRoutes");
migrationBuilder.DropTable(
name: "Warehouses");
migrationBuilder.DropTable(
name: "Routes");
migrationBuilder.DropTable(
name: "Items");
migrationBuilder.DropTable(
name: "Orders");
migrationBuilder.DropTable(
name: "Vehicles");
migrationBuilder.DropTable(
name: "Stores");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,456 +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 AddUserManagement : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Guid>(
name: "FK_RouteId",
table: "Stores",
type: "char(36)",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.AddColumn<Guid>(
name: "FK_RegionId",
table: "Routes",
type: "char(36)",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.CreateTable(
name: "Permissions",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Code = table.Column<string>(type: "longtext", nullable: false),
Description = table.Column<string>(type: "longtext", 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_Permissions", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Roles",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "longtext", nullable: false),
Level = table.Column<int>(type: "int", 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_Roles", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "RolePermissions",
columns: table => new
{
FK_RoleId = table.Column<Guid>(type: "char(36)", nullable: false),
FK_PermissionId = table.Column<Guid>(type: "char(36)", nullable: false),
Id = table.Column<Guid>(type: "char(36)", 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_RolePermissions", x => new { x.FK_RoleId, x.FK_PermissionId });
table.ForeignKey(
name: "FK_RolePermissions_Permissions_FK_PermissionId",
column: x => x.FK_PermissionId,
principalTable: "Permissions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RolePermissions_Roles_FK_RoleId",
column: x => x.FK_RoleId,
principalTable: "Roles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Username = table.Column<string>(type: "longtext", nullable: false),
PasswordHash = table.Column<string>(type: "longtext", nullable: false),
FullName = table.Column<string>(type: "longtext", nullable: false),
FK_RoleId = table.Column<Guid>(type: "char(36)", nullable: false),
FK_ReportsToUserId = table.Column<Guid>(type: "char(36)", nullable: true),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", 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_Users", x => x.Id);
table.ForeignKey(
name: "FK_Users_Roles_FK_RoleId",
column: x => x.FK_RoleId,
principalTable: "Roles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Users_Users_FK_ReportsToUserId",
column: x => x.FK_ReportsToUserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserRegionScopes",
columns: table => new
{
FK_UserId = table.Column<Guid>(type: "char(36)", nullable: false),
FK_RegionId = table.Column<Guid>(type: "char(36)", nullable: false),
Id = table.Column<Guid>(type: "char(36)", 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_UserRegionScopes", x => new { x.FK_UserId, x.FK_RegionId });
table.ForeignKey(
name: "FK_UserRegionScopes_Regions_FK_RegionId",
column: x => x.FK_RegionId,
principalTable: "Regions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_UserRegionScopes_Users_FK_UserId",
column: x => x.FK_UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserRouteScopes",
columns: table => new
{
FK_UserId = table.Column<Guid>(type: "char(36)", nullable: false),
FK_RouteId = table.Column<Guid>(type: "char(36)", nullable: false),
Id = table.Column<Guid>(type: "char(36)", 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_UserRouteScopes", x => new { x.FK_UserId, x.FK_RouteId });
table.ForeignKey(
name: "FK_UserRouteScopes_Routes_FK_RouteId",
column: x => x.FK_RouteId,
principalTable: "Routes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_UserRouteScopes_Users_FK_UserId",
column: x => x.FK_UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "UserStoreScopes",
columns: table => new
{
FK_UserId = table.Column<Guid>(type: "char(36)", nullable: false),
FK_StoreId = table.Column<Guid>(type: "char(36)", nullable: false),
Id = table.Column<Guid>(type: "char(36)", 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_UserStoreScopes", x => new { x.FK_UserId, x.FK_StoreId });
table.ForeignKey(
name: "FK_UserStoreScopes_Stores_FK_StoreId",
column: x => x.FK_StoreId,
principalTable: "Stores",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_UserStoreScopes_Users_FK_UserId",
column: x => x.FK_UserId,
principalTable: "Users",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.InsertData(
table: "Permissions",
columns: new[] { "Id", "Code", "CreatedAt", "Description", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000001"), "regions.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View regions", true },
{ new Guid("20000000-0000-0000-0000-000000000002"), "regions.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create regions", true },
{ new Guid("20000000-0000-0000-0000-000000000003"), "regions.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update regions", true },
{ new Guid("20000000-0000-0000-0000-000000000004"), "regions.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete regions", true },
{ new Guid("20000000-0000-0000-0000-000000000005"), "routes.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View routes", true },
{ new Guid("20000000-0000-0000-0000-000000000006"), "routes.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create routes", true },
{ new Guid("20000000-0000-0000-0000-000000000007"), "routes.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update routes", true },
{ new Guid("20000000-0000-0000-0000-000000000008"), "routes.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete routes", true },
{ new Guid("20000000-0000-0000-0000-000000000009"), "vehicles.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View vehicles", true },
{ new Guid("20000000-0000-0000-0000-000000000010"), "vehicles.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create vehicles", true },
{ new Guid("20000000-0000-0000-0000-000000000011"), "vehicles.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update vehicles", true },
{ new Guid("20000000-0000-0000-0000-000000000012"), "vehicles.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete vehicles", true },
{ new Guid("20000000-0000-0000-0000-000000000013"), "stores.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View stores", true },
{ new Guid("20000000-0000-0000-0000-000000000014"), "stores.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create stores", true },
{ new Guid("20000000-0000-0000-0000-000000000015"), "stores.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update stores", true },
{ new Guid("20000000-0000-0000-0000-000000000016"), "stores.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete stores", true },
{ new Guid("20000000-0000-0000-0000-000000000017"), "warehouses.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View warehouses", true },
{ new Guid("20000000-0000-0000-0000-000000000018"), "warehouses.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create warehouses", true },
{ new Guid("20000000-0000-0000-0000-000000000019"), "warehouses.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update warehouses", true },
{ new Guid("20000000-0000-0000-0000-000000000020"), "warehouses.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete warehouses", true },
{ new Guid("20000000-0000-0000-0000-000000000021"), "orders.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View orders", true },
{ new Guid("20000000-0000-0000-0000-000000000022"), "orders.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create orders", true },
{ new Guid("20000000-0000-0000-0000-000000000023"), "orders.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update orders", true },
{ new Guid("20000000-0000-0000-0000-000000000024"), "orders.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete orders", true },
{ new Guid("20000000-0000-0000-0000-000000000025"), "users.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View users", true },
{ new Guid("20000000-0000-0000-0000-000000000026"), "users.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create users", true },
{ new Guid("20000000-0000-0000-0000-000000000027"), "users.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update users", true },
{ new Guid("20000000-0000-0000-0000-000000000028"), "users.deactivate", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Deactivate users", true },
{ new Guid("20000000-0000-0000-0000-000000000029"), "users.assign_role", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Assign a role to a user", true },
{ new Guid("20000000-0000-0000-0000-000000000030"), "users.assign_scope", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Assign region/route/store scope to a user", true }
});
migrationBuilder.InsertData(
table: "Roles",
columns: new[] { "Id", "CreatedAt", "IsActive", "Level", "Name" },
values: new object[,]
{
{ new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), true, 10, "SalesRep" },
{ new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), true, 20, "Supervisor" },
{ new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), true, 30, "AreaManager" },
{ new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), true, 40, "AreaSupervisor" },
{ new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), true, 50, "RegionalManager" },
{ new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), true, 60, "RegionalAgency" }
});
migrationBuilder.InsertData(
table: "RolePermissions",
columns: new[] { "FK_PermissionId", "FK_RoleId", "CreatedAt", "Id", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("75737fa8-fed0-d97a-8c24-5716758a7222"), true },
{ new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("0e0613fd-d62c-1e87-a5b6-8bd2c3697c2a"), true },
{ 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-000000000023"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("dfe4bb14-1047-219c-cabe-a2b49b105d86"), true },
{ new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7ee233b9-3758-e005-7bb2-5ad1edf36e21"), true },
{ new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("eb4ffa50-b09a-f0a5-1994-3fc2ae3a35d0"), true },
{ new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5adb4d1a-eba8-16cb-8603-c3443d4ee8c8"), true },
{ new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("23105bb1-ef1f-6e19-1a48-d62ccaec1db4"), 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-000000000023"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e1f39dc4-6c33-45f4-8c23-3ad8ae5784a8"), true },
{ new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("357c36de-9b6c-1c9a-4926-c18a9bccf0ca"), true },
{ new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e9c8355a-26a9-4107-504e-d61722f9e7cd"), true },
{ new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7fef12f3-6875-14bb-9554-0c9d82f02a37"), true },
{ new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("680b582c-dbc9-cfde-f54b-58c3ad5a57b6"), true },
{ new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("0b7d47cf-efd9-9589-682b-78df22062e5a"), true },
{ new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4aaa0f3d-4360-5f11-41c1-5257662428af"), true },
{ new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("38ea5531-a29d-a6bb-eebe-a18f3afe066d"), 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-000000000023"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5cee999e-1b77-cb87-5148-6a793af7c44e"), true },
{ new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("73e00ce7-c124-4677-4369-1eb9876852c0"), true },
{ new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("c6d74049-3f46-88af-1067-c9ae133132f7"), true },
{ new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("29d71000-6715-de8a-a3af-814938d50dfb"), true },
{ new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f58f4242-af91-0b8d-5be5-4b07b4367e8c"), true },
{ new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("dafe8f7e-e527-5863-5cde-92599c4ba9eb"), true },
{ new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("76f58da8-09f6-c4e2-01bd-ddd94809c1f5"), true },
{ new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("c99adad6-94e8-0d5b-3d35-086f393207fb"), true },
{ new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b22d4f78-7a21-da50-5351-553bdf06c9c2"), true },
{ new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3cb22998-b618-c13f-48cd-9e7416f324fc"), 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-000000000023"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("db15215a-0a16-ef1f-5c82-6bb902a2b319"), true },
{ new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7b4f3482-b8bd-d348-e4c1-ae6dc93a3771"), true },
{ new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3e3e6f06-72c8-42fa-f7e6-8feeaca36d60"), true },
{ new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d95e7d5a-b12c-12b8-fee9-39576c905fed"), true },
{ new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d97abb20-e53d-c970-d337-3764584874fa"), true },
{ new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a63446ad-14a9-6239-8791-0a1f86813903"), true },
{ new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7f9502a2-feb4-f0ef-cb71-a62d00570fd0"), true },
{ new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d1f4316a-72a0-66af-2a8a-1fdbdb4f8c3a"), true },
{ new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("30e94e9b-c70c-2df3-0813-e99ce4511838"), true },
{ new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("94f2f2ec-94b7-b768-76a4-9ee4256d95c1"), true },
{ new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7201efa2-f829-8035-6607-174214f8fdba"), true },
{ new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("fcc6af61-cc43-066c-5634-2ddc24a8460d"), true },
{ new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("2f994b6b-b055-28c2-2fb1-99a0076a0e3f"), true },
{ new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("55e84a29-428d-bf95-d589-793ecd8bac6e"), true },
{ new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("43ec940a-44d2-9c47-a37d-049f2cfb2615"), true },
{ new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("ee175c87-23bd-5529-ed18-6ce46985c6ed"), true },
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("2ae2eba4-4427-ab1e-cf03-e59a3925ef89"), true },
{ new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("c88131d2-51b2-2bac-ad15-c7c130eb26f8"), true },
{ new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3a2ccc28-7416-388d-17f2-424d0520049f"), true },
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("08de9913-8cfc-4ab4-2cb9-2bc9217fbb6e"), true },
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f3c8f315-3b2f-f923-e3cd-f3e575010138"), true },
{ new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4d682c93-d6df-4214-436d-85f76a3ade93"), true },
{ new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4b2c3b3b-c27d-410c-c1fc-7e43e280242f"), true },
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("1d227ae7-0eb9-c742-41df-3472718cb077"), true },
{ new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f64e20e2-f9ca-7ea5-42f4-c1256b0c0798"), true },
{ new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7b6765bc-1510-cfc6-55ae-ac689caf0dcc"), true },
{ new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d9e06d2d-82d6-84e8-e9ba-5406e9b4122d"), true },
{ new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b53e01bb-4e54-3270-87b1-0d54f947e09b"), true },
{ new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("111b7d3c-3640-66e6-0757-b9fb67572943"), true },
{ new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7ee06ff0-8557-b5bd-02dc-c4ff99e76348"), true },
{ new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d20bcba0-a5af-de47-919d-a8645a828d27"), true },
{ new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b3ef35de-afc2-d80a-115f-77ba954f9586"), true },
{ new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d1b7e0a2-149f-b56b-8c63-bb8d10bfcc1e"), true },
{ new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("51e06fd0-cd20-ceeb-04cc-7dc79388c4a1"), true },
{ new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("25639115-7083-1324-c3bd-3ad90fcfa1a0"), true },
{ new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("51011cb7-5753-14ad-280c-86a6bd33124f"), true },
{ new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("51ce3fad-cdbc-cfad-6cf0-52b47ec3f200"), true },
{ new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4a080973-c23f-3d1b-9883-6b7e06025a77"), true },
{ new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3f78910a-76ee-f34b-52d3-af79d7f3b724"), true },
{ new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("812cbb8d-e268-aad3-373e-42b8720f0f45"), true },
{ new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("046cd13e-77f1-78c7-fa52-d49ea7fb9855"), true },
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("96f24adf-386d-14d0-46fe-a22ceff2f79b"), true },
{ new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("9b5f23fb-2396-3f43-1d3e-97551eb4248d"), true },
{ new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("30397d69-3b96-56e7-0ca1-1e612dfb64f1"), true },
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("91260fa1-3754-ad7e-10d8-2a8fd9b208ff"), true },
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("8b993e65-b066-198a-385d-602660ed85ac"), true },
{ new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("248d6092-c2e5-5f8f-5ef0-cd60dc94cbc8"), true },
{ new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5f6e3c68-27d2-e00f-d5c9-4ce9e2b9587f"), true },
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("96a4ac9e-cfea-6391-8020-75b2980bf2a3"), true },
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("6eb59953-807d-aa61-29e3-1699c0aebda9"), true },
{ new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("1095440c-ce52-235b-b95f-6b28c5d1b3a8"), true },
{ new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3a56ab5c-f0c5-a37b-0795-de061597628f"), true },
{ new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("104ebcfb-ca82-3f95-d75e-35a943618176"), true },
{ new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("ace990cf-6654-5e68-3dc8-1e62347e0946"), true }
});
migrationBuilder.CreateIndex(
name: "IX_Stores_FK_RouteId",
table: "Stores",
column: "FK_RouteId");
migrationBuilder.CreateIndex(
name: "IX_Routes_FK_RegionId",
table: "Routes",
column: "FK_RegionId");
migrationBuilder.CreateIndex(
name: "IX_RolePermissions_FK_PermissionId",
table: "RolePermissions",
column: "FK_PermissionId");
migrationBuilder.CreateIndex(
name: "IX_UserRegionScopes_FK_RegionId",
table: "UserRegionScopes",
column: "FK_RegionId");
migrationBuilder.CreateIndex(
name: "IX_UserRouteScopes_FK_RouteId",
table: "UserRouteScopes",
column: "FK_RouteId");
migrationBuilder.CreateIndex(
name: "IX_Users_FK_ReportsToUserId",
table: "Users",
column: "FK_ReportsToUserId");
migrationBuilder.CreateIndex(
name: "IX_Users_FK_RoleId",
table: "Users",
column: "FK_RoleId");
migrationBuilder.CreateIndex(
name: "IX_UserStoreScopes_FK_StoreId",
table: "UserStoreScopes",
column: "FK_StoreId");
migrationBuilder.AddForeignKey(
name: "FK_Routes_Regions_FK_RegionId",
table: "Routes",
column: "FK_RegionId",
principalTable: "Regions",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Stores_Routes_FK_RouteId",
table: "Stores",
column: "FK_RouteId",
principalTable: "Routes",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Routes_Regions_FK_RegionId",
table: "Routes");
migrationBuilder.DropForeignKey(
name: "FK_Stores_Routes_FK_RouteId",
table: "Stores");
migrationBuilder.DropTable(
name: "RolePermissions");
migrationBuilder.DropTable(
name: "UserRegionScopes");
migrationBuilder.DropTable(
name: "UserRouteScopes");
migrationBuilder.DropTable(
name: "UserStoreScopes");
migrationBuilder.DropTable(
name: "Permissions");
migrationBuilder.DropTable(
name: "Users");
migrationBuilder.DropTable(
name: "Roles");
migrationBuilder.DropIndex(
name: "IX_Stores_FK_RouteId",
table: "Stores");
migrationBuilder.DropIndex(
name: "IX_Routes_FK_RegionId",
table: "Routes");
migrationBuilder.DropColumn(
name: "FK_RouteId",
table: "Stores");
migrationBuilder.DropColumn(
name: "FK_RegionId",
table: "Routes");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,621 +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 AddItemCatalog : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<decimal>(
name: "UnitPrice",
table: "OrderItems",
type: "decimal(18,2)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<string>(
name: "Description",
table: "Items",
type: "longtext",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "ExternalErpItemId",
table: "Items",
type: "int",
nullable: true);
migrationBuilder.AddColumn<Guid>(
name: "FK_BaseUomId",
table: "Items",
type: "char(36)",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.AddColumn<Guid>(
name: "FK_BrandId",
table: "Items",
type: "char(36)",
nullable: true);
migrationBuilder.AddColumn<Guid>(
name: "FK_CategoryId",
table: "Items",
type: "char(36)",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.AddColumn<Guid>(
name: "FK_SubCategoryId",
table: "Items",
type: "char(36)",
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "LastSyncedAt",
table: "Items",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Name",
table: "Items",
type: "longtext",
nullable: false);
migrationBuilder.AddColumn<decimal>(
name: "SalePrice",
table: "Items",
type: "decimal(18,2)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Sku",
table: "Items",
type: "longtext",
nullable: false);
migrationBuilder.AddColumn<int>(
name: "SyncSource",
table: "Items",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateTable(
name: "Brands",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "longtext", nullable: false),
ExternalErpId = table.Column<int>(type: "int", 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_Brands", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Categories",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "longtext", nullable: false),
ExternalErpId = table.Column<int>(type: "int", 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_Categories", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "Uoms",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "longtext", nullable: false),
ExternalErpId = table.Column<int>(type: "int", 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_Uoms", x => x.Id);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "SubCategories",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "longtext", nullable: false),
FK_CategoryId = table.Column<Guid>(type: "char(36)", nullable: false),
ExternalErpId = table.Column<int>(type: "int", 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_SubCategories", x => x.Id);
table.ForeignKey(
name: "FK_SubCategories_Categories_FK_CategoryId",
column: x => x.FK_CategoryId,
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "UomConversions",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
FK_ItemId = table.Column<Guid>(type: "char(36)", nullable: false),
FK_FromUomId = table.Column<Guid>(type: "char(36)", nullable: false),
FK_ToUomId = table.Column<Guid>(type: "char(36)", nullable: false),
Factor = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UomConversions", x => x.Id);
table.ForeignKey(
name: "FK_UomConversions_Items_FK_ItemId",
column: x => x.FK_ItemId,
principalTable: "Items",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_UomConversions_Uoms_FK_FromUomId",
column: x => x.FK_FromUomId,
principalTable: "Uoms",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_UomConversions_Uoms_FK_ToUomId",
column: x => x.FK_ToUomId,
principalTable: "Uoms",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.InsertData(
table: "Permissions",
columns: new[] { "Id", "Code", "CreatedAt", "Description", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000031"), "items.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View items, brands and UOMs", true },
{ new Guid("20000000-0000-0000-0000-000000000032"), "items.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create items, brands and UOMs", true },
{ new Guid("20000000-0000-0000-0000-000000000033"), "items.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update items, brands and UOMs", true },
{ new Guid("20000000-0000-0000-0000-000000000034"), "items.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete items, brands and UOMs", true },
{ new Guid("20000000-0000-0000-0000-000000000035"), "categories.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View categories", true },
{ new Guid("20000000-0000-0000-0000-000000000036"), "categories.create", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create categories and subcategories", true },
{ new Guid("20000000-0000-0000-0000-000000000037"), "categories.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update categories and subcategories", true },
{ new Guid("20000000-0000-0000-0000-000000000038"), "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-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-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-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-000000000033"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d49f086e-30f0-6ce8-ae96-4395d5e04472"), true },
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("1e7fe1b6-5150-4b99-38ed-088d9495cfd8"), 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-000000000033"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7c392a13-1a57-0d85-dffa-2fb9e892abe9"), true },
{ new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("97708eed-6ce4-7710-abde-01d00c0c879b"), true },
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("9afe507e-191e-bdee-0c5a-cfbcbf1efb3e"), true },
{ new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("9c278616-4289-96fb-944d-b8f1495ccb00"), true },
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d1dcef02-d4c3-caba-372f-dab82011e9c1"), true },
{ new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("9cc36229-dfba-49b9-1d6e-8929546e894d"), 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 },
{ new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("0efa7259-aadb-0019-4be5-38d3f8f4cd54"), true },
{ new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("9e60e7d7-8bd6-c1c7-4bf1-4de2c9dcb91c"), true },
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5df82318-bc01-1947-09ef-60508e02b257"), true },
{ new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("34f478f4-6c96-4b31-b68a-28c7942c0789"), true },
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("69598e0e-b7ad-477b-c587-7abf6189162d"), true },
{ new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b36fb2d4-43df-44f8-ff51-de6d88644c94"), true },
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("bd209f90-6671-8ea0-eb20-aa151faec6a0"), true },
{ new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4cc32686-8391-0214-5747-db14f53c5b6f"), true },
{ new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("26c6d86a-835d-6f0d-3730-66a46ea26b11"), true },
{ new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e8039d9c-a286-fb74-5abb-b5c6c67f243a"), true },
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d9e038cb-bcff-cce1-5d34-b4e63a9ce694"), true },
{ new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("343e71f0-da6b-2489-5571-f8d7c6378ee7"), true },
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("ac894328-a935-8e6e-8427-6c0f36ac75da"), true },
{ new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("1d6273d4-db6a-d70e-4b5f-98cb634d668a"), true }
});
migrationBuilder.CreateIndex(
name: "IX_Items_FK_BaseUomId",
table: "Items",
column: "FK_BaseUomId");
migrationBuilder.CreateIndex(
name: "IX_Items_FK_BrandId",
table: "Items",
column: "FK_BrandId");
migrationBuilder.CreateIndex(
name: "IX_Items_FK_CategoryId",
table: "Items",
column: "FK_CategoryId");
migrationBuilder.CreateIndex(
name: "IX_Items_FK_SubCategoryId",
table: "Items",
column: "FK_SubCategoryId");
migrationBuilder.CreateIndex(
name: "IX_SubCategories_FK_CategoryId",
table: "SubCategories",
column: "FK_CategoryId");
migrationBuilder.CreateIndex(
name: "IX_UomConversions_FK_FromUomId",
table: "UomConversions",
column: "FK_FromUomId");
migrationBuilder.CreateIndex(
name: "IX_UomConversions_FK_ItemId",
table: "UomConversions",
column: "FK_ItemId");
migrationBuilder.CreateIndex(
name: "IX_UomConversions_FK_ToUomId",
table: "UomConversions",
column: "FK_ToUomId");
migrationBuilder.AddForeignKey(
name: "FK_Items_Brands_FK_BrandId",
table: "Items",
column: "FK_BrandId",
principalTable: "Brands",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Items_Categories_FK_CategoryId",
table: "Items",
column: "FK_CategoryId",
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Items_SubCategories_FK_SubCategoryId",
table: "Items",
column: "FK_SubCategoryId",
principalTable: "SubCategories",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Items_Uoms_FK_BaseUomId",
table: "Items",
column: "FK_BaseUomId",
principalTable: "Uoms",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Items_Brands_FK_BrandId",
table: "Items");
migrationBuilder.DropForeignKey(
name: "FK_Items_Categories_FK_CategoryId",
table: "Items");
migrationBuilder.DropForeignKey(
name: "FK_Items_SubCategories_FK_SubCategoryId",
table: "Items");
migrationBuilder.DropForeignKey(
name: "FK_Items_Uoms_FK_BaseUomId",
table: "Items");
migrationBuilder.DropTable(
name: "Brands");
migrationBuilder.DropTable(
name: "SubCategories");
migrationBuilder.DropTable(
name: "UomConversions");
migrationBuilder.DropTable(
name: "Categories");
migrationBuilder.DropTable(
name: "Uoms");
migrationBuilder.DropIndex(
name: "IX_Items_FK_BaseUomId",
table: "Items");
migrationBuilder.DropIndex(
name: "IX_Items_FK_BrandId",
table: "Items");
migrationBuilder.DropIndex(
name: "IX_Items_FK_CategoryId",
table: "Items");
migrationBuilder.DropIndex(
name: "IX_Items_FK_SubCategoryId",
table: "Items");
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-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-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-000000000033"), 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-000000000035"), 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-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-000000000033"), 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-000000000034"), 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-000000000035"), 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-000000000036"), 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-000000000037"), 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-000000000038"), 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.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-000000000005") });
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-000000000005") });
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-000000000005") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), 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-000000000037"), 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-000000000038"), 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-000000000031"), 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-000000000032"), 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-000000000033"), 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-000000000034"), 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-000000000035"), 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-000000000036"), 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-000000000037"), 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-000000000038"), new Guid("10000000-0000-0000-0000-000000000006") });
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000031"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000032"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000033"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000034"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000035"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000036"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000037"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000038"));
migrationBuilder.DropColumn(
name: "UnitPrice",
table: "OrderItems");
migrationBuilder.DropColumn(
name: "Description",
table: "Items");
migrationBuilder.DropColumn(
name: "ExternalErpItemId",
table: "Items");
migrationBuilder.DropColumn(
name: "FK_BaseUomId",
table: "Items");
migrationBuilder.DropColumn(
name: "FK_BrandId",
table: "Items");
migrationBuilder.DropColumn(
name: "FK_CategoryId",
table: "Items");
migrationBuilder.DropColumn(
name: "FK_SubCategoryId",
table: "Items");
migrationBuilder.DropColumn(
name: "LastSyncedAt",
table: "Items");
migrationBuilder.DropColumn(
name: "Name",
table: "Items");
migrationBuilder.DropColumn(
name: "SalePrice",
table: "Items");
migrationBuilder.DropColumn(
name: "Sku",
table: "Items");
migrationBuilder.DropColumn(
name: "SyncSource",
table: "Items");
}
}
}
@@ -1,164 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class item_catalog : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<decimal>(
name: "Factor",
table: "UomConversions",
type: "decimal(65,30)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)");
migrationBuilder.AlterColumn<decimal>(
name: "OneTimeAmount",
table: "Stores",
type: "decimal(65,30)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)");
migrationBuilder.AlterColumn<decimal>(
name: "Longitude",
table: "Stores",
type: "decimal(65,30)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)");
migrationBuilder.AlterColumn<decimal>(
name: "Latitude",
table: "Stores",
type: "decimal(65,30)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)");
migrationBuilder.AlterColumn<decimal>(
name: "CreditAmount",
table: "Stores",
type: "decimal(65,30)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)");
migrationBuilder.AlterColumn<decimal>(
name: "Length",
table: "Routes",
type: "decimal(65,30)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)");
migrationBuilder.AlterColumn<decimal>(
name: "TotalAmount",
table: "Orders",
type: "decimal(65,30)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)");
migrationBuilder.AlterColumn<decimal>(
name: "UnitPrice",
table: "OrderItems",
type: "decimal(65,30)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)");
migrationBuilder.AlterColumn<decimal>(
name: "SalePrice",
table: "Items",
type: "decimal(65,30)",
nullable: true,
oldClrType: typeof(decimal),
oldType: "decimal(18,2)",
oldNullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<decimal>(
name: "Factor",
table: "UomConversions",
type: "decimal(18,2)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)");
migrationBuilder.AlterColumn<decimal>(
name: "OneTimeAmount",
table: "Stores",
type: "decimal(18,2)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)");
migrationBuilder.AlterColumn<decimal>(
name: "Longitude",
table: "Stores",
type: "decimal(18,2)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)");
migrationBuilder.AlterColumn<decimal>(
name: "Latitude",
table: "Stores",
type: "decimal(18,2)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)");
migrationBuilder.AlterColumn<decimal>(
name: "CreditAmount",
table: "Stores",
type: "decimal(18,2)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)");
migrationBuilder.AlterColumn<decimal>(
name: "Length",
table: "Routes",
type: "decimal(18,2)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)");
migrationBuilder.AlterColumn<decimal>(
name: "TotalAmount",
table: "Orders",
type: "decimal(18,2)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)");
migrationBuilder.AlterColumn<decimal>(
name: "UnitPrice",
table: "OrderItems",
type: "decimal(18,2)",
nullable: false,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)");
migrationBuilder.AlterColumn<decimal>(
name: "SalePrice",
table: "Items",
type: "decimal(18,2)",
nullable: true,
oldClrType: typeof(decimal),
oldType: "decimal(65,30)",
oldNullable: true);
}
}
}
@@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Distribution.Migrations
{
[DbContext(typeof(AppDBContext))]
[Migration("20260819074545_item_catalog")]
partial class item_catalog
[Migration("20260819163125_init")]
partial class init
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -55,6 +55,9 @@ namespace Distribution.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<bool>("AllowCustomerReturn")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
@@ -1682,6 +1685,81 @@ namespace Distribution.Migrations
b.ToTable("SaleRoutes");
});
modelBuilder.Entity("Distribution.Models.StockBalance", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<Guid>("FK_ItemId")
.HasColumnType("char(36)");
b.Property<Guid>("LocationId")
.HasColumnType("char(36)");
b.Property<int>("LocationType")
.HasColumnType("int");
b.Property<decimal>("Quantity")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("FK_ItemId", "LocationId")
.IsUnique();
b.ToTable("StockBalances");
});
modelBuilder.Entity("Distribution.Models.StockMovement", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid>("CreatedBy")
.HasColumnType("char(36)");
b.Property<Guid>("FK_ItemId")
.HasColumnType("char(36)");
b.Property<Guid?>("FromLocationId")
.HasColumnType("char(36)");
b.Property<int?>("FromLocationType")
.HasColumnType("int");
b.Property<decimal>("Quantity")
.HasColumnType("decimal(65,30)");
b.Property<string>("ReasonCode")
.HasColumnType("longtext");
b.Property<Guid?>("ReferenceId")
.HasColumnType("char(36)");
b.Property<Guid?>("ToLocationId")
.HasColumnType("char(36)");
b.Property<int?>("ToLocationType")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("FK_ItemId");
b.ToTable("StockMovements");
});
modelBuilder.Entity("Distribution.Models.Store", b =>
{
b.Property<Guid>("Id")
@@ -2095,6 +2173,28 @@ namespace Distribution.Migrations
b.Navigation("Region");
});
modelBuilder.Entity("Distribution.Models.StockBalance", b =>
{
b.HasOne("Distribution.Models.Item", "Item")
.WithMany()
.HasForeignKey("FK_ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Item");
});
modelBuilder.Entity("Distribution.Models.StockMovement", b =>
{
b.HasOne("Distribution.Models.Item", "Item")
.WithMany()
.HasForeignKey("FK_ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Item");
});
modelBuilder.Entity("Distribution.Models.Store", b =>
{
b.HasOne("Distribution.Models.Route", "Route")
File diff suppressed because it is too large Load Diff
@@ -52,6 +52,9 @@ namespace Distribution.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<bool>("AllowCustomerReturn")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
@@ -1679,6 +1682,81 @@ namespace Distribution.Migrations
b.ToTable("SaleRoutes");
});
modelBuilder.Entity("Distribution.Models.StockBalance", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<Guid>("FK_ItemId")
.HasColumnType("char(36)");
b.Property<Guid>("LocationId")
.HasColumnType("char(36)");
b.Property<int>("LocationType")
.HasColumnType("int");
b.Property<decimal>("Quantity")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("FK_ItemId", "LocationId")
.IsUnique();
b.ToTable("StockBalances");
});
modelBuilder.Entity("Distribution.Models.StockMovement", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<Guid>("CreatedBy")
.HasColumnType("char(36)");
b.Property<Guid>("FK_ItemId")
.HasColumnType("char(36)");
b.Property<Guid?>("FromLocationId")
.HasColumnType("char(36)");
b.Property<int?>("FromLocationType")
.HasColumnType("int");
b.Property<decimal>("Quantity")
.HasColumnType("decimal(65,30)");
b.Property<string>("ReasonCode")
.HasColumnType("longtext");
b.Property<Guid?>("ReferenceId")
.HasColumnType("char(36)");
b.Property<Guid?>("ToLocationId")
.HasColumnType("char(36)");
b.Property<int?>("ToLocationType")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("FK_ItemId");
b.ToTable("StockMovements");
});
modelBuilder.Entity("Distribution.Models.Store", b =>
{
b.Property<Guid>("Id")
@@ -2092,6 +2170,28 @@ namespace Distribution.Migrations
b.Navigation("Region");
});
modelBuilder.Entity("Distribution.Models.StockBalance", b =>
{
b.HasOne("Distribution.Models.Item", "Item")
.WithMany()
.HasForeignKey("FK_ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Item");
});
modelBuilder.Entity("Distribution.Models.StockMovement", b =>
{
b.HasOne("Distribution.Models.Item", "Item")
.WithMany()
.HasForeignKey("FK_ItemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Item");
});
modelBuilder.Entity("Distribution.Models.Store", b =>
{
b.HasOne("Distribution.Models.Route", "Route")
+1
View File
@@ -4,5 +4,6 @@ namespace Distribution.Models
{
public string Name { get; set; }
public int? ExternalErpId { get; set; }
public bool AllowCustomerReturn { get; set; } = false;
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace Distribution.Models
{
public enum LocationType { Warehouse, Vehicle }
public enum MovementType
{
Sale,
CustomerReturn,
Transfer,
Damage,
Adjustment
}
}
+19
View File
@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Distribution.Models
{
public class StockBalance
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid FK_ItemId { get; set; }
[ForeignKey("FK_ItemId")]
public Item Item { get; set; }
public Guid LocationId { get; set; }
public LocationType LocationType { get; set; }
public decimal Quantity { get; set; }
public DateTime UpdatedAt { get; set; } = DateTime.Now;
}
}
+28
View File
@@ -0,0 +1,28 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Distribution.Models
{
public class StockMovement
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid FK_ItemId { get; set; }
[ForeignKey("FK_ItemId")]
public Item Item { get; set; }
public Guid? FromLocationId { get; set; }
public LocationType? FromLocationType { get; set; }
public Guid? ToLocationId { get; set; }
public LocationType? ToLocationType { get; set; }
public decimal Quantity { get; set; }
public MovementType Type { get; set; }
public string? ReasonCode { get; set; }
public Guid? ReferenceId { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.Now;
public Guid CreatedBy { get; set; }
}
}
+3
View File
@@ -13,6 +13,7 @@ using Distribution.Features.Sync;
using Distribution.Features.Uom;
using Distribution.Features.User;
using Distribution.Features.Vehicle;
using Distribution.Features.Stock;
using Distribution.Features.Warehouse;
using Distribution.Infra.Authorization;
using Distribution.Infra.UoW;
@@ -44,6 +45,7 @@ builder.Services.AddScoped<ISubCategoryRepository, SubCategoryRepository>();
builder.Services.AddScoped<IBrandRepository, BrandRepository>();
builder.Services.AddScoped<IUomRepository, UomRepository>();
builder.Services.AddScoped<IItemRepository, ItemRepository>();
builder.Services.AddScoped<IStockRepository, StockRepository>();
builder.Services.AddScoped<RegionService>();
builder.Services.AddScoped<RouteService>();
@@ -59,6 +61,7 @@ builder.Services.AddScoped<BrandService>();
builder.Services.AddScoped<UomService>();
builder.Services.AddScoped<ItemService>();
builder.Services.AddScoped<SyncService>();
builder.Services.AddScoped<StockService>();
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<ICurrentUserService, CurrentUserService>();
+1 -1
View File
@@ -1,6 +1,6 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=187.127.102.190;Port=3306;Database=distribution_db;User=kalana;Password=kalana@hexdive"
"DefaultConnection": "Server=187.127.102.190;Port=3306;Database=distribution;User=kalana;Password=kalana@hexdive"
},
"Logging": {
"LogLevel": {
+210 -14
View File
@@ -1,62 +1,258 @@
# 02 — Stock Ledger
**Status**: Not Started
**Status**: Done
**Depends On**: 01 — Item Catalog
---
## Goal
Introduce stock tracking per location. Every warehouse and vehicle holds a quantity of each item.
Stock is never edited directly — all changes happen through movement transactions.
The current balance is always the materialized sum kept in sync with the transaction log.
---
## Background / Context
Two tables work together:
- **StockBalance** — one row per (ItemId, LocationId). Updated atomically on every movement. Used for fast reads and enforcing stock limits (e.g. driver can't sell more than loaded).
- **StockMovement** — append-only transaction log. Source of truth. Used for audit, reconciliation at ride close (Step 07), and re-deriving balance if drift is ever suspected.
Both are updated in the same UoW commit. They must always agree.
**Location abstraction:** A single `LocationId` (+ `LocationType` enum) covers both warehouses and vehicles. Same query pattern regardless of location type.
---
## Data Model Changes
### Stock Balance (per location)
### New Enum — LocationType
```csharp
public enum LocationType { Warehouse, Vehicle }
```
### New Enum — MovementType
### Stock Movement Transaction
```csharp
public enum MovementType
{
Sale,
CustomerReturn,
Transfer, // covers: warehouse→vehicle (load), vehicle→warehouse (driver return), warehouse→warehouse
Damage,
Adjustment
}
```
### New Entity — StockBalance
One row per (ItemId, LocationId). Updated on every movement.
### Location Abstraction (Warehouse vs Vehicle)
| Column | Type | Notes |
|---|---|---|
| Id | Guid | PK |
| FK_ItemId | Guid | FK → Item |
| LocationId | Guid | FK → Warehouse or Vehicle |
| LocationType | LocationType | Warehouse or Vehicle |
| Quantity | decimal | Current balance. Never goes below 0 |
| UpdatedAt | DateTime | Last movement time |
No `IsActive` / no soft delete — balance rows are permanent once created.
Composite unique index on `(FK_ItemId, LocationId)`.
### New Entity — StockMovement
Append-only. Never updated or deleted.
| Column | Type | Notes |
|---|---|---|
| Id | Guid | PK |
| FK_ItemId | Guid | FK → Item |
| FromLocationId | Guid? | Null for Sale, Damage, Adjustment (single-location) |
| FromLocationType | LocationType? | Null when FromLocationId is null |
| ToLocationId | Guid? | Null for Sale, Damage (stock leaves system) |
| ToLocationType | LocationType? | Null when ToLocationId is null |
| Quantity | decimal | Always positive — direction implied by movement type |
| Type | MovementType | |
| ReasonCode | string? | Required for Adjustment and Damage |
| ReferenceId | Guid? | Links to the originating business event (OrderId, RideId, etc.) |
| CreatedAt | DateTime | |
| CreatedBy | Guid | UserId of who triggered this |
---
## Category Configuration
`Category` gets one new flag to support configurable customer returns:
| Column | Type | Notes |
|---|---|---|
| AllowCustomerReturn | bool | Default false. If false, CustomerReturn movements are rejected for items in this category |
---
## API Endpoints
Base route: `/api/stock`
### Query
| Method | Route | Description |
|---|---|---|
| GET | `/balances` | Get all stock balances (paginated). Filter by `locationId`, `locationType`, `itemId` |
| GET | `/balances/{itemId}/total` | Total stock of one item across all locations |
| GET | `/movements` | Get movement history (paginated). Filter by `locationId`, `itemId`, `type`, `from`, `to` |
### Write
| Method | Route | Description |
|---|---|---|
| POST | `/transfer` | Move stock between two locations |
| POST | `/damage` | Record damaged stock at a location |
| POST | `/customer-return` | Record a customer return to a vehicle |
| POST | `/adjustment` | Manual correction at a location (requires reason code) |
---
## Request / Response Shapes
### GET `/balances` response (paginated)
```json
{
"page": 1,
"pageSize": 20,
"total": 85,
"items": [
{
"itemId": "...",
"itemName": "Sprite 330ml",
"locationId": "...",
"locationType": "Warehouse",
"quantity": 120,
"updatedAt": "2026-08-19T10:00:00"
}
]
}
```
### GET `/balances/{itemId}/total` response
```json
{
"itemId": "...",
"itemName": "Sprite 330ml",
"totalQuantity": 340,
"breakdown": [
{ "locationId": "...", "locationType": "Warehouse", "quantity": 200 },
{ "locationId": "...", "locationType": "Vehicle", "quantity": 140 }
]
}
```
### GET `/movements` response (paginated)
```json
{
"page": 1,
"pageSize": 20,
"total": 412,
"items": [
{
"id": "...",
"itemId": "...",
"itemName": "Sprite 330ml",
"fromLocationId": "...",
"fromLocationType": "Warehouse",
"toLocationId": "...",
"toLocationType": "Vehicle",
"quantity": 50,
"type": "Transfer",
"reasonCode": null,
"referenceId": "...",
"createdAt": "2026-08-19T08:00:00",
"createdBy": "..."
}
]
}
```
### POST `/transfer` request
```json
{
"itemId": "...",
"fromLocationId": "...",
"fromLocationType": "Warehouse",
"toLocationId": "...",
"toLocationType": "Vehicle",
"quantity": 50,
"referenceId": "..."
}
```
### POST `/damage` request
```json
{
"itemId": "...",
"locationId": "...",
"locationType": "Warehouse",
"quantity": 3,
"reasonCode": "Broken during handling"
}
```
### POST `/customer-return` request
```json
{
"itemId": "...",
"vehicleId": "...",
"quantity": 2,
"referenceId": "..."
}
```
### POST `/adjustment` request
```json
{
"itemId": "...",
"locationId": "...",
"locationType": "Warehouse",
"quantity": -2,
"reasonCode": "Counting error corrected after audit"
}
```
---
## Business Rules
---
## Fraud / Control Considerations
1. `StockBalance.Quantity` must never go below 0. Any movement that would result in negative stock is rejected with a 400.
2. `Adjustment` and `Damage` require a non-empty `ReasonCode`.
3. `CustomerReturn` is rejected if `Category.AllowCustomerReturn = false` for the item's category.
4. `Transfer` debits `FromLocation` and credits `ToLocation` atomically.
5. Both `StockBalance` update and `StockMovement` insert happen in the same transaction — never one without the other.
6. `StockMovement` rows are never updated or deleted. Wrong entries are corrected by a counter-movement.
7. All list endpoints return paginated responses.
---
## Open Questions
None — all design decisions resolved in planning discussion.
---
## Implementation Notes
> Fill this section in during planning discussion before writing any code.
**Feature folder:** `Features/Stock/`
**Entities:** `StockBalance.cs`, `StockMovement.cs` in `Models/`
**Migration:** Add after entities and DbContext are updated
**Service layer:** One `StockService` handles all movement types. Each write method: begins transaction → validates stock → inserts movement → updates balance → commits.
**Category change:** Add `AllowCustomerReturn` column to existing `Category` entity and migration.
+1 -1
View File
@@ -36,7 +36,7 @@ They must be resolved before new feature steps begin because later steps depend
|---|---|---|---|---|
| 00 | Existing Gap Fixes | Done | — | [00_existing_gaps.md](./00_existing_gaps.md) |
| 01 | Item Catalog | Done | 00 | [01_item_catalog.md](./01_item_catalog.md) |
| 02 | Stock Ledger | Not Started | 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 | Not Started | 02 | [03_ride_lifecycle.md](./03_ride_lifecycle.md) |
| 04 | Loading Event | Not Started | 03 | [04_loading_event.md](./04_loading_event.md) |
| 05 | Delivery Ride Execution | Not Started | 04 | [05_delivery_ride.md](./05_delivery_ride.md) |