Merge pull request 'Dev' (#4) from dev into production

Reviewed-on: #4
This commit was merged in pull request #4.
This commit is contained in:
2026-08-20 08:14:20 +00:00
22 changed files with 4144 additions and 202 deletions
+1
View File
@@ -29,6 +29,7 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
public DbSet<UserStoreScope> UserStoreScopes { get; set; } public DbSet<UserStoreScope> UserStoreScopes { get; set; }
public DbSet<StockBalance> StockBalances { get; set; } public DbSet<StockBalance> StockBalances { get; set; }
public DbSet<StockMovement> StockMovements { get; set; } public DbSet<StockMovement> StockMovements { get; set; }
public DbSet<StoreKycDocument> StoreKycDocuments { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
@@ -35,6 +35,8 @@ public static class RoleAndPermissionSeed
("stores.create", "Create stores"), ("stores.create", "Create stores"),
("stores.update", "Update stores"), ("stores.update", "Update stores"),
("stores.delete", "Delete stores"), ("stores.delete", "Delete stores"),
("stores.kyc.verify", "Verify or reject store KYC documents"),
("stores.credit.update", "Update store credit limit and outstanding balance"),
("warehouses.view", "View warehouses"), ("warehouses.view", "View warehouses"),
("warehouses.create", "Create warehouses"), ("warehouses.create", "Create warehouses"),
@@ -98,14 +100,14 @@ public static class RoleAndPermissionSeed
var itemPerms = new[] { "items.view", "items.create", "items.update", "items.delete", "categories.view", "categories.create", "categories.update", "categories.delete" }; var itemPerms = new[] { "items.view", "items.create", "items.update", "items.delete", "categories.view", "categories.create", "categories.update", "categories.delete" };
var salesRepPerms = new[] { "orders.view", "orders.create", "orders.update", "stores.view", "routes.view" }.Concat(itemViewPerms).ToArray(); var salesRepPerms = new[] { "orders.view", "orders.create", "orders.update", "stores.view", "routes.view" }.Concat(itemViewPerms).ToArray();
var supervisorPerms = salesRepPerms.Concat(["orders.delete", "stores.create", "stores.update"]).ToArray(); var supervisorPerms = salesRepPerms.Concat(["orders.delete", "stores.create", "stores.update", "stores.credit.update"]).ToArray();
var areaManagerPerms = supervisorPerms.Concat(["vehicles.view", "warehouses.view"]).Concat(itemManagePerms).Distinct().ToArray(); var areaManagerPerms = supervisorPerms.Concat(["vehicles.view", "warehouses.view", "stores.kyc.verify"]).Concat(itemManagePerms).Distinct().ToArray();
var areaSupervisorPerms = areaManagerPerms.Concat(["routes.create", "routes.update"]).Concat(itemPerms).Distinct().ToArray(); var areaSupervisorPerms = areaManagerPerms.Concat(["routes.create", "routes.update", "stores.delete"]).Concat(itemPerms).Distinct().ToArray();
var regionalManagerPerms = new[] var regionalManagerPerms = new[]
{ {
"orders.view", "orders.create", "orders.update", "orders.delete", "orders.view", "orders.create", "orders.update", "orders.delete",
"stores.view", "stores.create", "stores.update", "stores.delete", "stores.view", "stores.create", "stores.update", "stores.delete", "stores.kyc.verify", "stores.credit.update",
"routes.view", "routes.create", "routes.update", "routes.delete", "routes.view", "routes.create", "routes.update", "routes.delete",
"vehicles.view", "vehicles.create", "vehicles.update", "vehicles.delete", "vehicles.view", "vehicles.create", "vehicles.update", "vehicles.delete",
"warehouses.view", "warehouses.create", "warehouses.update", "warehouses.delete", "warehouses.view", "warehouses.create", "warehouses.update", "warehouses.delete",
+18 -1
View File
@@ -1,9 +1,18 @@
using Distribution.Features.Store;
using Distribution.Infra.Authorization; using Distribution.Infra.Authorization;
using Distribution.Infra.UoW; using Distribution.Infra.UoW;
using Distribution.Models;
using Microsoft.Extensions.Configuration;
namespace Distribution.Features.Order; namespace Distribution.Features.Order;
public class OrderService(IOrderRepository repo, IUnitOfWork uow, ICurrentUserService currentUser, IScopeAccessService scopeAccess) public class OrderService(
IOrderRepository repo,
IStoreRepository storeRepo,
IUnitOfWork uow,
ICurrentUserService currentUser,
IScopeAccessService scopeAccess,
IConfiguration configuration)
{ {
private const int GlobalScopeRoleLevel = 50; private const int GlobalScopeRoleLevel = 50;
@@ -63,6 +72,14 @@ public class OrderService(IOrderRepository repo, IUnitOfWork uow, ICurrentUserSe
{ {
if (!await HasStoreScopeAsync(request.StoreId)) return null; if (!await HasStoreScopeAsync(request.StoreId)) return null;
var store = await storeRepo.GetByIdAsync(request.StoreId);
if (store is null || !store.IsActive) return null;
if (store.KycStatus != KycStatus.Verified)
{
var threshold = configuration.GetValue<decimal>("StoreManagement:UnverifiedKycOrderThreshold");
if (request.TotalAmount > threshold) return null;
}
var order = new Models.Order var order = new Models.Order
{ {
FK_StoreId = request.StoreId, FK_StoreId = request.StoreId,
@@ -7,4 +7,5 @@ public interface IStoreRepository
Task AddAsync(Models.Store entity); Task AddAsync(Models.Store entity);
void Update(Models.Store entity); void Update(Models.Store entity);
void Remove(Models.Store entity); void Remove(Models.Store entity);
Task<List<Models.Order>> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive);
} }
@@ -0,0 +1,7 @@
namespace Distribution.Features.Store.Kyc;
public interface IStoreKycDocumentRepository
{
Task<List<Models.StoreKycDocument>> GetByStoreIdAsync(Guid storeId);
Task AddAsync(Models.StoreKycDocument entity);
}
@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Store.Kyc;
[ApiController]
[Route("api/stores/{storeId:guid}/kyc-documents")]
[Authorize]
public class StoreKycDocumentController(StoreKycDocumentService service) : ControllerBase
{
[HttpGet]
[Authorize(Policy = "stores.view")]
public async Task<IActionResult> GetByStoreId(Guid storeId)
{
var result = await service.GetByStoreIdAsync(storeId);
return result is null ? NotFound() : Ok(result);
}
[HttpPost]
[Authorize(Policy = "stores.update")]
public async Task<IActionResult> Upload(Guid storeId, [FromForm] UploadKycDocumentRequest request, CancellationToken ct)
{
var result = await service.UploadAsync(storeId, request, ct);
return result is null ? NotFound() : Ok(result);
}
}
@@ -0,0 +1,5 @@
namespace Distribution.Features.Store.Kyc;
public record UploadKycDocumentRequest(string DocumentType, IFormFile File);
public record StoreKycDocumentResponse(Guid Id, Guid StoreId, string DocumentType, string FileReference, DateTime UploadedAt);
@@ -0,0 +1,13 @@
using Distribution.Data;
using Microsoft.EntityFrameworkCore;
namespace Distribution.Features.Store.Kyc;
public class StoreKycDocumentRepository(AppDBContext context) : IStoreKycDocumentRepository
{
public async Task<List<Models.StoreKycDocument>> GetByStoreIdAsync(Guid storeId) =>
await context.StoreKycDocuments.Where(d => d.FK_StoreId == storeId && d.IsActive).ToListAsync();
public async Task AddAsync(Models.StoreKycDocument entity) =>
await context.StoreKycDocuments.AddAsync(entity);
}
@@ -0,0 +1,71 @@
using Distribution.Infra.Authorization;
using Distribution.Infra.UoW;
namespace Distribution.Features.Store.Kyc;
public class StoreKycDocumentService(
IStoreKycDocumentRepository repo,
IStoreRepository storeRepo,
IUnitOfWork uow,
ICurrentUserService currentUser,
IScopeAccessService scopeAccess,
IWebHostEnvironment env)
{
private const int GlobalScopeRoleLevel = 50;
private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel;
private async Task<bool> HasStoreScopeAsync(Guid storeId)
{
if (HasGlobalScope || currentUser.UserId is null) return HasGlobalScope;
return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId);
}
private static StoreKycDocumentResponse ToResponse(Models.StoreKycDocument d) =>
new(d.Id, d.FK_StoreId, d.DocumentType, d.FileReference, d.UploadedAt);
public async Task<List<StoreKycDocumentResponse>?> GetByStoreIdAsync(Guid storeId)
{
if (!await HasStoreScopeAsync(storeId)) return null;
var docs = await repo.GetByStoreIdAsync(storeId);
return docs.Select(ToResponse).ToList();
}
public async Task<StoreKycDocumentResponse?> UploadAsync(Guid storeId, UploadKycDocumentRequest request, CancellationToken ct = default)
{
var store = await storeRepo.GetByIdAsync(storeId);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(storeId)) return null;
var uploadsRoot = Path.Combine(env.ContentRootPath, "wwwroot", "uploads", "kyc", storeId.ToString());
Directory.CreateDirectory(uploadsRoot);
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(request.File.FileName)}";
var filePath = Path.Combine(uploadsRoot, fileName);
await using (var stream = new FileStream(filePath, FileMode.Create))
{
await request.File.CopyToAsync(stream, ct);
}
var fileReference = $"uploads/kyc/{storeId}/{fileName}";
var doc = new Models.StoreKycDocument
{
FK_StoreId = storeId,
DocumentType = request.DocumentType,
FileReference = fileReference,
UploadedAt = DateTime.Now
};
await uow.BeginAsync(ct);
try
{
await repo.AddAsync(doc);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(doc);
}
}
@@ -44,4 +44,68 @@ public class StoreController(StoreService service) : ControllerBase
var deleted = await service.DeleteAsync(id, ct); var deleted = await service.DeleteAsync(id, ct);
return deleted ? NoContent() : NotFound(); return deleted ? NoContent() : NotFound();
} }
[HttpPut("{id:guid}/credit-limit")]
[Authorize(Policy = "stores.credit.update")]
public async Task<IActionResult> UpdateCreditLimit(Guid id, UpdateCreditLimitRequest request, CancellationToken ct)
{
var result = await service.UpdateCreditLimitAsync(id, request, ct);
return result is null ? Forbid() : Ok(result);
}
[HttpPut("{id:guid}/outstanding-balance")]
[Authorize(Policy = "stores.credit.update")]
public async Task<IActionResult> UpdateOutstandingBalance(Guid id, UpdateOutstandingBalanceRequest request, CancellationToken ct)
{
var result = await service.UpdateOutstandingBalanceAsync(id, request, ct);
return result is null ? Forbid() : Ok(result);
}
[HttpGet("{id:guid}/outstanding-balance")]
[Authorize(Policy = "stores.view")]
public async Task<IActionResult> GetOutstandingBalance(Guid id)
{
var result = await service.GetOutstandingBalanceAsync(id);
return result is null ? NotFound() : Ok(result);
}
[HttpPut("{id:guid}/kyc/verify")]
[Authorize(Policy = "stores.kyc.verify")]
public async Task<IActionResult> VerifyKyc(Guid id, VerifyKycRequest request, CancellationToken ct)
{
var result = await service.VerifyKycAsync(id, request, ct);
return result is null ? NotFound() : Ok(result);
}
[HttpPut("{id:guid}/segment")]
[Authorize(Policy = "stores.update")]
public async Task<IActionResult> ClassifySegment(Guid id, ClassifySegmentRequest request, CancellationToken ct)
{
var result = await service.ClassifySegmentAsync(id, request, ct);
return result is null ? NotFound() : Ok(result);
}
[HttpGet("{id:guid}/visit-history")]
[Authorize(Policy = "stores.view")]
public async Task<IActionResult> GetVisitHistory(Guid id)
{
var result = await service.GetVisitHistoryAsync(id);
return result is null ? NotFound() : Ok(result);
}
[HttpGet("{id:guid}/schemes/{schemeId:guid}/eligibility")]
[Authorize(Policy = "stores.view")]
public async Task<IActionResult> CheckSchemeEligibility(Guid id, Guid schemeId)
{
var result = await service.CheckSchemeEligibilityAsync(id, schemeId);
return result is null ? NotFound() : Ok(result);
}
[HttpGet("{id:guid}/dashboard")]
[Authorize(Policy = "stores.view")]
public async Task<IActionResult> GetDashboard(Guid id, [FromQuery] string period)
{
var result = await service.GetDashboardAsync(id, period);
return result is null ? NotFound() : Ok(result);
}
} }
+22
View File
@@ -1,3 +1,5 @@
using Distribution.Models;
namespace Distribution.Features.Store; namespace Distribution.Features.Store;
public record CreateStoreRequest( public record CreateStoreRequest(
@@ -30,5 +32,25 @@ public record StoreResponse(
decimal Longitude, decimal Longitude,
decimal OneTimeAmount, decimal OneTimeAmount,
decimal CreditAmount, decimal CreditAmount,
decimal CreditLimit,
decimal OutstandingBalance,
string? Segment,
KycStatus KycStatus,
bool IsActive, bool IsActive,
DateTime CreatedAt); DateTime CreatedAt);
public record UpdateCreditLimitRequest(decimal NewLimit, Guid ApproverId);
public record UpdateOutstandingBalanceRequest(decimal NewBalance);
public record VerifyKycRequest(KycStatus Status, string? Notes);
public record ClassifySegmentRequest(string Segment);
public record OutstandingBalanceResponse(Guid StoreId, decimal CreditLimit, decimal OutstandingBalance, decimal AvailableCredit);
public record StoreVisitHistoryItem(Guid VisitId, DateTime VisitDate, Guid RepUserId, string Outcome);
public record SchemeEligibilityResponse(bool Eligible, string? Reason);
public record StoreDashboardResponse(Guid StoreId, string Period, int OrderCount, decimal TotalOrderValue, DateTime? LastOrderDate);
@@ -22,4 +22,9 @@ public class StoreRepository(AppDBContext context) : IStoreRepository
entity.IsActive = false; entity.IsActive = false;
context.Stores.Update(entity); context.Stores.Update(entity);
} }
public async Task<List<Models.Order>> GetOrdersForDashboardAsync(Guid storeId, DateTime periodStart, DateTime periodEndExclusive) =>
await context.Orders
.Where(o => o.FK_StoreId == storeId && o.IsActive && o.OrderDate >= periodStart && o.OrderDate < periodEndExclusive)
.ToListAsync();
} }
+137 -4
View File
@@ -1,11 +1,13 @@
using Distribution.Infra.Authorization; using Distribution.Infra.Authorization;
using Distribution.Infra.UoW; using Distribution.Infra.UoW;
using Distribution.Models;
namespace Distribution.Features.Store; namespace Distribution.Features.Store;
public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserService currentUser, IScopeAccessService scopeAccess) public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserService currentUser, IScopeAccessService scopeAccess)
{ {
private const int GlobalScopeRoleLevel = 50; private const int GlobalScopeRoleLevel = 50;
private const int CreditApproverRoleLevel = 20;
private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel; private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel;
@@ -15,6 +17,10 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId); return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId);
} }
private static StoreResponse ToResponse(Models.Store s) =>
new(s.Id, s.FK_RouteId, s.OwnerName, s.StoreName, s.StoreAddress, s.Latitude, s.Longitude, s.OneTimeAmount, s.CreditAmount,
s.CreditLimit, s.OutstandingBalance, s.Segment, s.KycStatus, s.IsActive, s.CreatedAt);
public async Task<List<StoreResponse>> GetAllAsync() public async Task<List<StoreResponse>> GetAllAsync()
{ {
var stores = (await repo.GetAllAsync()).Where(s => s.IsActive).ToList(); var stores = (await repo.GetAllAsync()).Where(s => s.IsActive).ToList();
@@ -23,7 +29,7 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
var accessibleStoreIds = (await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value)).ToHashSet(); var accessibleStoreIds = (await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value)).ToHashSet();
stores = stores.Where(s => accessibleStoreIds.Contains(s.Id)).ToList(); stores = stores.Where(s => accessibleStoreIds.Contains(s.Id)).ToList();
} }
return stores.Select(s => new StoreResponse(s.Id, s.FK_RouteId, s.OwnerName, s.StoreName, s.StoreAddress, s.Latitude, s.Longitude, s.OneTimeAmount, s.CreditAmount, s.IsActive, s.CreatedAt)).ToList(); return stores.Select(ToResponse).ToList();
} }
public async Task<StoreResponse?> GetByIdAsync(Guid id) public async Task<StoreResponse?> GetByIdAsync(Guid id)
@@ -31,7 +37,7 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
var store = await repo.GetByIdAsync(id); var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null; if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null; if (!await HasStoreScopeAsync(id)) return null;
return new StoreResponse(store.Id, store.FK_RouteId, store.OwnerName, store.StoreName, store.StoreAddress, store.Latitude, store.Longitude, store.OneTimeAmount, store.CreditAmount, store.IsActive, store.CreatedAt); return ToResponse(store);
} }
public async Task<StoreResponse> CreateAsync(CreateStoreRequest request, CancellationToken ct = default) public async Task<StoreResponse> CreateAsync(CreateStoreRequest request, CancellationToken ct = default)
@@ -58,7 +64,7 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
await uow.RollbackAsync(ct); await uow.RollbackAsync(ct);
throw; throw;
} }
return new StoreResponse(store.Id, store.FK_RouteId, store.OwnerName, store.StoreName, store.StoreAddress, store.Latitude, store.Longitude, store.OneTimeAmount, store.CreditAmount, store.IsActive, store.CreatedAt); return ToResponse(store);
} }
public async Task<StoreResponse?> UpdateAsync(Guid id, UpdateStoreRequest request, CancellationToken ct = default) public async Task<StoreResponse?> UpdateAsync(Guid id, UpdateStoreRequest request, CancellationToken ct = default)
@@ -85,7 +91,7 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
await uow.RollbackAsync(ct); await uow.RollbackAsync(ct);
throw; throw;
} }
return new StoreResponse(store.Id, store.FK_RouteId, store.OwnerName, store.StoreName, store.StoreAddress, store.Latitude, store.Longitude, store.OneTimeAmount, store.CreditAmount, store.IsActive, store.CreatedAt); return ToResponse(store);
} }
public async Task<bool> DeleteAsync(Guid id, CancellationToken ct = default) public async Task<bool> DeleteAsync(Guid id, CancellationToken ct = default)
@@ -106,4 +112,131 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
} }
return true; return true;
} }
public async Task<StoreResponse?> UpdateCreditLimitAsync(Guid id, UpdateCreditLimitRequest request, CancellationToken ct = default)
{
if (currentUser.RoleLevel < CreditApproverRoleLevel) return null;
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
store.CreditLimit = request.NewLimit;
await uow.BeginAsync(ct);
try
{
repo.Update(store);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(store);
}
public async Task<StoreResponse?> UpdateOutstandingBalanceAsync(Guid id, UpdateOutstandingBalanceRequest request, CancellationToken ct = default)
{
if (currentUser.RoleLevel < CreditApproverRoleLevel) return null;
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
store.OutstandingBalance = request.NewBalance;
await uow.BeginAsync(ct);
try
{
repo.Update(store);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(store);
}
public async Task<OutstandingBalanceResponse?> GetOutstandingBalanceAsync(Guid id)
{
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
return new OutstandingBalanceResponse(store.Id, store.CreditLimit, store.OutstandingBalance, store.CreditLimit - store.OutstandingBalance);
}
public async Task<StoreResponse?> VerifyKycAsync(Guid id, VerifyKycRequest request, CancellationToken ct = default)
{
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
store.KycStatus = request.Status;
await uow.BeginAsync(ct);
try
{
repo.Update(store);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(store);
}
public async Task<StoreResponse?> ClassifySegmentAsync(Guid id, ClassifySegmentRequest request, CancellationToken ct = default)
{
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
store.Segment = request.Segment;
await uow.BeginAsync(ct);
try
{
repo.Update(store);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(store);
}
public async Task<List<StoreVisitHistoryItem>?> GetVisitHistoryAsync(Guid id)
{
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
// Wired to Step 11 (Route & Sales Management) once ride/visit tracking exists.
return [];
}
public async Task<SchemeEligibilityResponse?> CheckSchemeEligibilityAsync(Guid id, Guid schemeId)
{
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
// Wired to Step 17 (Promotions & Schemes) once scheme rules exist.
return new SchemeEligibilityResponse(true, null);
}
public async Task<StoreDashboardResponse?> GetDashboardAsync(Guid id, string period)
{
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
if (!DateTime.TryParseExact(period, "yyyy-MM", null, System.Globalization.DateTimeStyles.None, out var periodStart))
periodStart = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
var periodEndExclusive = periodStart.AddMonths(1);
var orders = await repo.GetOrdersForDashboardAsync(id, periodStart, periodEndExclusive);
return new StoreDashboardResponse(
id,
periodStart.ToString("yyyy-MM"),
orders.Count,
orders.Sum(o => o.TotalAmount),
orders.Count == 0 ? null : orders.Max(o => o.OrderDate));
}
} }
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,716 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class AddStoreCreditAndKyc : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000001") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000001") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000001") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000001") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000005") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000005") });
migrationBuilder.AddColumn<decimal>(
name: "CreditLimit",
table: "Stores",
type: "decimal(65,30)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<int>(
name: "KycStatus",
table: "Stores",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<decimal>(
name: "OutstandingBalance",
table: "Stores",
type: "decimal(65,30)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<string>(
name: "Segment",
table: "Stores",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "StoreKycDocuments",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
FK_StoreId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
DocumentType = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
FileReference = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
UploadedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_StoreKycDocuments", x => x.Id);
table.ForeignKey(
name: "FK_StoreKycDocuments_Stores_FK_StoreId",
column: x => x.FK_StoreId,
principalTable: "Stores",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000017"),
columns: new[] { "Code", "Description" },
values: new object[] { "stores.kyc.verify", "Verify or reject store KYC documents" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000018"),
columns: new[] { "Code", "Description" },
values: new object[] { "stores.credit.update", "Update store credit limit and outstanding balance" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000019"),
columns: new[] { "Code", "Description" },
values: new object[] { "warehouses.view", "View warehouses" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000020"),
columns: new[] { "Code", "Description" },
values: new object[] { "warehouses.create", "Create warehouses" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000021"),
columns: new[] { "Code", "Description" },
values: new object[] { "warehouses.update", "Update warehouses" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000022"),
columns: new[] { "Code", "Description" },
values: new object[] { "warehouses.delete", "Delete warehouses" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000023"),
columns: new[] { "Code", "Description" },
values: new object[] { "orders.view", "View orders" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000024"),
columns: new[] { "Code", "Description" },
values: new object[] { "orders.create", "Create orders" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000025"),
columns: new[] { "Code", "Description" },
values: new object[] { "orders.update", "Update orders" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000026"),
columns: new[] { "Code", "Description" },
values: new object[] { "orders.delete", "Delete orders" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000027"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.view", "View users" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000028"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.create", "Create users" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000029"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.update", "Update users" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000030"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.deactivate", "Deactivate users" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000031"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.assign_role", "Assign a role to a user" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000032"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.assign_scope", "Assign region/route/store scope to a user" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000033"),
columns: new[] { "Code", "Description" },
values: new object[] { "items.view", "View items, brands and UOMs" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000034"),
columns: new[] { "Code", "Description" },
values: new object[] { "items.create", "Create items, brands and UOMs" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000035"),
columns: new[] { "Code", "Description" },
values: new object[] { "items.update", "Update items, brands and UOMs" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000036"),
columns: new[] { "Code", "Description" },
values: new object[] { "items.delete", "Delete items, brands and UOMs" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000037"),
columns: new[] { "Code", "Description" },
values: new object[] { "categories.view", "View categories" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000038"),
columns: new[] { "Code", "Description" },
values: new object[] { "categories.create", "Create categories and subcategories" });
migrationBuilder.InsertData(
table: "Permissions",
columns: new[] { "Id", "Code", "CreatedAt", "Description", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000039"), "categories.update", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update categories and subcategories", true },
{ new Guid("20000000-0000-0000-0000-000000000040"), "categories.delete", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Delete categories and subcategories", true }
});
migrationBuilder.InsertData(
table: "RolePermissions",
columns: new[] { "FK_PermissionId", "FK_RoleId", "CreatedAt", "Id", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("c0739b84-50a2-0971-429b-02bab8354c51"), true },
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("c268a531-44eb-0f29-82ba-18394ac2dcb5"), true },
{ new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("ddb2d04d-19b0-20b1-2639-b157d12a9eec"), true },
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("320ba3fb-666c-ce57-3e61-95c9824c4048"), true },
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f2c14d55-d557-5cd2-a70a-4a6f58933436"), true },
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("1b126bb0-e582-3e84-4728-a7ab5628fe7b"), true },
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f50b201c-6c8d-0df8-85ad-08cb137bc213"), true },
{ new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("0f291826-e169-c06a-0735-bd06cbb2062d"), true },
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("10dd0249-ce04-c5d9-8f94-ccb348c1d979"), true },
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d92d572f-f1bf-9e7d-1d4d-7c7b0d575c8e"), true },
{ new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f367f6f6-3d26-7a6c-888b-da1a240b59af"), true },
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("929950da-d51b-ad5d-c4e5-55175908fb43"), true },
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a9a49749-f99d-3166-5d92-b7e380fcabb2"), true },
{ new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b17df3df-022c-c903-6ce0-e6423e648dc8"), true },
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a41f94ba-c24d-93dc-9f25-c462df19785a"), true },
{ new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e0b27435-f505-43f5-7ed9-4711f2248495"), true },
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5e10d61c-2d7a-3388-722f-45232d2cfb71"), true },
{ new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d8257363-d838-fe7e-57a5-51b626dbfc83"), true },
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("04ece77e-b36f-8ed0-4ef9-2f6962b6f9c6"), true },
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("bf2a2f96-04ed-905d-5a8a-9047d814aa3e"), true },
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4d287b19-ba40-7d4d-3d39-291be64197f8"), true },
{ new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("43a4c7b4-a50f-aa37-b147-a30636d9d65f"), true },
{ new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a66f3854-5a8f-95c2-cb1c-b2b2e67ee226"), true },
{ new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("14bcecd1-b1a2-6da3-155a-233611484467"), true },
{ new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("aeb29e0e-e819-1446-6cc6-1fb64b5ecc6b"), true },
{ new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e18a6eca-1009-bcc6-35e9-ead943c1649f"), true },
{ new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3f32cdac-6925-23f2-064e-8226d781d4a3"), true },
{ new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000006"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("dc3dd9ff-b123-a8d4-dcea-b4f5f8ff171e"), true }
});
migrationBuilder.CreateIndex(
name: "IX_StoreKycDocuments_FK_StoreId",
table: "StoreKycDocuments",
column: "FK_StoreId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "StoreKycDocuments");
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000001") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000001") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000001") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000001") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000002") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000003") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000004") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000005") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000005") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000005") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000005") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000006") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000006") });
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000039"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000040"));
migrationBuilder.DropColumn(
name: "CreditLimit",
table: "Stores");
migrationBuilder.DropColumn(
name: "KycStatus",
table: "Stores");
migrationBuilder.DropColumn(
name: "OutstandingBalance",
table: "Stores");
migrationBuilder.DropColumn(
name: "Segment",
table: "Stores");
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000017"),
columns: new[] { "Code", "Description" },
values: new object[] { "warehouses.view", "View warehouses" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000018"),
columns: new[] { "Code", "Description" },
values: new object[] { "warehouses.create", "Create warehouses" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000019"),
columns: new[] { "Code", "Description" },
values: new object[] { "warehouses.update", "Update warehouses" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000020"),
columns: new[] { "Code", "Description" },
values: new object[] { "warehouses.delete", "Delete warehouses" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000021"),
columns: new[] { "Code", "Description" },
values: new object[] { "orders.view", "View orders" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000022"),
columns: new[] { "Code", "Description" },
values: new object[] { "orders.create", "Create orders" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000023"),
columns: new[] { "Code", "Description" },
values: new object[] { "orders.update", "Update orders" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000024"),
columns: new[] { "Code", "Description" },
values: new object[] { "orders.delete", "Delete orders" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000025"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.view", "View users" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000026"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.create", "Create users" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000027"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.update", "Update users" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000028"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.deactivate", "Deactivate users" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000029"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.assign_role", "Assign a role to a user" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000030"),
columns: new[] { "Code", "Description" },
values: new object[] { "users.assign_scope", "Assign region/route/store scope to a user" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000031"),
columns: new[] { "Code", "Description" },
values: new object[] { "items.view", "View items, brands and UOMs" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000032"),
columns: new[] { "Code", "Description" },
values: new object[] { "items.create", "Create items, brands and UOMs" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000033"),
columns: new[] { "Code", "Description" },
values: new object[] { "items.update", "Update items, brands and UOMs" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000034"),
columns: new[] { "Code", "Description" },
values: new object[] { "items.delete", "Delete items, brands and UOMs" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000035"),
columns: new[] { "Code", "Description" },
values: new object[] { "categories.view", "View categories" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000036"),
columns: new[] { "Code", "Description" },
values: new object[] { "categories.create", "Create categories and subcategories" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000037"),
columns: new[] { "Code", "Description" },
values: new object[] { "categories.update", "Update categories and subcategories" });
migrationBuilder.UpdateData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000038"),
columns: new[] { "Code", "Description" },
values: new object[] { "categories.delete", "Delete categories and subcategories" });
migrationBuilder.InsertData(
table: "RolePermissions",
columns: new[] { "FK_PermissionId", "FK_RoleId", "CreatedAt", "Id", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("85ef4e27-8643-9c43-71f6-da56f66a5c47"), true },
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("1e353909-d682-58f6-df5c-8e57fa2512c9"), true },
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7596f703-c6ab-316c-7c80-3f4e3daa174e"), true },
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000001"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("aa120c36-488e-34ba-e10a-2ac45e46e119"), true },
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e4648655-7267-141e-51fa-f7d5fe3d2356"), true },
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d427b9ea-2c9b-d93e-0843-02dfa1ae8887"), true },
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b7dee5e3-f329-95a5-75c1-d02c3e40e229"), true },
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000002"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e5506b30-527d-08f9-6caa-8a45d3d02999"), true },
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("0dd5c943-3ace-0560-6fbc-54d8e37ce014"), true },
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("ca97fb3d-132c-d8a5-4ab8-f7b8fc60f5e5"), true },
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7780d277-9597-84ff-1a1a-f63fc6b4d3cb"), true },
{ new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000003"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("8083c659-9506-0bd9-b793-3d6148ce9192"), true },
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5c00e972-a697-d71a-6545-1fd8618826cf"), true },
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e9b6af8e-7947-7290-9c92-2d9b6239f395"), true },
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a701da28-aa75-3c1d-abdb-4317404f8df6"), true },
{ new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000004"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("2c025310-765f-7d07-ab9a-50524c13d1d3"), true },
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("69f93a29-1df1-7b20-9d5c-94c264f8c4b8"), true },
{ new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000005"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("070813f7-4053-2889-0d14-d0d5834208c2"), true }
});
}
}
}
@@ -380,6 +380,22 @@ namespace Distribution.Migrations
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000017"), Id = new Guid("20000000-0000-0000-0000-000000000017"),
Code = "stores.kyc.verify",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Verify or reject store KYC documents",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000018"),
Code = "stores.credit.update",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Update store credit limit and outstanding balance",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000019"),
Code = "warehouses.view", Code = "warehouses.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View warehouses", Description = "View warehouses",
@@ -387,7 +403,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000018"), Id = new Guid("20000000-0000-0000-0000-000000000020"),
Code = "warehouses.create", Code = "warehouses.create",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create warehouses", Description = "Create warehouses",
@@ -395,7 +411,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000019"), Id = new Guid("20000000-0000-0000-0000-000000000021"),
Code = "warehouses.update", Code = "warehouses.update",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Update warehouses", Description = "Update warehouses",
@@ -403,7 +419,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000020"), Id = new Guid("20000000-0000-0000-0000-000000000022"),
Code = "warehouses.delete", Code = "warehouses.delete",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Delete warehouses", Description = "Delete warehouses",
@@ -411,7 +427,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000021"), Id = new Guid("20000000-0000-0000-0000-000000000023"),
Code = "orders.view", Code = "orders.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View orders", Description = "View orders",
@@ -419,7 +435,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000022"), Id = new Guid("20000000-0000-0000-0000-000000000024"),
Code = "orders.create", Code = "orders.create",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create orders", Description = "Create orders",
@@ -427,7 +443,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000023"), Id = new Guid("20000000-0000-0000-0000-000000000025"),
Code = "orders.update", Code = "orders.update",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Update orders", Description = "Update orders",
@@ -435,7 +451,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000024"), Id = new Guid("20000000-0000-0000-0000-000000000026"),
Code = "orders.delete", Code = "orders.delete",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Delete orders", Description = "Delete orders",
@@ -443,7 +459,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000025"), Id = new Guid("20000000-0000-0000-0000-000000000027"),
Code = "users.view", Code = "users.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View users", Description = "View users",
@@ -451,7 +467,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000026"), Id = new Guid("20000000-0000-0000-0000-000000000028"),
Code = "users.create", Code = "users.create",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create users", Description = "Create users",
@@ -459,7 +475,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000027"), Id = new Guid("20000000-0000-0000-0000-000000000029"),
Code = "users.update", Code = "users.update",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Update users", Description = "Update users",
@@ -467,7 +483,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000028"), Id = new Guid("20000000-0000-0000-0000-000000000030"),
Code = "users.deactivate", Code = "users.deactivate",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Deactivate users", Description = "Deactivate users",
@@ -475,7 +491,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000029"), Id = new Guid("20000000-0000-0000-0000-000000000031"),
Code = "users.assign_role", Code = "users.assign_role",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Assign a role to a user", Description = "Assign a role to a user",
@@ -483,7 +499,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000030"), Id = new Guid("20000000-0000-0000-0000-000000000032"),
Code = "users.assign_scope", Code = "users.assign_scope",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Assign region/route/store scope to a user", Description = "Assign region/route/store scope to a user",
@@ -491,7 +507,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000031"), Id = new Guid("20000000-0000-0000-0000-000000000033"),
Code = "items.view", Code = "items.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View items, brands and UOMs", Description = "View items, brands and UOMs",
@@ -499,7 +515,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000032"), Id = new Guid("20000000-0000-0000-0000-000000000034"),
Code = "items.create", Code = "items.create",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create items, brands and UOMs", Description = "Create items, brands and UOMs",
@@ -507,7 +523,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000033"), Id = new Guid("20000000-0000-0000-0000-000000000035"),
Code = "items.update", Code = "items.update",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Update items, brands and UOMs", Description = "Update items, brands and UOMs",
@@ -515,7 +531,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000034"), Id = new Guid("20000000-0000-0000-0000-000000000036"),
Code = "items.delete", Code = "items.delete",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Delete items, brands and UOMs", Description = "Delete items, brands and UOMs",
@@ -523,7 +539,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000035"), Id = new Guid("20000000-0000-0000-0000-000000000037"),
Code = "categories.view", Code = "categories.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View categories", Description = "View categories",
@@ -531,7 +547,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000036"), Id = new Guid("20000000-0000-0000-0000-000000000038"),
Code = "categories.create", Code = "categories.create",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create categories and subcategories", Description = "Create categories and subcategories",
@@ -539,7 +555,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000037"), Id = new Guid("20000000-0000-0000-0000-000000000039"),
Code = "categories.update", Code = "categories.update",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Update categories and subcategories", Description = "Update categories and subcategories",
@@ -547,7 +563,7 @@ namespace Distribution.Migrations
}, },
new new
{ {
Id = new Guid("20000000-0000-0000-0000-000000000038"), Id = new Guid("20000000-0000-0000-0000-000000000040"),
Code = "categories.delete", Code = "categories.delete",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Delete categories and subcategories", Description = "Delete categories and subcategories",
@@ -674,22 +690,6 @@ namespace Distribution.Migrations
b.ToTable("RolePermissions"); b.ToTable("RolePermissions");
b.HasData( b.HasData(
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000021"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("85ef4e27-8643-9c43-71f6-da56f66a5c47"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000022"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("1e353909-d682-58f6-df5c-8e57fa2512c9"),
IsActive = true
},
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
@@ -699,6 +699,22 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000024"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("c0739b84-50a2-0971-429b-02bab8354c51"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000025"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("c268a531-44eb-0f29-82ba-18394ac2dcb5"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"),
@@ -717,33 +733,17 @@ namespace Distribution.Migrations
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000031"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000033"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("7596f703-c6ab-316c-7c80-3f4e3daa174e"), Id = new Guid("ddb2d04d-19b0-20b1-2639-b157d12a9eec"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000035"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000037"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("aa120c36-488e-34ba-e10a-2ac45e46e119"), Id = new Guid("320ba3fb-666c-ce57-3e61-95c9824c4048"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000021"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("e4648655-7267-141e-51fa-f7d5fe3d2356"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000022"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("d427b9ea-2c9b-d93e-0843-02dfa1ae8887"),
IsActive = true IsActive = true
}, },
new new
@@ -755,6 +755,22 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000024"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("357c36de-9b6c-1c9a-4926-c18a9bccf0ca"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000025"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("1b126bb0-e582-3e84-4728-a7ab5628fe7b"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"),
@@ -773,25 +789,25 @@ namespace Distribution.Migrations
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000031"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000033"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("b7dee5e3-f329-95a5-75c1-d02c3e40e229"), Id = new Guid("0f291826-e169-c06a-0735-bd06cbb2062d"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000035"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000037"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("e5506b30-527d-08f9-6caa-8a45d3d02999"), Id = new Guid("10dd0249-ce04-c5d9-8f94-ccb348c1d979"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000024"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000026"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("357c36de-9b6c-1c9a-4926-c18a9bccf0ca"), Id = new Guid("f50b201c-6c8d-0df8-85ad-08cb137bc213"),
IsActive = true IsActive = true
}, },
new new
@@ -812,18 +828,10 @@ namespace Distribution.Migrations
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000021"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000018"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("0dd5c943-3ace-0560-6fbc-54d8e37ce014"), Id = new Guid("f2c14d55-d557-5cd2-a70a-4a6f58933436"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000022"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("ca97fb3d-132c-d8a5-4ab8-f7b8fc60f5e5"),
IsActive = true IsActive = true
}, },
new new
@@ -835,6 +843,22 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000024"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("73e00ce7-c124-4677-4369-1eb9876852c0"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000025"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("929950da-d51b-ad5d-c4e5-55175908fb43"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"),
@@ -853,25 +877,25 @@ namespace Distribution.Migrations
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000031"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000033"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("7780d277-9597-84ff-1a1a-f63fc6b4d3cb"), Id = new Guid("d49f086e-30f0-6ce8-ae96-4395d5e04472"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000035"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000037"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("1e7fe1b6-5150-4b99-38ed-088d9495cfd8"), Id = new Guid("a41f94ba-c24d-93dc-9f25-c462df19785a"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000024"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000026"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("73e00ce7-c124-4677-4369-1eb9876852c0"), Id = new Guid("a9a49749-f99d-3166-5d92-b7e380fcabb2"),
IsActive = true IsActive = true
}, },
new new
@@ -891,6 +915,14 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000018"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("d92d572f-f1bf-9e7d-1d4d-7c7b0d575c8e"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000009"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000009"),
@@ -899,6 +931,14 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000019"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("f367f6f6-3d26-7a6c-888b-da1a240b59af"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000017"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000017"),
@@ -909,33 +949,17 @@ namespace Distribution.Migrations
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000032"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000034"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("8083c659-9506-0bd9-b793-3d6148ce9192"), Id = new Guid("b17df3df-022c-c903-6ce0-e6423e648dc8"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000003"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000033"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000035"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("d49f086e-30f0-6ce8-ae96-4395d5e04472"), Id = new Guid("1e7fe1b6-5150-4b99-38ed-088d9495cfd8"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000021"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("5c00e972-a697-d71a-6545-1fd8618826cf"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000022"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("e9b6af8e-7947-7290-9c92-2d9b6239f395"),
IsActive = true IsActive = true
}, },
new new
@@ -947,6 +971,22 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000024"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("7b4f3482-b8bd-d348-e4c1-ae6dc93a3771"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000025"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("04ece77e-b36f-8ed0-4ef9-2f6962b6f9c6"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"),
@@ -965,25 +1005,25 @@ namespace Distribution.Migrations
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000031"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000033"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("a701da28-aa75-3c1d-abdb-4317404f8df6"), Id = new Guid("7c392a13-1a57-0d85-dffa-2fb9e892abe9"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000035"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000037"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("9afe507e-191e-bdee-0c5a-cfbcbf1efb3e"), Id = new Guid("d1dcef02-d4c3-caba-372f-dab82011e9c1"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000024"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000026"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("7b4f3482-b8bd-d348-e4c1-ae6dc93a3771"), Id = new Guid("bf2a2f96-04ed-905d-5a8a-9047d814aa3e"),
IsActive = true IsActive = true
}, },
new new
@@ -1003,6 +1043,14 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000018"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("5e10d61c-2d7a-3388-722f-45232d2cfb71"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000009"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000009"),
@@ -1011,6 +1059,14 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000019"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("d8257363-d838-fe7e-57a5-51b626dbfc83"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000017"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000017"),
@@ -1021,17 +1077,17 @@ namespace Distribution.Migrations
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000032"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000034"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("2c025310-765f-7d07-ab9a-50524c13d1d3"), Id = new Guid("97708eed-6ce4-7710-abde-01d00c0c879b"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000033"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000035"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("7c392a13-1a57-0d85-dffa-2fb9e892abe9"), Id = new Guid("9afe507e-191e-bdee-0c5a-cfbcbf1efb3e"),
IsActive = true IsActive = true
}, },
new new
@@ -1053,9 +1109,9 @@ namespace Distribution.Migrations
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000034"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000016"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("97708eed-6ce4-7710-abde-01d00c0c879b"), Id = new Guid("e0b27435-f505-43f5-7ed9-4711f2248495"),
IsActive = true IsActive = true
}, },
new new
@@ -1067,14 +1123,6 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000037"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("d1dcef02-d4c3-caba-372f-dab82011e9c1"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000038"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000038"),
@@ -1084,18 +1132,18 @@ namespace Distribution.Migrations
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000021"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000039"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("08de9913-8cfc-4ab4-2cb9-2bc9217fbb6e"), Id = new Guid("a66f3854-5a8f-95c2-cb1c-b2b2e67ee226"),
IsActive = true IsActive = true
}, },
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000004"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000022"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000040"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("f3c8f315-3b2f-f923-e3cd-f3e575010138"), Id = new Guid("14bcecd1-b1a2-6da3-155a-233611484467"),
IsActive = true IsActive = true
}, },
new new
@@ -1115,6 +1163,22 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000025"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("1d227ae7-0eb9-c742-41df-3472718cb077"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000026"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("4d287b19-ba40-7d4d-3d39-291be64197f8"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"),
@@ -1147,6 +1211,22 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000017"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("ee175c87-23bd-5529-ed18-6ce46985c6ed"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000018"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("2ae2eba4-4427-ab1e-cf03-e59a3925ef89"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000005"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000005"),
@@ -1211,22 +1291,6 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000017"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("ee175c87-23bd-5529-ed18-6ce46985c6ed"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000018"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("2ae2eba4-4427-ab1e-cf03-e59a3925ef89"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000019"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000019"),
@@ -1243,6 +1307,22 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000021"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("08de9913-8cfc-4ab4-2cb9-2bc9217fbb6e"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000022"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("f3c8f315-3b2f-f923-e3cd-f3e575010138"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000001"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000001"),
@@ -1253,25 +1333,9 @@ namespace Distribution.Migrations
new new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000025"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000027"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("1d227ae7-0eb9-c742-41df-3472718cb077"), Id = new Guid("43a4c7b4-a50f-aa37-b147-a30636d9d65f"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000031"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("69f93a29-1df1-7b20-9d5c-94c264f8c4b8"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000032"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("070813f7-4053-2889-0d14-d0d5834208c2"),
IsActive = true IsActive = true
}, },
new new
@@ -1323,6 +1387,22 @@ namespace Distribution.Migrations
IsActive = true IsActive = true
}, },
new new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000039"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("aeb29e0e-e819-1446-6cc6-1fb64b5ecc6b"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000040"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("e18a6eca-1009-bcc6-35e9-ead943c1649f"),
IsActive = true
},
new
{ {
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"), FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000001"), FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000001"),
@@ -1625,6 +1705,22 @@ namespace Distribution.Migrations
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("1d6273d4-db6a-d70e-4b5f-98cb634d668a"), Id = new Guid("1d6273d4-db6a-d70e-4b5f-98cb634d668a"),
IsActive = true IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000039"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("3f32cdac-6925-23f2-064e-8226d781d4a3"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000040"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("dc3dd9ff-b123-a8d4-dcea-b4f5f8ff171e"),
IsActive = true
}); });
}); });
@@ -1769,12 +1865,18 @@ namespace Distribution.Migrations
b.Property<decimal>("CreditAmount") b.Property<decimal>("CreditAmount")
.HasColumnType("decimal(65,30)"); .HasColumnType("decimal(65,30)");
b.Property<decimal>("CreditLimit")
.HasColumnType("decimal(65,30)");
b.Property<Guid>("FK_RouteId") b.Property<Guid>("FK_RouteId")
.HasColumnType("char(36)"); .HasColumnType("char(36)");
b.Property<bool>("IsActive") b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)"); .HasColumnType("tinyint(1)");
b.Property<int>("KycStatus")
.HasColumnType("int");
b.Property<decimal>("Latitude") b.Property<decimal>("Latitude")
.HasColumnType("decimal(65,30)"); .HasColumnType("decimal(65,30)");
@@ -1784,10 +1886,16 @@ namespace Distribution.Migrations
b.Property<decimal>("OneTimeAmount") b.Property<decimal>("OneTimeAmount")
.HasColumnType("decimal(65,30)"); .HasColumnType("decimal(65,30)");
b.Property<decimal>("OutstandingBalance")
.HasColumnType("decimal(65,30)");
b.Property<string>("OwnerName") b.Property<string>("OwnerName")
.IsRequired() .IsRequired()
.HasColumnType("longtext"); .HasColumnType("longtext");
b.Property<string>("Segment")
.HasColumnType("longtext");
b.Property<string>("StoreAddress") b.Property<string>("StoreAddress")
.IsRequired() .IsRequired()
.HasColumnType("longtext"); .HasColumnType("longtext");
@@ -1803,6 +1911,39 @@ namespace Distribution.Migrations
b.ToTable("Stores"); b.ToTable("Stores");
}); });
modelBuilder.Entity("Distribution.Models.StoreKycDocument", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("DocumentType")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("FK_StoreId")
.HasColumnType("char(36)");
b.Property<string>("FileReference")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("UploadedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("FK_StoreId");
b.ToTable("StoreKycDocuments");
});
modelBuilder.Entity("Distribution.Models.SubCategory", b => modelBuilder.Entity("Distribution.Models.SubCategory", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@@ -2203,6 +2344,17 @@ namespace Distribution.Migrations
b.Navigation("Route"); b.Navigation("Route");
}); });
modelBuilder.Entity("Distribution.Models.StoreKycDocument", b =>
{
b.HasOne("Distribution.Models.Store", "Store")
.WithMany()
.HasForeignKey("FK_StoreId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Store");
});
modelBuilder.Entity("Distribution.Models.SubCategory", b => modelBuilder.Entity("Distribution.Models.SubCategory", b =>
{ {
b.HasOne("Distribution.Models.Category", "Category") b.HasOne("Distribution.Models.Category", "Category")
+11 -1
View File
@@ -1,6 +1,16 @@
namespace Distribution.Models namespace Distribution.Models
{ {
public enum LocationType { Warehouse, Vehicle } public enum LocationType
{
Warehouse,
Vehicle
}
public enum KycStatus
{
Pending,
Verified,
Rejected }
public enum MovementType public enum MovementType
{ {
+4
View File
@@ -11,6 +11,10 @@ namespace Distribution.Models
public decimal Longitude { get; set; } = 0; public decimal Longitude { get; set; } = 0;
public decimal OneTimeAmount { get; set; } = 0; public decimal OneTimeAmount { get; set; } = 0;
public decimal CreditAmount { get; set; } = 0; public decimal CreditAmount { get; set; } = 0;
public decimal CreditLimit { get; set; } = 0;
public decimal OutstandingBalance { get; set; } = 0;
public String? Segment { get; set; } //Gold ,silver,key Account,high risk
public KycStatus KycStatus { get; set; } = KycStatus.Pending;
public Guid FK_RouteId { get; set; } public Guid FK_RouteId { get; set; }
[ForeignKey("FK_RouteId")] [ForeignKey("FK_RouteId")]
+14
View File
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Distribution.Models
{
public class StoreKycDocument : Template
{
public Guid FK_StoreId { get; set; }
[ForeignKey("FK_StoreId")]
public Store Store { get; set; }
public String DocumentType { get; set; }
public String FileReference { get; set; }
public DateTime UploadedAt { get; set; } = DateTime.Now;
}
}
+3
View File
@@ -9,6 +9,7 @@ using Distribution.Features.Region;
using Distribution.Features.Role; using Distribution.Features.Role;
using Distribution.Features.Route; using Distribution.Features.Route;
using Distribution.Features.Store; using Distribution.Features.Store;
using Distribution.Features.Store.Kyc;
using Distribution.Features.Sync; using Distribution.Features.Sync;
using Distribution.Features.Uom; using Distribution.Features.Uom;
using Distribution.Features.User; using Distribution.Features.User;
@@ -46,6 +47,7 @@ builder.Services.AddScoped<IBrandRepository, BrandRepository>();
builder.Services.AddScoped<IUomRepository, UomRepository>(); builder.Services.AddScoped<IUomRepository, UomRepository>();
builder.Services.AddScoped<IItemRepository, ItemRepository>(); builder.Services.AddScoped<IItemRepository, ItemRepository>();
builder.Services.AddScoped<IStockRepository, StockRepository>(); builder.Services.AddScoped<IStockRepository, StockRepository>();
builder.Services.AddScoped<IStoreKycDocumentRepository, StoreKycDocumentRepository>();
builder.Services.AddScoped<RegionService>(); builder.Services.AddScoped<RegionService>();
builder.Services.AddScoped<RouteService>(); builder.Services.AddScoped<RouteService>();
@@ -62,6 +64,7 @@ builder.Services.AddScoped<UomService>();
builder.Services.AddScoped<ItemService>(); builder.Services.AddScoped<ItemService>();
builder.Services.AddScoped<SyncService>(); builder.Services.AddScoped<SyncService>();
builder.Services.AddScoped<StockService>(); builder.Services.AddScoped<StockService>();
builder.Services.AddScoped<StoreKycDocumentService>();
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<ICurrentUserService, CurrentUserService>(); builder.Services.AddScoped<ICurrentUserService, CurrentUserService>();
+3
View File
@@ -14,5 +14,8 @@
"Issuer": "Distribution.Api", "Issuer": "Distribution.Api",
"Audience": "Distribution.Api", "Audience": "Distribution.Api",
"ExpiryMinutes": 120 "ExpiryMinutes": 120
},
"StoreManagement": {
"UnverifiedKycOrderThreshold": 0
} }
} }
+215 -32
View File
@@ -1,22 +1,32 @@
# 12 — Store Management (Beyond CRUD) # 12 — Store Management (Beyond CRUD)
**Status**: Not Started **Status**: Done — migration applied to the database
**Depends On**: 00 — Existing Gap Fixes **Depends On**: 00 — Existing Gap Fixes, 10 — Region Management, 11 — Route & Sales Management
--- ---
## Goal ## Goal
Store CRUD already exists (`Features/Store`). This step covers everything in Store CRUD already exists (`Features/Store`). This step adds everything in
[mainPlan.md §4](./mainPlan.md#4-store-outlet-management) that isn't [mainPlan.md §4](./mainPlan.md#4-store-outlet-management) that isn't plain CRUD: credit control,
plain CRUD: KYC, credit, segmentation, and dashboarding. KYC verification, segmentation, outstanding balance, visit history, scheme eligibility, and a
sales dashboard.
--- ---
## Background / Context ## Background / Context
`Store` currently has no credit limit, outstanding balance, segment, or KYC fields — flagged as `Store` currently has no credit limit, outstanding balance, segment, or KYC fields — flagged as
gap #8 in [00_existing_gaps.md](./00_existing_gaps.md). gap #8 in [00_existing_gaps.md](./00_existing_gaps.md). Credit fields exist informally today as
`OneTimeAmount` / `CreditAmount`, which stay as-is; this step adds the real credit-limit +
outstanding-balance + KYC-gated-ordering flow on top.
`getStoreVisitHistory` and `checkStoreSchemeEligibility` are read-only integration points into
modules that don't exist yet ([11_route_sales_management.md](./11_route_sales_management.md) for
visits, [17_promotions_schemes.md](./17_promotions_schemes.md) for schemes). Implement them now
with the query shape defined below; wire the actual join once those modules land — return an empty
list / `eligible: true` (no active schemes to check) until then, guarded by a `NotImplementedYet`
style short-circuit, not a broken query.
--- ---
@@ -24,51 +34,224 @@ gap #8 in [00_existing_gaps.md](./00_existing_gaps.md).
### Store — New Fields ### Store — New Fields
`CreditLimit` (decimal), `OutstandingBalance` (decimal, derived/cached from Finance ledger once ```
[19_finance_accounting.md](./19_finance_accounting.md) exists), `Segment` (string), `KycStatus` Store (existing, add columns)
(`Pending`, `Verified`, `Rejected`). ├── CreditLimit (decimal) — default 0. Max outstanding allowed before new orders are blocked.
├── OutstandingBalance (decimal) — default 0. Cached/denormalized. Updated by Finance module
│ (step 19) on invoice/payment events via UpdateOutstandingBalanceAsync.
│ Until Finance exists, only moved by manual adjustment endpoint.
├── Segment (string?) — free text, e.g. "Gold", "Silver", "Key Account", "High Risk".
├── KycStatus (enum) — Pending | Verified | Rejected. Default Pending.
```
### KYC Document ### New Enum — KycStatus
`StoreId`, `DocumentType`, `FileReference`, `UploadedAt` — file storage mechanism TBD (out of scope ```csharp
for this step's data model, just the record). public enum KycStatus { Pending, Verified, Rejected }
```
### New Entity — StoreKycDocument
```
StoreKycDocument
├── Id (Guid) — PK, from Template
├── FK_StoreId (Guid) — required
├── DocumentType (string) — free text, e.g. "GST Certificate", "PAN Card", "Shop License,NIC"
├── FileReference (string) — relative path under wwwroot/uploads/kyc/{storeId}/
├── UploadedAt (DateTime)
├── IsActive, CreatedAt — from Template
```
### AppSettings — New Config Key
```
StoreManagement:UnverifiedKycOrderThreshold (decimal) — default 0.
Max single-order value a store with KycStatus != Verified may place.
0 disables ordering entirely for unverified stores; set higher to allow small orders through.
```
---
## Migrations
One migration needed:
1. **AddStoreCreditAndKyc** — adds `CreditLimit`, `OutstandingBalance`, `Segment`, `KycStatus`
columns to `Stores`; creates `StoreKycDocuments` table.
--- ---
## API Endpoints ## API Endpoints
| Function reference | Endpoint intent | ### Existing (unchanged)
|---|---| | Method | Route | Permission | Notes |
| `createStore(storeData, kycDocs)` | Extends existing `POST /api/stores` with doc upload | |---|---|---|---|
| `verifyStoreKyc(storeId)` | `PUT /api/stores/{id}/kyc/verify` | | GET | /api/stores | stores.view | |
| `updateStoreCreditLimit(storeId, newLimit, approverId)` | `PUT /api/stores/{id}/credit-limit` | | GET | /api/stores/{id} | stores.view | |
| `getStoreOutstandingBalance(storeId)` | `GET /api/stores/{id}/outstanding-balance` | | POST | /api/stores | stores.create | |
| `classifyStore(storeId, segment)` | `PUT /api/stores/{id}/segment` | | PUT | /api/stores/{id} | stores.update | |
| `deactivateStore(storeId, reason)` | Extends existing `DELETE /api/stores/{id}` with a reason field | | DELETE | /api/stores/{id} | stores.delete | Soft delete |
| `getStoreVisitHistory(storeId)` | `GET /api/stores/{id}/visit-history` — reads from [11_route_sales_management.md](./11_route_sales_management.md) |
| `checkStoreSchemeEligibility(storeId, schemeId)` | `GET /api/stores/{id}/schemes/{schemeId}/eligibility` — depends on [17_promotions_schemes.md](./17_promotions_schemes.md) | ### New
| `getStoreSalesDashboard(storeId, period)` | `GET /api/stores/{id}/dashboard?period=...` | | Method | Route | Permission | Notes |
|---|---|---|---|
| POST | /api/stores/{id}/kyc-documents | stores.update | Multipart upload, appends a KYC document |
| GET | /api/stores/{id}/kyc-documents | stores.view | Lists documents for a store |
| PUT | /api/stores/{id}/kyc/verify | stores.kyc.verify | Sets KycStatus, body carries `status` (Verified/Rejected) + optional `notes` |
| PUT | /api/stores/{id}/credit-limit | stores.credit.update | Requires Supervisor (roleLevel ≥ 20) or above |
| PUT | /api/stores/{id}/outstanding-balance | stores.credit.update | Manual adjustment until Finance owns this; same permission as credit-limit |
| GET | /api/stores/{id}/outstanding-balance | stores.view | Returns cached value + CreditLimit + available credit |
| PUT | /api/stores/{id}/segment | stores.update | Body: `{ "segment": "Gold" }` |
| GET | /api/stores/{id}/visit-history | stores.view | Paginated. Empty list until Step 11 wiring lands |
| GET | /api/stores/{id}/schemes/{schemeId}/eligibility | stores.view | Returns `{ eligible: true, reason: null }` until Step 17 wiring lands |
| GET | /api/stores/{id}/dashboard?period=... | stores.view | Aggregates order count/value for the period from existing Order tables |
---
## Request / Response Shapes
### POST `/api/stores/{id}/kyc-documents` (multipart/form-data)
Fields: `documentType` (string), `file` (binary).
Response:
```json
{ "id": "...", "storeId": "...", "documentType": "GST Certificate", "fileReference": "uploads/kyc/{storeId}/{guid}.pdf", "uploadedAt": "2026-08-20T10:00:00" }
```
### PUT `/api/stores/{id}/kyc/verify` request
```json
{ "status": "Verified", "notes": "GST + PAN checked against ERP records" }
```
### PUT `/api/stores/{id}/credit-limit` request
```json
{ "newLimit": 50000, "approverId": "..." }
```
`approverId` must resolve to a user with `RoleLevel >= 20` (Supervisor or above); enforced
server-side from the authenticated caller, not trusted from the body — the field is echoed back
for audit display only.
### GET `/api/stores/{id}/outstanding-balance` response
```json
{ "storeId": "...", "creditLimit": 50000, "outstandingBalance": 32000, "availableCredit": 18000 }
```
### GET `/api/stores/{id}/dashboard` response
```json
{
"storeId": "...",
"period": "2026-08",
"orderCount": 12,
"totalOrderValue": 145000,
"lastOrderDate": "2026-08-18T09:00:00"
}
```
--- ---
## Business Rules ## Business Rules
- `updateStoreCreditLimit` requires an approver at Supervisor level or above. 1. `updateStoreCreditLimit` requires the authenticated caller to have `RoleLevel >= 20`
- A store with `KycStatus != Verified` should not be able to place orders above a configurable (Supervisor or above) — enforced by the `stores.credit.update` policy plus a role-level check
threshold (or at all) — confirm exact rule with the user before implementing. in the service, same pattern as `StoreService.HasGlobalScope`.
- `deactivateStore` blocks new orders against it, matching the existing `IsActive` soft-delete 2. A store with `KycStatus != Verified` may only place orders up to
filter already used in `OrderService`. `StoreManagement:UnverifiedKycOrderThreshold`. `OrderService` must check this at order creation
time; orders exceeding the threshold are rejected with a 400. This mirrors the stock-ledger
pattern of rejecting at the point of the write, not after.
3. `deactivateStore` (existing `DELETE /api/stores/{id}`) blocks new orders against the store,
matching the existing `IsActive` soft-delete filter already used in `OrderService`. No separate
reason field is added — soft delete already covers it via the existing `Template.IsActive` flag.
4. `OutstandingBalance` is never edited directly by client-supplied arbitrary values outside the
dedicated endpoint — always through `UpdateOutstandingBalanceAsync`, so Finance (step 19) has a
single integration point to call into later.
5. KYC documents are append-only from the API's perspective — no update endpoint. To replace a
document, upload a new one; old ones stay for audit trail (soft-deletable via `IsActive` if
ever needed).
6. Scope rules for all new endpoints follow the existing `StoreService` pattern: global-scope roles
(`RoleLevel >= 50`) see everything, others are checked via `IScopeAccessService.HasStoreScopeAsync`.
---
## Permissions to Add to Seed
New permission codes to add to the existing seed:
```
stores.kyc.verify, stores.credit.update
```
(`stores.view`, `stores.create`, `stores.update`, `stores.delete` already exist.)
Role assignments:
- **SalesRep (10)**: stores.view (unchanged)
- **Supervisor (20)**: stores.view, stores.update, stores.credit.update
- **AreaManager (30)**: stores.view, stores.update, stores.credit.update, stores.kyc.verify
- **AreaSupervisor (40)**: all store permissions
- **RegionalManager (50)**: all store permissions
- **RegionalAgency (60)**: all store permissions
--- ---
## Open Questions ## Open Questions
- Is `OutstandingBalance` a cached/denormalized field updated on invoice/payment events, or always - None. Resolved in planning discussion (2026-08-20): OutstandingBalance is cached/denormalized;
computed live from Finance records? KYC document type is free text with local disk storage; unverified stores are gated by a
- What document types are required for KYC, and is file storage local, blob, or third-party? configurable order-value threshold rather than a hard block.
--- ---
## Implementation Notes ## Implementation Notes
> Fill this section in during planning discussion before writing any code. ### File structure created / touched
```
Features/
Store/
StoreController.cs (extended — credit-limit, balance, kyc/verify, segment,
visit-history, scheme-eligibility, dashboard endpoints)
StoreDTOs.cs (extended — new request/response records)
StoreService.cs (extended — new methods, RoleLevel >= 20 credit-approver check)
IStoreRepository.cs (extended — GetOrdersForDashboardAsync)
StoreRepository.cs (extended)
Kyc/
StoreKycDocumentController.cs
StoreKycDocumentDTOs.cs
StoreKycDocumentService.cs
IStoreKycDocumentRepository.cs
StoreKycDocumentRepository.cs
Order/
OrderService.cs (extended — KycStatus + UnverifiedKycOrderThreshold gate in CreateAsync)
Models/
Store.cs (add CreditLimit, OutstandingBalance, Segment, KycStatus columns)
StoreKycDocument.cs (new)
Enums.cs (add KycStatus enum)
Migrations/
AddStoreCreditAndKyc
appsettings.json
add "StoreManagement": { "UnverifiedKycOrderThreshold": 0 }
Program.cs
register IStoreKycDocumentRepository, StoreKycDocumentRepository, StoreKycDocumentService
```
KYC documents live as a sub-namespace `Features/Store/Kyc/` rather than a top-level feature,
matching the one-feature-per-folder convention (`Features/Store`, `Features/Stock`) — they only
ever belong to a Store and have no independent lifecycle.
### KYC upload logic (pseudo)
```
POST /api/stores/{id}/kyc-documents — multipart (documentType, file):
1. Load Store by id, reject if missing/inactive or caller lacks store scope
2. Ensure wwwroot/uploads/kyc/{storeId}/ exists
3. Save file as {guid}.{ext}, record FileReference = "uploads/kyc/{storeId}/{guid}.{ext}"
4. Insert StoreKycDocument row, commit in the same UoW transaction
```
### Order-creation KYC gate (pseudo)
```
OrderService.CreateAsync — before inserting the order:
1. Load Store by request.StoreId
2. If Store.KycStatus != Verified:
threshold = config["StoreManagement:UnverifiedKycOrderThreshold"]
if request.TotalAmount > threshold: reject (return null → 403 at controller)
```
</content>