Compare commits

..

64 Commits

Author SHA1 Message Date
DeepnaPooja 6b608ad2ef Update permission feature with edit and create role functionality 2026-10-19 16:39:47 +05:30
DeepnaPooja 3c75f9786e Add multi-series charts and enhance dashboard functionality 2026-10-19 15:51:39 +05:30
DeepnaPooja 2d6723a040 Update dashboard 2026-10-19 15:48:45 +05:30
kalana_Thilakarathna 2fe2ba007c Merge pull request 'fix: update login function to handle profile data correctly' (#68) from dev into production
Reviewed-on: #68
2026-10-19 10:25:57 +05:30
Kalana B. Thilakarathna f3f2b71bd4 fix: update login function to handle profile data correctly
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 12m43s
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 16m30s
2026-10-19 10:25:29 +05:30
kalana_Thilakarathna bc72426495 Merge pull request 'auth fix' (#67) from dev into production
Reviewed-on: #67
2026-10-19 10:20:29 +05:30
Kalana B. Thilakarathna da29492798 auth fix
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 13m10s
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 16m51s
2026-10-19 10:19:40 +05:30
kalana_Thilakarathna ce21aa6588 Merge pull request 'feat: add toast notifications for successful and failed login attempts' (#66) from dev into production
Reviewed-on: #66
2026-10-19 02:50:47 +05:30
Kalana B. Thilakarathna f44cbf711b feat: add toast notifications for successful and failed login attempts
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 12m53s
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 16m41s
2026-10-19 02:50:06 +05:30
kalana_Thilakarathna aaac42b481 Merge pull request 'Dev' (#65) from dev into production
Reviewed-on: #65
2026-10-19 02:45:35 +05:30
Kalana B. Thilakarathna 7a21cde217 refactor: simplify user API calls by removing pageSize parameter in multiple components
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 11m52s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 13m5s
2026-10-19 02:44:19 +05:30
Kalana B. Thilakarathna 531b3a7fef Redesign login UI, add theme toggle, refactor user update
- Redesigned login page with two-panel layout and branding
- Added HexaDistro logo and theme toggle to sidebar/header
- Refactored user update: roles via update endpoint, removed assignRole API/controller
- Extended UpdateUserRequest for username, role, password changes
- UserService.UpdateAsync syncs changes with AuthHex, with rollback
- Stock balances client dedupes by itemId-locationId
- Middleware matcher excludes static assets from auth checks
- Improved localStorage clearing for user context
- Added lucide-react for icons
- Minor UI/code cleanups for consistency and UX
2026-10-19 02:20:14 +05:30
kalana_Thilakarathna a81e32bbe2 Merge pull request 'fe fix for loggin redirection' (#64) from dev into production
Reviewed-on: #64
2026-10-19 02:16:31 +05:30
Kalana B. Thilakarathna 4ef63420b7 fe fix for loggin redirection
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 11m36s
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 15m19s
2026-10-18 23:38:28 +05:30
Kalana B. Thilakarathna 9fdf5aa8e3 Merge branch 'dev' into production 2026-10-18 23:23:12 +05:30
Kalana B. Thilakarathna d9c339949e conflict fixed 2026-10-18 23:22:04 +05:30
Kalana B. Thilakarathna 0052725b88 feat: add user and role view sheets with detailed information display
- Created UserViewSheet component to display user details including username, full name, role, status, and timestamps.
- Created RoleViewSheet component to display role details including name, level, status, creation date, and associated permissions.
- Introduced permissions configuration in a new permissions.ts file, defining categories and permission codes for better management.
- Implemented middleware for authentication, ensuring access control for protected routes.
2026-10-18 23:11:01 +05:30
DeepnaPooja 5d18aba1f9 Merge pull request 'Dev' (#63) from dev into production
Reviewed-on: #63
2026-10-16 10:53:09 +00:00
DeepnaPooja 5828879ddc Merge pull request 'chore: add exceljs, jspdf, and jspdf-autotable dependencies to package.json' (#62) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 14m0s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 15m11s
Reviewed-on: #62
2026-10-16 10:52:30 +00:00
DeepnaPooja 728f2a8b17 Merge pull request 'Dev' (#61) from dev into production
Reviewed-on: #61
2026-10-16 10:26:15 +00:00
DeepnaPooja 1b66d5d767 Merge pull request 'Refactor/main flow' (#60) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 12m3s
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 15m51s
Reviewed-on: #60
2026-10-16 10:25:08 +00:00
DeepnaPooja 5c37f02f19 Merge pull request 'Dev' (#59) from dev into production
Reviewed-on: #59
2026-10-09 04:38:19 +00:00
DeepnaPooja 6b3f28d3ae Merge pull request 'Refactor/main flow' (#58) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 13m37s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 15m0s
Reviewed-on: #58
2026-10-09 04:37:42 +00:00
Kalana B. Thilakarathna 558afc6f9d auth layer implemented 2026-10-09 09:58:45 +05:30
Kalana B. Thilakarathna 5b2ac8cc14 Merge branch 'dev' of https://gitea.hexdive.com/New_REP_SYSTEM/ERP_Distribution into dev 2026-10-09 09:37:38 +05:30
Kalana B. Thilakarathna 5cb32bee95 Revert "auth layer implemented"
This reverts commit 9adfff48a7.
2026-10-09 09:37:28 +05:30
Kalana B. Thilakarathna 9adfff48a7 auth layer implemented 2026-10-09 09:37:05 +05:30
DeepnaPooja f5967497be Merge pull request 'Dev' (#57) from dev into production
Reviewed-on: #57
2026-10-08 07:36:24 +00:00
DeepnaPooja 74f33d8979 Merge pull request 'Refactor/main flow' (#56) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Successful in 1m42s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 11m55s
Reviewed-on: #56
2026-10-08 07:35:34 +00:00
DeepnaPooja 4110e2fcfc Merge pull request 'Dev' (#55) from dev into production
Reviewed-on: #55
2026-10-07 05:17:54 +00:00
DeepnaPooja 23fb7361a4 Merge pull request 'Refactor/main flow' (#54) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 14m8s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 15m25s
Reviewed-on: #54
2026-10-07 05:16:58 +00:00
DeepnaPooja c52eaabec4 Merge pull request 'Dev' (#53) from dev into production
Reviewed-on: #53
2026-09-29 12:14:53 +00:00
DeepnaPooja 63c1c4ad1a Merge pull request 'fix' (#52) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 12m12s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 13m26s
Reviewed-on: #52
2026-09-29 12:14:19 +00:00
DeepnaPooja df0eb3cd5a Merge pull request 'Refactor/main flow' (#50) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 11m24s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 12m16s
Reviewed-on: #50
2026-09-29 12:04:26 +00:00
DeepnaPooja cc72e22664 Merge pull request 'Refactor/main flow' (#49) from refactor/main_flow into dev
Reviewed-on: #49
2026-09-29 09:45:51 +00:00
DeepnaPooja 37f4a88014 Merge pull request 'Dev' (#48) from dev into production
Reviewed-on: #48
2026-09-28 07:39:55 +00:00
DeepnaPooja a4f5d12234 Merge pull request 'Refactor/main flow' (#47) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 12m10s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 13m24s
Reviewed-on: #47
2026-09-28 07:39:07 +00:00
DeepnaPooja 2d365cd906 Merge pull request 'Dev' (#46) from dev into production
Reviewed-on: #46
2026-09-25 08:38:12 +00:00
DeepnaPooja d6fd685b3c Merge pull request 'Add loading sheet edit flow' (#45) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 13m57s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 15m8s
Reviewed-on: #45
2026-09-25 08:37:39 +00:00
DeepnaPooja c68c6e1ab9 Merge pull request 'Dev' (#44) from dev into production
Reviewed-on: #44
2026-09-24 12:00:43 +00:00
DeepnaPooja aaf6e5f12d Merge pull request 'Refactor/main flow' (#43) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 11m24s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 12m36s
Reviewed-on: #43
2026-09-24 12:00:17 +00:00
DeepnaPooja ddc3ecd3e6 Merge pull request 'Dev' (#42) from dev into production
Reviewed-on: #42
2026-09-23 08:38:21 +00:00
DeepnaPooja 556dedb8a3 Merge pull request 'Refactor/main flow' (#41) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 13m49s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 14m58s
Reviewed-on: #41
2026-09-23 08:36:57 +00:00
DeepnaPooja d7b6f29200 Merge pull request 'Dev' (#40) from dev into production
Reviewed-on: #40
2026-09-23 07:23:59 +00:00
DeepnaPooja 6f72f7a0e9 Merge pull request 'Refactor/main flow' (#39) from refactor/main_flow into dev
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 13m8s
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 14m21s
Reviewed-on: #39
2026-09-23 07:23:19 +00:00
DeepnaPooja 53dcdf929a Merge pull request 'Refactor/main flow' (#37) from refactor/main_flow into dev
Reviewed-on: #37
2026-09-22 11:43:52 +00:00
DeepnaPooja d2277f626c Merge pull request 'Refactor/main flow' (#38) from refactor/main_flow into production
Reviewed-on: #38
2026-09-22 11:43:07 +00:00
kalana_Thilakarathna 3149902574 Merge pull request 'Dev' (#36) from dev into production
Reviewed-on: #36
2026-09-21 04:05:56 +00:00
kalana_Thilakarathna 37fb72376a Merge pull request 'Dev' (#35) from dev into production
Reviewed-on: #35
2026-09-21 03:47:22 +00:00
kalana_Thilakarathna 52a9a3fde7 Merge pull request 'Add build argument for NEXT_PUBLIC_API_URL in Dockerfile and CI/CD workflow' (#32) from dev into production
Reviewed-on: #32
2026-09-20 11:21:49 +00:00
kalana_Thilakarathna 1b310c86b3 Merge pull request 'Add Dockerfile and .dockerignore; configure Next.js output settings' (#31) from dev into production
Reviewed-on: #31
2026-09-20 11:07:29 +00:00
kalana_Thilakarathna e398ee9d6b Merge pull request 'docker log' (#30) from dev into production
Reviewed-on: #30
2026-09-20 11:03:16 +00:00
kalana_Thilakarathna a3c0211654 Merge pull request 'pipline update' (#29) from dev into production
Reviewed-on: #29
2026-09-20 10:53:45 +00:00
kalana_Thilakarathna e4e12aa05a Merge pull request 'build fix' (#28) from dev into production
Reviewed-on: #28
2026-09-20 10:42:24 +00:00
kalana_Thilakarathna 3103fb66ef Merge pull request 'Dev' (#27) from dev into production
Reviewed-on: #27
2026-09-20 10:35:40 +00:00
Kalana B. Thilakarathna 93355d34f1 Merge branch 'dev' into production 2026-09-16 11:30:37 +05:30
Kalana B. Thilakarathna 9151f47d15 Merge branch 'production' of https://gitea.hexdive.com/New_REP_SYSTEM/ERP_Distribution into production 2026-09-16 10:58:02 +05:30
Kalana B. Thilakarathna 661b522b7d Merge branch 'dev' into production 2026-09-16 10:57:55 +05:30
DeepnaPooja e0bb17d0ff Merge pull request 'Dev' (#25) from dev into production
Reviewed-on: #25
2026-09-16 05:13:39 +00:00
Kalana B. Thilakarathna 0f29413375 Merge branch 'dev' into production 2026-09-16 10:41:32 +05:30
DeepnaPooja ef17f7da0a Merge pull request 'Dev' (#23) from dev into production
Reviewed-on: #23
2026-09-14 06:29:20 +00:00
DeepnaPooja d9031f8e73 Merge pull request 'Dev' (#20) from dev into production
Reviewed-on: #20
2026-09-01 10:28:44 +00:00
Kalana B. Thilakarathna 75578ea7f6 Merge branch 'production' of https://gitea.hexdive.com/New_REP_SYSTEM/ERP_Distribution into production 2026-09-01 10:54:20 +05:30
DeepnaPooja 4f02fa303d Merge pull request 'Dev' (#18) from dev into production
Reviewed-on: #18
2026-08-31 07:41:03 +00:00
147 changed files with 47283 additions and 1478 deletions
+1
View File
@@ -600,5 +600,6 @@ public class AppDBContext(DbContextOptions<AppDBContext> options) : DbContext(op
Seed.ProcurementSeed.Apply(modelBuilder);
Seed.CommerceSeed.Apply(modelBuilder);
Seed.OperationsExtrasSeed.Apply(modelBuilder);
Seed.AdminSeed.Apply(modelBuilder);
}
}
+25
View File
@@ -0,0 +1,25 @@
using Distribution.Models;
using Microsoft.EntityFrameworkCore;
namespace Distribution.Data.Seed;
public static class AdminSeed
{
private static readonly DateTime SeedDate = new(2026, 10, 13);
// Same GUID as the AuthHex user — the sub claim from the JWT maps to this Id
internal static readonly Guid SuperAdminUserId = new("00000001-0000-0000-0000-000000000001");
public static void Apply(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasData(new User
{
Id = SuperAdminUserId,
Username = "superadmin",
FullName = "Super Admin",
FK_RoleId = RoleAndPermissionSeed.SuperAdminRoleId,
IsActive = true,
CreatedAt = SeedDate
});
}
}
+6 -10
View File
@@ -7,10 +7,6 @@ public static class MasterDataSeed
{
private static readonly DateTime SeedDate = new(2026, 8, 20);
// Precomputed via PasswordHasher<User>().HashPassword(new User(), "Passw0rd!123") — see
// Implementation Notes in the plan; not derivable from HasData at migration time.
internal const string SeedPasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==";
// Role ids match Data/Seed/RoleAndPermissionSeed.cs (private there, so re-declared here by value).
internal static readonly Guid SalesRepRoleId = new("10000000-0000-0000-0000-000000000001");
internal static readonly Guid SupervisorRoleId = new("10000000-0000-0000-0000-000000000002");
@@ -115,12 +111,12 @@ public static class MasterDataSeed
);
modelBuilder.Entity<User>().HasData(
new User { Id = Supervisor1UserId, Username = "sunil.fernando", PasswordHash = SeedPasswordHash, FullName = "Sunil Fernando", FK_RoleId = SupervisorRoleId, FK_ReportsToUserId = null, CreatedAt = SeedDate, IsActive = true },
new User { Id = SalesRep1UserId, Username = "nimal.perera", PasswordHash = SeedPasswordHash, FullName = "Nimal Perera", FK_RoleId = SalesRepRoleId, FK_ReportsToUserId = Supervisor1UserId, CreatedAt = SeedDate, IsActive = true },
new User { Id = SalesRep2UserId, Username = "kamal.silva", PasswordHash = SeedPasswordHash, FullName = "Kamal Silva", FK_RoleId = SalesRepRoleId, FK_ReportsToUserId = Supervisor1UserId, CreatedAt = SeedDate, IsActive = true },
new User { Id = Driver1UserId, Username = "ruwan.jayasuriya", PasswordHash = SeedPasswordHash, FullName = "Ruwan Jayasuriya", FK_RoleId = SalesRepRoleId, FK_ReportsToUserId = Supervisor1UserId, CreatedAt = SeedDate, IsActive = true },
new User { Id = Driver2UserId, Username = "priyantha.kumara", PasswordHash = SeedPasswordHash, FullName = "Priyantha Kumara", FK_RoleId = SalesRepRoleId, FK_ReportsToUserId = Supervisor1UserId, CreatedAt = SeedDate, IsActive = true },
new User { Id = RegionalManager1UserId, Username = "priya.rajapaksa", PasswordHash = SeedPasswordHash, FullName = "Priya Rajapaksa", FK_RoleId = RegionalManagerRoleId, FK_ReportsToUserId = null, CreatedAt = SeedDate, IsActive = true }
new User { Id = Supervisor1UserId, Username = "sunil.fernando",FullName = "Sunil Fernando", FK_RoleId = SupervisorRoleId, FK_ReportsToUserId = null, CreatedAt = SeedDate, IsActive = true },
new User { Id = SalesRep1UserId, Username = "nimal.perera",FullName = "Nimal Perera", FK_RoleId = SalesRepRoleId, FK_ReportsToUserId = Supervisor1UserId, CreatedAt = SeedDate, IsActive = true },
new User { Id = SalesRep2UserId, Username = "kamal.silva",FullName = "Kamal Silva", FK_RoleId = SalesRepRoleId, FK_ReportsToUserId = Supervisor1UserId, CreatedAt = SeedDate, IsActive = true },
new User { Id = Driver1UserId, Username = "ruwan.jayasuriya",FullName = "Ruwan Jayasuriya", FK_RoleId = SalesRepRoleId, FK_ReportsToUserId = Supervisor1UserId, CreatedAt = SeedDate, IsActive = true },
new User { Id = Driver2UserId, Username = "priyantha.kumara",FullName = "Priyantha Kumara", FK_RoleId = SalesRepRoleId, FK_ReportsToUserId = Supervisor1UserId, CreatedAt = SeedDate, IsActive = true },
new User { Id = RegionalManager1UserId, Username = "priya.rajapaksa",FullName = "Priya Rajapaksa", FK_RoleId = RegionalManagerRoleId, FK_ReportsToUserId = null, CreatedAt = SeedDate, IsActive = true }
);
modelBuilder.Entity<DriverProfile>().HasData(
@@ -43,7 +43,7 @@ public static class OperationsExtrasSeed
public static void Apply(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().HasData(
new User { Id = RegionalAgency1UserId, Username = "channa.desilva", PasswordHash = MasterDataSeed.SeedPasswordHash, FullName = "Channa De Silva", FK_RoleId = RegionalAgencyRoleId, FK_ReportsToUserId = null, CreatedAt = new DateTime(2026, 8, 20), IsActive = true }
new User { Id = RegionalAgency1UserId, Username = "channa.desilva", FullName = "Channa De Silva", FK_RoleId = RegionalAgencyRoleId, FK_ReportsToUserId = null, CreatedAt = new DateTime(2026, 8, 20), IsActive = true }
);
modelBuilder.Entity<Uom>().HasData(
+181 -12
View File
@@ -7,22 +7,191 @@ public static class RoleAndPermissionSeed
{
private static readonly DateTime SeedDate = new(2026, 8, 18);
private static readonly Guid SalesRepId = new("10000000-0000-0000-0000-000000000001");
private static readonly Guid SupervisorId = new("10000000-0000-0000-0000-000000000002");
private static readonly Guid AreaManagerId = new("10000000-0000-0000-0000-000000000003");
private static readonly Guid AreaSupervisorId = new("10000000-0000-0000-0000-000000000004");
private static readonly Guid RegionalManagerId = new("10000000-0000-0000-0000-000000000005");
private static readonly Guid RegionalAgencyId = new("10000000-0000-0000-0000-000000000006");
private static readonly Guid SalesRepId = new("10000000-0000-0000-0000-000000000001");
private static readonly Guid SupervisorId = new("10000000-0000-0000-0000-000000000002");
private static readonly Guid AreaManagerId = new("10000000-0000-0000-0000-000000000003");
private static readonly Guid AreaSupervisorId = new("10000000-0000-0000-0000-000000000004");
private static readonly Guid RegionalManagerId = new("10000000-0000-0000-0000-000000000005");
private static readonly Guid RegionalAgencyId = new("10000000-0000-0000-0000-000000000006");
internal static readonly Guid SuperAdminRoleId = new("10000000-0000-0000-0000-000000000007");
// ── Legacy broad permissions (nav.ts uses these for sidebar visibility) ────
private static readonly Guid PermOrdersView = new("20000000-0000-0000-0000-000000000001");
private static readonly Guid PermRidesView = new("20000000-0000-0000-0000-000000000002");
private static readonly Guid PermLoadingView = new("20000000-0000-0000-0000-000000000003");
private static readonly Guid PermStoresView = new("20000000-0000-0000-0000-000000000004");
private static readonly Guid PermSalesVisitsCheckin = new("20000000-0000-0000-0000-000000000005");
private static readonly Guid PermItemsView = new("20000000-0000-0000-0000-000000000006");
private static readonly Guid PermCategoriesView = new("20000000-0000-0000-0000-000000000007");
private static readonly Guid PermWarehousesView = new("20000000-0000-0000-0000-000000000008");
private static readonly Guid PermPurchaseOrdersView = new("20000000-0000-0000-0000-000000000009");
private static readonly Guid PermPricelistsView = new("20000000-0000-0000-0000-000000000010");
private static readonly Guid PermSchemesView = new("20000000-0000-0000-0000-000000000011");
private static readonly Guid PermSuppliersView = new("20000000-0000-0000-0000-000000000012");
private static readonly Guid PermDriverProfilesView = new("20000000-0000-0000-0000-000000000013");
private static readonly Guid PermComplianceManage = new("20000000-0000-0000-0000-000000000014");
private static readonly Guid PermUsersView = new("20000000-0000-0000-0000-000000000015");
private static readonly Guid PermRolesView = new("20000000-0000-0000-0000-000000000016");
private static readonly Guid PermRegionsView = new("20000000-0000-0000-0000-000000000017");
private static readonly Guid PermRoutesView = new("20000000-0000-0000-0000-000000000018");
private static readonly Guid PermVehiclesView = new("20000000-0000-0000-0000-000000000019");
// ── Granular API permissions (used in [Authorize("...")] on controller actions) ─
private static readonly Guid PermClaimView = new("20000000-0000-0000-0000-000000000020");
private static readonly Guid PermClaimManage = new("20000000-0000-0000-0000-000000000021");
private static readonly Guid PermDeliveryTaskView = new("20000000-0000-0000-0000-000000000022");
private static readonly Guid PermDeliveryTaskManage = new("20000000-0000-0000-0000-000000000023");
private static readonly Guid PermDriverView = new("20000000-0000-0000-0000-000000000024");
private static readonly Guid PermDriverManage = new("20000000-0000-0000-0000-000000000025");
private static readonly Guid PermGrnView = new("20000000-0000-0000-0000-000000000026");
private static readonly Guid PermGrnManage = new("20000000-0000-0000-0000-000000000027");
private static readonly Guid PermLoadingSheetView = new("20000000-0000-0000-0000-000000000028");
private static readonly Guid PermLoadingSheetManage = new("20000000-0000-0000-0000-000000000029");
private static readonly Guid PermPriceListView = new("20000000-0000-0000-0000-000000000030");
private static readonly Guid PermPriceListManage = new("20000000-0000-0000-0000-000000000031");
private static readonly Guid PermPurchaseOrderView = new("20000000-0000-0000-0000-000000000032");
private static readonly Guid PermPurchaseOrderManage= new("20000000-0000-0000-0000-000000000033");
private static readonly Guid PermPurchaseReturnManage=new("20000000-0000-0000-0000-000000000034");
private static readonly Guid PermRegionView = new("20000000-0000-0000-0000-000000000035");
private static readonly Guid PermRegionManage = new("20000000-0000-0000-0000-000000000036");
private static readonly Guid PermReturnView = new("20000000-0000-0000-0000-000000000037");
private static readonly Guid PermReturnManage = new("20000000-0000-0000-0000-000000000038");
private static readonly Guid PermRouteView = new("20000000-0000-0000-0000-000000000039");
private static readonly Guid PermRouteManage = new("20000000-0000-0000-0000-000000000040");
private static readonly Guid PermSchemeView = new("20000000-0000-0000-0000-000000000041");
private static readonly Guid PermSchemeManage = new("20000000-0000-0000-0000-000000000042");
private static readonly Guid PermStockView = new("20000000-0000-0000-0000-000000000043");
private static readonly Guid PermStockManage = new("20000000-0000-0000-0000-000000000044");
private static readonly Guid PermStoreView = new("20000000-0000-0000-0000-000000000045");
private static readonly Guid PermStoreManage = new("20000000-0000-0000-0000-000000000046");
private static readonly Guid PermSupplierClaimView = new("20000000-0000-0000-0000-000000000047");
private static readonly Guid PermSupplierClaimManage= new("20000000-0000-0000-0000-000000000048");
private static readonly Guid PermSysConfigView = new("20000000-0000-0000-0000-000000000049");
private static readonly Guid PermSysConfigManage = new("20000000-0000-0000-0000-000000000050");
public static void Apply(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Role>().HasData(
new Role { Id = SalesRepId, Name = "SalesRep", Level = 10, CreatedAt = SeedDate, IsActive = true },
new Role { Id = SupervisorId, Name = "Supervisor", Level = 20, CreatedAt = SeedDate, IsActive = true },
new Role { Id = AreaManagerId, Name = "AreaManager", Level = 30, CreatedAt = SeedDate, IsActive = true },
new Role { Id = AreaSupervisorId, Name = "AreaSupervisor", Level = 40, CreatedAt = SeedDate, IsActive = true },
new Role { Id = RegionalManagerId, Name = "RegionalManager", Level = 50, CreatedAt = SeedDate, IsActive = true },
new Role { Id = RegionalAgencyId, Name = "RegionalAgency", Level = 60, CreatedAt = SeedDate, IsActive = true }
new Role { Id = SalesRepId, Name = "SalesRep", Level = 10, CreatedAt = SeedDate, IsActive = true },
new Role { Id = SupervisorId, Name = "Supervisor", Level = 20, CreatedAt = SeedDate, IsActive = true },
new Role { Id = AreaManagerId, Name = "AreaManager", Level = 30, CreatedAt = SeedDate, IsActive = true },
new Role { Id = AreaSupervisorId, Name = "AreaSupervisor", Level = 40, CreatedAt = SeedDate, IsActive = true },
new Role { Id = RegionalManagerId,Name = "RegionalManager",Level = 50, CreatedAt = SeedDate, IsActive = true },
new Role { Id = RegionalAgencyId, Name = "RegionalAgency", Level = 60, CreatedAt = SeedDate, IsActive = true },
new Role { Id = SuperAdminRoleId, Name = "SuperAdmin", Level = 100, CreatedAt = SeedDate, IsActive = true }
);
modelBuilder.Entity<Permission>().HasData(
// ── Legacy broad permissions ──────────────────────────────────────────
new Permission { Id = PermOrdersView, Code = "orders.view", Description = "View shop POs, invoices, payments and returns", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermRidesView, Code = "rides.view", Description = "View and manage delivery rides and delivery tasks", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermLoadingView, Code = "loading.view", Description = "View and manage loading sheets", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermStoresView, Code = "stores.view", Description = "View store accounts, credit limits and balances", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSalesVisitsCheckin, Code = "sales_visits.checkin", Description = "Check in and out of scheduled store visits", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermItemsView, Code = "items.view", Description = "View and manage catalogue products", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermCategoriesView, Code = "categories.view", Description = "View and manage product categories and brands", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermWarehousesView, Code = "warehouses.view", Description = "View stock balances, movements, warehouses and reports", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermPurchaseOrdersView, Code = "purchase_orders.view", Description = "View and manage purchase orders, GRNs and supplier claims", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermPricelistsView, Code = "pricelists.view", Description = "View and manage regional price lists", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSchemesView, Code = "schemes.view", Description = "View and manage pricing schemes and promotions", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSuppliersView, Code = "suppliers.view", Description = "View and manage supplier accounts", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermDriverProfilesView, Code = "driver_profiles.view", Description = "View and manage driver profiles and licensing", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermComplianceManage, Code = "compliance.manage", Description = "Manage driver compliance rules", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermUsersView, Code = "users.view", Description = "View and manage staff user accounts", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermRolesView, Code = "roles.view", Description = "View and manage roles and their permission sets", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermRegionsView, Code = "regions.view", Description = "View and manage regions and region configuration", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermRoutesView, Code = "routes.view", Description = "View and manage delivery routes", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermVehiclesView, Code = "vehicles.view", Description = "View and manage fleet vehicles", CreatedAt = SeedDate, IsActive = true },
// ── Granular API permissions ──────────────────────────────────────────
new Permission { Id = PermClaimView, Code = "claim.view", Description = "View agency claims and settlement status", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermClaimManage, Code = "claim.manage", Description = "Create and settle agency claims", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermDeliveryTaskView, Code = "delivery-task.view", Description = "View delivery tasks within a ride", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermDeliveryTaskManage, Code = "delivery-task.manage", Description = "Confirm and fail delivery tasks", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermDriverView, Code = "driver.view", Description = "View driver profiles and license details", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermDriverManage, Code = "driver.manage", Description = "Create and update driver profiles", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermGrnView, Code = "grn.view", Description = "View goods receipt notes", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermGrnManage, Code = "grn.manage", Description = "Create and confirm goods receipts", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermLoadingSheetView, Code = "loading-sheet.view", Description = "View loading sheets and their items", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermLoadingSheetManage, Code = "loading-sheet.manage", Description = "Create, edit, and confirm loading sheets", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermPriceListView, Code = "price-list.view", Description = "View regional price lists", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermPriceListManage, Code = "price-list.manage", Description = "Create and manage item price lists", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermPurchaseOrderView, Code = "purchase-order.view", Description = "View purchase orders and line items", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermPurchaseOrderManage,Code = "purchase-order.manage", Description = "Create, confirm, and close purchase orders", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermPurchaseReturnManage,Code= "purchase-return.manage",Description = "Create and manage purchase returns to suppliers", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermRegionView, Code = "region.view", Description = "View regions and their configuration", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermRegionManage, Code = "region.manage", Description = "Create and update regions, targets, and budgets", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermReturnView, Code = "return.view", Description = "View order returns", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermReturnManage, Code = "return.manage", Description = "Create and manage order returns", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermRouteView, Code = "route.view", Description = "View delivery routes", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermRouteManage, Code = "route.manage", Description = "Create and manage delivery routes", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSchemeView, Code = "scheme.view", Description = "View pricing schemes and promotions", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSchemeManage, Code = "scheme.manage", Description = "Create and configure pricing schemes", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermStockView, Code = "stock.view", Description = "View stock balances and movements", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermStockManage, Code = "stock.manage", Description = "Transfer stock and record damage or adjustments", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermStoreView, Code = "store.view", Description = "View store accounts and balances", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermStoreManage, Code = "store.manage", Description = "Create and update store accounts", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSupplierClaimView, Code = "supplier-claim.view", Description = "View supplier claims", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSupplierClaimManage,Code = "supplier-claim.manage", Description = "Create and resolve supplier claims", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSysConfigView, Code = "sys-config.view", Description = "View system configuration settings", CreatedAt = SeedDate, IsActive = true },
new Permission { Id = PermSysConfigManage, Code = "sys-config.manage", Description = "Update system configuration settings", CreatedAt = SeedDate, IsActive = true }
);
// SuperAdmin gets every permission
modelBuilder.Entity<RolePermission>().HasData(
// ── Legacy broad permissions ──────────────────────────────────────────
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermOrdersView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermRidesView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermLoadingView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermStoresView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSalesVisitsCheckin, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermItemsView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermCategoriesView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermWarehousesView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermPurchaseOrdersView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermPricelistsView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSchemesView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSuppliersView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermDriverProfilesView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermComplianceManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermUsersView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermRolesView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermRegionsView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermRoutesView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermVehiclesView, CreatedAt = SeedDate, IsActive = true },
// ── Granular API permissions ──────────────────────────────────────────
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermClaimView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermClaimManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermDeliveryTaskView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermDeliveryTaskManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermDriverView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermDriverManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermGrnView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermGrnManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermLoadingSheetView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermLoadingSheetManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermPriceListView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermPriceListManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermPurchaseOrderView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermPurchaseOrderManage,CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermPurchaseReturnManage,CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermRegionView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermRegionManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermReturnView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermReturnManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermRouteView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermRouteManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSchemeView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSchemeManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermStockView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermStockManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermStoreView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermStoreManage, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSupplierClaimView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSupplierClaimManage,CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSysConfigView, CreatedAt = SeedDate, IsActive = true },
new RolePermission { FK_RoleId = SuperAdminRoleId, FK_PermissionId = PermSysConfigManage, CreatedAt = SeedDate, IsActive = true }
);
}
}
+73 -10
View File
@@ -1,3 +1,5 @@
using System.IdentityModel.Tokens.Jwt;
using Distribution.Features.User;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -6,32 +8,93 @@ namespace Distribution.Features.Auth;
[ApiController]
[Route("api/auth")]
public class AuthController(AuthService service, ICurrentUserService currentUser) : ControllerBase
public class AuthController(AuthService service, ICurrentUserService currentUser, IUserRepository userRepo) : ControllerBase
{
private static IActionResult ToActionResult(AuthHexResponse result) =>
result.Success ? new OkObjectResult(result) : new ObjectResult(result) { StatusCode = result.StatusCode is >= 400 and < 600 ? result.StatusCode : 401 };
[HttpPost("login")]
public async Task<IActionResult> Login(LoginRequest request, CancellationToken ct) =>
ToActionResult(await service.LoginAsync(request, ct));
[AllowAnonymous]
public async Task<IActionResult> Login(LoginRequest request, CancellationToken ct)
{
var result = await service.LoginAsync(request, ct);
if (!result.Success || result.Data is not { } data)
return ToActionResult(result);
string? token = null;
TimeSpan maxAge = TimeSpan.FromHours(1);
if (data.TryGetProperty("accessToken", out var tokenEl))
token = tokenEl.GetString();
if (data.TryGetProperty("expiresIn", out var expEl))
maxAge = TimeSpan.FromSeconds(expEl.GetInt32());
if (!string.IsNullOrEmpty(token))
{
Response.Cookies.Append("access-token", token, new CookieOptions
{
HttpOnly = true,
SameSite = SameSiteMode.Lax,
Path = "/",
MaxAge = maxAge,
Secure = Request.IsHttps,
});
}
MeResponse? profile = null;
if (!string.IsNullOrEmpty(token))
{
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(token);
var userIdStr = jwt.Claims.FirstOrDefault(c => c.Type == "UserId")?.Value;
if (Guid.TryParse(userIdStr, out var userId))
{
var user = await userRepo.GetByIdAsync(userId);
if (user is not null)
profile = new MeResponse(
user.Id,
user.Username,
user.FK_RoleId,
user.Role?.Name ?? string.Empty,
user.Role?.Level ?? 0);
}
}
return Ok(new { result.StatusCode, result.Success, result.Message, result.Data, profile });
}
[HttpPost("register")]
[AllowAnonymous]
public async Task<IActionResult> Register(RegisterRequest request, CancellationToken ct) =>
ToActionResult(await service.RegisterAsync(request, ct));
[HttpGet("me")]
[Authorize]
public async Task<IActionResult> Me(CancellationToken ct)
public async Task<IActionResult> Me()
{
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
return ToActionResult(await service.GetUserDetailsAsync(userId, ct));
if (currentUser.UserId is null) return Unauthorized();
var user = await userRepo.GetByIdAsync(currentUser.UserId.Value);
if (user is null) return Unauthorized();
return Ok(new MeResponse(
user.Id,
user.Username,
user.FK_RoleId,
user.Role?.Name ?? string.Empty,
user.Role?.Level ?? 0));
}
[HttpPost("logout")]
[Authorize]
public async Task<IActionResult> Logout(CancellationToken ct)
[AllowAnonymous]
public IActionResult Logout()
{
var token = Request.Headers.Authorization.ToString().Replace("Bearer ", "", StringComparison.OrdinalIgnoreCase);
return ToActionResult(await service.LogoutAsync(token, ct));
Response.Cookies.Delete("access-token", new CookieOptions
{
HttpOnly = true,
SameSite = SameSiteMode.Lax,
Path = "/",
Secure = Request.IsHttps,
});
return Ok(new { success = true });
}
}
+13 -2
View File
@@ -1,5 +1,16 @@
namespace Distribution.Features.Auth;
public record LoginRequest(string Username, string Password);
public record LoginRequest(
string Identifier,
string Password,
Guid? UserTypeId = null,
string DeviceName = "Unknown Device");
public record RegisterRequest(string Username, string Password, string? FullName);
public record RegisterRequest(string Username, string email, string Password, string? FullName);
public record MeResponse(
Guid UserId,
string Username,
Guid RoleId,
string RoleCode,
int RoleLevel);
@@ -1,12 +1,11 @@
using System.Net.Http.Json;
namespace Distribution.Infra.Authorization;
namespace Distribution.Features.Auth;
/// <summary>
/// Proxies own-user auth calls (login/register/getUserDetails/logout) to the external AuthHex
/// identity service. AuthHex owns credentials and issues the RS256-signed JWT this app validates
/// (see JwtTokenService's replacement — token generation is no longer done locally); this app
/// never sees or stores a plaintext/hashed password for the AuthHex-authenticated flow.
/// identity service. AuthHex owns credentials and issues the RS256-signed JWT this app validates;
/// this app never sees or stores a plaintext/hashed password.
/// </summary>
public class AuthHexClient(HttpClient http) : IAuthHexClient
{
@@ -1,7 +1,7 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Distribution.Infra.Authorization;
namespace Distribution.Features.Auth;
/// <summary>Raw response shape returned by AuthHex's `/api/user` endpoint for every functionName.</summary>
public record AuthHexResponse(
+8 -4
View File
@@ -1,17 +1,21 @@
using Distribution.Infra.Authorization;
namespace Distribution.Features.Auth;
/// <summary>
/// Own-user auth is fully delegated to AuthHex — this service only proxies the four functions
/// AuthHex exposes (loginUser/registerUser/getUserDetails/LogoutUser). No local password check or
/// token issuance happens here; AuthHex owns credentials and signs the JWT this app validates
/// (see Program.cs's JwtBearer registration + OnTokenValidated role mapping).
/// token issuance happens here; AuthHex owns credentials and signs the JWT this app validates.
/// </summary>
public class AuthService(IAuthHexClient authHex)
{
public Task<AuthHexResponse> LoginAsync(LoginRequest request, CancellationToken ct = default) =>
authHex.CallAsync("loginUser", request, reference: Guid.NewGuid().ToString(), ct: ct);
authHex.CallAsync("loginUser", new
{
identifier = request.Identifier,
password = request.Password,
userTypeId = request.UserTypeId,
deviceName = request.DeviceName
}, reference: Guid.NewGuid().ToString(), ct: ct);
public Task<AuthHexResponse> RegisterAsync(RegisterRequest request, CancellationToken ct = default) =>
authHex.CallAsync("registerUser", request, reference: Guid.NewGuid().ToString(), ct: ct);
@@ -1,20 +0,0 @@
namespace Distribution.Features.Auth;
/// <summary>
/// Typed HttpClient that proxies requests to the external Auth Service.
/// Registered via AddHttpClient&lt;AuthServiceClient&gt; in Program.cs.
/// BaseAddress is configured from AuthService:BaseUrl in appsettings.json.
///
/// TODO: Implement methods once Auth Service contract is agreed.
/// </summary>
public class AuthServiceClient(HttpClient http) : IAuthServiceClient
{
// TODO: implement proxy methods, e.g.:
//
// public async Task<AuthServiceResponse?> LoginAsync(LoginRequest request, CancellationToken ct)
// {
// var response = await http.PostAsJsonAsync("/TODO_AUTH_SERVICE_LOGIN_PATH", request, ct);
// if (!response.IsSuccessStatusCode) return null;
// return await response.Content.ReadFromJsonAsync<AuthServiceResponse>(ct);
// }
}
@@ -1,11 +0,0 @@
namespace Distribution.Features.Auth;
public class AuthServiceOptions
{
public const string SectionName = "AuthService";
/// <summary>Base URL of the external Auth Service, e.g. "https://auth.internal".</summary>
public string BaseUrl { get; set; } = string.Empty;
// TODO: add other config (API keys, timeout, etc.) once Auth Service is defined.
}
@@ -1,4 +1,4 @@
namespace Distribution.Infra.Authorization;
namespace Distribution.Features.Auth;
public interface IAuthHexClient
{
@@ -1,16 +0,0 @@
namespace Distribution.Features.Auth;
/// <summary>
/// Connector to the external Auth Service. This backend proxies all auth
/// traffic from the Next.js frontend through to the Auth Service — the
/// frontend never calls the Auth Service directly.
///
/// TODO: Fill in the method signatures once the Auth Service contract is agreed.
/// </summary>
public interface IAuthServiceClient
{
// TODO: define methods based on Auth Service contract, e.g.:
// Task<AuthServiceResponse?> LoginAsync(LoginRequest request, CancellationToken ct);
// Task<AuthServiceResponse?> RefreshAsync(string refreshToken, CancellationToken ct);
// Task LogoutAsync(string token, CancellationToken ct);
}
@@ -1,4 +1,5 @@
using Distribution.Infra.Authorization;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Claims;
@@ -7,10 +8,12 @@ namespace Distribution.Features.Claims;
public class ClaimController(ClaimService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpGet("api/claims")]
[Authorize("claim.view")]
public async Task<IActionResult> GetAll() =>
Ok(await service.GetAllAsync());
[HttpGet("api/claims/{id:guid}")]
[Authorize("claim.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -18,6 +21,7 @@ public class ClaimController(ClaimService service, ICurrentUserService currentUs
}
[HttpPost("api/claims")]
[Authorize("claim.manage")]
public async Task<IActionResult> Create(CreateClaimRequest request, CancellationToken ct)
{
try
@@ -29,6 +33,7 @@ public class ClaimController(ClaimService service, ICurrentUserService currentUs
}
[HttpPut("api/claims/{id:guid}")]
[Authorize("claim.manage")]
public async Task<IActionResult> Update(Guid id, UpdateClaimRequest request, CancellationToken ct)
{
try
@@ -40,6 +45,7 @@ public class ClaimController(ClaimService service, ICurrentUserService currentUs
}
[HttpPost("api/claims/{id:guid}/settle")]
[Authorize("claim.manage")]
public async Task<IActionResult> Settle(Guid id, SettleClaimRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? request.SettledByUserId;
@@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.DashboardReport;
[ApiController]
[Route("api/reports/dashboard")]
public class DashboardReportController(DashboardReportService service) : ControllerBase
{
[HttpGet("sales")]
public async Task<IActionResult> Sales(
[FromQuery] DateTime? from, [FromQuery] DateTime? to,
[FromQuery] Guid? regionId, [FromQuery] Guid? categoryId)
{
var f = DashboardReportService.BuildFilter(from, to, regionId, categoryId, null);
var error = DashboardReportService.Validate(f);
return error is null ? Ok(await service.GetSalesSummaryAsync(f)) : BadRequest(new { message = error });
}
[HttpGet("inventory")]
public async Task<IActionResult> Inventory(
[FromQuery] DateTime? from, [FromQuery] DateTime? to,
[FromQuery] Guid? warehouseId, [FromQuery] Guid? categoryId)
{
var f = DashboardReportService.BuildFilter(from, to, null, categoryId, warehouseId);
var error = DashboardReportService.Validate(f);
return error is null ? Ok(await service.GetInventorySummaryAsync(f)) : BadRequest(new { message = error });
}
}
@@ -0,0 +1,32 @@
namespace Distribution.Features.DashboardReport;
public record DashboardFilter(DateTime From, DateTime To, Guid? RegionId, Guid? CategoryId, Guid? WarehouseId);
public record SalesTotals(decimal GrossSales, decimal ReturnValue, int Orders, decimal CostedSales, decimal CostOfSales);
public record SalesKpis(
decimal GrossSales, decimal ReturnValue, decimal NetSales, int Orders, decimal AverageOrderValue,
decimal GrossProfit, decimal? GrossProfitMarginPercent);
public record SalesKpiComparison(SalesKpis Current, SalesKpis Previous, DateTime PreviousFrom, DateTime PreviousTo);
public record TrendPoint(string Period, decimal Sales, decimal Returns);
public record NamedAmount(Guid? Id, string Name, decimal Amount);
public record SalesSummaryResponse(
DateTime From, DateTime To, string Granularity,
SalesKpiComparison Kpis, List<TrendPoint> Trend,
List<NamedAmount> ByCategory, List<NamedAmount> ByRegion, List<NamedAmount> ByRep);
public record PeriodAmount(DateTime Date, decimal Amount);
public record MovementPoint(string Period, decimal Received, decimal Issued, decimal Net);
public record WarehouseStockRow(Guid WarehouseId, string Name, decimal Quantity, decimal Value);
public record CategoryValueRow(string Category, decimal Quantity, decimal Value);
public record InventorySummaryResponse(
DateTime From, DateTime To, string Granularity,
List<CategoryValueRow> ValueByCategory, List<WarehouseStockRow> ByWarehouse, List<MovementPoint> MovementTrend);
@@ -0,0 +1,171 @@
using Distribution.Data;
using Distribution.Models;
using Microsoft.EntityFrameworkCore;
namespace Distribution.Features.DashboardReport;
public class DashboardReportRepository(AppDBContext db) : IDashboardReportRepository
{
private sealed class SoldLine
{
public DateTime Date { get; set; }
public Guid PoId { get; set; }
public decimal Value { get; set; }
public decimal? Cost { get; set; }
public Guid CategoryId { get; set; }
public string CategoryName { get; set; } = "";
public Guid RegionId { get; set; }
public string RegionName { get; set; } = "";
public Guid RepId { get; set; }
}
// Same definition of "sold" as ProductReportRepository: fulfilled lines on non-cancelled POs
// whose invoice is Finalized, dated by Invoice.FinalizedAt. 'To' is inclusive (whole day).
private IQueryable<SoldLine> SoldLines(DashboardFilter f)
{
var start = f.From.Date;
var end = f.To.Date.AddDays(1);
var q =
from li in db.ShopPOItems.AsNoTracking()
join inv in db.Invoices.AsNoTracking() on li.FK_ShopPOId equals inv.FK_ShopPOId
where inv.Status == InvoiceStatus.Finalized
&& li.ShopPO.Status != ShopPOStatus.Cancelled
&& inv.FinalizedAt >= start && inv.FinalizedAt < end
select new SoldLine
{
Date = inv.FinalizedAt!.Value.Date,
PoId = li.FK_ShopPOId,
Value = li.QuantityFulfilled * li.UnitPrice,
Cost = li.Item.CostPrice == null ? null : li.QuantityFulfilled * li.Item.CostPrice,
CategoryId = li.Item.FK_CategoryId,
CategoryName = li.Item.Category.Name,
RegionId = li.ShopPO.Store.Route.FK_RegionId,
RegionName = li.ShopPO.Store.Route.Region.Name,
RepId = li.ShopPO.RaisedById,
};
if (f.RegionId.HasValue) q = q.Where(l => l.RegionId == f.RegionId.Value);
if (f.CategoryId.HasValue) q = q.Where(l => l.CategoryId == f.CategoryId.Value);
return q;
}
private IQueryable<SaleReturnItem> ReturnLines(DashboardFilter f)
{
var start = f.From.Date;
var end = f.To.Date.AddDays(1);
var q = db.SaleReturnItems.AsNoTracking()
.Where(r => r.SaleReturn.CreatedAt >= start && r.SaleReturn.CreatedAt < end);
if (f.RegionId.HasValue) q = q.Where(r => r.SaleReturn.ShopPO.Store.Route.FK_RegionId == f.RegionId.Value);
if (f.CategoryId.HasValue) q = q.Where(r => r.Item.FK_CategoryId == f.CategoryId.Value);
return q;
}
public async Task<SalesTotals> GetSalesTotalsAsync(DashboardFilter f)
{
var lines = SoldLines(f);
var gross = await lines.SumAsync(l => (decimal?)l.Value) ?? 0m;
var orders = await lines.Select(l => l.PoId).Distinct().CountAsync();
var costed = lines.Where(l => l.Cost != null);
var costedSales = await costed.SumAsync(l => (decimal?)l.Value) ?? 0m;
var cost = await costed.SumAsync(l => l.Cost) ?? 0m;
var returns = await ReturnLines(f).SumAsync(r => (decimal?)(r.Quantity * r.UnitPrice)) ?? 0m;
return new SalesTotals(gross, returns, orders, costedSales, cost);
}
public async Task<List<PeriodAmount>> GetDailySalesAsync(DashboardFilter f) =>
(await SoldLines(f).GroupBy(l => l.Date)
.Select(g => new { Date = g.Key, Amount = g.Sum(x => x.Value) })
.ToListAsync())
.Select(x => new PeriodAmount(x.Date, x.Amount)).ToList();
public async Task<List<PeriodAmount>> GetDailyReturnsAsync(DashboardFilter f) =>
(await ReturnLines(f).GroupBy(r => r.SaleReturn.CreatedAt.Date)
.Select(g => new { Date = g.Key, Amount = g.Sum(x => x.Quantity * x.UnitPrice) })
.ToListAsync())
.Select(x => new PeriodAmount(x.Date, x.Amount)).ToList();
public async Task<List<GroupAggregate>> GetSalesByCategoryAsync(DashboardFilter f) =>
(await SoldLines(f).GroupBy(l => new { l.CategoryId, l.CategoryName })
.Select(g => new { g.Key.CategoryId, g.Key.CategoryName, Amount = g.Sum(x => x.Value) })
.OrderByDescending(x => x.Amount).ToListAsync())
.Select(x => new GroupAggregate(x.CategoryId, x.CategoryName, x.Amount)).ToList();
public async Task<List<GroupAggregate>> GetSalesByRegionAsync(DashboardFilter f) =>
(await SoldLines(f).GroupBy(l => new { l.RegionId, l.RegionName })
.Select(g => new { g.Key.RegionId, g.Key.RegionName, Amount = g.Sum(x => x.Value) })
.OrderByDescending(x => x.Amount).ToListAsync())
.Select(x => new GroupAggregate(x.RegionId, x.RegionName, x.Amount)).ToList();
public async Task<List<GroupAggregate>> GetSalesByRepAsync(DashboardFilter f)
{
var rows = await SoldLines(f).GroupBy(l => l.RepId)
.Select(g => new { RepId = g.Key, Amount = g.Sum(x => x.Value) })
.OrderByDescending(x => x.Amount).Take(20).ToListAsync();
var ids = rows.Select(r => r.RepId).ToList();
var names = await db.Users.AsNoTracking().Where(u => ids.Contains(u.Id))
.ToDictionaryAsync(u => u.Id, u => u.FullName);
return rows.Select(r => new GroupAggregate(r.RepId, names.GetValueOrDefault(r.RepId, "Unknown"), r.Amount)).ToList();
}
private IQueryable<StockBalance> Balances(DashboardFilter f)
{
var q = db.StockBalances.AsNoTracking().AsQueryable();
if (f.WarehouseId.HasValue)
q = q.Where(b => b.LocationType == LocationType.Warehouse && b.LocationId == f.WarehouseId.Value);
if (f.CategoryId.HasValue) q = q.Where(b => b.Item.FK_CategoryId == f.CategoryId.Value);
return q;
}
// Value = quantity x cost price; items without a cost price contribute quantity only.
public async Task<List<CategoryValueRow>> GetStockValueByCategoryAsync(DashboardFilter f) =>
(await Balances(f).GroupBy(b => b.Item.Category.Name)
.Select(g => new
{
Category = g.Key,
Quantity = g.Sum(x => x.Quantity),
Value = g.Sum(x => x.Quantity * (x.Item.CostPrice ?? 0m)),
})
.OrderByDescending(x => x.Value).ToListAsync())
.Select(x => new CategoryValueRow(x.Category, x.Quantity, x.Value)).ToList();
public async Task<List<WarehouseStockRow>> GetStockByWarehouseAsync(DashboardFilter f)
{
var rows = await Balances(f).Where(b => b.LocationType == LocationType.Warehouse)
.GroupBy(b => b.LocationId)
.Select(g => new
{
Id = g.Key,
Quantity = g.Sum(x => x.Quantity),
Value = g.Sum(x => x.Quantity * (x.Item.CostPrice ?? 0m)),
})
.ToListAsync();
var ids = rows.Select(r => r.Id).ToList();
var names = await db.Warehouses.AsNoTracking().Where(w => ids.Contains(w.Id))
.ToDictionaryAsync(w => w.Id, w => w.Name);
return rows.Select(r => new WarehouseStockRow(r.Id, names.GetValueOrDefault(r.Id, "Unknown"), r.Quantity, r.Value))
.OrderByDescending(r => r.Value).ToList();
}
// Received = purchase receipts + customer returns; Issued = sales + purchase returns + damages.
// Transfers, loads and adjustments are internal/signed and excluded from this trend.
public async Task<List<(DateTime Date, decimal Received, decimal Issued)>> GetDailyMovementsAsync(DashboardFilter f)
{
var start = f.From.Date;
var end = f.To.Date.AddDays(1);
var q = db.StockMovements.AsNoTracking()
.Where(m => m.CreatedAt >= start && m.CreatedAt < end
&& (m.Type == MovementType.PurchaseReceipt || m.Type == MovementType.CustomerReturn
|| m.Type == MovementType.Sale || m.Type == MovementType.PurchaseReturn || m.Type == MovementType.Damage));
if (f.CategoryId.HasValue) q = q.Where(m => m.Item.FK_CategoryId == f.CategoryId.Value);
if (f.WarehouseId.HasValue)
q = q.Where(m => m.ToLocationId == f.WarehouseId.Value || m.FromLocationId == f.WarehouseId.Value);
var rows = await q.GroupBy(m => new { m.CreatedAt.Date, m.Type })
.Select(g => new { g.Key.Date, g.Key.Type, Qty = g.Sum(x => x.Quantity) })
.ToListAsync();
return rows.GroupBy(r => r.Date)
.Select(g => (g.Key,
g.Where(r => r.Type is MovementType.PurchaseReceipt or MovementType.CustomerReturn).Sum(r => r.Qty),
g.Where(r => r.Type is MovementType.Sale or MovementType.PurchaseReturn or MovementType.Damage).Sum(r => r.Qty)))
.ToList();
}
}
@@ -0,0 +1,83 @@
namespace Distribution.Features.DashboardReport;
public class DashboardReportService(IDashboardReportRepository repo)
{
public const int MaxRangeDays = 366;
private const int DailyGranularityMaxDays = 62;
public static DashboardFilter BuildFilter(DateTime? from, DateTime? to, Guid? regionId, Guid? categoryId, Guid? warehouseId)
{
var end = (to ?? DateTime.Now).Date;
var start = (from ?? end.AddDays(-29)).Date;
return new DashboardFilter(start, end, regionId, categoryId, warehouseId);
}
public static string? Validate(DashboardFilter f)
{
if (f.To < f.From) return "'to' must not be before 'from'.";
if ((f.To - f.From).TotalDays > MaxRangeDays) return $"Date range cannot exceed {MaxRangeDays} days.";
return null;
}
private static bool Daily(DashboardFilter f) => (f.To - f.From).TotalDays <= DailyGranularityMaxDays;
private static string Bucket(DateTime d, bool daily) => daily ? d.ToString("yyyy-MM-dd") : d.ToString("yyyy-MM");
private static SalesKpis ToKpis(SalesTotals t)
{
var net = t.GrossSales - t.ReturnValue;
var gp = t.CostedSales - t.CostOfSales;
return new SalesKpis(
t.GrossSales, t.ReturnValue, net, t.Orders,
t.Orders > 0 ? Math.Round(t.GrossSales / t.Orders, 2) : 0m,
gp, t.CostedSales > 0 ? Math.Round(gp / t.CostedSales * 100, 2) : null);
}
public async Task<SalesSummaryResponse> GetSalesSummaryAsync(DashboardFilter f)
{
var days = (f.To - f.From).Days + 1;
var prev = f with { From = f.From.AddDays(-days), To = f.From.AddDays(-1) };
var daily = Daily(f);
var current = await repo.GetSalesTotalsAsync(f);
var previous = await repo.GetSalesTotalsAsync(prev);
var sales = await repo.GetDailySalesAsync(f);
var returns = await repo.GetDailyReturnsAsync(f);
var trend = sales.Select(s => (s.Date, Sales: s.Amount, Returns: 0m))
.Concat(returns.Select(r => (r.Date, Sales: 0m, Returns: r.Amount)))
.GroupBy(x => Bucket(x.Date, daily))
.OrderBy(g => g.Key)
.Select(g => new TrendPoint(g.Key, g.Sum(x => x.Sales), g.Sum(x => x.Returns)))
.ToList();
static NamedAmount Map(GroupAggregate g) => new(g.Key, g.Name, g.Amount);
return new SalesSummaryResponse(
f.From, f.To, daily ? "day" : "month",
new SalesKpiComparison(ToKpis(current), ToKpis(previous), prev.From, prev.To),
trend,
(await repo.GetSalesByCategoryAsync(f)).Select(Map).ToList(),
(await repo.GetSalesByRegionAsync(f)).Select(Map).ToList(),
(await repo.GetSalesByRepAsync(f)).Select(Map).ToList());
}
public async Task<InventorySummaryResponse> GetInventorySummaryAsync(DashboardFilter f)
{
var daily = Daily(f);
var movements = (await repo.GetDailyMovementsAsync(f))
.GroupBy(m => Bucket(m.Date, daily))
.OrderBy(g => g.Key)
.Select(g =>
{
var rec = g.Sum(x => x.Received);
var iss = g.Sum(x => x.Issued);
return new MovementPoint(g.Key, rec, iss, rec - iss);
}).ToList();
return new InventorySummaryResponse(
f.From, f.To, daily ? "day" : "month",
await repo.GetStockValueByCategoryAsync(f),
await repo.GetStockByWarehouseAsync(f),
movements);
}
}
@@ -0,0 +1,16 @@
namespace Distribution.Features.DashboardReport;
public record GroupAggregate(Guid? Key, string Name, decimal Amount);
public interface IDashboardReportRepository
{
Task<SalesTotals> GetSalesTotalsAsync(DashboardFilter f);
Task<List<PeriodAmount>> GetDailySalesAsync(DashboardFilter f);
Task<List<PeriodAmount>> GetDailyReturnsAsync(DashboardFilter f);
Task<List<GroupAggregate>> GetSalesByCategoryAsync(DashboardFilter f);
Task<List<GroupAggregate>> GetSalesByRegionAsync(DashboardFilter f);
Task<List<GroupAggregate>> GetSalesByRepAsync(DashboardFilter f);
Task<List<CategoryValueRow>> GetStockValueByCategoryAsync(DashboardFilter f);
Task<List<WarehouseStockRow>> GetStockByWarehouseAsync(DashboardFilter f);
Task<List<(DateTime Date, decimal Received, decimal Issued)>> GetDailyMovementsAsync(DashboardFilter f);
}
@@ -1,5 +1,6 @@
using Distribution.Models;
using Distribution.Infra.Authorization;
using Distribution.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.DeliveryRide;
@@ -9,6 +10,7 @@ namespace Distribution.Features.DeliveryRide;
public class DeliveryTaskController(DeliveryTaskService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpPost("rides/{rideId:guid}/tasks/generate")]
[Authorize("delivery-task.manage")]
public async Task<IActionResult> Generate(Guid rideId, CancellationToken ct)
{
try
@@ -22,6 +24,7 @@ public class DeliveryTaskController(DeliveryTaskService service, ICurrentUserSer
[HttpGet("rides/{rideId:guid}/tasks")]
[HttpGet("rides/{rideId:guid}/delivery-tasks")]
[Authorize("delivery-task.view")]
public async Task<IActionResult> GetByRide(Guid rideId)
{
var result = await service.GetByRideIdAsync(rideId);
@@ -29,6 +32,7 @@ public class DeliveryTaskController(DeliveryTaskService service, ICurrentUserSer
}
[HttpGet("delivery-tasks")]
//[Authorize("delivery-task.view")]
public async Task<IActionResult> GetAll(
[FromQuery] DeliveryTaskStatus? status,
[FromQuery] int page = 1,
@@ -39,6 +43,7 @@ public class DeliveryTaskController(DeliveryTaskService service, ICurrentUserSer
}
[HttpGet("delivery-tasks/{id:guid}")]
[Authorize("delivery-task.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -46,6 +51,7 @@ public class DeliveryTaskController(DeliveryTaskService service, ICurrentUserSer
}
[HttpPut("delivery-tasks/{id:guid}/quantities")]
[Authorize("delivery-task.manage")]
public async Task<IActionResult> SetQuantities(Guid id, SetQuantitiesRequest request, CancellationToken ct)
{
try
@@ -58,6 +64,7 @@ public class DeliveryTaskController(DeliveryTaskService service, ICurrentUserSer
}
[HttpPost("delivery-tasks/{id:guid}/confirm")]
[Authorize("delivery-task.manage")]
public async Task<IActionResult> Confirm(Guid id, CancellationToken ct)
{
try
@@ -70,6 +77,7 @@ public class DeliveryTaskController(DeliveryTaskService service, ICurrentUserSer
}
[HttpPost("delivery-tasks/{id:guid}/fail")]
[Authorize("delivery-task.manage")]
public async Task<IActionResult> Fail(Guid id, FailTaskRequest request, CancellationToken ct)
{
try
@@ -1,5 +1,6 @@
using Distribution.Features.DriverComplianceConfig;
using Distribution.Features.DriverComplianceConfig;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.DriverProfile;
@@ -12,6 +13,7 @@ public class DriverProfileController(
ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
[Authorize("driver.view")]
public async Task<IActionResult> GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 20)
{
var result = await service.GetAllAsync(page, pageSize);
@@ -19,6 +21,7 @@ public class DriverProfileController(
}
[HttpGet("{id:guid}")]
[Authorize("driver.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -26,6 +29,7 @@ public class DriverProfileController(
}
[HttpPost]
[Authorize("driver.manage")]
public async Task<IActionResult> Create(CreateDriverProfileRequest request, CancellationToken ct)
{
try
@@ -44,6 +48,7 @@ public class DriverProfileController(
}
[HttpPut("{id:guid}")]
[Authorize("driver.manage")]
public async Task<IActionResult> Update(Guid id, UpdateDriverProfileRequest request, CancellationToken ct)
{
var result = await service.UpdateAsync(id, request, ct);
@@ -51,6 +56,7 @@ public class DriverProfileController(
}
[HttpDelete("{id:guid}")]
[Authorize("driver.manage")]
public async Task<IActionResult> Deactivate(Guid id, CancellationToken ct)
{
var success = await service.DeactivateAsync(id, ct);
@@ -58,6 +64,7 @@ public class DriverProfileController(
}
[HttpGet("compliance")]
[Authorize("driver.view")]
public async Task<IActionResult> GetCompliance()
{
var result = await complianceService.GetAsync();
@@ -65,6 +72,7 @@ public class DriverProfileController(
}
[HttpPut("compliance")]
[Authorize("driver.manage")]
public async Task<IActionResult> UpsertCompliance(UpdateDriverComplianceConfigRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
+8 -1
View File
@@ -1,4 +1,5 @@
using Distribution.Infra.Authorization;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Grn;
@@ -7,6 +8,7 @@ namespace Distribution.Features.Grn;
public class GrnController(GrnService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpGet("api/goods-receipts")]
[Authorize("grn.view")]
public async Task<IActionResult> GetAll(
[FromQuery] Guid? purchaseOrderId,
[FromQuery] int page = 1,
@@ -17,6 +19,7 @@ public class GrnController(GrnService service, ICurrentUserService currentUser)
}
[HttpGet("api/goods-receipts/{id:guid}")]
[Authorize("grn.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -24,6 +27,7 @@ public class GrnController(GrnService service, ICurrentUserService currentUser)
}
[HttpPost("api/goods-receipts")]
[Authorize("grn.manage")]
public async Task<IActionResult> CreateFlat(CreateFlatGrnRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
@@ -42,6 +46,7 @@ public class GrnController(GrnService service, ICurrentUserService currentUser)
/// <summary>Goods received without a purchase order.</summary>
[HttpPost("api/goods-receipts/direct")]
[Authorize("grn.manage")]
public async Task<IActionResult> CreateDirect(CreateDirectGrnRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? request.ReceivedByUserId;
@@ -55,10 +60,12 @@ public class GrnController(GrnService service, ICurrentUserService currentUser)
}
[HttpGet("api/purchase-orders/{id:guid}/goods-receipts")]
[Authorize("grn.view")]
public async Task<IActionResult> GetByPurchaseOrder(Guid id) =>
Ok(await service.GetByPurchaseOrderIdAsync(id));
[HttpPost("api/purchase-orders/{id:guid}/goods-receipts")]
[Authorize("grn.manage")]
public async Task<IActionResult> Create(Guid id, CreateGrnRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? request.ReceivedByUserId;
@@ -1,14 +1,19 @@
using Distribution.Models;
using Distribution.Infra.Authorization;
using Distribution.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.LoadingEvent;
[ApiController]
[Route("api/loading-sheets")]
public class LoadingSheetController(LoadingSheetService service, ICurrentUserService currentUser) : ControllerBase
public class LoadingSheetController(
LoadingSheetService service,
IScopeAccessService scopeAccess,
ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
//[Authorize("loading-sheet.view")]
public async Task<IActionResult> GetAll(
[FromQuery] Guid? rideId,
[FromQuery] LoadingSheetStatus? status,
@@ -17,11 +22,26 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
[FromQuery] int page = 1,
[FromQuery] int pageSize = 20)
{
if (routeId.HasValue)
{
var userId = currentUser.UserId;
if (userId.HasValue && !await scopeAccess.HasRouteScopeAsync(userId.Value, routeId.Value))
return StatusCode(403);
}
if (regionId.HasValue)
{
var userId = currentUser.UserId;
if (userId.HasValue && !await scopeAccess.HasRegionScopeAsync(userId.Value, regionId.Value))
return StatusCode(403);
}
var result = await service.GetAllAsync(rideId, status, routeId, regionId, page, pageSize);
return Ok(result);
}
[HttpGet("{id:guid}")]
[Authorize("loading-sheet.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -29,6 +49,7 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
}
[HttpPost]
[Authorize("loading-sheet.manage")]
public async Task<IActionResult> Create(CreateLoadingSheetRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
@@ -45,6 +66,7 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
}
[HttpPut("{id:guid}/items")]
[Authorize("loading-sheet.manage")]
public async Task<IActionResult> SetItems(Guid id, SetItemsRequest request, CancellationToken ct)
{
try
@@ -57,6 +79,7 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
}
[HttpPost("{id:guid}/confirm")]
[Authorize("loading-sheet.manage")]
public async Task<IActionResult> Confirm(Guid id, ConfirmLoadingSheetRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
@@ -1,16 +1,31 @@
using Microsoft.AspNetCore.Mvc;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.PriceList;
[ApiController]
[Route("api/price-lists")]
public class PriceListController(PriceListService service) : ControllerBase
public class PriceListController(
PriceListService service,
IScopeAccessService scopeAccess,
ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetAll([FromQuery] Guid? regionId) =>
Ok(await service.GetAllAsync(regionId));
[Authorize("price-list.view")]
public async Task<IActionResult> GetAll([FromQuery] Guid? regionId)
{
if (regionId.HasValue)
{
var userId = currentUser.UserId;
if (userId.HasValue && !await scopeAccess.HasRegionScopeAsync(userId.Value, regionId.Value))
return StatusCode(403);
}
return Ok(await service.GetAllAsync(regionId));
}
[HttpGet("resolve")]
[Authorize("price-list.view")]
public async Task<IActionResult> Resolve([FromQuery] Guid itemId, [FromQuery] Guid storeId, [FromQuery] DateTime saleDate)
{
var result = await service.ResolveByStoreAsync(itemId, storeId, saleDate);
@@ -18,6 +33,7 @@ public class PriceListController(PriceListService service) : ControllerBase
}
[HttpGet("{id:guid}")]
[Authorize("price-list.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -25,6 +41,7 @@ public class PriceListController(PriceListService service) : ControllerBase
}
[HttpPost]
[Authorize("price-list.manage")]
public async Task<IActionResult> Create(CreatePriceListRequest request, CancellationToken ct)
{
var result = await service.CreateAsync(request, ct);
@@ -32,6 +49,7 @@ public class PriceListController(PriceListService service) : ControllerBase
}
[HttpPut("{id:guid}")]
[Authorize("price-list.manage")]
public async Task<IActionResult> Update(Guid id, UpdatePriceListRequest request, CancellationToken ct)
{
try
@@ -46,6 +64,7 @@ public class PriceListController(PriceListService service) : ControllerBase
}
[HttpDelete("{id:guid}")]
[Authorize("price-list.manage")]
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
{
var deleted = await service.DeleteAsync(id, ct);
@@ -53,6 +72,7 @@ public class PriceListController(PriceListService service) : ControllerBase
}
[HttpPut("{id:guid}/items/{sku}")]
[Authorize("price-list.manage")]
public async Task<IActionResult> UpsertItem(Guid id, string sku, UpsertPriceListItemRequest request, CancellationToken ct)
{
try
@@ -67,6 +87,7 @@ public class PriceListController(PriceListService service) : ControllerBase
}
[HttpDelete("{id:guid}/items/{sku}")]
[Authorize("price-list.manage")]
public async Task<IActionResult> RemoveItem(Guid id, string sku, CancellationToken ct)
{
try
@@ -1,5 +1,6 @@
using Distribution.Infra.Authorization;
using Distribution.Infra.Authorization;
using Distribution.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Po;
@@ -9,10 +10,12 @@ namespace Distribution.Features.Po;
public class PoController(PoService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
[Authorize("purchase-order.view")]
public async Task<IActionResult> GetAll([FromQuery] Guid? supplierId, [FromQuery] PurchaseOrderStatus? status) =>
Ok(await service.GetAllAsync(supplierId, status));
[HttpGet("{id:guid}")]
[Authorize("purchase-order.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -20,6 +23,7 @@ public class PoController(PoService service, ICurrentUserService currentUser) :
}
[HttpPost]
[Authorize("purchase-order.manage")]
public async Task<IActionResult> Create(CreatePoRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
@@ -35,6 +39,7 @@ public class PoController(PoService service, ICurrentUserService currentUser) :
}
[HttpPut("{id:guid}")]
[Authorize("purchase-order.manage")]
public async Task<IActionResult> Update(Guid id, UpdatePoRequest request, CancellationToken ct)
{
try
@@ -46,6 +51,7 @@ public class PoController(PoService service, ICurrentUserService currentUser) :
}
[HttpPost("{id:guid}/close")]
[Authorize("purchase-order.manage")]
public async Task<IActionResult> Close(Guid id, CancellationToken ct)
{
try
@@ -57,6 +63,7 @@ public class PoController(PoService service, ICurrentUserService currentUser) :
}
[HttpPost("{id:guid}/cancel")]
[Authorize("purchase-order.manage")]
public async Task<IActionResult> Cancel(Guid id, CancelPoRequest request, CancellationToken ct)
{
try
@@ -68,6 +75,7 @@ public class PoController(PoService service, ICurrentUserService currentUser) :
}
[HttpPost("{id:guid}/items/{itemId:guid}/cancel")]
[Authorize("purchase-order.manage")]
public async Task<IActionResult> CancelLine(Guid id, Guid itemId, CancelPoLineRequest request, CancellationToken ct)
{
try
@@ -79,6 +87,7 @@ public class PoController(PoService service, ICurrentUserService currentUser) :
}
[HttpPost("{id:guid}/match-invoice")]
[Authorize("purchase-order.view")]
public async Task<IActionResult> MatchInvoice(Guid id, [FromQuery] Guid? invoiceId, [FromQuery] Guid? grnId)
{
var result = await service.MatchInvoiceToPoAsync(id, invoiceId, grnId);
@@ -86,6 +95,7 @@ public class PoController(PoService service, ICurrentUserService currentUser) :
}
[HttpPost("{id:guid}/resolve-variance")]
[Authorize("purchase-order.manage")]
public async Task<IActionResult> ResolveVariance(Guid id, ResolveInvoiceVarianceRequest request, CancellationToken ct)
{
try
@@ -1,4 +1,5 @@
using Distribution.Infra.Authorization;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.PurchaseReturn;
@@ -7,6 +8,7 @@ namespace Distribution.Features.PurchaseReturn;
public class PurchaseReturnController(PurchaseReturnService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpGet("api/purchase-returns/{id:guid}")]
[Authorize("purchase-order.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -14,10 +16,12 @@ public class PurchaseReturnController(PurchaseReturnService service, ICurrentUse
}
[HttpGet("api/purchase-orders/{id:guid}/returns")]
[Authorize("purchase-order.view")]
public async Task<IActionResult> GetByPurchaseOrder(Guid id) =>
Ok(await service.GetByPurchaseOrderIdAsync(id));
[HttpPost("api/purchase-orders/{id:guid}/returns")]
[Authorize("purchase-return.manage")]
public async Task<IActionResult> Create(Guid id, CreatePurchaseReturnRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
@@ -1,28 +1,39 @@
using Microsoft.AspNetCore.Mvc;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Region;
[ApiController]
[Route("api/regions")]
public class RegionController(RegionService service) : ControllerBase
public class RegionController(
RegionService service,
IScopeAccessService scopeAccess,
ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
[Authorize("region.view")]
public async Task<IActionResult> GetAll() =>
Ok(await service.GetAllAsync());
// Suggested code for the Add Region form; the user may override it.
[HttpGet("next-code")]
[Authorize("region.view")]
public async Task<IActionResult> GetNextCode() =>
Ok(await service.GetNextCodeAsync());
[HttpGet("{id:guid}")]
[Authorize("region.view")]
public async Task<IActionResult> GetById(Guid id)
{
var userId = currentUser.UserId;
if (userId.HasValue && !await scopeAccess.HasRegionScopeAsync(userId.Value, id))
return StatusCode(403);
var result = await service.GetByIdAsync(id);
return result is null ? NotFound() : Ok(result);
}
[HttpPost]
[Authorize("region.manage")]
public async Task<IActionResult> Create(CreateRegionRequest request, CancellationToken ct)
{
var result = await service.CreateAsync(request, ct);
@@ -30,6 +41,7 @@ public class RegionController(RegionService service) : ControllerBase
}
[HttpPut("{id:guid}")]
[Authorize("region.manage")]
public async Task<IActionResult> Update(Guid id, UpdateRegionRequest request, CancellationToken ct)
{
var result = await service.UpdateAsync(id, request, ct);
@@ -37,6 +49,7 @@ public class RegionController(RegionService service) : ControllerBase
}
[HttpDelete("{id:guid}")]
[Authorize("region.manage")]
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
{
var deleted = await service.DeleteAsync(id, ct);
@@ -44,6 +57,7 @@ public class RegionController(RegionService service) : ControllerBase
}
[HttpGet("{id:guid}/manager")]
[Authorize("region.view")]
public async Task<IActionResult> GetManager(Guid id)
{
var result = await service.GetManagerAsync(id);
@@ -51,6 +65,7 @@ public class RegionController(RegionService service) : ControllerBase
}
[HttpPut("{id:guid}/manager")]
[Authorize("region.manage")]
public async Task<IActionResult> SetManager(Guid id, SetRegionManagerRequest request, CancellationToken ct)
{
try
@@ -65,14 +80,15 @@ public class RegionController(RegionService service) : ControllerBase
}
[HttpDelete("{id:guid}/manager")]
[Authorize("region.manage")]
public async Task<IActionResult> RemoveManager(Guid id, CancellationToken ct)
{
var removed = await service.RemoveManagerAsync(id, ct);
return removed ? NoContent() : NotFound();
}
//targets/budgets/agencies/tax-rule.
[HttpPut("{id:guid}/manage")]
[Authorize("region.manage")]
public async Task<IActionResult> Manage(Guid id, ManageRegionRequest request, CancellationToken ct)
{
var result = await service.ManageAsync(id, request, ct);
@@ -80,6 +96,7 @@ public class RegionController(RegionService service) : ControllerBase
}
[HttpGet("{id:guid}/hierarchy")]
[Authorize("region.view")]
public async Task<IActionResult> GetHierarchy(Guid id)
{
var result = await service.GetHierarchyAsync(id);
@@ -87,18 +104,20 @@ public class RegionController(RegionService service) : ControllerBase
}
[HttpGet("{id:guid}/dashboard")]
[Authorize("region.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);
}
// Flat CRUD-list view over targets/budgets/tax-rules/agency-maps across all regions.
[HttpGet("manage-entries")]
[Authorize("region.view")]
public async Task<IActionResult> GetManageEntries() =>
Ok(await service.GetManageEntriesAsync());
[HttpDelete("manage-entries/{entryType}/{id:guid}")]
[Authorize("region.manage")]
public async Task<IActionResult> DeleteManageEntry(RegionManageEntryType entryType, Guid id, CancellationToken ct)
{
var deleted = await service.DeleteManageEntryAsync(entryType, id, ct);
@@ -1,4 +1,5 @@
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Returns;
@@ -7,10 +8,12 @@ namespace Distribution.Features.Returns;
public class ReturnController(ReturnService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpGet("api/returns")]
[Authorize("return.view")]
public async Task<IActionResult> GetAll() =>
Ok(await service.GetAllAsync());
[HttpGet("api/returns/{id:guid}")]
[Authorize("return.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -18,6 +21,7 @@ public class ReturnController(ReturnService service, ICurrentUserService current
}
[HttpPatch("api/returns/{id:guid}/reasons")]
[Authorize("return.manage")]
public async Task<IActionResult> UpdateReasons(Guid id, UpdateSaleReturnReasonsRequest request, CancellationToken ct)
{
try
@@ -29,10 +33,12 @@ public class ReturnController(ReturnService service, ICurrentUserService current
}
[HttpGet("api/shop-pos/{id:guid}/returns")]
[Authorize("return.view")]
public async Task<IActionResult> GetByShopPO(Guid id) =>
Ok(await service.GetByShopPOIdAsync(id));
[HttpPost("api/shop-pos/{id:guid}/returns")]
[Authorize("return.manage")]
public async Task<IActionResult> Create(Guid id, CreateSaleReturnRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? request.CreatedByUserId;
@@ -5,4 +5,8 @@ public interface IRoleRepository
Task<Models.Role?> GetByIdAsync(Guid id);
Task<List<Models.Role>> GetAllAsync();
Task<List<Models.RolePermission>> GetPermissionsAsync(Guid roleId);
Task AddAsync(Models.Role role);
void Update(Models.Role role);
void Remove(Models.Role role);
Task ReplacePermissionsAsync(Guid roleId, List<Guid> permissionIds);
}
@@ -23,4 +23,32 @@ public class RoleController(RoleService service) : ControllerBase
var result = await service.GetPermissionsAsync(id);
return result is null ? NotFound() : Ok(result);
}
[HttpPost]
public async Task<IActionResult> Create(CreateRoleRequest request, CancellationToken ct)
{
var result = await service.CreateAsync(request, ct);
return CreatedAtAction(nameof(GetById), new { id = result.Id }, result);
}
[HttpPut("{id:guid}")]
public async Task<IActionResult> Update(Guid id, UpdateRoleRequest request, CancellationToken ct)
{
var result = await service.UpdateAsync(id, request, ct);
return result is null ? NotFound() : Ok(result);
}
[HttpPut("{id:guid}/permissions")]
public async Task<IActionResult> AssignPermissions(Guid id, AssignRolePermissionsRequest request, CancellationToken ct)
{
var result = await service.AssignPermissionsAsync(id, request, ct);
return result is null ? NotFound() : Ok(result);
}
[HttpDelete("{id:guid}")]
public async Task<IActionResult> Deactivate(Guid id, CancellationToken ct)
{
var deactivated = await service.DeactivateAsync(id, ct);
return deactivated ? NoContent() : NotFound();
}
}
+3 -1
View File
@@ -1,5 +1,7 @@
namespace Distribution.Features.Role;
public record RoleResponse(Guid Id, string Name, int Level, bool IsActive, DateTime CreatedAt);
public record RolePermissionResponse(Guid PermissionId, string Code, string Description);
public record CreateRoleRequest(string Name, int Level);
public record UpdateRoleRequest(string Name, int Level);
public record AssignRolePermissionsRequest(List<Guid> PermissionIds);
@@ -1,4 +1,5 @@
using Distribution.Data;
using Distribution.Models;
using Microsoft.EntityFrameworkCore;
namespace Distribution.Features.Role;
@@ -16,4 +17,29 @@ public class RoleRepository(AppDBContext context) : IRoleRepository
.Include(rp => rp.Permission)
.Where(rp => rp.FK_RoleId == roleId && rp.IsActive)
.ToListAsync();
public async Task AddAsync(Models.Role role) =>
await context.Roles.AddAsync(role);
public void Update(Models.Role role) =>
context.Roles.Update(role);
public void Remove(Models.Role role)
{
role.IsActive = false;
context.Roles.Update(role);
}
public async Task ReplacePermissionsAsync(Guid roleId, List<Guid> permissionIds)
{
var existing = await context.RolePermissions
.Where(rp => rp.FK_RoleId == roleId)
.ToListAsync();
context.RolePermissions.RemoveRange(existing);
context.RolePermissions.AddRange(permissionIds.Select(pid => new RolePermission
{
FK_RoleId = roleId,
FK_PermissionId = pid
}));
}
}
+81 -3
View File
@@ -1,18 +1,23 @@
using Distribution.Infra.UoW;
namespace Distribution.Features.Role;
public class RoleService(IRoleRepository repo)
public class RoleService(IRoleRepository repo, IUnitOfWork uow)
{
private static RoleResponse ToResponse(Models.Role r) =>
new(r.Id, r.Name, r.Level, r.IsActive, r.CreatedAt);
public async Task<List<RoleResponse>> GetAllAsync() =>
(await repo.GetAllAsync())
.Where(r => r.IsActive)
.Select(r => new RoleResponse(r.Id, r.Name, r.Level, r.IsActive, r.CreatedAt))
.Select(ToResponse)
.ToList();
public async Task<RoleResponse?> GetByIdAsync(Guid id)
{
var role = await repo.GetByIdAsync(id);
if (role is null || !role.IsActive) return null;
return new RoleResponse(role.Id, role.Name, role.Level, role.IsActive, role.CreatedAt);
return ToResponse(role);
}
public async Task<List<RolePermissionResponse>?> GetPermissionsAsync(Guid roleId)
@@ -23,4 +28,77 @@ public class RoleService(IRoleRepository repo)
.Select(rp => new RolePermissionResponse(rp.FK_PermissionId, rp.Permission.Code, rp.Permission.Description))
.ToList();
}
public async Task<RoleResponse> CreateAsync(CreateRoleRequest request, CancellationToken ct = default)
{
var role = new Models.Role { Name = request.Name, Level = request.Level };
await uow.BeginAsync(ct);
try
{
await repo.AddAsync(role);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(role);
}
public async Task<RoleResponse?> UpdateAsync(Guid id, UpdateRoleRequest request, CancellationToken ct = default)
{
var role = await repo.GetByIdAsync(id);
if (role is null || !role.IsActive) return null;
role.Name = request.Name;
role.Level = request.Level;
await uow.BeginAsync(ct);
try
{
repo.Update(role);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(role);
}
public async Task<bool> DeactivateAsync(Guid id, CancellationToken ct = default)
{
var role = await repo.GetByIdAsync(id);
if (role is null || !role.IsActive) return false;
await uow.BeginAsync(ct);
try
{
repo.Remove(role);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return true;
}
public async Task<List<RolePermissionResponse>?> AssignPermissionsAsync(Guid id, AssignRolePermissionsRequest request, CancellationToken ct = default)
{
var role = await repo.GetByIdAsync(id);
if (role is null || !role.IsActive) return null;
await uow.BeginAsync(ct);
try
{
await repo.ReplacePermissionsAsync(id, request.PermissionIds);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return await GetPermissionsAsync(id);
}
}
+21 -2
View File
@@ -1,23 +1,34 @@
using Microsoft.AspNetCore.Mvc;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Route;
[ApiController]
[Route("api/routes")]
public class RouteController(RouteService service) : ControllerBase
public class RouteController(
RouteService service,
IScopeAccessService scopeAccess,
ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
[Authorize("route.view")]
public async Task<IActionResult> GetAll() =>
Ok(await service.GetAllAsync());
[HttpGet("{id:guid}")]
[Authorize("route.view")]
public async Task<IActionResult> GetById(Guid id)
{
var userId = currentUser.UserId;
if (userId.HasValue && !await scopeAccess.HasRouteScopeAsync(userId.Value, id))
return StatusCode(403);
var result = await service.GetByIdAsync(id);
return result is null ? NotFound() : Ok(result);
}
[HttpPost]
[Authorize("route.manage")]
public async Task<IActionResult> Create(CreateRouteRequest request, CancellationToken ct)
{
var result = await service.CreateAsync(request, ct);
@@ -25,6 +36,7 @@ public class RouteController(RouteService service) : ControllerBase
}
[HttpPut("{id:guid}")]
[Authorize("route.manage")]
public async Task<IActionResult> Update(Guid id, UpdateRouteRequest request, CancellationToken ct)
{
var result = await service.UpdateAsync(id, request, ct);
@@ -32,6 +44,7 @@ public class RouteController(RouteService service) : ControllerBase
}
[HttpPut("{id:guid}/region")]
[Authorize("route.manage")]
public async Task<IActionResult> AssignToRegion(Guid id, AssignRouteToRegionRequest request, CancellationToken ct)
{
var result = await service.AssignToRegionAsync(id, request, ct);
@@ -39,6 +52,7 @@ public class RouteController(RouteService service) : ControllerBase
}
[HttpDelete("{id:guid}")]
[Authorize("route.manage")]
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
{
var deleted = await service.DeleteAsync(id, ct);
@@ -46,6 +60,7 @@ public class RouteController(RouteService service) : ControllerBase
}
[HttpPost("{id:guid}/stores")]
[Authorize("route.manage")]
public async Task<IActionResult> AssignStores(Guid id, AssignStoresToRouteRequest request, CancellationToken ct)
{
var result = await service.AssignStoresToRouteAsync(id, request, ct);
@@ -53,6 +68,7 @@ public class RouteController(RouteService service) : ControllerBase
}
[HttpPut("{id:guid}/owner")]
[Authorize("route.manage")]
public async Task<IActionResult> AssignOwner(Guid id, AssignRouteOwnerRequest request, CancellationToken ct)
{
var result = await service.AssignOwnerAsync(id, request, ct);
@@ -60,10 +76,12 @@ public class RouteController(RouteService service) : ControllerBase
}
[HttpPost("{id:guid}/optimize")]
[Authorize("route.manage")]
public IActionResult OptimizeSequence(Guid id) =>
StatusCode(StatusCodes.Status501NotImplemented);
[HttpPost("{id:guid}/visits/check-in")]
[Authorize("route.manage")]
public async Task<IActionResult> CheckIn(Guid id, RecordCheckInRequest request, CancellationToken ct)
{
try
@@ -75,6 +93,7 @@ public class RouteController(RouteService service) : ControllerBase
}
[HttpPost("{id:guid}/visits/check-out")]
[Authorize("route.manage")]
public async Task<IActionResult> CheckOut(Guid id, RecordCheckOutRequest request, CancellationToken ct)
{
var result = await service.RecordCheckOutAsync(id, request, ct);
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Scheme;
@@ -7,10 +8,12 @@ namespace Distribution.Features.Scheme;
public class SchemeController(SchemeService service) : ControllerBase
{
[HttpGet]
[Authorize("scheme.view")]
public async Task<IActionResult> GetAll([FromQuery] Guid? regionId) =>
Ok(await service.GetAllAsync(regionId));
[HttpGet("{id:guid}")]
[Authorize("scheme.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -18,6 +21,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpPost]
[Authorize("scheme.manage")]
public async Task<IActionResult> Create(CreateSchemeRequest request, CancellationToken ct)
{
try
@@ -32,6 +36,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpPut("{id:guid}")]
[Authorize("scheme.manage")]
public async Task<IActionResult> Update(Guid id, UpdateSchemeRequest request, CancellationToken ct)
{
try
@@ -46,6 +51,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpDelete("{id:guid}")]
[Authorize("scheme.manage")]
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
{
var deleted = await service.DeleteAsync(id, ct);
@@ -53,6 +59,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpPut("{id:guid}/free-goods-rule")]
[Authorize("scheme.manage")]
public async Task<IActionResult> SetFreeGoodsRule(Guid id, SetFreeGoodsRuleRequest request, CancellationToken ct)
{
try
@@ -67,6 +74,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpDelete("{id:guid}/free-goods-rule")]
[Authorize("scheme.manage")]
public async Task<IActionResult> ClearFreeGoodsRule(Guid id, CancellationToken ct)
{
var result = await service.ClearFreeGoodsRuleAsync(id, ct);
@@ -74,6 +82,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpPut("{id:guid}/bundle-components/{itemId:guid}")]
[Authorize("scheme.manage")]
public async Task<IActionResult> UpsertBundleComponent(Guid id, Guid itemId, UpsertBundleComponentRequest request, CancellationToken ct)
{
try
@@ -88,6 +97,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpDelete("{id:guid}/bundle-components/{itemId:guid}")]
[Authorize("scheme.manage")]
public async Task<IActionResult> RemoveBundleComponent(Guid id, Guid itemId, CancellationToken ct)
{
var result = await service.RemoveBundleComponentAsync(id, itemId, ct);
@@ -95,6 +105,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpGet("eligible")]
[Authorize("scheme.view")]
public async Task<IActionResult> GetEligible([FromQuery] Guid storeId, [FromQuery] Guid orderId)
{
var result = await service.EvaluateEligibilityAsync(storeId, orderId);
@@ -102,6 +113,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpGet("{id:guid}/spend")]
[Authorize("scheme.view")]
public async Task<IActionResult> GetSpend(Guid id)
{
var result = await service.GetSpendAsync(id);
@@ -109,6 +121,7 @@ public class SchemeController(SchemeService service) : ControllerBase
}
[HttpGet("{id:guid}/roi")]
[Authorize("scheme.view")]
public async Task<IActionResult> GetROI(Guid id)
{
var result = await service.GetROIAsync(id);
@@ -121,6 +134,7 @@ public class SchemeController(SchemeService service) : ControllerBase
public class SchemeOrderController(SchemeService service) : ControllerBase
{
[HttpPost("{id:guid}/apply-scheme")]
[Authorize("scheme.manage")]
public async Task<IActionResult> ApplyScheme(Guid id, ApplySchemeRequest request, CancellationToken ct)
{
try
+14 -3
View File
@@ -1,5 +1,6 @@
using Distribution.Infra.Authorization;
using Distribution.Infra.Authorization;
using Distribution.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Stock;
@@ -8,9 +9,10 @@ namespace Distribution.Features.Stock;
[Route("api/stock")]
public class StockController(StockService service, ICurrentUserService currentUser) : ControllerBase
{
// ── Query ──────────────────────────────────────────────────────────────
// ── Query ──────────────────────────────────────────────────────────────────
[HttpGet("balances")]
[Authorize("stock.view")]
public async Task<IActionResult> GetBalances(
[FromQuery] Guid? locationId,
[FromQuery] LocationType? locationType,
@@ -23,6 +25,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
}
[HttpGet("low-stock")]
[Authorize("stock.view")]
public async Task<IActionResult> GetLowStock([FromQuery] Guid? locationId)
{
var result = await service.GetLowStockAsync(locationId);
@@ -30,6 +33,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
}
[HttpGet("balances/{itemId}/total")]
[Authorize("stock.view")]
public async Task<IActionResult> GetItemTotal(Guid itemId)
{
var result = await service.GetItemTotalAsync(itemId);
@@ -39,6 +43,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
/// <summary>Next free number for auto-generated serials (e.g. after ...-0005 the answer is 6).</summary>
[HttpGet("serials/next-sequence")]
[Authorize("stock.view")]
public async Task<IActionResult> GetNextSerialSequence([FromQuery] Guid itemId, [FromQuery] string prefix = "")
{
var next = await service.GetNextSerialSequenceAsync(itemId, prefix);
@@ -46,6 +51,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
}
[HttpGet("movements")]
//[Authorize("stock.view")]
public async Task<IActionResult> GetMovements(
[FromQuery] Guid? locationId,
[FromQuery] Guid? itemId,
@@ -77,9 +83,10 @@ public class StockController(StockService service, ICurrentUserService currentUs
return Ok(result);
}
// ── Write ──────────────────────────────────────────────────────────────
// ── Write ──────────────────────────────────────────────────────────────────
[HttpPost("transfer")]
[Authorize("stock.manage")]
public async Task<IActionResult> Transfer(TransferRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
@@ -92,6 +99,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
}
[HttpPost("damage")]
[Authorize("stock.manage")]
public async Task<IActionResult> RecordDamage(DamageRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
@@ -104,6 +112,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
}
[HttpPost("customer-return")]
[Authorize("stock.manage")]
public async Task<IActionResult> RecordCustomerReturn(CustomerReturnRequest request, CancellationToken ct)
{
if (currentUser.UserId is null) return Unauthorized();
@@ -116,6 +125,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
}
[HttpPost("adjustment")]
[Authorize("stock.manage")]
public async Task<IActionResult> Adjust(AdjustmentRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
@@ -131,6 +141,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
}
[HttpPatch("movements/{id}/reason")]
[Authorize("stock.manage")]
public async Task<IActionResult> UpdateMovementReason(Guid id, UpdateMovementReasonRequest request, CancellationToken ct)
{
try
+23 -2
View File
@@ -1,13 +1,19 @@
using Distribution.Models;
using Distribution.Infra.Authorization;
using Distribution.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.Store;
[ApiController]
[Route("api/stores")]
public class StoreController(StoreService service) : ControllerBase
public class StoreController(
StoreService service,
IScopeAccessService scopeAccess,
ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
[Authorize("store.view")]
public async Task<IActionResult> GetAll(
[FromQuery] Guid? routeId,
[FromQuery] string? search,
@@ -16,13 +22,18 @@ public class StoreController(StoreService service) : ControllerBase
Ok(await service.GetAllAsync(routeId, search, page, pageSize));
[HttpGet("{id:guid}")]
[Authorize("store.view")]
public async Task<IActionResult> GetById(Guid id)
{
var userId = currentUser.UserId;
//if (userId.HasValue && !await scopeAccess.HasStoreScopeAsync(userId.Value, id))
// return StatusCode(403);
var result = await service.GetByIdAsync(id);
return result is null ? NotFound() : Ok(result);
}
[HttpPost]
[Authorize("store.manage")]
public async Task<IActionResult> Create(CreateStoreRequest request, CancellationToken ct)
{
var result = await service.CreateAsync(request, ct);
@@ -30,6 +41,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpPut("{id:guid}")]
[Authorize("store.manage")]
public async Task<IActionResult> Update(Guid id, UpdateStoreRequest request, CancellationToken ct)
{
var result = await service.UpdateAsync(id, request, ct);
@@ -37,6 +49,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpDelete("{id:guid}")]
[Authorize("store.manage")]
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
{
var deleted = await service.DeleteAsync(id, ct);
@@ -44,6 +57,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpPut("{id:guid}/credit-limit")]
[Authorize("store.manage")]
public async Task<IActionResult> UpdateCreditLimit(Guid id, UpdateCreditLimitRequest request, CancellationToken ct)
{
var result = await service.UpdateCreditLimitAsync(id, request, ct);
@@ -51,6 +65,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpPut("{id:guid}/outstanding-balance")]
[Authorize("store.manage")]
public async Task<IActionResult> UpdateOutstandingBalance(Guid id, UpdateOutstandingBalanceRequest request, CancellationToken ct)
{
var result = await service.UpdateOutstandingBalanceAsync(id, request, ct);
@@ -58,6 +73,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpGet("{id:guid}/outstanding-balance")]
[Authorize("store.view")]
public async Task<IActionResult> GetOutstandingBalance(Guid id)
{
var result = await service.GetOutstandingBalanceAsync(id);
@@ -65,6 +81,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpPut("{id:guid}/segment")]
[Authorize("store.manage")]
public async Task<IActionResult> ClassifySegment(Guid id, ClassifySegmentRequest request, CancellationToken ct)
{
var result = await service.ClassifySegmentAsync(id, request, ct);
@@ -72,6 +89,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpGet("{id:guid}/visit-history")]
[Authorize("store.view")]
public async Task<IActionResult> GetVisitHistory(Guid id)
{
var result = await service.GetVisitHistoryAsync(id);
@@ -79,6 +97,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpGet("{id:guid}/schemes/{schemeId:guid}/eligibility")]
[Authorize("store.view")]
public async Task<IActionResult> CheckSchemeEligibility(Guid id, Guid schemeId)
{
var result = await service.CheckSchemeEligibilityAsync(id, schemeId);
@@ -86,6 +105,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpGet("{id:guid}/dashboard")]
[Authorize("store.view")]
public async Task<IActionResult> GetDashboard(Guid id, [FromQuery] string period)
{
var result = await service.GetDashboardAsync(id, period);
@@ -100,6 +120,7 @@ public class StoreController(StoreService service) : ControllerBase
}
[HttpPatch("{id:guid}/status")]
[Authorize("store.manage")]
public async Task<IActionResult> PatchStatus(Guid id, PatchStoreStatusRequest request, CancellationToken ct)
{
var result = await service.SetActiveStatusAsync(id, request.IsActive, ct);
+3 -3
View File
@@ -11,7 +11,7 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
private const int GlobalScopeRoleLevel = 50;
private const int CreditApproverRoleLevel = 20;
private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel;
private async Task<bool> HasGlobalScopeAsync() => await currentUser.GetRoleLevelAsync() >= GlobalScopeRoleLevel;
private async Task<bool> HasStoreScopeAsync(Guid storeId)
{
@@ -122,7 +122,7 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
public async Task<StoreResponse?> UpdateCreditLimitAsync(Guid id, UpdateCreditLimitRequest request, CancellationToken ct = default)
{
if (currentUser.RoleLevel < CreditApproverRoleLevel) return null;
if (await currentUser.GetRoleLevelAsync() < CreditApproverRoleLevel) return null;
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
@@ -143,7 +143,7 @@ public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserSe
public async Task<StoreResponse?> UpdateOutstandingBalanceAsync(Guid id, UpdateOutstandingBalanceRequest request, CancellationToken ct = default)
{
if (currentUser.RoleLevel < CreditApproverRoleLevel) return null;
if (await currentUser.GetRoleLevelAsync() < CreditApproverRoleLevel) return null;
var store = await repo.GetByIdAsync(id);
if (store is null || !store.IsActive) return null;
if (!await HasStoreScopeAsync(id)) return null;
@@ -1,4 +1,5 @@
using Distribution.Infra.Authorization;
using Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.SupplierClaims;
@@ -7,10 +8,12 @@ namespace Distribution.Features.SupplierClaims;
public class SupplierClaimController(SupplierClaimService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpGet("api/supplier-claims")]
[Authorize("supplier-claim.view")]
public async Task<IActionResult> GetAll() =>
Ok(await service.GetAllAsync());
[HttpGet("api/supplier-claims/{id:guid}")]
[Authorize("supplier-claim.view")]
public async Task<IActionResult> GetById(Guid id)
{
var result = await service.GetByIdAsync(id);
@@ -18,10 +21,12 @@ public class SupplierClaimController(SupplierClaimService service, ICurrentUserS
}
[HttpGet("api/purchase-orders/{id:guid}/claims")]
[Authorize("supplier-claim.view")]
public async Task<IActionResult> GetByPurchaseOrder(Guid id) =>
Ok(await service.GetByPurchaseOrderIdAsync(id));
[HttpPost("api/purchase-orders/{id:guid}/claims")]
[Authorize("supplier-claim.manage")]
public async Task<IActionResult> Create(Guid id, CreateSupplierClaimRequest request, CancellationToken ct)
{
// TEMPORARY: currentUser.UserId is always unset due to the broken auth middleware
@@ -37,6 +42,7 @@ public class SupplierClaimController(SupplierClaimService service, ICurrentUserS
}
[HttpPut("api/supplier-claims/{id:guid}")]
[Authorize("supplier-claim.manage")]
public async Task<IActionResult> Update(Guid id, UpdateSupplierClaimRequest request, CancellationToken ct)
{
try
@@ -48,6 +54,7 @@ public class SupplierClaimController(SupplierClaimService service, ICurrentUserS
}
[HttpPost("api/supplier-claims/{id:guid}/approve")]
[Authorize("supplier-claim.manage")]
public async Task<IActionResult> Approve(Guid id, ApproveSupplierClaimRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? request.ApprovedByUserId;
@@ -62,6 +69,7 @@ public class SupplierClaimController(SupplierClaimService service, ICurrentUserS
}
[HttpPost("api/supplier-claims/{id:guid}/reject")]
[Authorize("supplier-claim.manage")]
public async Task<IActionResult> Reject(Guid id, RejectSupplierClaimRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? request.RejectedByUserId;
@@ -1,5 +1,6 @@
using Distribution.Infra.Authorization;
using Distribution.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Features.SysConfig;
@@ -9,11 +10,12 @@ namespace Distribution.Features.SysConfig;
public class SysConfigController(SysConfigService service, ICurrentUserService currentUser) : ControllerBase
{
[HttpGet]
[Authorize("sys-config.view")]
public async Task<IActionResult> GetAll() =>
Ok(await service.GetAllAsync());
// Typed shortcut — must be declared before {key} to take precedence
[HttpGet("invoice-creation-mode")]
[Authorize("sys-config.view")]
public async Task<IActionResult> GetInvoiceCreationMode()
{
var mode = await service.GetInvoiceCreationModeAsync();
@@ -21,6 +23,7 @@ public class SysConfigController(SysConfigService service, ICurrentUserService c
}
[HttpPut("invoice-creation-mode")]
[Authorize("sys-config.manage")]
public async Task<IActionResult> SetInvoiceCreationMode(SetInvoiceCreationModeRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
@@ -33,6 +36,7 @@ public class SysConfigController(SysConfigService service, ICurrentUserService c
}
[HttpGet("{key}")]
[Authorize("sys-config.view")]
public async Task<IActionResult> GetByKey(string key)
{
var result = await service.GetByKeyAsync(key);
@@ -40,6 +44,7 @@ public class SysConfigController(SysConfigService service, ICurrentUserService c
}
[HttpPut("{key}")]
[Authorize("sys-config.manage")]
public async Task<IActionResult> Set(string key, SetSysConfigRequest request, CancellationToken ct)
{
var userId = currentUser.UserId ?? request.UserId;
@@ -31,13 +31,6 @@ public class UserController(UserService service) : ControllerBase
return result is null ? NotFound() : Ok(result);
}
[HttpPut("{id:guid}/role")]
public async Task<IActionResult> AssignRole(Guid id, AssignUserRoleRequest request, CancellationToken ct)
{
var result = await service.AssignRoleAsync(id, request, ct);
return result is null ? NotFound() : Ok(result);
}
[HttpPut("{id:guid}/scope")]
public async Task<IActionResult> AssignScope(Guid id, AssignUserScopeRequest request, CancellationToken ct)
{
+9 -2
View File
@@ -1,13 +1,20 @@
using System.ComponentModel.DataAnnotations;
namespace Distribution.Features.User;
public record CreateUserRequest(
string Username,
[EmailAddress] string Username,
string Password,
string FullName,
Guid RoleId,
Guid? ReportsToUserId);
public record UpdateUserRequest(string FullName);
public record UpdateUserRequest(
string FullName,
string? Username = null,
Guid? RoleId = null,
string? CurrentPassword = null,
string? NewPassword = null);
public record AssignUserRoleRequest(Guid RoleId);
+64 -21
View File
@@ -1,12 +1,10 @@
using Distribution.Features.Auth;
using Distribution.Infra.UoW;
using Microsoft.AspNetCore.Identity;
namespace Distribution.Features.User;
public class UserService(IUserRepository repo, IUnitOfWork uow)
public class UserService(IUserRepository repo, IUnitOfWork uow, IAuthHexClient authHex)
{
private readonly PasswordHasher<Models.User> _hasher = new();
private static UserResponse ToResponse(Models.User u) =>
new(u.Id, u.Username, u.FullName, u.FK_RoleId, u.Role?.Name ?? string.Empty,
u.FK_ReportsToUserId, u.IsActive, u.CreatedAt, u.UpdatedAt);
@@ -33,12 +31,30 @@ public class UserService(IUserRepository repo, IUnitOfWork uow)
FK_RoleId = request.RoleId,
FK_ReportsToUserId = request.ReportsToUserId
};
user.PasswordHash = _hasher.HashPassword(user, request.Password);
await uow.BeginAsync(ct);
try
{
await repo.AddAsync(user);
var authResult = await authHex.CallAsync("registerUser", new
{
userId = user.Id,
userName = request.Username,
email = request.Username,
fullname = request.FullName,
password = request.Password,
roleId = request.RoleId.ToString(),
userTypeId = "00000001-0000-0000-0000-200000000000",
sendCredentialsEmail = false
}, reference: user.Id.ToString(), ct: ct);
if (!authResult.Success)
{
await uow.RollbackAsync(ct);
throw new InvalidOperationException($"AuthHex registration failed: {authResult.Message}");
}
await uow.CommitAsync(ct);
}
catch
@@ -53,12 +69,52 @@ public class UserService(IUserRepository repo, IUnitOfWork uow)
{
var user = await repo.GetByIdAsync(id);
if (user is null || !user.IsActive) return null;
user.FullName = request.FullName;
if (!string.IsNullOrWhiteSpace(request.Username))
user.Username = request.Username;
if (request.RoleId.HasValue)
user.FK_RoleId = request.RoleId.Value;
user.UpdatedAt = DateTime.Now;
await uow.BeginAsync(ct);
try
{
repo.Update(user);
var hasUsernameChange = !string.IsNullOrWhiteSpace(request.Username);
var hasRoleChange = request.RoleId.HasValue;
if (hasUsernameChange || hasRoleChange)
{
var payload = new Dictionary<string, object> { ["userId"] = user.Id.ToString() };
if (hasUsernameChange) payload["userName"] = request.Username!;
if (hasRoleChange) payload["roleCode"] = request.RoleId!.Value.ToString();
var authResult = await authHex.CallAsync("UpdateUser", payload, reference: user.Id.ToString(), ct: ct);
if (!authResult.Success)
{
await uow.RollbackAsync(ct);
throw new InvalidOperationException($"AuthHex update failed: {authResult.Message}");
}
}
if (!string.IsNullOrWhiteSpace(request.CurrentPassword) && !string.IsNullOrWhiteSpace(request.NewPassword))
{
var authResult = await authHex.CallAsync("ChangeUserPassword", new
{
userId = user.Id.ToString(),
currentPassword = request.CurrentPassword,
newPassword = request.NewPassword
}, reference: user.Id.ToString(), ct: ct);
if (!authResult.Success)
{
await uow.RollbackAsync(ct);
throw new InvalidOperationException($"AuthHex password change failed: {authResult.Message}");
}
}
await uow.CommitAsync(ct);
}
catch
@@ -71,22 +127,9 @@ public class UserService(IUserRepository repo, IUnitOfWork uow)
public async Task<UserResponse?> AssignRoleAsync(Guid id, AssignUserRoleRequest request, CancellationToken ct = default)
{
var user = await repo.GetByIdAsync(id);
if (user is null || !user.IsActive) return null;
user.FK_RoleId = request.RoleId;
user.UpdatedAt = DateTime.Now;
await uow.BeginAsync(ct);
try
{
repo.Update(user);
await uow.CommitAsync(ct);
}
catch
{
await uow.RollbackAsync(ct);
throw;
}
return ToResponse(user);
return await UpdateAsync(id, new UpdateUserRequest(
FullName: (await repo.GetByIdAsync(id))?.FullName ?? string.Empty,
RoleId: request.RoleId), ct);
}
public async Task<bool> AssignScopeAsync(Guid id, AssignUserScopeRequest request, CancellationToken ct = default)
@@ -1,14 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Distribution.Infra.Authorization;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthenticatedAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (context.HttpContext.User.Identity?.IsAuthenticated != true)
context.Result = new UnauthorizedResult();
}
}
@@ -1,4 +1,4 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace Distribution.Infra.Authorization;
@@ -17,6 +17,14 @@ public class AuthorizationController(
return Ok(new PermissionCheckResponse(result));
}
[HttpGet("my-permissions")]
public async Task<IActionResult> GetMyPermissions()
{
if (currentUser.RoleId is not { } roleId) return Unauthorized();
var permissions = await permissionService.GetRolePermissionsAsync(roleId);
return Ok(new RolePermissionsResponse(permissions));
}
[HttpGet("scopes/stores/{storeId:guid}")]
public async Task<IActionResult> CheckStoreScope(Guid storeId)
{
@@ -49,3 +57,15 @@ public class AuthorizationController(
return Ok(new AccessibleStoresResponse(result));
}
}
[ApiController]
[Route("api/permissions")]
public class PermissionController(IPermissionService permissionService) : ControllerBase
{
[HttpGet]
public async Task<IActionResult> GetAll()
{
var permissions = await permissionService.GetAllAsync();
return Ok(permissions.Select(p => new { permissionId = p.Id, p.Code, p.Description }));
}
}
@@ -2,6 +2,8 @@ namespace Distribution.Infra.Authorization;
public record PermissionCheckResponse(bool HasPermission);
public record RolePermissionsResponse(List<string> Permissions);
public record StoreScopeCheckResponse(bool HasScope);
public record RouteScopeCheckResponse(bool HasScope);
@@ -1,46 +0,0 @@
using Microsoft.AspNetCore.Http;
namespace Distribution.Infra.Authorization;
public class CurrentUserService : ICurrentUserService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public CurrentUserService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
private System.Security.Claims.ClaimsPrincipal? User => _httpContextAccessor.HttpContext?.User;
public bool IsAuthenticated => User?.Identity?.IsAuthenticated ?? false;
public Guid? UserId
{
get
{
var value = User?.FindFirst("sub")?.Value ?? User?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
return Guid.TryParse(value, out var id) ? id : null;
}
}
public Guid? RoleId
{
get
{
var value = User?.FindFirst("role_id")?.Value;
return Guid.TryParse(value, out var id) ? id : null;
}
}
public string? Username => User?.FindFirst("username")?.Value;
public int RoleLevel
{
get
{
var value = User?.FindFirst("role_level")?.Value;
return int.TryParse(value, out var level) ? level : 0;
}
}
}
@@ -0,0 +1,47 @@
using System.Security.Claims;
using Distribution.Data;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
namespace Distribution.Infra.Authorization;
public class CurrentUserService(IHttpContextAccessor http, AppDBContext db, IMemoryCache cache) : ICurrentUserService
{
private ClaimsPrincipal? User => http.HttpContext?.User;
public bool IsAuthenticated => User?.Identity?.IsAuthenticated ?? false;
public Guid? UserId => Guid.TryParse(User?.FindFirst("UserId")?.Value, out var id) ? id : null;
public Guid? RoleId => Guid.TryParse(User?.FindFirst("RoleId")?.Value, out var id) ? id : null;
public async Task<string?> GetUsernameAsync()
{
if (UserId is not { } id) return null;
var key = $"user_rolename_{id}";
if (cache.TryGetValue(key, out string? cached)) return cached;
var user = await db.Users.AsNoTracking().FirstOrDefaultAsync(u => u.Id == id);
cache.Set(key, user?.Username, TimeSpan.FromMinutes(10));
return user?.Username;
}
public async Task<string?> GetRoleCodeAsync()
{
if (RoleId is not { } id) return null;
var key = $"role_name_{id}";
if (cache.TryGetValue(key, out string? cached)) return cached;
var role = await db.Roles.AsNoTracking().FirstOrDefaultAsync(r => r.Id == id);
cache.Set(key, role?.Name, TimeSpan.FromMinutes(10));
return role?.Name;
}
public async Task<int> GetRoleLevelAsync()
{
if (RoleId is not { } id) return 0;
var key = $"role_level_{id}";
if (cache.TryGetValue(key, out int cached)) return cached;
var role = await db.Roles.AsNoTracking().FirstOrDefaultAsync(r => r.Id == id);
var level = role?.Level ?? 0;
cache.Set(key, level, TimeSpan.FromMinutes(10));
return level;
}
}
@@ -4,7 +4,8 @@ public interface ICurrentUserService
{
Guid? UserId { get; }
Guid? RoleId { get; }
string? Username { get; }
int RoleLevel { get; }
bool IsAuthenticated { get; }
Task<string?> GetUsernameAsync();
Task<string?> GetRoleCodeAsync();
Task<int> GetRoleLevelAsync();
}
@@ -1,32 +0,0 @@
using System.Security.Cryptography;
using System.Xml.Linq;
namespace Distribution.Infra.Authorization;
/// <summary>
/// Parses an XML-format RSA public key (`&lt;RSAKeyValue&gt;...&lt;/RSAKeyValue&gt;`, as issued by
/// AuthHex) into an <see cref="RSA"/> instance. Written by hand instead of relying on
/// RSA.FromXmlString, which is Windows-only in .NET (throws PlatformNotSupportedException on
/// Linux/macOS) — this keeps token validation portable across hosts.
/// </summary>
public static class RsaXmlKeyReader
{
public static RSA ReadPublicKey(string xml)
{
var root = XElement.Parse(xml);
var modulus = root.Element("Modulus")?.Value
?? throw new InvalidOperationException("RSA XML key is missing <Modulus>.");
var exponent = root.Element("Exponent")?.Value
?? throw new InvalidOperationException("RSA XML key is missing <Exponent>.");
var parameters = new RSAParameters
{
Modulus = Convert.FromBase64String(modulus),
Exponent = Convert.FromBase64String(exponent)
};
var rsa = RSA.Create();
rsa.ImportParameters(parameters);
return rsa;
}
}
@@ -1,10 +0,0 @@
namespace Distribution.Infra.Authorization.Middleware;
/// <summary>Stand-in for OSMCore's OMSCore.Common.Models.IOs.ApiResponse&lt;T&gt;, which has no equivalent in this project.</summary>
public sealed record ApiResponse<T>
{
public int StatusCode { get; init; }
public bool Success { get; init; }
public string? Message { get; init; }
public T? Data { get; init; }
}
@@ -1,13 +0,0 @@
namespace Distribution.Infra.Authorization.Middleware;
/// <summary>
/// Ported from OSMCore's System/Authentication/JwtOptions.cs. Binds to the same "Jwt" config
/// section already used by Program.cs's AddJwtBearer setup (Jwt:PublicKey/Audience/Issuer) — no
/// new config keys needed.
/// </summary>
public sealed record JwtOptions
{
public string PublicKey { get; init; } = string.Empty;
public string Audience { get; init; } = string.Empty;
public string Issuer { get; init; } = string.Empty;
}
@@ -1,6 +1,10 @@
using Distribution.Models;
namespace Distribution.Infra.Authorization;
public interface IPermissionRepository
{
Task<bool> HasPermissionAsync(Guid roleId, string permissionCode);
Task<List<string>> GetRolePermissionsAsync(Guid roleId);
Task<List<Permission>> GetAllAsync();
}
@@ -1,6 +1,10 @@
using Distribution.Models;
namespace Distribution.Infra.Authorization;
public interface IPermissionService
{
Task<bool> HasPermissionAsync(Guid roleId, string permissionCode);
Task<List<string>> GetRolePermissionsAsync(Guid roleId);
Task<List<Permission>> GetAllAsync();
}
@@ -1,4 +1,5 @@
using Distribution.Data;
using Distribution.Models;
using Microsoft.EntityFrameworkCore;
namespace Distribution.Infra.Authorization;
@@ -10,4 +11,15 @@ public class PermissionRepository(AppDBContext context) : IPermissionRepository
.Where(rp => rp.FK_RoleId == roleId && rp.IsActive)
.Join(context.Permissions.Where(p => p.IsActive), rp => rp.FK_PermissionId, p => p.Id, (rp, p) => p.Code)
.AnyAsync(code => code == permissionCode);
public Task<List<string>> GetRolePermissionsAsync(Guid roleId) =>
context.RolePermissions
.Where(rp => rp.FK_RoleId == roleId && rp.IsActive)
.Select(rp => rp.Permission)
.Where(p => p.IsActive)
.Select(p => p.Code)
.ToListAsync();
public Task<List<Permission>> GetAllAsync() =>
context.Permissions.Where(p => p.IsActive).ToListAsync();
}
@@ -1,7 +1,15 @@
using Distribution.Models;
namespace Distribution.Infra.Authorization;
public class PermissionService(IPermissionRepository repo) : IPermissionService
{
public Task<bool> HasPermissionAsync(Guid roleId, string permissionCode) =>
repo.HasPermissionAsync(roleId, permissionCode);
public Task<List<string>> GetRolePermissionsAsync(Guid roleId) =>
repo.GetRolePermissionsAsync(roleId);
public Task<List<Permission>> GetAllAsync() =>
repo.GetAllAsync();
}
@@ -1,23 +1,24 @@
//namespace Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
//public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
//{
// private readonly IPermissionService _permissionService;
namespace Distribution.Infra.Authorization;
// public PermissionAuthorizationHandler(IPermissionService permissionService)
// {
// _permissionService = permissionService;
// }
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
{
private readonly IPermissionService _permissionService;
// protected override async Task HandleRequirementAsync(
// AuthorizationHandlerContext context, PermissionRequirement requirement)
// {
// var roleIdClaim = context.User.FindFirst("role_id")?.Value;
// if (!Guid.TryParse(roleIdClaim, out var roleId))
// return;
public PermissionAuthorizationHandler(IPermissionService permissionService)
{
_permissionService = permissionService;
}
// if (await _permissionService.HasPermissionAsync(roleId, requirement.PermissionCode))
// context.Succeed(requirement);
// }
//}
protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context, PermissionRequirement requirement)
{
var roleIdClaim = context.User.FindFirst("RoleId")?.Value;
if (!Guid.TryParse(roleIdClaim, out var roleId))
return;
if (await _permissionService.HasPermissionAsync(roleId, requirement.PermissionCode))
context.Succeed(requirement);
}
}
@@ -1,31 +1,32 @@
//using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
//namespace Distribution.Infra.Authorization;
namespace Distribution.Infra.Authorization;
//public class PermissionPolicyProvider : IAuthorizationPolicyProvider
//{
// private readonly DefaultAuthorizationPolicyProvider _fallback;
public class PermissionPolicyProvider : IAuthorizationPolicyProvider
{
private readonly DefaultAuthorizationPolicyProvider _fallback;
// public PermissionPolicyProvider(IOptions<AuthorizationOptions> options)
// {
// _fallback = new DefaultAuthorizationPolicyProvider(options);
// }
public PermissionPolicyProvider(IOptions<AuthorizationOptions> options)
{
_fallback = new DefaultAuthorizationPolicyProvider(options);
}
// public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => _fallback.GetDefaultPolicyAsync();
public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => _fallback.GetDefaultPolicyAsync();
// public Task<AuthorizationPolicy?> GetFallbackPolicyAsync() => _fallback.GetFallbackPolicyAsync();
public Task<AuthorizationPolicy?> GetFallbackPolicyAsync() => _fallback.GetFallbackPolicyAsync();
// public Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
// {
// if (policyName.Contains('.'))
// {
// var policy = new AuthorizationPolicyBuilder()
// .RequireAuthenticatedUser()
// .AddRequirements(new PermissionRequirement(policyName))
// .Build();
// return Task.FromResult<AuthorizationPolicy?>(policy);
// }
public Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
{
if (policyName.Contains('.'))
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddRequirements(new PermissionRequirement(policyName))
.Build();
return Task.FromResult<AuthorizationPolicy?>(policy);
}
// return _fallback.GetPolicyAsync(policyName);
// }
//}
return _fallback.GetPolicyAsync(policyName);
}
}
@@ -1,12 +1,13 @@
//namespace Distribution.Infra.Authorization;
using Microsoft.AspNetCore.Authorization;
//public class PermissionRequirement : IAuthorizationRequirement
//{
// public string PermissionCode { get; }
namespace Distribution.Infra.Authorization;
// public PermissionRequirement(string permissionCode)
// {
// PermissionCode = permissionCode;
// }
//}
public class PermissionRequirement : IAuthorizationRequirement
{
public string PermissionCode { get; }
public PermissionRequirement(string permissionCode)
{
PermissionCode = permissionCode;
}
}
+10 -4
View File
@@ -1,5 +1,5 @@
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;
namespace Distribution.Middleware;
@@ -13,18 +13,24 @@ public class AuthMiddleware(RequestDelegate next, IConfiguration config)
.Replace("Bearer ", "", StringComparison.OrdinalIgnoreCase)
.Trim();
if (string.IsNullOrEmpty(token))
token = context.Request.Cookies["access-token"] ?? string.Empty;
if (!string.IsNullOrEmpty(token))
{
var key = config["Jwt:Key"];
if (!string.IsNullOrEmpty(key))
var publicKeyXml = config["Jwt:PublicKey"];
if (!string.IsNullOrEmpty(publicKeyXml))
{
try
{
var rsa = RSA.Create();
rsa.FromXmlString(publicKeyXml);
var principal = new JwtSecurityTokenHandler().ValidateToken(token,
new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)),
IssuerSigningKey = new RsaSecurityKey(rsa),
ValidAlgorithms = [SecurityAlgorithms.RsaSha256],
ValidateIssuer = true,
ValidIssuer = config["Jwt:Issuer"],
ValidateAudience = true,
@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using System.Text.Encodings.Web;
namespace Distribution.Middleware;
/// <summary>
/// Authentication handler that exists solely to provide Challenge (401) and Forbid (403)
/// responses for UseAuthorization(). Token validation is handled upstream by AuthMiddleware,
/// so HandleAuthenticateAsync returns NoResult to leave HttpContext.User untouched.
/// </summary>
public class BearerResponseHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder) : AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder)
{
protected override Task<AuthenticateResult> HandleAuthenticateAsync() =>
Task.FromResult(AuthenticateResult.NoResult());
protected override Task HandleChallengeAsync(AuthenticationProperties properties)
{
Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
protected override Task HandleForbiddenAsync(AuthenticationProperties properties)
{
Response.StatusCode = StatusCodes.Status403Forbidden;
return Task.CompletedTask;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class SeedPermissionsAndRolePermissions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,29 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class user : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "Users",
columns: new[] { "Id", "CreatedAt", "FK_ReportsToUserId", "FK_RoleId", "FullName", "IsActive", "PasswordHash", "UpdatedAt", "Username" },
values: new object[] { new Guid("00000001-0000-0000-0000-000000000001"), new DateTime(2026, 10, 13, 0, 0, 0, 0, DateTimeKind.Unspecified), null, new Guid("10000000-0000-0000-0000-000000000006"), "Super Admin", true, "N/A", null, "superadmin" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("00000001-0000-0000-0000-000000000001"));
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,287 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class seed_permissions_and_superadmin : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "Permissions",
columns: new[] { "Id", "Code", "CreatedAt", "Description", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000001"), "orders.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View shop POs, invoices, payments and returns", true },
{ new Guid("20000000-0000-0000-0000-000000000002"), "rides.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage delivery rides and delivery tasks", true },
{ new Guid("20000000-0000-0000-0000-000000000003"), "loading.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage loading sheets", true },
{ new Guid("20000000-0000-0000-0000-000000000004"), "stores.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View store accounts, credit limits and balances", true },
{ new Guid("20000000-0000-0000-0000-000000000005"), "sales_visits.checkin", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Check in and out of scheduled store visits", true },
{ new Guid("20000000-0000-0000-0000-000000000006"), "items.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage catalogue products", true },
{ new Guid("20000000-0000-0000-0000-000000000007"), "categories.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage product categories and brands", true },
{ new Guid("20000000-0000-0000-0000-000000000008"), "warehouses.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View stock balances, movements, warehouses and reports", true },
{ new Guid("20000000-0000-0000-0000-000000000009"), "purchase_orders.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage purchase orders, GRNs and supplier claims", true },
{ new Guid("20000000-0000-0000-0000-000000000010"), "pricelists.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage regional price lists", true },
{ new Guid("20000000-0000-0000-0000-000000000011"), "schemes.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage pricing schemes and promotions", true },
{ new Guid("20000000-0000-0000-0000-000000000012"), "suppliers.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage supplier accounts", true },
{ new Guid("20000000-0000-0000-0000-000000000013"), "driver_profiles.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage driver profiles and licensing", true },
{ new Guid("20000000-0000-0000-0000-000000000014"), "compliance.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Manage driver compliance rules", true },
{ new Guid("20000000-0000-0000-0000-000000000015"), "users.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage staff user accounts", true },
{ new Guid("20000000-0000-0000-0000-000000000016"), "roles.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage roles and their permission sets", true },
{ new Guid("20000000-0000-0000-0000-000000000017"), "regions.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage regions and region configuration", true },
{ new Guid("20000000-0000-0000-0000-000000000018"), "routes.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage delivery routes", true },
{ new Guid("20000000-0000-0000-0000-000000000019"), "vehicles.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View and manage fleet vehicles", true }
});
migrationBuilder.InsertData(
table: "Roles",
columns: new[] { "Id", "CreatedAt", "IsActive", "Level", "Name" },
values: new object[] { new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), true, 100, "SuperAdmin" });
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("00000001-0000-0000-0000-000000000001"),
column: "FK_RoleId",
value: new Guid("10000000-0000-0000-0000-000000000007"));
migrationBuilder.InsertData(
table: "RolePermissions",
columns: new[] { "FK_PermissionId", "FK_RoleId", "CreatedAt", "Id", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("18023ad9-33e9-4a8c-81ab-dc53a932bdb7"), true },
{ new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("825d5a5f-2c80-4082-8c33-d49aa37feaae"), true },
{ new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a1e975e8-0444-44f4-99c9-ecb145f5e178"), true },
{ new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("fa741a9c-6ea9-4b44-bc1c-98251e2ce264"), true },
{ new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("fd511b82-6a48-459e-8da8-8db040b8b5a6"), true },
{ new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("92e7a255-974a-47e1-94bd-227f2b40f61f"), true },
{ new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b82510e3-b3c1-4f41-97f9-e76790f9728c"), true },
{ new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4b35173b-142c-4387-8991-604d32f6dc27"), true },
{ new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("c41ce69f-e683-4c3f-8e5c-f7b0f06f6496"), true },
{ new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7aa9f9a1-3c36-4141-97cd-074f47ba6c5a"), true },
{ new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("deb01208-aca1-473f-ae08-1f64f54ddd6c"), true },
{ new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3c426f42-2433-489b-a85c-7d94ca0290f6"), true },
{ new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3ed4863f-6683-47e2-b4f4-89f73655c461"), true },
{ new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f4346c74-c269-4bf1-9626-e7670d8075ef"), true },
{ new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("3ca2691e-ae21-436e-9204-1333a727ffd4"), true },
{ new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("b86df36b-17c4-4d3e-a102-4aa2f2d8e2c3"), true },
{ new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("8c82e198-b505-428b-b1a0-05eb8207bd5d"), true },
{ new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a3c69976-d0d6-4890-be7e-5e40f1d36506"), true },
{ new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("ba9dc1ed-beea-424b-9db0-30e4825ab011"), true }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") });
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-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") });
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-000000000007") });
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-000000000007") });
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000001"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000002"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000003"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000004"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000005"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000006"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000007"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000008"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000009"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000010"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000011"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000012"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000013"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000014"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000015"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000016"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000017"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000018"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000019"));
migrationBuilder.DeleteData(
table: "Roles",
keyColumn: "Id",
keyValue: new Guid("10000000-0000-0000-0000-000000000007"));
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("00000001-0000-0000-0000-000000000001"),
column: "FK_RoleId",
value: new Guid("10000000-0000-0000-0000-000000000006"));
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,285 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class useradmin : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7475d3c3-2388-4939-8a09-d7879ffd81c9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e8303485-de75-4541-8616-3dc3d043dead"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("63baa4e1-e268-4afb-b045-0bbc89b6e559"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c75fddcd-7f32-4878-8558-9a70fc752760"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4fcfb308-625f-42e0-b54e-ddfb8beaf7a6"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("09d70c50-aa17-4e21-bbef-8f800c009c38"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5201456f-d2d1-47d8-a1be-a74f89d2598e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e4d7f7f9-4149-41af-a79f-d37845dfb30b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e796d680-ac2e-4e8e-aa39-86137067714a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("97b043ea-aa01-4c3e-81ee-e9e91f1f9f8a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f04db587-2f88-4e9f-9ccf-4ac650aea07b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("372a968b-a962-4a60-afd6-1b69a6a5dd3f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2dd911e7-2217-4dd1-b0aa-18ae5983c6af"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("03f4ab42-49dc-4aac-912b-a0a14415cf87"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d9522f5e-963a-4670-8241-35e65a349970"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2f789a49-103e-4ad9-adda-9ab1cd2e86d9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("17d668ef-09e7-4886-af6e-63817bf25a1b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8b90d8fa-ca60-4eca-a0ba-02a32d99bf50"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("17e9237e-b390-4779-ab51-0e872c25c67d"));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("18023ad9-33e9-4a8c-81ab-dc53a932bdb7"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("825d5a5f-2c80-4082-8c33-d49aa37feaae"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a1e975e8-0444-44f4-99c9-ecb145f5e178"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fa741a9c-6ea9-4b44-bc1c-98251e2ce264"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fd511b82-6a48-459e-8da8-8db040b8b5a6"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("92e7a255-974a-47e1-94bd-227f2b40f61f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b82510e3-b3c1-4f41-97f9-e76790f9728c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4b35173b-142c-4387-8991-604d32f6dc27"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c41ce69f-e683-4c3f-8e5c-f7b0f06f6496"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7aa9f9a1-3c36-4141-97cd-074f47ba6c5a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("deb01208-aca1-473f-ae08-1f64f54ddd6c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3c426f42-2433-489b-a85c-7d94ca0290f6"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3ed4863f-6683-47e2-b4f4-89f73655c461"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f4346c74-c269-4bf1-9626-e7670d8075ef"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3ca2691e-ae21-436e-9204-1333a727ffd4"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b86df36b-17c4-4d3e-a102-4aa2f2d8e2c3"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8c82e198-b505-428b-b1a0-05eb8207bd5d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a3c69976-d0d6-4890-be7e-5e40f1d36506"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ba9dc1ed-beea-424b-9db0-30e4825ab011"));
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,673 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class userpermissions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "Permissions",
columns: new[] { "Id", "Code", "CreatedAt", "Description", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000020"), "claim.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View agency claims and settlement status", true },
{ new Guid("20000000-0000-0000-0000-000000000021"), "claim.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and settle agency claims", true },
{ new Guid("20000000-0000-0000-0000-000000000022"), "delivery-task.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View delivery tasks within a ride", true },
{ new Guid("20000000-0000-0000-0000-000000000023"), "delivery-task.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Confirm and fail delivery tasks", true },
{ new Guid("20000000-0000-0000-0000-000000000024"), "driver.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View driver profiles and license details", true },
{ new Guid("20000000-0000-0000-0000-000000000025"), "driver.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and update driver profiles", true },
{ new Guid("20000000-0000-0000-0000-000000000026"), "grn.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View goods receipt notes", true },
{ new Guid("20000000-0000-0000-0000-000000000027"), "grn.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and confirm goods receipts", true },
{ new Guid("20000000-0000-0000-0000-000000000028"), "loading-sheet.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View loading sheets and their items", true },
{ new Guid("20000000-0000-0000-0000-000000000029"), "loading-sheet.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create, edit, and confirm loading sheets", true },
{ new Guid("20000000-0000-0000-0000-000000000030"), "price-list.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View regional price lists", true },
{ new Guid("20000000-0000-0000-0000-000000000031"), "price-list.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and manage item price lists", true },
{ new Guid("20000000-0000-0000-0000-000000000032"), "purchase-order.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View purchase orders and line items", true },
{ new Guid("20000000-0000-0000-0000-000000000033"), "purchase-order.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create, confirm, and close purchase orders", true },
{ new Guid("20000000-0000-0000-0000-000000000034"), "purchase-return.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and manage purchase returns to suppliers", true },
{ new Guid("20000000-0000-0000-0000-000000000035"), "region.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View regions and their configuration", true },
{ new Guid("20000000-0000-0000-0000-000000000036"), "region.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and update regions, targets, and budgets", true },
{ new Guid("20000000-0000-0000-0000-000000000037"), "return.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View order returns", true },
{ new Guid("20000000-0000-0000-0000-000000000038"), "return.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and manage order returns", true },
{ new Guid("20000000-0000-0000-0000-000000000039"), "route.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View delivery routes", true },
{ new Guid("20000000-0000-0000-0000-000000000040"), "route.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and manage delivery routes", true },
{ new Guid("20000000-0000-0000-0000-000000000041"), "scheme.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View pricing schemes and promotions", true },
{ new Guid("20000000-0000-0000-0000-000000000042"), "scheme.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and configure pricing schemes", true },
{ new Guid("20000000-0000-0000-0000-000000000043"), "stock.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View stock balances and movements", true },
{ new Guid("20000000-0000-0000-0000-000000000044"), "stock.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Transfer stock and record damage or adjustments", true },
{ new Guid("20000000-0000-0000-0000-000000000045"), "store.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View store accounts and balances", true },
{ new Guid("20000000-0000-0000-0000-000000000046"), "store.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and update store accounts", true },
{ new Guid("20000000-0000-0000-0000-000000000047"), "supplier-claim.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View supplier claims", true },
{ new Guid("20000000-0000-0000-0000-000000000048"), "supplier-claim.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Create and resolve supplier claims", true },
{ new Guid("20000000-0000-0000-0000-000000000049"), "sys-config.view", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "View system configuration settings", true },
{ new Guid("20000000-0000-0000-0000-000000000050"), "sys-config.manage", new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), "Update system configuration settings", true }
});
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e7ab6e43-7142-456e-a7f4-41a98daafbd9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("38c173a0-6fb4-475e-8743-643b143cde23"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("587c3956-3c69-49da-8839-5bee906ac5bd"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7e1a8a4d-807b-4b3d-ad76-21ab2b4b5a65"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5272f534-dba6-4899-8661-5687fffef070"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b3cd2db4-f3c4-44cc-bc94-d3b39f4c4672"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f9483ce1-aa1a-409e-a618-d049642f8972"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1e82cd6b-7024-4a5e-a987-b7c6f2ff706e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("64171cfe-734a-4f02-adc4-20a51cc7526f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fd7bcaf8-2022-4cdb-8964-76d5e98a4cfb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bb8e7d27-eebe-4cd9-91ec-124397e69040"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0f85f8d1-40c9-49f7-9bbd-35aead4f4bc8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("defa1474-5a40-4def-9759-a3130859584d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("02e29292-1019-42de-a4d8-d4f125892d51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("172a530b-a9c9-41f7-b523-174d77ff1dd2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8a5a322d-c2b6-428b-8f78-f743cf5abfef"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cba0ecc5-2219-437c-8cfc-b989d6274261"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("aefa2578-8a39-45cd-b054-e86e15199831"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a8cd8a2e-3e24-4768-9203-70d2323a535b"));
migrationBuilder.InsertData(
table: "RolePermissions",
columns: new[] { "FK_PermissionId", "FK_RoleId", "CreatedAt", "Id", "IsActive" },
values: new object[,]
{
{ new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e46f2b96-2913-4536-a427-b67a792cba72"), true },
{ new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f727a037-c5a2-4745-b426-703b3e73d651"), true },
{ new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("4ef8970e-3f1b-49bd-a30d-289c4584da3b"), true },
{ new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("00531be2-4d6d-492d-8ab8-72d5e94c36f0"), true },
{ new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("5b6a5647-5a28-4326-8802-1d13ecfc94b1"), true },
{ new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("69ec8424-eab4-45a6-a503-941d5738d3f9"), true },
{ new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f6d80758-8221-41b8-9099-c6bae5611f86"), true },
{ new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("db1dd417-9733-46e0-ab24-b174da6197e9"), true },
{ new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a04196e8-d113-433f-a672-317f7f0d4faa"), true },
{ new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("2a15a3df-317f-4f0f-abc7-360c8ec97fbb"), true },
{ new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("68b90295-945a-430e-afdc-16bb61ef5d43"), true },
{ new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7fa5ec71-edb1-4687-a95f-a506a794626a"), true },
{ new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d3fef7f2-d827-4064-a900-9f872647eb82"), true },
{ new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("88c098e2-d32a-40ff-9832-a08977c6adb0"), true },
{ new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("e77ea9ea-20e5-4689-af38-a21489ffb9fd"), true },
{ new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("47efe028-429d-4213-a86f-62a5c88e9cbf"), true },
{ new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("025cf58c-b01a-4d27-ae0e-395c9b0f7e55"), true },
{ new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("88a3c70e-cc58-4844-ae2c-4670784c2977"), true },
{ new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("63994f0c-edb8-4ac4-9d06-3f433799dd1a"), true },
{ new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("a167986f-164e-4e3b-876e-2113cba53d51"), true },
{ new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("2a470650-ecb2-488d-a3ad-ea4afe51de29"), true },
{ new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("f0882a97-6eed-4800-830e-0ad60df76b56"), true },
{ new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d5afb82e-2001-4ef7-87b0-b0a510919f6b"), true },
{ new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("79ed7453-80b7-499f-b9fd-41d5aa0c258c"), true },
{ new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("bb0ae3a2-0dfd-41ae-898d-02fbc31636e8"), true },
{ new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("7f176330-117a-4dd2-931f-eb0543818378"), true },
{ new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("0ac9e74e-34ae-48b2-af29-0646c443cc6d"), true },
{ new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("37bda3bc-88df-45e2-9cf5-5014df0df5c0"), true },
{ new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("209149dc-eb8d-4825-9ee1-9aea3d8a8371"), true },
{ new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("961f7973-672b-4837-b16f-d0976ccd3d14"), true },
{ new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007"), new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified), new Guid("d0908026-efc0-4226-95b7-340e03add727"), true }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") });
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-000000000007") });
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-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") });
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-000000000007") });
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-000000000007") });
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-000000000007") });
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-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") });
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-000000000007") });
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-000000000007") });
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-000000000007") });
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-000000000007") });
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-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") });
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-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") });
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-000000000007") });
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-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") });
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000020"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000021"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000022"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000023"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000024"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000025"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000026"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000027"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000028"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000029"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000030"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000031"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000032"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000033"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000034"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000035"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000036"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000037"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000038"));
migrationBuilder.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.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000041"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000042"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000043"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000044"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000045"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000046"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000047"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000048"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000049"));
migrationBuilder.DeleteData(
table: "Permissions",
keyColumn: "Id",
keyValue: new Guid("20000000-0000-0000-0000-000000000050"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7475d3c3-2388-4939-8a09-d7879ffd81c9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e8303485-de75-4541-8616-3dc3d043dead"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("63baa4e1-e268-4afb-b045-0bbc89b6e559"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c75fddcd-7f32-4878-8558-9a70fc752760"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4fcfb308-625f-42e0-b54e-ddfb8beaf7a6"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("09d70c50-aa17-4e21-bbef-8f800c009c38"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5201456f-d2d1-47d8-a1be-a74f89d2598e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e4d7f7f9-4149-41af-a79f-d37845dfb30b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e796d680-ac2e-4e8e-aa39-86137067714a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("97b043ea-aa01-4c3e-81ee-e9e91f1f9f8a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f04db587-2f88-4e9f-9ccf-4ac650aea07b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("372a968b-a962-4a60-afd6-1b69a6a5dd3f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2dd911e7-2217-4dd1-b0aa-18ae5983c6af"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("03f4ab42-49dc-4aac-912b-a0a14415cf87"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d9522f5e-963a-4670-8241-35e65a349970"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2f789a49-103e-4ad9-adda-9ab1cd2e86d9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("17d668ef-09e7-4886-af6e-63817bf25a1b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8b90d8fa-ca60-4eca-a0ba-02a32d99bf50"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("17e9237e-b390-4779-ab51-0e872c25c67d"));
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,719 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class seed_granular_permissions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2933abc2-b472-4870-8af7-a54a3adc4163"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d599d707-9645-4aad-8277-b492b2284eca"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("912132ef-5996-4a7f-acdf-e70a8aebec61"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3193b6b5-8656-41a5-88f1-264cda89dc38"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("33a3bace-319c-4394-a8ca-66f4983e8a65"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d67d727b-6bc6-437e-b52a-69bc6a78a009"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("03c210fa-f841-4262-96a8-d167bcca84de"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4949daa6-2136-400a-8b92-a0650ebd433d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("abd013d2-5d26-4e08-ab9c-506a8bd8a4fc"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f6ea9dbf-42ec-4fdf-b61a-5359f302e3de"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1a6d4dfe-32f5-4860-8c0c-3109f6dbdc56"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6387f234-eb63-43f1-8b20-1262cc646ef7"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bf6e1071-4c1e-45ba-ac90-54935832ab33"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2e009c83-d9be-41b1-9cfb-a720671f9531"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0a1c09c4-4851-4c03-a728-be2be77425cb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6d5cfd42-9ad3-4c6a-81c1-27c92fa70746"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cdd856de-60ba-431a-9c18-59368cf5f325"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("28ecd453-8762-4614-8c75-321017dc8338"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("697b6d8b-4d31-4e40-b8f2-46bc4c25e8c0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2648e7f7-34fe-4c86-99eb-f42fb0a92384"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5c19d416-b3c5-4b78-b80e-0ebdf2255d2f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e464f639-caa3-4425-867d-60acde28d6c7"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2cab1137-c04d-4c18-a1fd-d8124f22e884"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("08269d0d-a571-472b-be37-ff18235f30ef"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1823483d-ddfc-4350-a856-d2b320fc87e9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8c80626e-c979-46b5-8148-2cbec4f501d2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1f67a189-4f7a-4ff1-8041-5c84b85aa6aa"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fbac4979-75e8-4042-b5f2-adbbbe79b636"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("65594d44-edad-4d65-a3b8-a65724ad95ff"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b4ad27a0-a8a0-4240-b5ec-ea35741cf19f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("870ec304-5917-40c9-8d12-fae978878145"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6f6e106a-7b27-46fe-8adb-d21f0ad04062"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e32960f9-5a95-4c6f-be9d-85d59643bd62"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4fbb45f2-1826-4f4e-8846-a937f04fc9c6"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f051c92e-c893-4148-a0c4-987382532c3b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ed96284a-ed40-4521-91c5-6d757efc9ea4"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("34e8490d-a7ac-4940-bb92-b04c5f2d2a0f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cba2d7cb-7a88-4635-b059-0bb7da52aa5a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4e0efeeb-463b-48d7-835f-4337e5f8db1d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ded75a35-1149-4831-8980-a5552b8aba39"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5376fc5a-24df-4a10-ae8d-bf4a7cb41dce"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("736c95bf-4f53-46e7-b773-ad38ec3ddd8d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a08f24a4-f5c0-426c-a415-42c7823dae7a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1bfece31-2930-4a2f-beef-be08d3bfb95b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b04a9be1-cf18-4c25-9ea7-a71db0973fd1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6973c3f9-6578-4965-ada2-f257f0933c16"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7e191e49-0548-4943-8811-d53c3740d6ad"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b419616e-ccd8-4872-ba8d-10dc80482a85"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c0f12314-72e1-438b-b5f2-0b3aafa8ee40"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7357049c-1163-4dbf-afb4-44c77cdff207"));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e7ab6e43-7142-456e-a7f4-41a98daafbd9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("38c173a0-6fb4-475e-8743-643b143cde23"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("587c3956-3c69-49da-8839-5bee906ac5bd"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7e1a8a4d-807b-4b3d-ad76-21ab2b4b5a65"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5272f534-dba6-4899-8661-5687fffef070"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b3cd2db4-f3c4-44cc-bc94-d3b39f4c4672"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f9483ce1-aa1a-409e-a618-d049642f8972"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1e82cd6b-7024-4a5e-a987-b7c6f2ff706e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("64171cfe-734a-4f02-adc4-20a51cc7526f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fd7bcaf8-2022-4cdb-8964-76d5e98a4cfb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bb8e7d27-eebe-4cd9-91ec-124397e69040"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0f85f8d1-40c9-49f7-9bbd-35aead4f4bc8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("defa1474-5a40-4def-9759-a3130859584d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("02e29292-1019-42de-a4d8-d4f125892d51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("172a530b-a9c9-41f7-b523-174d77ff1dd2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8a5a322d-c2b6-428b-8f78-f743cf5abfef"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cba0ecc5-2219-437c-8cfc-b989d6274261"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("aefa2578-8a39-45cd-b054-e86e15199831"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a8cd8a2e-3e24-4768-9203-70d2323a535b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e46f2b96-2913-4536-a427-b67a792cba72"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f727a037-c5a2-4745-b426-703b3e73d651"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4ef8970e-3f1b-49bd-a30d-289c4584da3b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("00531be2-4d6d-492d-8ab8-72d5e94c36f0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5b6a5647-5a28-4326-8802-1d13ecfc94b1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("69ec8424-eab4-45a6-a503-941d5738d3f9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f6d80758-8221-41b8-9099-c6bae5611f86"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("db1dd417-9733-46e0-ab24-b174da6197e9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a04196e8-d113-433f-a672-317f7f0d4faa"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2a15a3df-317f-4f0f-abc7-360c8ec97fbb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("68b90295-945a-430e-afdc-16bb61ef5d43"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7fa5ec71-edb1-4687-a95f-a506a794626a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d3fef7f2-d827-4064-a900-9f872647eb82"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("88c098e2-d32a-40ff-9832-a08977c6adb0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e77ea9ea-20e5-4689-af38-a21489ffb9fd"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("47efe028-429d-4213-a86f-62a5c88e9cbf"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("025cf58c-b01a-4d27-ae0e-395c9b0f7e55"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("88a3c70e-cc58-4844-ae2c-4670784c2977"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("63994f0c-edb8-4ac4-9d06-3f433799dd1a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a167986f-164e-4e3b-876e-2113cba53d51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2a470650-ecb2-488d-a3ad-ea4afe51de29"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f0882a97-6eed-4800-830e-0ad60df76b56"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d5afb82e-2001-4ef7-87b0-b0a510919f6b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("79ed7453-80b7-499f-b9fd-41d5aa0c258c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bb0ae3a2-0dfd-41ae-898d-02fbc31636e8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7f176330-117a-4dd2-931f-eb0543818378"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0ac9e74e-34ae-48b2-af29-0646c443cc6d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("37bda3bc-88df-45e2-9cf5-5014df0df5c0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("209149dc-eb8d-4825-9ee1-9aea3d8a8371"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("961f7973-672b-4837-b16f-d0976ccd3d14"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d0908026-efc0-4226-95b7-340e03add727"));
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,786 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class DropUserPasswordHash : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PasswordHash",
table: "Users");
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("acbf0349-4cd7-4948-8d22-9219310c7a07"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4b1e0b1a-882e-4ae7-b803-386e1e61acb2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("15d15e2a-ab44-43e0-b3bf-ccaa35e3fb91"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c2343053-018d-4026-bf14-a135479ab631"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a77e8dd8-3092-49f7-bee9-aeaaa767e134"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4083847f-a4e8-43fd-92d1-27277a039efe"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b5ca40f7-369f-4430-b5e9-765c11bf6c13"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1d42928a-bec4-4b3c-b883-a119d783a613"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8adf4b1a-b698-458f-8a4d-d959829cc56e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a01bf160-9d5f-4f34-8973-769df6805e45"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b4457af3-480c-4955-bc52-14d153491cb1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a7f9799f-7543-4f04-9a1c-a3223798d99a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b44bce8a-2bcf-4a63-a9e8-f27d0f6c6e89"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5e75cbdd-6504-404e-a189-ec2f0bf8bfdd"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4e36584f-1037-47e0-85ed-697d1c1783f0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("eee22621-efb1-4d61-afb6-8d7fded31a16"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f587f5d1-9138-413a-aaa1-7dd56dcc981d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0bda014d-3942-4367-9293-6cbde6ac39a5"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a88ddd26-e0fa-4a13-8696-882af90fb4e4"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bd2a1844-8506-4f0b-bb0e-f20325d87bc0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("048ab71b-72d3-44b8-aea8-b05b4596d8bf"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("dbebf109-7413-425e-aaa8-5f58d2513d23"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1316245a-b4e0-4657-bdbf-8d8e257b26f9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("29bbdcca-19e6-4888-b43a-15cca7e3b4d2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("96796f8a-ce0a-47d7-9ba0-c1230bc588bb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("91994dc9-b18c-43d4-8cf1-47fe3f81ce7c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("71270de2-8615-4084-a379-11069d0ab05b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5f974740-5e83-4483-9a93-8db1d62a7bb0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2faed272-d596-44c7-a131-eb78d7fcc72f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("505fd8fb-3d1d-4ce0-8cf3-010e828a801b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("71ce7b4d-bff6-4ab1-97d4-1c11ae17f05e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7fcc357a-a68e-4966-bddb-3dfd02223ffa"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e77ec892-1a69-45d2-a9f5-11fd92b07b96"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a6b56c75-c110-4122-9ecc-65145bed96a1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("723bdc97-c6da-4950-adf3-77bee7e97405"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bf074feb-9bda-4244-8372-1abe67706060"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ed4592b7-e4a6-40bb-b846-6f0f42fedb0e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0428f07f-2a19-4cab-a61e-013356607a3e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cc6396f7-7a64-4af9-9e66-7ca9a642f615"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("17f53c09-0ff5-4491-86a8-9725b4dbc7cc"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7731cbca-d29e-41d0-85d1-7016b2a2f26f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c60ed0dd-eedf-4f15-accc-5913c182dd50"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4bffcc65-ec6d-4b8b-8613-b872bedf8399"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b6817e86-b3bf-4e87-882a-128dfa11c3dc"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a02e4ff9-b950-400b-b312-e0a59c5a6cf0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3563d851-8dda-4d6c-b33a-cb16a3538a51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bcd5a22a-0d6d-4fe6-a9d9-c179188f6a4c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("08376f57-d92c-411f-bcb9-d88bcb646e51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1dbe1273-2cc6-4d0e-b7d2-1c1e5b620935"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3927638d-2b9b-463f-907e-ec4ae5e30ad4"));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "PasswordHash",
table: "Users",
type: "longtext",
nullable: false)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2933abc2-b472-4870-8af7-a54a3adc4163"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d599d707-9645-4aad-8277-b492b2284eca"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("912132ef-5996-4a7f-acdf-e70a8aebec61"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3193b6b5-8656-41a5-88f1-264cda89dc38"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("33a3bace-319c-4394-a8ca-66f4983e8a65"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d67d727b-6bc6-437e-b52a-69bc6a78a009"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("03c210fa-f841-4262-96a8-d167bcca84de"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4949daa6-2136-400a-8b92-a0650ebd433d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("abd013d2-5d26-4e08-ab9c-506a8bd8a4fc"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f6ea9dbf-42ec-4fdf-b61a-5359f302e3de"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1a6d4dfe-32f5-4860-8c0c-3109f6dbdc56"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6387f234-eb63-43f1-8b20-1262cc646ef7"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bf6e1071-4c1e-45ba-ac90-54935832ab33"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2e009c83-d9be-41b1-9cfb-a720671f9531"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0a1c09c4-4851-4c03-a728-be2be77425cb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6d5cfd42-9ad3-4c6a-81c1-27c92fa70746"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cdd856de-60ba-431a-9c18-59368cf5f325"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("28ecd453-8762-4614-8c75-321017dc8338"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("697b6d8b-4d31-4e40-b8f2-46bc4c25e8c0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2648e7f7-34fe-4c86-99eb-f42fb0a92384"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5c19d416-b3c5-4b78-b80e-0ebdf2255d2f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e464f639-caa3-4425-867d-60acde28d6c7"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2cab1137-c04d-4c18-a1fd-d8124f22e884"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("08269d0d-a571-472b-be37-ff18235f30ef"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1823483d-ddfc-4350-a856-d2b320fc87e9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8c80626e-c979-46b5-8148-2cbec4f501d2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1f67a189-4f7a-4ff1-8041-5c84b85aa6aa"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fbac4979-75e8-4042-b5f2-adbbbe79b636"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("65594d44-edad-4d65-a3b8-a65724ad95ff"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b4ad27a0-a8a0-4240-b5ec-ea35741cf19f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("870ec304-5917-40c9-8d12-fae978878145"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6f6e106a-7b27-46fe-8adb-d21f0ad04062"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e32960f9-5a95-4c6f-be9d-85d59643bd62"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4fbb45f2-1826-4f4e-8846-a937f04fc9c6"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f051c92e-c893-4148-a0c4-987382532c3b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ed96284a-ed40-4521-91c5-6d757efc9ea4"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("34e8490d-a7ac-4940-bb92-b04c5f2d2a0f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cba2d7cb-7a88-4635-b059-0bb7da52aa5a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4e0efeeb-463b-48d7-835f-4337e5f8db1d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ded75a35-1149-4831-8980-a5552b8aba39"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5376fc5a-24df-4a10-ae8d-bf4a7cb41dce"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("736c95bf-4f53-46e7-b773-ad38ec3ddd8d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a08f24a4-f5c0-426c-a415-42c7823dae7a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1bfece31-2930-4a2f-beef-be08d3bfb95b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b04a9be1-cf18-4c25-9ea7-a71db0973fd1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6973c3f9-6578-4965-ada2-f257f0933c16"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7e191e49-0548-4943-8811-d53c3740d6ad"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b419616e-ccd8-4872-ba8d-10dc80482a85"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c0f12314-72e1-438b-b5f2-0b3aafa8ee40"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7357049c-1163-4dbf-afb4-44c77cdff207"));
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("00000001-0000-0000-0000-000000000001"),
column: "PasswordHash",
value: "N/A");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("29000000-0000-0000-0000-000000000001"),
column: "PasswordHash",
value: "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("29000000-0000-0000-0000-000000000002"),
column: "PasswordHash",
value: "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("29000000-0000-0000-0000-000000000003"),
column: "PasswordHash",
value: "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("29000000-0000-0000-0000-000000000004"),
column: "PasswordHash",
value: "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("29000000-0000-0000-0000-000000000005"),
column: "PasswordHash",
value: "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("29000000-0000-0000-0000-000000000006"),
column: "PasswordHash",
value: "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: new Guid("70000000-0000-0000-0000-000000000001"),
column: "PasswordHash",
value: "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==");
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,719 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Distribution.Migrations
{
/// <inheritdoc />
public partial class removepass : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("db785a23-5337-4fc8-b460-80c30b707d79"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b07b73f9-2c8b-4dff-af5c-42622b026321"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2e867ba5-2739-4ce4-b8d7-25b14ed392c1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("203d855d-f2d0-43d0-9d4f-9c4d0e8e7566"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("edd2a0ee-1ca9-47ff-9df6-7254929aef80"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("644b5ee5-f2c5-4187-a3d4-322cdd5c95d7"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("70fdf921-f3fd-4e66-bfd2-cb7bb156fa34"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e2de5341-4146-4c84-a584-8788774c14df"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ece07436-4a0b-435c-888b-a22c14612dc4"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b72f8737-7a21-48c0-809a-bc0d3fdd7063"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fe1efed0-271f-45e3-a58b-244f1115246f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1b58e809-e4a0-4108-af6e-fd0dac7b3163"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("881e8e67-e2ee-47be-94f7-77da73a05365"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e5d0baa8-9def-4b81-8727-5886b2906eaf"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a46ec771-5e79-4595-bb40-91e8a954a792"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ef8b1808-3b14-43a8-ba75-30551e643cc5"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("50142904-8d40-424b-aeb3-53e8cb110445"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4bd67f53-7f84-492c-83f9-fd6488fa88b7"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("d9a0eb59-600e-47e9-8e07-8b7bffc93f8b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e5a9d4da-9497-4e7e-8fb9-796927cbb510"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ffa29833-505e-4f56-9a4d-58f5df844af2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4e54994b-7ce1-4b99-aa98-de00c1d205fa"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f45b7352-f42a-4bb3-9d1e-d7cbe2665c0c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("27744965-334b-4da2-8a2d-5d7433d11b9d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cec1991b-ea93-45b0-b380-01cf0d36fc17"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("25675bb4-2ab5-437c-bee8-1b1ec1741736"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5fc66d40-1960-4028-af48-cf51a80bff04"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bd4e1740-a8b6-4a53-8633-a68c9858b3f5"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("9de97081-77d7-43c3-90b9-af3bc9d4bbef"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6ae05e16-95e5-4d43-bfa0-56991393d76f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("eb096aea-92c9-4556-ba4f-3084da223c7d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("6c9dac72-200a-46eb-b49e-699b1ca775b5"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8c8d0c74-40f6-4164-a6a7-6d2374ef162a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4a0d8cea-c33d-45a6-bd42-d8a51ce321c8"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a0ea0280-8e40-45bc-88e4-c3feb92e36d4"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("61da4c55-4f19-4ce4-bfc9-3fa9073365a2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("fbab8f2e-f224-42a0-be16-b7ea4e24eec5"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bcf7f883-e6c8-4a97-8a27-6814b0ed9144"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("13c01d81-198b-45cb-9de9-f25130e16313"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("667c3022-ea0d-4d1c-8ae4-b64e2f104295"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("78607299-2f5c-4edb-9143-c4a83395f731"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e53313fd-c6d4-4d52-827f-14cfd55401eb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c2521113-60f4-41fa-8ded-6b6a6b91a584"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("14532efd-d9f9-4a46-a7c3-fbfbe85a6f13"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("438bbd52-ee61-4afc-9d59-7d0407da4f1d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3e3d0cd9-f95e-4c1c-b829-cd02f1bad987"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("84daf87e-d3e1-4f4e-9a57-ec9996fff41d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ddcb8caf-106e-4072-b48e-a2542de51211"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("95d39d28-c5c7-4e82-87eb-40570db1c1f5"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b8e7b327-33c9-4420-b4d1-0071c58a5c95"));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000001"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("acbf0349-4cd7-4948-8d22-9219310c7a07"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000002"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4b1e0b1a-882e-4ae7-b803-386e1e61acb2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000003"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("15d15e2a-ab44-43e0-b3bf-ccaa35e3fb91"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000004"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c2343053-018d-4026-bf14-a135479ab631"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000005"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a77e8dd8-3092-49f7-bee9-aeaaa767e134"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000006"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4083847f-a4e8-43fd-92d1-27277a039efe"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000007"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b5ca40f7-369f-4430-b5e9-765c11bf6c13"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000008"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1d42928a-bec4-4b3c-b883-a119d783a613"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000009"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("8adf4b1a-b698-458f-8a4d-d959829cc56e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000010"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a01bf160-9d5f-4f34-8973-769df6805e45"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000011"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b4457af3-480c-4955-bc52-14d153491cb1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000012"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a7f9799f-7543-4f04-9a1c-a3223798d99a"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000013"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b44bce8a-2bcf-4a63-a9e8-f27d0f6c6e89"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000014"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5e75cbdd-6504-404e-a189-ec2f0bf8bfdd"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000015"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4e36584f-1037-47e0-85ed-697d1c1783f0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000016"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("eee22621-efb1-4d61-afb6-8d7fded31a16"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000017"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("f587f5d1-9138-413a-aaa1-7dd56dcc981d"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000018"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0bda014d-3942-4367-9293-6cbde6ac39a5"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000019"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a88ddd26-e0fa-4a13-8696-882af90fb4e4"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000020"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bd2a1844-8506-4f0b-bb0e-f20325d87bc0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000021"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("048ab71b-72d3-44b8-aea8-b05b4596d8bf"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000022"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("dbebf109-7413-425e-aaa8-5f58d2513d23"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000023"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1316245a-b4e0-4657-bdbf-8d8e257b26f9"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000024"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("29bbdcca-19e6-4888-b43a-15cca7e3b4d2"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000025"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("96796f8a-ce0a-47d7-9ba0-c1230bc588bb"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000026"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("91994dc9-b18c-43d4-8cf1-47fe3f81ce7c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000027"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("71270de2-8615-4084-a379-11069d0ab05b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000028"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("5f974740-5e83-4483-9a93-8db1d62a7bb0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000029"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("2faed272-d596-44c7-a131-eb78d7fcc72f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000030"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("505fd8fb-3d1d-4ce0-8cf3-010e828a801b"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000031"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("71ce7b4d-bff6-4ab1-97d4-1c11ae17f05e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000032"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7fcc357a-a68e-4966-bddb-3dfd02223ffa"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000033"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("e77ec892-1a69-45d2-a9f5-11fd92b07b96"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000034"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a6b56c75-c110-4122-9ecc-65145bed96a1"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000035"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("723bdc97-c6da-4950-adf3-77bee7e97405"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000036"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bf074feb-9bda-4244-8372-1abe67706060"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000037"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("ed4592b7-e4a6-40bb-b846-6f0f42fedb0e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000038"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("0428f07f-2a19-4cab-a61e-013356607a3e"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000039"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("cc6396f7-7a64-4af9-9e66-7ca9a642f615"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000040"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("17f53c09-0ff5-4491-86a8-9725b4dbc7cc"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000041"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("7731cbca-d29e-41d0-85d1-7016b2a2f26f"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000042"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("c60ed0dd-eedf-4f15-accc-5913c182dd50"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000043"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("4bffcc65-ec6d-4b8b-8613-b872bedf8399"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000044"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("b6817e86-b3bf-4e87-882a-128dfa11c3dc"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000045"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("a02e4ff9-b950-400b-b312-e0a59c5a6cf0"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000046"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3563d851-8dda-4d6c-b33a-cb16a3538a51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000047"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("bcd5a22a-0d6d-4fe6-a9d9-c179188f6a4c"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000048"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("08376f57-d92c-411f-bcb9-d88bcb646e51"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000049"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("1dbe1273-2cc6-4d0e-b7d2-1c1e5b620935"));
migrationBuilder.UpdateData(
table: "RolePermissions",
keyColumns: new[] { "FK_PermissionId", "FK_RoleId" },
keyValues: new object[] { new Guid("20000000-0000-0000-0000-000000000050"), new Guid("10000000-0000-0000-0000-000000000007") },
column: "Id",
value: new Guid("3927638d-2b9b-463f-907e-ec4ae5e30ad4"));
}
}
}
@@ -1193,6 +1193,408 @@ namespace Distribution.Migrations
b.HasKey("Id");
b.ToTable("Permissions");
b.HasData(
new
{
Id = new Guid("20000000-0000-0000-0000-000000000001"),
Code = "orders.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View shop POs, invoices, payments and returns",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000002"),
Code = "rides.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage delivery rides and delivery tasks",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000003"),
Code = "loading.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage loading sheets",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000004"),
Code = "stores.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View store accounts, credit limits and balances",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000005"),
Code = "sales_visits.checkin",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Check in and out of scheduled store visits",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000006"),
Code = "items.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage catalogue products",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000007"),
Code = "categories.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage product categories and brands",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000008"),
Code = "warehouses.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View stock balances, movements, warehouses and reports",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000009"),
Code = "purchase_orders.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage purchase orders, GRNs and supplier claims",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000010"),
Code = "pricelists.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage regional price lists",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000011"),
Code = "schemes.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage pricing schemes and promotions",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000012"),
Code = "suppliers.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage supplier accounts",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000013"),
Code = "driver_profiles.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage driver profiles and licensing",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000014"),
Code = "compliance.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Manage driver compliance rules",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000015"),
Code = "users.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage staff user accounts",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000016"),
Code = "roles.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage roles and their permission sets",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000017"),
Code = "regions.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage regions and region configuration",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000018"),
Code = "routes.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage delivery routes",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000019"),
Code = "vehicles.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View and manage fleet vehicles",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000020"),
Code = "claim.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View agency claims and settlement status",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000021"),
Code = "claim.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and settle agency claims",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000022"),
Code = "delivery-task.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View delivery tasks within a ride",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000023"),
Code = "delivery-task.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Confirm and fail delivery tasks",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000024"),
Code = "driver.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View driver profiles and license details",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000025"),
Code = "driver.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and update driver profiles",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000026"),
Code = "grn.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View goods receipt notes",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000027"),
Code = "grn.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and confirm goods receipts",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000028"),
Code = "loading-sheet.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View loading sheets and their items",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000029"),
Code = "loading-sheet.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create, edit, and confirm loading sheets",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000030"),
Code = "price-list.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View regional price lists",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000031"),
Code = "price-list.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and manage item price lists",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000032"),
Code = "purchase-order.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View purchase orders and line items",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000033"),
Code = "purchase-order.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create, confirm, and close purchase orders",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000034"),
Code = "purchase-return.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and manage purchase returns to suppliers",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000035"),
Code = "region.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View regions and their configuration",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000036"),
Code = "region.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and update regions, targets, and budgets",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000037"),
Code = "return.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View order returns",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000038"),
Code = "return.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and manage order returns",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000039"),
Code = "route.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View delivery routes",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000040"),
Code = "route.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and manage delivery routes",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000041"),
Code = "scheme.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View pricing schemes and promotions",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000042"),
Code = "scheme.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and configure pricing schemes",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000043"),
Code = "stock.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View stock balances and movements",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000044"),
Code = "stock.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Transfer stock and record damage or adjustments",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000045"),
Code = "store.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View store accounts and balances",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000046"),
Code = "store.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and update store accounts",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000047"),
Code = "supplier-claim.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View supplier claims",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000048"),
Code = "supplier-claim.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Create and resolve supplier claims",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000049"),
Code = "sys-config.view",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "View system configuration settings",
IsActive = true
},
new
{
Id = new Guid("20000000-0000-0000-0000-000000000050"),
Code = "sys-config.manage",
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Description = "Update system configuration settings",
IsActive = true
});
});
modelBuilder.Entity("Distribution.Models.PriceList", b =>
@@ -1787,6 +2189,14 @@ namespace Distribution.Migrations
IsActive = true,
Level = 60,
Name = "RegionalAgency"
},
new
{
Id = new Guid("10000000-0000-0000-0000-000000000007"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
IsActive = true,
Level = 100,
Name = "SuperAdmin"
});
});
@@ -1812,6 +2222,408 @@ namespace Distribution.Migrations
b.HasIndex("FK_PermissionId");
b.ToTable("RolePermissions");
b.HasData(
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000001"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("db785a23-5337-4fc8-b460-80c30b707d79"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000002"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("b07b73f9-2c8b-4dff-af5c-42622b026321"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000003"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("2e867ba5-2739-4ce4-b8d7-25b14ed392c1"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000004"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("203d855d-f2d0-43d0-9d4f-9c4d0e8e7566"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000005"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("edd2a0ee-1ca9-47ff-9df6-7254929aef80"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000006"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("644b5ee5-f2c5-4187-a3d4-322cdd5c95d7"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000007"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("70fdf921-f3fd-4e66-bfd2-cb7bb156fa34"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000008"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("e2de5341-4146-4c84-a584-8788774c14df"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000009"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("ece07436-4a0b-435c-888b-a22c14612dc4"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000010"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("b72f8737-7a21-48c0-809a-bc0d3fdd7063"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000011"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("fe1efed0-271f-45e3-a58b-244f1115246f"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000012"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("1b58e809-e4a0-4108-af6e-fd0dac7b3163"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000013"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("881e8e67-e2ee-47be-94f7-77da73a05365"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000014"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("e5d0baa8-9def-4b81-8727-5886b2906eaf"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000015"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("a46ec771-5e79-4595-bb40-91e8a954a792"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000016"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("ef8b1808-3b14-43a8-ba75-30551e643cc5"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000017"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("50142904-8d40-424b-aeb3-53e8cb110445"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000018"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("4bd67f53-7f84-492c-83f9-fd6488fa88b7"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000019"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("d9a0eb59-600e-47e9-8e07-8b7bffc93f8b"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000020"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("e5a9d4da-9497-4e7e-8fb9-796927cbb510"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000021"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("ffa29833-505e-4f56-9a4d-58f5df844af2"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000022"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("4e54994b-7ce1-4b99-aa98-de00c1d205fa"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000023"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("f45b7352-f42a-4bb3-9d1e-d7cbe2665c0c"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000024"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("27744965-334b-4da2-8a2d-5d7433d11b9d"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000025"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("cec1991b-ea93-45b0-b380-01cf0d36fc17"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000026"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("25675bb4-2ab5-437c-bee8-1b1ec1741736"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000027"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("5fc66d40-1960-4028-af48-cf51a80bff04"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000028"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("bd4e1740-a8b6-4a53-8633-a68c9858b3f5"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000029"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("9de97081-77d7-43c3-90b9-af3bc9d4bbef"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000030"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("6ae05e16-95e5-4d43-bfa0-56991393d76f"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000031"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("eb096aea-92c9-4556-ba4f-3084da223c7d"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000032"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("6c9dac72-200a-46eb-b49e-699b1ca775b5"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000033"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("8c8d0c74-40f6-4164-a6a7-6d2374ef162a"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000034"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("4a0d8cea-c33d-45a6-bd42-d8a51ce321c8"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000035"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("a0ea0280-8e40-45bc-88e4-c3feb92e36d4"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000036"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("61da4c55-4f19-4ce4-bfc9-3fa9073365a2"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000037"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("fbab8f2e-f224-42a0-be16-b7ea4e24eec5"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000038"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("bcf7f883-e6c8-4a97-8a27-6814b0ed9144"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000039"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("13c01d81-198b-45cb-9de9-f25130e16313"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000040"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("667c3022-ea0d-4d1c-8ae4-b64e2f104295"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000041"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("78607299-2f5c-4edb-9143-c4a83395f731"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000042"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("e53313fd-c6d4-4d52-827f-14cfd55401eb"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000043"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("c2521113-60f4-41fa-8ded-6b6a6b91a584"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000044"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("14532efd-d9f9-4a46-a7c3-fbfbe85a6f13"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000045"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("438bbd52-ee61-4afc-9d59-7d0407da4f1d"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000046"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("3e3d0cd9-f95e-4c1c-b829-cd02f1bad987"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000047"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("84daf87e-d3e1-4f4e-9a57-ec9996fff41d"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000048"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("ddcb8caf-106e-4072-b48e-a2542de51211"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000049"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("95d39d28-c5c7-4e82-87eb-40570db1c1f5"),
IsActive = true
},
new
{
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FK_PermissionId = new Guid("20000000-0000-0000-0000-000000000050"),
CreatedAt = new DateTime(2026, 8, 18, 0, 0, 0, 0, DateTimeKind.Unspecified),
Id = new Guid("b8e7b327-33c9-4420-b4d1-0071c58a5c95"),
IsActive = true
});
});
modelBuilder.Entity("Distribution.Models.Route", b =>
@@ -3157,10 +3969,6 @@ namespace Distribution.Migrations
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
@@ -3184,7 +3992,6 @@ namespace Distribution.Migrations
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000002"),
FullName = "Sunil Fernando",
IsActive = true,
PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==",
Username = "sunil.fernando"
},
new
@@ -3195,7 +4002,6 @@ namespace Distribution.Migrations
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FullName = "Nimal Perera",
IsActive = true,
PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==",
Username = "nimal.perera"
},
new
@@ -3206,7 +4012,6 @@ namespace Distribution.Migrations
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FullName = "Kamal Silva",
IsActive = true,
PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==",
Username = "kamal.silva"
},
new
@@ -3217,7 +4022,6 @@ namespace Distribution.Migrations
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FullName = "Ruwan Jayasuriya",
IsActive = true,
PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==",
Username = "ruwan.jayasuriya"
},
new
@@ -3228,7 +4032,6 @@ namespace Distribution.Migrations
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000001"),
FullName = "Priyantha Kumara",
IsActive = true,
PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==",
Username = "priyantha.kumara"
},
new
@@ -3238,7 +4041,6 @@ namespace Distribution.Migrations
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000005"),
FullName = "Priya Rajapaksa",
IsActive = true,
PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==",
Username = "priya.rajapaksa"
},
new
@@ -3248,8 +4050,16 @@ namespace Distribution.Migrations
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000006"),
FullName = "Channa De Silva",
IsActive = true,
PasswordHash = "AQAAAAIAAYagAAAAEKGnq/U4j6uM9g5mFkxbUE8WU/AhnSNiwrKCiPAqGnzNcaMgZAF5Zal/rJUUYPZPpg==",
Username = "channa.desilva"
},
new
{
Id = new Guid("00000001-0000-0000-0000-000000000001"),
CreatedAt = new DateTime(2026, 10, 13, 0, 0, 0, 0, DateTimeKind.Unspecified),
FK_RoleId = new Guid("10000000-0000-0000-0000-000000000007"),
FullName = "Super Admin",
IsActive = true,
Username = "superadmin"
});
});
-1
View File
@@ -5,7 +5,6 @@ namespace Distribution.Models
public class User : Template
{
public string Username { get; set; }
public string PasswordHash { get; set; }
public string FullName { get; set; }
public Guid FK_RoleId { get; set; }
+22 -16
View File
@@ -30,6 +30,7 @@ using Distribution.Features.Sync;
using Distribution.Features.Uom;
using Distribution.Features.User;
using Distribution.Features.Vehicle;
using Distribution.Features.DashboardReport;
using Distribution.Features.ProductReport;
using Distribution.Features.Stock;
using Distribution.Features.StockReport;
@@ -37,6 +38,9 @@ using Distribution.Features.SysConfig;
using Distribution.Features.Warehouse;
using Distribution.Infra.Authorization;
using Distribution.Infra.UoW;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
@@ -68,6 +72,8 @@ builder.Services.AddScoped<IItemRepository, ItemRepository>();
builder.Services.AddScoped<IStockRepository, StockRepository>();
builder.Services.AddScoped<IProductReportRepository, ProductReportRepository>();
builder.Services.AddScoped<ProductReportService>();
builder.Services.AddScoped<IDashboardReportRepository, DashboardReportRepository>();
builder.Services.AddScoped<DashboardReportService>();
builder.Services.AddScoped<IStockReportRepository, StockReportRepository>();
builder.Services.AddScoped<StockReportService>();
builder.Services.AddScoped<IDriverProfileRepository, DriverProfileRepository>();
@@ -123,6 +129,7 @@ builder.Services.AddScoped<DeliveryTaskService>();
builder.Services.AddScoped<PaymentService>();
builder.Services.AddScoped<SysConfigService>();
builder.Services.AddMemoryCache();
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<ICurrentUserService, CurrentUserService>();
builder.Services.AddHttpClient<IAuthHexClient, AuthHexClient>(client =>
@@ -134,29 +141,26 @@ builder.Services.AddScoped<IPermissionRepository, PermissionRepository>();
builder.Services.AddScoped<IScopeRepository, ScopeRepository>();
builder.Services.AddScoped<IPermissionService, PermissionService>();
builder.Services.AddScoped<IScopeAccessService, ScopeAccessService>();
// ── Auth Service connector ───────────────────────────────────────────────────
builder.Services.Configure<AuthServiceOptions>(
builder.Configuration.GetSection(AuthServiceOptions.SectionName));
var authServiceBaseUrl = builder.Configuration[$"{AuthServiceOptions.SectionName}:BaseUrl"];
builder.Services.AddHttpClient<AuthServiceClient>(client =>
{
if (!string.IsNullOrWhiteSpace(authServiceBaseUrl))
client.BaseAddress = new Uri(authServiceBaseUrl);
});
builder.Services.AddScoped<IAuthServiceClient, AuthServiceClient>();
builder.Services.AddAuthentication("Bearer")
.AddScheme<AuthenticationSchemeOptions, BearerResponseHandler>("Bearer", _ => { });
builder.Services.AddAuthorization();
builder.Services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
builder.Services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
var allowedOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>() ?? [];
builder.Services.AddCors(options =>
options.AddDefaultPolicy(policy =>
policy.WithOrigins(allowedOrigins)
.AllowAnyHeader()
.AllowAnyMethod()));
.AllowAnyMethod()
.AllowCredentials()));
builder.Services.AddControllers()
.AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
builder.Services.AddControllers(options =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();
@@ -173,6 +177,8 @@ if (app.Environment.IsDevelopment())
//app.UseHttpsRedirection();
app.UseCors();
app.UseMiddleware<AuthMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
+2 -2
View File
@@ -6,7 +6,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5089",
"applicationUrl": "http://localhost:8802",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@@ -16,7 +16,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7025;http://localhost:5089",
"applicationUrl": "https://localhost:7025;http://localhost:8802",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
+1 -1
View File
@@ -21,7 +21,7 @@
},
"AuthHex": {
"BaseUrl": "http://localhost:8801"
"BaseUrl": "http://localhost:6705"
},
"StoreManagement": {
"UnverifiedKycOrderThreshold": 0
+108 -94
View File
@@ -1,102 +1,116 @@
# Authentication — Own-User Auth via External Identity Service (AuthHex)
# Authentication & Authorization Layer
**Status**: Done
**Depends On**: — (cross-cutting infrastructure, not a numbered feature step)
## External Auth Service (AuthHex)
- Runs on `http://localhost:6703`
- Owns credentials — this app never stores passwords
- Issues RS256-signed JWTs with claims: `sub`, `role_id`, `role_level`, `username`, `role_code`
---
## Goal
Own-user (staff/API) authentication is delegated to an external identity service ("AuthHex"),
which owns credentials and signs RS256 JWTs. This app validates those tokens and maps them onto
its own `User`/`Role` tables so the existing permission-policy authorization stays unchanged.
---
## Background / Context
Previously this app verified passwords and minted its own HMAC-signed JWT locally. That's been
replaced — AuthHex now owns credentials and signing; this app only holds AuthHex's **public** key
to validate tokens, and never sees a plaintext password for this flow.
Authorization is untouched: permission policies, role levels, scope checks, and the seeded role
set all still work exactly as before, because every validated token is mapped back onto a local
`User`/`Role` row before any authorization check runs.
---
## Configuration Changes
```jsonc
"Jwt": {
"PublicKey": "<RSAKeyValue>...</RSAKeyValue>",
"Audience": "AuthHexClient",
"Issuer": "AuthHex"
},
"AuthHex": { "BaseUrl": "http://localhost:6102" }
```
`Jwt:Key` (old symmetric secret) is removed. `Jwt:PublicKey` is AuthHex's RSA public key in XML
format (not PEM).
---
## API Endpoints
| Method | Route | Notes |
|---|---|---|
| POST | /api/auth/login | Proxies to AuthHex `loginUser` |
| POST | /api/auth/register | Proxies to AuthHex `registerUser` |
| GET | /api/auth/me | `[Authorize]`, proxies to AuthHex `getUserDetails` |
| POST | /api/auth/logout | `[Authorize]`, proxies to AuthHex `LogoutUser` |
All four just forward to `POST {AuthHex:BaseUrl}/api/user` and pass AuthHex's response back
as-is. No cookie — token returned in the response body, sent back as `Authorization: Bearer`.
---
## Business Rules
1. No local password check or token issuance — both delegated to AuthHex.
2. `AddJwtBearer` validates issuer/audience/signature/lifetime against AuthHex's public key.
3. `OnTokenValidated` maps the token's `sub` claim to a local `User` (`IUserRepository`); fails
the token if no matching active user exists.
4. On success, `username`/`role_id`/`role_level` claims are attached from the **local** `User`/
`Role` row — authorization checks downstream are unaffected by anything AuthHex's own token
claims contain.
5. Only one validation mechanism runs (`AddJwtBearer`) — two ported alternatives exist but are not
registered (see Implementation Notes).
6. No refresh tokens — once the AuthHex-issued token expires, the client must log in again.
---
## Permissions to Add to Seed
None — this only changes authentication. Permission policies and role seed data are untouched.
---
## Open Questions
- Add a refresh-token flow if AuthHex doesn't offer one and re-login UX proves disruptive.
- Keep or delete the ported `AuthMiddleware`/`JwtMiddleware` if never actually needed.
- No retry/circuit-breaker if AuthHex is unreachable.
---
## Implementation Notes
## Directory Structure
```
Features/Auth/ — AuthController, AuthService, AuthDTOs (thin AuthHex proxies)
Infra/Authorization/
AuthHex/ — IAuthHexClient, AuthHexClient, AuthHexResponse
Jwt/RsaXmlKeyReader.cs — portable XML→RSA key parser (RSA.FromXmlString is Windows-only)
Middleware/ — AuthMiddleware, JwtMiddleware, JwtOptions, ApiResponse
(ported from OSMCore for reference — NOT registered)
Program.cs — AddHttpClient<IAuthHexClient>, AddJwtBearer + OnTokenValidated
(maps token → local User/Role → role_id/role_level claims)
Infra/
├── Auth/ External auth service integration
│ ├── AuthHexClient.cs HTTP proxy to AuthHex (/api/user)
│ ├── IAuthHexClient.cs
│ └── AuthHexResponse.cs Raw response shape from AuthHex
│
└── Authorization/ This app's permission enforcement
├── PermissionRequirement.cs ASP.NET Core requirement (wraps permission code string)
├── PermissionPolicyProvider.cs Builds policy dynamically for any "x.y" string
├── PermissionAuthorizationHandler.cs Evaluates requirement against DB
├── AuthorizationController.cs Exposes permission/scope check endpoints
├── CurrentUserService.cs Extracts typed claims from HttpContext.User
├── ICurrentUserService.cs
├── AuthorizationDTOs.cs
├── Permission/
│ ├── PermissionRepository.cs Queries RolePermissions + Permissions tables
│ ├── PermissionService.cs
│ ├── IPermissionRepository.cs
│ └── IPermissionService.cs
└── Scope/
├── ScopeRepository.cs Queries UserStoreScopes / UserRouteScopes / UserRegionScopes
├── ScopeAccessService.cs Resolves accessible stores via store → route → region hierarchy
├── IScopeRepository.cs
└── IScopeAccessService.cs
```
**Gotcha:** don't run more than one of `AddJwtBearer` / `AuthMiddleware` /
`JwtMiddleware.CustomMiddlewareAttribute` at once — each re-validates the same token
independently.
---
## Login Flow
```
POST /api/auth/login
→ AuthController
→ AuthService.LoginAsync
→ AuthHexClient.CallAsync("loginUser", ...)
→ POST http://localhost:6703/api/user
← RS256-signed JWT returned to client
```
---
## Request Flow
```
Incoming request with Authorization: Bearer <jwt>
│
▼
AuthMiddleware (Middleware/AuthMiddleware.cs)
- Reads Jwt:PublicKey from appsettings.json
- RSA.Create().FromXmlString(publicKeyXml)
- Validates JWT signature (RS256), issuer, audience, lifetime
- Sets HttpContext.User = principal (claims: sub, role_id, role_level, username)
│
▼
app.UseAuthorization()
- Global AuthorizeFilter: requires IsAuthenticated on every endpoint
- [Authorize("brand.view")] triggers PermissionPolicyProvider
→ builds AuthorizationPolicy with PermissionRequirement("brand.view")
→ PermissionAuthorizationHandler reads role_id claim
→ PermissionService.HasPermissionAsync(roleId, "brand.view")
→ DB: RolePermissions JOIN Permissions WHERE code = "brand.view"
│
▼
Controller
- ICurrentUserService.UserId / RoleId / RoleLevel extracted from HttpContext.User
- Scope guards: HasStoreScopeAsync / HasRouteScopeAsync / HasRegionScopeAsync
```
---
## Scope System
Scope controls which **records** a user can access (not just which actions).
| Assignment table | Access granted to |
|---|---|
| `UserStoreScopes` | Specific stores directly |
| `UserRouteScopes` | All stores on that route |
| `UserRegionScopes` | All routes → all stores in that region |
`ScopeAccessService.GetAccessibleStoreIdsAsync` merges all three levels and deduplicates.
---
## Pipeline Order (Program.cs)
```csharp
app.UseCors();
app.UseMiddleware<AuthMiddleware>(); // 1. populate HttpContext.User
app.UseAuthorization(); // 2. evaluate [Authorize] attributes
```
`UseAuthentication()` is intentionally absent — JWT validation is done manually in `AuthMiddleware`, not via ASP.NET Core's built-in bearer scheme.
---
## appsettings.json Keys
| Key | Purpose |
|---|---|
| `Jwt:PublicKey` | RSA XML public key from AuthHex (used by AuthMiddleware) |
| `Jwt:Issuer` | `AuthHex` |
| `Jwt:Audience` | `AuthHexClient` |
| `AuthHex:BaseUrl` | `http://localhost:6703` |
@@ -1,6 +1,6 @@
# Frontend API Reference — ERP Distribution (Post-Refactor)
> Last updated: 2026-09-17
> Last updated: 2026-10-13
> Base URL: `https://<host>/api`
> All responses are JSON. Enum fields are serialized as **strings** (e.g. `"Pending"`, `"ModeB"`).
> All `Guid` fields are UUID v4 strings. All `DateTime` fields are ISO 8601.
@@ -9,7 +9,8 @@
## Table of Contents
1. [Pagination](#pagination)
1. [Authentication](#authentication)
2. [Pagination](#pagination)
2. [Enums Reference](#enums-reference)
3. [ShopPO](#shoppo)
4. [Invoice](#invoice)
@@ -24,6 +25,146 @@
---
## Authentication
### Login
```http
POST /api/auth/login
Content-Type: application/json
{
"identifier": "string",
"password": "string",
"userTypeId": "uuid | null",
"deviceName": "string"
}
```
| Field | Type | Required | Notes |
|-------|------|----------|-------|
| `identifier` | `string` | Yes | Username or email |
| `password` | `string` | Yes | |
| `userTypeId` | `Guid?` | No | Scopes login to a specific user type |
| `deviceName` | `string` | No | Defaults to `"Unknown Device"` |
**Response:** AuthHex response. On success, the server also sets an **HttpOnly** cookie `access-token` containing the JWT (expiry driven by the `expiresIn` field, defaulting to 1 hour).
```json
{
"statusCode": 200,
"success": true,
"message": null,
"data": {
"accessToken": "<jwt>",
"expiresIn": 3600
}
}
```
### Using the Token
The server sets the JWT as an `HttpOnly` cookie (`access-token`) on login. For browser clients the cookie is sent automatically on every same-origin request — no manual token handling is needed.
For non-browser clients (or cross-origin requests with `withCredentials: true`), include the JWT explicitly:
```http
Authorization: Bearer <jwt>
```
The middleware accepts either the `Authorization: Bearer` header **or** the `access-token` cookie, preferring the header.
### Register
```http
POST /api/auth/register
Content-Type: application/json
{
"username": "string",
"password": "string"
}
```
### Get Current User
```http
GET /api/auth/me
Authorization: Bearer <jwt>
```
**Response:**
```json
{
"userId": "uuid",
"username": "string",
"roleId": "uuid",
"roleCode": "string",
"roleLevel": 0
}
```
### Logout
```http
POST /api/auth/logout
```
Deletes the `access-token` cookie server-side. No request body required.
**Response:**
```json
{ "success": true }
```
> **Note:** Logout only clears the cookie on this server. The JWT itself is not invalidated at AuthHex — it remains valid until it expires.
### Error Responses
| Status | Meaning |
|--------|---------|
| `401` | No token supplied, token invalid, or token expired |
| `403` | Token is valid but the user's role does not have the required permission |
### Permission Check (optional)
The frontend can check whether the current user holds a specific permission before rendering UI elements:
```http
GET /api/authorization/permissions/{permissionCode}
Authorization: Bearer <jwt>
```
**Response:**
```json
{ "hasPermission": true }
```
Common permission codes: `brand.view`, `stock.manage`, `ride.view`, `loading-sheet.manage`, etc.
### Scope Check (optional)
Check whether the user has data-access scope over a specific resource:
```http
GET /api/authorization/scopes/stores/{storeId}
GET /api/authorization/scopes/routes/{routeId}
GET /api/authorization/scopes/regions/{regionId}
GET /api/authorization/scopes/stores
```
Single-resource checks (`/stores/{id}`, `/routes/{id}`, `/regions/{id}`) return:
```json
{ "hasScope": true }
```
`GET /api/authorization/scopes/stores` returns all store IDs the current user can access:
```json
{ "storeIds": ["uuid", "uuid"] }
```
---
## Pagination
All list endpoints return a `PagedResponse<T>`:
+193 -6
View File
@@ -1,14 +1,201 @@
'use client'
import { useState, useEffect, type FormEvent } from 'react'
import { Eye, EyeOff } from 'lucide-react'
import { useRouter } from 'next/navigation'
import Image from 'next/image'
import { Space_Grotesk } from 'next/font/google'
import { useAuth } from '@/contexts/auth-context'
import { getApiError } from '@/lib/api'
import { toast } from '@/components/ui/toast'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Button } from '@/components/ui/button'
const sg = Space_Grotesk({ subsets: ['latin'], weight: ['400', '500', '600', '700'] })
export default function LoginPage() {
const { login, user, loading } = useAuth()
const router = useRouter()
const [identifier, setIdentifier] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState<string | null>(null)
const [submitting, setSubmitting] = useState(false)
const [showPassword, setShowPassword] = useState(false)
useEffect(() => {
if (!loading && user) router.replace('/')
}, [user, loading, router])
async function handleSubmit(e: FormEvent) {
e.preventDefault()
setError(null)
setSubmitting(true)
try {
await login(identifier, password)
toast.add({ title: 'Signed in successfully', type: 'success' })
} catch (err) {
const message = getApiError(err)
setError(message)
toast.add({ title: 'Sign in failed', description: message, type: 'error' })
} finally {
setSubmitting(false)
}
}
return (
<div className="flex min-h-svh items-center justify-center bg-background">
<div className="flex w-full max-w-sm flex-col gap-6 p-6">
<div className="flex flex-col gap-1 text-center">
<h1 className="text-2xl font-semibold text-foreground">Sign in</h1>
<p className="text-sm text-muted-foreground">
Authentication will be wired up once the backend is ready.
<div className={`${sg.className} min-h-svh flex flex-col md:flex-row`}>
{/* ── Left panel: image (hidden on mobile, 60% on desktop) ── */}
<div className="relative hidden md:flex md:w-[60%] shrink-0 flex-col">
<Image
src="/HexaDistribution.png"
alt="Distribution warehouse"
fill
sizes="60vw"
className="object-cover object-center"
priority
unoptimized
/>
{/* Logo overlay top-left */}
<div className="relative z-10 px-10 pt-9">
<div className="flex items-center gap-2.5">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://hexdive.com/_next/image?url=%2F2.png&w=256&q=75"
alt="HexDive"
className="h-7 w-auto object-contain"
/>
<span className="font-bold text-[15px] tracking-wide text-black">
HexaDistro
</span>
</div>
</div>
{/* Gradient at bottom */}
<div
className="absolute inset-0"
style={{ background: 'linear-gradient(to top, rgba(0,0,0,0.65) 0%, rgba(0,0,0,0.2) 40%, transparent 70%)' }}
/>
{/* Text content pinned to bottom-left */}
<div className="relative z-10 mt-auto px-12 pb-12">
<h1
className="font-bold leading-tight mb-3"
style={{ fontSize: 'clamp(28px, 3vw, 46px)', color: '#ffffff' }}
>
Your operations.<br />
<span
className="inline-block px-2.5 py-1 mt-1 rounded-sm"
style={{ backgroundColor: '#1A1033', color: '#ffffff' }}
>
Fully in control.
</span>
</h1>
<p style={{ color: 'rgba(255,255,255,0.72)', fontSize: 15, lineHeight: 1.65, maxWidth: 380 }}>
Distribution ERP built for teams that deliver right, every time.
</p>
</div>
</div>
{/* ── Right panel: login card ── */}
<div className="flex-1 bg-white flex flex-col items-center justify-center px-6 py-10 sm:px-10">
{/* Mobile-only logo */}
<div className="flex items-center gap-2.5 mb-8 md:hidden">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://hexdive.com/_next/image?url=%2F2.png&w=256&q=75"
alt="HexDive"
className="h-7 w-auto object-contain"
/>
<span className="font-bold text-[14px] tracking-widest uppercase text-gray-900">
HexaDistro
</span>
</div>
<div
className="w-full rounded-2xl bg-white px-6 py-8 sm:px-10 sm:py-11"
style={{
maxWidth: 440,
boxShadow: '0 8px 40px rgba(0,0,0,0.12)',
}}
>
{/* Logo — desktop only inside card */}
<div className="hidden md:flex items-center gap-2.5 mb-8">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="https://hexdive.com/_next/image?url=%2F2.png&w=256&q=75"
alt="HexDive"
className="h-7 w-auto object-contain"
/>
<span className="font-bold text-[14px] tracking-widest uppercase text-gray-900">
HexaDistro
</span>
</div>
{/* Heading */}
<h1 className="text-3xl font-semibold text-gray-900 mb-1">Sign in</h1>
<p className="text-sm text-gray-500 mb-8">
Enter your credentials to access your account.
</p>
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
<div className="flex flex-col gap-1.5">
<Label htmlFor="identifier" className="text-gray-700">
Username or Email
</Label>
<Input
id="identifier"
type="text"
autoComplete="username"
required
value={identifier}
onChange={e => setIdentifier(e.target.value)}
className="border-gray-300 bg-white text-gray-900 placeholder:text-gray-400"
/>
</div>
<div className="flex flex-col gap-1.5">
<Label htmlFor="password" className="text-gray-700">
Password
</Label>
<div className="relative">
<Input
id="password"
type={showPassword ? 'text' : 'password'}
autoComplete="current-password"
required
value={password}
onChange={e => setPassword(e.target.value)}
className="border-gray-300 bg-white text-gray-900 placeholder:text-gray-400 pr-10"
/>
<button
type="button"
onClick={() => setShowPassword(v => !v)}
className="absolute inset-y-0 right-2.5 flex items-center text-gray-400 hover:text-gray-600"
tabIndex={-1}
aria-label={showPassword ? 'Hide password' : 'Show password'}
>
{showPassword ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
</div>
</div>
{error && (
<p className="text-sm text-destructive">{error}</p>
)}
<Button type="submit" disabled={submitting} className="w-full mt-2">
{submitting ? 'Signing in…' : 'Sign In'}
</Button>
</form>
</div>
</div>
</div>
)
}
@@ -0,0 +1,352 @@
'use client'
import { useEffect, useState, type ReactNode } from 'react'
import { Skeleton } from '@/components/ui/skeleton'
import { toast } from '@/components/ui/toast'
import { dashboardReports, productReports, stockReports, getApiError, getPaginatedItems } from '@/lib/api/index'
import type { DashboardInventorySummary, DashboardSalesSummary, ProductSalesRow, SalesKpis, StockOverview } from '@/lib/api/reports'
import { DonutChart, MultiAreaChart, seriesColor } from './dashboard-charts'
export interface DateRange {
from: string // yyyy-MM-dd
to: string
}
const fmtMoney = (v: number) => `Rs. ${v.toLocaleString('en-LK', { maximumFractionDigits: 0 })}`
const fmtNum = (v: number) => v.toLocaleString('en-LK', { maximumFractionDigits: 2 })
function ChartCard({ title, note, children, className = '' }: { title: string; note?: string; children: ReactNode; className?: string }) {
return (
<div className={`flex h-full flex-col rounded-xl border bg-card p-3 shadow-xs transition-shadow hover:shadow-md ${className}`}>
<div className="mb-1.5">
<div className="flex items-center gap-1.5 text-sm font-semibold text-foreground">
<span className="h-3.5 w-1 rounded-full bg-primary" />
{title}
</div>
{note && <div className="mt-0.5 text-[11px] text-muted-foreground">{note}</div>}
</div>
<div className="h-52 min-h-0">{children}</div>
</div>
)
}
function Delta({ current, previous }: { current: number; previous: number }) {
if (previous === 0) return <span className="text-[10px] text-muted-foreground">No previous-period data</span>
const pct = ((current - previous) / Math.abs(previous)) * 100
const up = pct >= 0
return (
<span className="inline-flex items-center gap-1">
<span className={`rounded-full px-1.5 py-px text-[10px] font-semibold ${up ? 'bg-foreground/10 text-foreground' : 'bg-destructive/10 text-destructive'}`}>
{up ? '▲' : '▼'} {Math.abs(pct).toFixed(1)}%
</span>
<span className="text-muted-foreground">vs prev.</span>
</span>
)
}
function Kpi({ title, value, footer }: { title: string; value: string; footer?: ReactNode }) {
return (
<div className="relative flex h-[76px] flex-col justify-between overflow-hidden rounded-xl border bg-card px-3 py-2 shadow-xs transition-shadow hover:shadow-md">
<div>
<div className="truncate text-[11px] font-medium text-muted-foreground">{title}</div>
<div className="truncate text-lg font-bold leading-tight text-foreground">{value}</div>
</div>
{footer && <div className="truncate text-[10px] leading-tight">{footer}</div>}
</div>
)
}
function LoadingGrid() {
return (
<div className="flex flex-col gap-3" aria-busy="true">
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 xl:grid-cols-6">
{Array.from({ length: 6 }).map((_, i) => <Skeleton key={i} className="h-[76px] rounded-xl" />)}
</div>
<div className="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
{Array.from({ length: 6 }).map((_, i) => (
<Skeleton key={i} className={`h-[262px] rounded-xl ${i % 3 === 0 ? 'md:col-span-2' : ''}`} />
))}
</div>
</div>
)
}
function useLoad<T>(load: () => Promise<T>, deps: unknown[], failTitle: string) {
const key = JSON.stringify(deps)
const [result, setResult] = useState<{ key: string; data: T | null } | null>(null)
useEffect(() => {
let cancelled = false
load()
.then(data => { if (!cancelled) setResult({ key, data }) })
.catch(err => {
if (cancelled) return
toast.add({ title: failTitle, description: getApiError(err), type: 'error' })
setResult({ key, data: null })
})
return () => { cancelled = true }
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [key])
// Loading until the response for the *current* deps has arrived, so a changed range shows the skeleton again.
return { data: result?.key === key ? result.data : null, loading: result?.key !== key }
}
function Empty({ text }: { text: string }) {
return <p className="py-6 text-center text-xs text-muted-foreground">{text}</p>
}
/** Ranked list with an inline share bar — friendlier than a bar chart for "top N" comparisons. */
function RankTable({ rows, fmt, empty, barClass = 'bg-primary' }: {
rows: Array<{ name: string; value: number; extra?: string }>
fmt: (v: number) => string
empty: string
barClass?: string
}) {
if (rows.length === 0 || rows.every(r => r.value === 0)) return <Empty text={empty} />
const max = Math.max(...rows.map(r => r.value), 1)
return (
<div className="h-full overflow-auto pr-1">
<table className="w-full text-xs">
<tbody>
{rows.map((r, i) => (
<tr key={`${r.name}-${i}`} className="border-b border-muted last:border-0">
<td className="w-5 py-1.5 text-[10px] font-semibold text-muted-foreground">{i + 1}</td>
<td className="max-w-0 truncate py-1.5 pr-2 font-medium text-foreground" title={r.name}>
<div className="truncate">{r.name}</div>
<div className="mt-1 h-1 overflow-hidden rounded-full bg-muted">
<div className={`h-full rounded-full ${barClass}`} style={{ width: `${(r.value / max) * 100}%` }} />
</div>
</td>
<td className="whitespace-nowrap py-1.5 pl-1 text-right font-semibold tabular-nums text-foreground">
{fmt(r.value)}
{r.extra && <div className="text-[10px] font-normal text-muted-foreground">{r.extra}</div>}
</td>
</tr>
))}
</tbody>
</table>
</div>
)
}
function DataTable({ cols, rows, empty }: { cols: string[]; rows: ReactNode[][]; empty: string }) {
if (rows.length === 0) return <Empty text={empty} />
return (
<div className="h-full overflow-auto">
<table className="w-full text-xs">
<thead className="sticky top-0 bg-card">
<tr className="border-b text-[10px] uppercase tracking-wide text-muted-foreground">
{cols.map((c, i) => <th key={c} className={`py-1.5 font-semibold ${i === 0 ? 'text-left' : 'text-right'}`}>{c}</th>)}
</tr>
</thead>
<tbody>
{rows.map((r, ri) => (
<tr key={ri} className="border-b border-muted last:border-0 hover:bg-muted/40">
{r.map((cell, ci) => (
<td key={ci} className={`py-1.5 tabular-nums ${ci === 0 ? 'max-w-0 truncate pr-2 text-left font-medium text-foreground' : 'text-right text-muted-foreground'}`}>{cell}</td>
))}
</tr>
))}
</tbody>
</table>
</div>
)
}
const named = (rows: Array<{ name: string; amount: number }>) => rows.map(r => ({ name: r.name, value: r.amount }))
/** Top (n-1) slices plus an "Other" slice, so donuts stay readable. */
function topWithOther(rows: Array<{ name: string; value: number }>, n = 5) {
const sorted = [...rows].filter(r => r.value > 0).sort((a, b) => b.value - a.value)
if (sorted.length <= n) return sorted
const head = sorted.slice(0, n - 1)
return [...head, { name: 'Other', value: sorted.slice(n - 1).reduce((t, r) => t + r.value, 0) }]
}
const sharePct = (v: number, total: number) => (total > 0 ? `${((v / total) * 100).toFixed(1)}%` : '—')
export function SalesSection({ range }: { range: DateRange }) {
const { data: sales, loading } = useLoad<DashboardSalesSummary>(
() => dashboardReports.sales(range), [range.from, range.to], 'Failed to load sales analytics')
const { data: products, loading: productsLoading } = useLoad<ProductSalesRow[]>(
() => productReports.sales({ ...range, pageSize: 10 }).then(r => getPaginatedItems(r)),
[range.from, range.to], 'Failed to load product sales')
if (loading || productsLoading || !sales) return <LoadingGrid />
const { current: c, previous: p } = sales.kpis
const kpi = (title: string, key: keyof SalesKpis, money = true) => (
<Kpi
title={title}
value={money ? fmtMoney(c[key] as number) : fmtNum(c[key] as number)}
footer={<Delta current={c[key] as number} previous={p[key] as number} />}
/>
)
const trend = sales.trend.map(t => ({ period: t.period, sales: t.sales, returns: t.returns }))
const regionTotal = sales.byRegion.reduce((t, r) => t + r.amount, 0)
const repTotal = sales.byRep.reduce((t, r) => t + r.amount, 0)
return (
<div className="flex flex-col gap-3">
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 xl:grid-cols-6">
{kpi('Net Sales', 'netSales')}
{kpi('Gross Sales', 'grossSales')}
{kpi('Total Orders', 'orders', false)}
{kpi('Average Order Value', 'averageOrderValue')}
<Kpi
title="Gross Profit"
value={fmtMoney(c.grossProfit)}
footer={
<span className="text-[10px] text-muted-foreground">
{c.grossProfitMarginPercent === null ? 'Margin n/a (no cost prices)' : `${c.grossProfitMarginPercent}% margin`}
</span>
}
/>
{kpi('Sales Returns', 'returnValue')}
</div>
<p className="text-[11px] text-muted-foreground">
Sales = fulfilled lines on non-cancelled orders with a finalized invoice, dated by finalization. Net = gross − customer returns.
Gross profit uses item cost prices and covers only items that have one. Discounts and sales targets are not tracked per order yet.
</p>
<div className="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
<ChartCard title="Sales Trend" note={`Gross sales per ${sales.granularity}`} className="md:col-span-2">
<MultiAreaChart data={trend} series={[{ key: 'sales', label: 'Sales', color: seriesColor(0) }]} emptyText="No sales in this period." />
</ChartCard>
<ChartCard title="Sales by Category" note="Share of gross sales">
<DonutChart data={topWithOther(named(sales.byCategory))} centerLabel="Rs." emptyText="No sales in this period." />
</ChartCard>
<ChartCard title="Top-Selling Products" note="Top 10 by sales value" className="md:col-span-2">
<DataTable
cols={['Product', 'Qty', 'Sales', 'Margin']}
empty="No product sales in this period."
rows={(products ?? []).map(r => [
r.name,
fmtNum(r.qtyFulfilled),
fmtMoney(r.salesValue),
r.marginPercent === null ? '—' : (
<span className={r.marginPercent >= 0 ? 'text-emerald-600 dark:text-emerald-400' : 'text-destructive'}>{r.marginPercent}%</span>
),
])}
/>
</ChartCard>
<ChartCard title="Sales by Region">
<RankTable rows={sales.byRegion.map(r => ({ name: r.name, value: r.amount, extra: sharePct(r.amount, regionTotal) }))} fmt={fmtMoney} empty="No sales in this period." />
</ChartCard>
<ChartCard title="Sales vs Returns" note={`Per ${sales.granularity}`} className="md:col-span-2">
<MultiAreaChart
data={trend}
series={[{ key: 'sales', label: 'Sales', color: seriesColor(0) }, { key: 'returns', label: 'Returns', color: '#f87171' }]}
emptyText="No sales or returns in this period."
/>
</ChartCard>
<ChartCard title="Sales by Representative" note="Top 20; rep = user who raised the order">
<RankTable rows={sales.byRep.map(r => ({ name: r.name, value: r.amount, extra: sharePct(r.amount, repTotal) }))} fmt={fmtMoney} empty="No sales in this period." />
</ChartCard>
</div>
</div>
)
}
export function InventorySection({ range }: { range: DateRange }) {
const { data: inv, loading } = useLoad<DashboardInventorySummary>(
() => dashboardReports.inventory(range), [range.from, range.to], 'Failed to load inventory analytics')
const { data: overview } = useLoad<StockOverview>(
() => stockReports.overview(), [], 'Failed to load stock overview')
const { data: lowStock } = useLoad(
() => productReports.stock({ lowStockOnly: true, pageSize: 50 }).then(r => getPaginatedItems(r)),
[], 'Failed to load low-stock products')
const { data: movers, loading: moversLoading } = useLoad<ProductSalesRow[]>(
() => productReports.sales({ ...range, pageSize: 50 }).then(r => getPaginatedItems(r)),
[range.from, range.to], 'Failed to load product sales')
if (loading || moversLoading || !inv || !overview) return <LoadingGrid />
const healthy = Math.max(0, overview.totalSkus - overview.lowStockCount - overview.outOfStockCount)
const sold = (movers ?? []).map(r => ({ name: r.name, value: r.qtyFulfilled }))
const fast = sold.slice(0, 3)
const slow = sold.slice(-3).reverse()
const catTotal = inv.valueByCategory.reduce((t, r) => t + r.value, 0)
const lowRows = (lowStock ?? [])
.filter(r => r.reorderLevel)
.sort((a, b) => a.warehouseQty / (a.reorderLevel ?? 1) - b.warehouseQty / (b.reorderLevel ?? 1))
.slice(0, 10)
return (
<div className="flex flex-col gap-3">
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 xl:grid-cols-6">
<Kpi title="Active Products" value={fmtNum(overview.totalSkus)} />
<Kpi title="Stock on Hand" value={fmtNum(overview.totalQty)} />
<Kpi title="Inventory Value" value={fmtMoney(overview.totalValue)} footer={<span className="text-[10px] text-muted-foreground">At cost price</span>} />
<Kpi title="Low-Stock Products" value={fmtNum(overview.lowStockCount)} />
<Kpi title="Out-of-Stock Products" value={fmtNum(overview.outOfStockCount)} />
<Kpi title="Expiring Soon (30 days)" value={fmtNum(overview.expiringSoonCount)} footer={<span className="text-[10px] text-muted-foreground">Batches · {fmtNum(overview.expiredCount)} already expired</span>} />
</div>
<p className="text-[11px] text-muted-foreground">
Reserved stock, excess stock, ageing, discrepancies and pending transfers are not tracked yet, so they are not shown.
</p>
<div className="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3">
<ChartCard title="Stock Movement Trend" note={`Quantity per ${inv.granularity}. Received = purchases + customer returns; issued = sales + purchase returns + damages`} className="md:col-span-2">
<MultiAreaChart
data={inv.movementTrend}
series={[{ key: 'received', label: 'Received', color: seriesColor(0) }, { key: 'issued', label: 'Issued', color: seriesColor(1) }]}
emptyText="No stock movements in this period."
/>
</ChartCard>
<ChartCard title="Stock Health" note="Active products">
<DonutChart
data={[
{ name: 'Healthy', value: healthy },
{ name: 'Low stock', value: overview.lowStockCount },
{ name: 'Out of stock', value: overview.outOfStockCount },
]}
centerLabel="products"
emptyText="No active products."
/>
</ChartCard>
<ChartCard title="Warehouse Stock" note="Quantity and value at cost price" className="md:col-span-2">
<DataTable
cols={['Warehouse', 'Quantity', 'Value']}
empty="No warehouse stock recorded."
rows={inv.byWarehouse.map(r => [r.name, fmtNum(r.quantity), fmtMoney(r.value)])}
/>
</ChartCard>
<ChartCard title="Inventory Value by Category" note="At cost price">
<RankTable
rows={inv.valueByCategory.map(r => ({ name: r.category, value: r.value, extra: sharePct(r.value, catTotal) }))}
fmt={fmtMoney} empty="No stock recorded."
/>
</ChartCard>
<ChartCard title="Low-Stock Products" note="Lowest coverage of reorder level first" className="md:col-span-2">
<DataTable
cols={['Product', 'On hand', 'Reorder at', 'Coverage']}
empty="No products below their reorder level."
rows={lowRows.map(r => {
const cov = Math.round((r.warehouseQty / (r.reorderLevel ?? 1)) * 100)
return [
r.name,
fmtNum(r.warehouseQty),
fmtNum(r.reorderLevel ?? 0),
<span key="c" className={`rounded-full px-1.5 py-px text-[10px] font-semibold ${cov < 50 ? 'bg-destructive/10 text-destructive' : 'bg-muted text-muted-foreground'}`}>{cov}%</span>,
]
})}
/>
</ChartCard>
<ChartCard title="Fast & Slow Movers" note="Top and bottom 3 by quantity sold (among top 50 sellers)">
<div className="flex h-full flex-col gap-1 overflow-auto">
<div className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">Fast-moving</div>
<RankTable rows={fast} fmt={fmtNum} empty="No sales in this period." />
<div className="mt-1 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">Slow-moving</div>
<RankTable rows={slow} fmt={fmtNum} empty="No sales in this period." />
</div>
</ChartCard>
</div>
</div>
)
}
@@ -1,6 +1,6 @@
'use client'
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, Label, PolarAngleAxis, Pie, PieChart, RadialBar, RadialBarChart, XAxis, YAxis } from 'recharts'
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, Label, Line, LineChart, PolarAngleAxis, Pie, PieChart, RadialBar, RadialBarChart, XAxis, YAxis } from 'recharts'
import {
ChartContainer,
@@ -60,10 +60,10 @@ export function DonutChart({ data, centerLabel, emptyText }: { data: ChartDatum[
)
}
export function HorizontalBarChart({ data, emptyText, color = 'var(--chart-2)' }: { data: ChartDatum[]; emptyText: string; color?: string }) {
export function HorizontalBarChart({ data, emptyText, color = 'var(--chart-2)', label = 'Quantity' }: { data: ChartDatum[]; emptyText: string; color?: string; label?: string }) {
if (data.length === 0 || data.every(d => d.value === 0)) return <Empty text={emptyText} />
const config = { value: { label: 'Quantity', color } } satisfies ChartConfig
const config = { value: { label, color } } satisfies ChartConfig
return (
<ChartContainer config={config} className="h-full min-h-40 w-full">
@@ -140,3 +140,83 @@ export function RadialGauge({ pct, label, sub }: { pct: number; label: string; s
</div>
)
}
export interface SeriesDef {
key: string
label: string
color: string
}
const SERIES_COLORS = ['var(--chart-2)', 'var(--chart-4)', 'var(--chart-1)']
export const seriesColor = (i: number) => SERIES_COLORS[i % SERIES_COLORS.length]
/** Multi-series line chart over a categorical x axis (day or month labels). */
export function MultiLineChart({ data, series, emptyText }: { data: Array<Record<string, string | number>>; series: SeriesDef[]; emptyText: string }) {
if (data.length === 0) return <Empty text={emptyText} />
const config = Object.fromEntries(series.map(s => [s.key, { label: s.label, color: s.color }])) as ChartConfig
return (
<ChartContainer config={config} className="h-full min-h-48 w-full">
<LineChart data={data}>
<CartesianGrid vertical={false} />
<XAxis dataKey="period" tickLine={false} axisLine={false} minTickGap={24} tick={{ fontSize: 10 }} />
<YAxis tickFormatter={fmtCompact} tickLine={false} axisLine={false} width={48} />
<ChartTooltip content={<ChartTooltipContent />} />
{series.map(s => (
<Line key={s.key} dataKey={s.key} type="monotone" stroke={`var(--color-${s.key})`} strokeWidth={2} dot={false} />
))}
<ChartLegend content={<ChartLegendContent />} />
</LineChart>
</ChartContainer>
)
}
/** Grouped (side-by-side) column chart comparing several series per category. */
export function GroupedColumnChart({ data, series, emptyText }: { data: Array<Record<string, string | number>>; series: SeriesDef[]; emptyText: string }) {
if (data.length === 0) return <Empty text={emptyText} />
const config = Object.fromEntries(series.map(s => [s.key, { label: s.label, color: s.color }])) as ChartConfig
return (
<ChartContainer config={config} className="h-full min-h-48 w-full">
<BarChart data={data}>
<CartesianGrid vertical={false} />
<XAxis dataKey="period" tickLine={false} axisLine={false} minTickGap={16} tick={{ fontSize: 10 }} />
<YAxis tickFormatter={fmtCompact} tickLine={false} axisLine={false} width={48} />
<ChartTooltip content={<ChartTooltipContent />} />
{series.map(s => (
<Bar key={s.key} dataKey={s.key} fill={`var(--color-${s.key})`} radius={3} maxBarSize={24} />
))}
<ChartLegend content={<ChartLegendContent />} />
</BarChart>
</ChartContainer>
)
}
/** Multi-series smooth area chart with a soft gradient under each line. */
export function MultiAreaChart({ data, series, emptyText }: { data: Array<Record<string, string | number>>; series: SeriesDef[]; emptyText: string }) {
if (data.length === 0) return <Empty text={emptyText} />
const config = Object.fromEntries(series.map(s => [s.key, { label: s.label, color: s.color }])) as ChartConfig
return (
<ChartContainer config={config} className="h-full min-h-40 w-full">
<AreaChart data={data}>
<defs>
{series.map(s => (
<linearGradient key={s.key} id={`area-${s.key}`} x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={`var(--color-${s.key})`} stopOpacity={0.45} />
<stop offset="95%" stopColor={`var(--color-${s.key})`} stopOpacity={0.03} />
</linearGradient>
))}
</defs>
<CartesianGrid vertical={false} strokeDasharray="3 3" />
<XAxis dataKey="period" tickLine={false} axisLine={false} minTickGap={24} tick={{ fontSize: 10 }} />
<YAxis tickFormatter={fmtCompact} tickLine={false} axisLine={false} width={44} tick={{ fontSize: 10 }} />
<ChartTooltip content={<ChartTooltipContent />} />
{series.map(s => (
<Area key={s.key} dataKey={s.key} type="monotone" stroke={`var(--color-${s.key})`} strokeWidth={2} fill={`url(#area-${s.key})`} />
))}
<ChartLegend content={<ChartLegendContent />} />
</AreaChart>
</ChartContainer>
)
}
@@ -1,14 +1,10 @@
'use client'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { HugeiconsIcon } from '@hugeicons/react'
import { Add01Icon, Cancel01Icon } from '@hugeicons/core-free-icons'
import { ResponsiveGridLayout, DEFAULT_BREAKPOINTS, DEFAULT_COLS, useContainerWidth } from 'react-grid-layout'
import type { Layout, LayoutItem } from 'react-grid-layout'
import type { LayoutItem } from 'react-grid-layout'
import 'react-grid-layout/css/styles.css'
import { Button } from '@/components/ui/button'
import { Checkbox } from '@/components/ui/checkbox'
import { Skeleton } from '@/components/ui/skeleton'
import { toast } from '@/components/ui/toast'
import {
@@ -21,13 +17,14 @@ import {
getApiError,
getPaginatedItems,
} from '@/lib/api/index'
import { useAuth } from '@/contexts/auth-context'
import type { LowStockItemResponse, StockMovementResponse } from '@/types/api'
import { InventorySection, SalesSection, type DateRange } from './analytics-sections'
import { ColumnBarChart, DonutChart, HorizontalBarChart, RadialGauge, SalesTrendChart } from './dashboard-charts'
import type { ChartDatum, MonthlySalesPoint } from './dashboard-charts'
const STORAGE_KEY = 'distribution-dashboard-widgets-v3'
const ROW_HEIGHT = 36
const GRID_MARGIN: [number, number] = [16, 16]
const ROW_HEIGHT = 26
const GRID_MARGIN: [number, number] = [10, 10]
type Breakpoint = keyof typeof DEFAULT_BREAKPOINTS
const BREAKPOINT_ORDER = Object.keys(DEFAULT_BREAKPOINTS) as Breakpoint[]
@@ -40,6 +37,7 @@ interface WidgetMeta {
cat: Category
title: string
size: Size
permission: string
}
const CATEGORY_META: Record<Category, { label: string; text: string; bg: string; solid: string }> = {
@@ -50,23 +48,17 @@ const CATEGORY_META: Record<Category, { label: string; text: string; bg: string;
}
const WIDGET_META: WidgetMeta[] = [
{ id: 'pendingPO', cat: 'sales', title: 'Pending Shop POs', size: 'sm' },
{ id: 'awaitingConfirm', cat: 'sales', title: 'Awaiting Confirmation', size: 'sm' },
{ id: 'fulfillRate', cat: 'sales', title: 'Fulfillment Rate', size: 'md' },
{ id: 'openRides', cat: 'ops', title: 'Open Rides', size: 'md' },
{ id: 'loadingSheetsByStatus', cat: 'ops', title: 'Loading Sheets by Status', size: 'md' },
{ id: 'deliveryTasks', cat: 'ops', title: 'Pending Delivery Tasks', size: 'sm' },
{ id: 'lowStock', cat: 'stock', title: 'Low Stock Alerts', size: 'lg' },
{ id: 'stockMovements', cat: 'stock', title: 'Recent Stock Movements', size: 'lg' },
{ id: 'warehouseBalance', cat: 'stock', title: 'Warehouse Balances', size: 'md' },
{ id: 'outstandingPay', cat: 'finance', title: 'Outstanding Payments', size: 'sm' },
{ id: 'invoiceStatus', cat: 'finance', title: 'Invoices by Status', size: 'md' },
{ id: 'salesTrendChart', cat: 'finance', title: 'Sales Trend (6 months)', size: 'chartWide' },
{ id: 'paymentStatusChart', cat: 'finance', title: 'Payment Status', size: 'chart' },
{ id: 'poStatusChart', cat: 'sales', title: 'Shop POs by Status', size: 'chart' },
{ id: 'loadingSheetsChart', cat: 'ops', title: 'Loading Sheets Split', size: 'chart' },
{ id: 'warehouseChart', cat: 'stock', title: 'Warehouse Stock Chart', size: 'chart' },
{ id: 'movementTypeChart', cat: 'stock', title: 'Movements by Type', size: 'chart' },
{ id: 'pendingPO', cat: 'sales', title: 'Pending Shop POs', size: 'sm', permission: 'orders.view' },
{ id: 'awaitingConfirm', cat: 'sales', title: 'Awaiting Confirmation', size: 'sm', permission: 'orders.view' },
{ id: 'fulfillRate', cat: 'sales', title: 'Fulfillment Rate', size: 'md', permission: 'orders.view' },
{ id: 'openRides', cat: 'ops', title: 'Open Rides', size: 'md', permission: 'rides.view' },
{ id: 'loadingSheetsByStatus',cat: 'ops', title: 'Loading Sheets by Status', size: 'md', permission: 'loading-sheet.view' },
{ id: 'deliveryTasks', cat: 'ops', title: 'Pending Delivery Tasks', size: 'sm', permission: 'delivery-task.view' },
{ id: 'lowStock', cat: 'stock', title: 'Low Stock Alerts', size: 'lg', permission: 'stock.view' },
{ id: 'stockMovements', cat: 'stock', title: 'Recent Stock Movements', size: 'lg', permission: 'stock.view' },
{ id: 'warehouseBalance', cat: 'stock', title: 'Warehouse Balances', size: 'md', permission: 'stock.view' },
{ id: 'outstandingPay', cat: 'finance', title: 'Outstanding Payments', size: 'sm', permission: 'orders.view' },
{ id: 'invoiceStatus', cat: 'finance', title: 'Invoices by Status', size: 'md', permission: 'orders.view' },
]
const DEFAULT_ACTIVE = [
@@ -87,14 +79,14 @@ const SIZE_CONFIG: Record<Breakpoint, Record<Size, { w: number; h: number; minW:
},
md: {
sm: { w: 5, h: 4, minW: 3, minH: 3 },
md: { w: 10, h: 6, minW: 4, minH: 3 },
md: { w: 5, h: 6, minW: 3, minH: 3 },
lg: { w: 10, h: 7, minW: 4, minH: 4 },
chart: { w: 5, h: 7, minW: 3, minH: 5 },
chartWide: { w: 10, h: 7, minW: 4, minH: 5 },
},
sm: {
sm: { w: 3, h: 4, minW: 2, minH: 3 },
md: { w: 6, h: 6, minW: 3, minH: 3 },
md: { w: 3, h: 6, minW: 2, minH: 3 },
lg: { w: 6, h: 7, minW: 3, minH: 4 },
chart: { w: 6, h: 7, minW: 3, minH: 5 },
chartWide: { w: 6, h: 7, minW: 3, minH: 5 },
@@ -137,54 +129,6 @@ function generateFlowLayout(ids: string[], bp: Breakpoint): LayoutItem[] {
return items
}
function generateFlowLayouts(ids: string[]): Record<Breakpoint, LayoutItem[]> {
return Object.fromEntries(BREAKPOINT_ORDER.map(bp => [bp, generateFlowLayout(ids, bp)])) as Record<Breakpoint, LayoutItem[]>
}
/** Places a newly-added widget below everything else on a given breakpoint, so it never overlaps what's already there. */
function appendWidget(layout: LayoutItem[], meta: WidgetMeta, bp: Breakpoint): LayoutItem[] {
const cfg = SIZE_CONFIG[bp][meta.size]
const y = layout.reduce((max, item) => Math.max(max, item.y + item.h), 0)
return [...layout, { i: meta.id, x: 0, y, w: cfg.w, h: cfg.h, minW: cfg.minW, minH: cfg.minH }]
}
interface DashboardLayoutState {
activeIds: string[]
layouts: Record<Breakpoint, LayoutItem[]>
}
function defaultLayoutState(): DashboardLayoutState {
return { activeIds: [...DEFAULT_ACTIVE], layouts: generateFlowLayouts(DEFAULT_ACTIVE) }
}
function loadStoredLayoutState(): DashboardLayoutState {
try {
const raw = window.localStorage.getItem(STORAGE_KEY)
if (!raw) return defaultLayoutState()
const parsed = JSON.parse(raw)
const validIds = new Set(WIDGET_META.map(w => w.id))
const activeIds: string[] = Array.isArray(parsed?.activeIds)
? parsed.activeIds.filter((id: unknown): id is string => typeof id === 'string' && validIds.has(id))
: []
if (activeIds.length === 0) return defaultLayoutState()
const layouts = {} as Record<Breakpoint, LayoutItem[]>
for (const bp of BREAKPOINT_ORDER) {
const storedLayout: LayoutItem[] = Array.isArray(parsed?.layouts?.[bp])
? parsed.layouts[bp].filter((l: unknown): l is LayoutItem =>
!!l && typeof l === 'object' && typeof (l as LayoutItem).i === 'string' && validIds.has((l as LayoutItem).i) && activeIds.includes((l as LayoutItem).i))
: []
const missingIds = activeIds.filter(id => !storedLayout.some(l => l.i === id))
layouts[bp] = missingIds.length > 0 ? [...storedLayout, ...generateFlowLayout(missingIds, bp)] : storedLayout
}
return { activeIds, layouts }
} catch {
return defaultLayoutState()
}
}
const fmtMoney = (v: number) => `Rs. ${v.toLocaleString('en-LK', { minimumFractionDigits: 2 })}`
interface OpenRide {
@@ -223,111 +167,183 @@ interface DashboardData {
monthlySales: MonthlySalesPoint[]
}
const PO_STATUSES = ['Pending', 'PartiallyFulfilled', 'Fulfilled', 'Cancelled'] as const
const PAYMENT_STATUSES = ['Pending', 'PartiallyPaid', 'Paid'] as const
const SALES_MONTHS = 6
/** Recent-activity charts aggregate this many latest records client-side. */
const CHART_SAMPLE_SIZE = 200
const splitWords = (s: string) => s.replace(/([a-z])([A-Z])/g, '$1 $2')
function buildMonthlySales(rows: Array<{ createdAt: string; totalAmount: number }>): MonthlySalesPoint[] {
const now = new Date()
const months: MonthlySalesPoint[] = []
for (let i = SALES_MONTHS - 1; i >= 0; i--) {
const d = new Date(now.getFullYear(), now.getMonth() - i, 1)
months.push({ month: `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`, invoiced: 0 })
}
for (const r of rows) {
const bucket = months.find(m => m.month === r.createdAt.slice(0, 7))
if (bucket) bucket.invoiced += r.totalAmount
}
return months
}
async function loadDashboardData(): Promise<DashboardData> {
const [
pendingPO, awaitingConfirm, allPO, fulfilledPO,
openRidesRes,
plannedSheets, confirmedSheets,
pendingTasks, partialTasks,
lowStock,
movements,
balances,
outstanding,
draftInv, printedInv, finalizedInv,
poStatusCounts, paymentStatusCounts,
recentInvoices, recentMovements,
] = await Promise.all([
shopPos.list({ status: 'Pending', pageSize: 1 }),
shopPos.list({ confirmed: true, status: 'Pending', pageSize: 1 }),
shopPos.list({ pageSize: 1 }),
shopPos.list({ status: 'Fulfilled', pageSize: 1 }),
rides.list({ status: 'Open', pageSize: 5 }),
loadingSheets.list({ status: 'Planned', pageSize: 1 }),
loadingSheets.list({ status: 'Confirmed', pageSize: 1 }),
deliveryTasks.list({ status: 'Pending', pageSize: 1 }),
deliveryTasks.list({ status: 'PartiallyDelivered', pageSize: 1 }),
stock.lowStock(),
stock.movements({ pageSize: 5 }),
stock.balances({ locationType: 'Warehouse', pageSize: 300 }),
invoices.outstandingSummary(),
invoices.list({ status: 'Draft', pageSize: 1 }),
invoices.list({ status: 'Printed', pageSize: 1 }),
invoices.list({ status: 'Finalized', pageSize: 1 }),
Promise.all(PO_STATUSES.map(status => shopPos.list({ status, pageSize: 1 }))),
Promise.all(PAYMENT_STATUSES.map(paymentStatus => invoices.list({ paymentStatus, pageSize: 1 }))),
invoices.list({ pageSize: CHART_SAMPLE_SIZE }),
stock.movements({ pageSize: CHART_SAMPLE_SIZE }),
])
const movementCounts = new Map<string, number>()
for (const m of getPaginatedItems(recentMovements)) {
movementCounts.set(m.type, (movementCounts.get(m.type) ?? 0) + 1)
}
const balanceRows = getPaginatedItems(balances)
const byWarehouse = new Map<string, WarehouseBalanceRow>()
for (const b of balanceRows) {
const existing = byWarehouse.get(b.locationId)
if (existing) existing.quantity += b.quantity
else byWarehouse.set(b.locationId, { locationId: b.locationId, name: b.locationName, quantity: b.quantity })
}
const warehouseBalances = Array.from(byWarehouse.values())
.sort((a, b) => b.quantity - a.quantity)
.slice(0, 5)
function emptyDashboardData(): DashboardData {
return {
pendingPOCount: pendingPO.total,
awaitingConfirmCount: awaitingConfirm.total,
totalPOCount: allPO.total,
fulfilledPOCount: fulfilledPO.total,
openRides: getPaginatedItems(openRidesRes).map(r => ({ id: r.id, vehicleNumberPlate: r.vehicleNumberPlate, driverFullName: r.driverFullName })),
plannedSheetsCount: plannedSheets.total,
confirmedSheetsCount: confirmedSheets.total,
pendingTasksCount: pendingTasks.total,
partialTasksCount: partialTasks.total,
lowStock: getPaginatedItems(lowStock).slice(0, 5),
movements: getPaginatedItems(movements),
warehouseBalances,
outstandingAmount: outstanding.outstandingAmount,
outstandingInvoiceCount: outstanding.invoiceCount,
draftInvoiceCount: draftInv.total,
printedInvoiceCount: printedInv.total,
finalizedInvoiceCount: finalizedInv.total,
poStatusChart: PO_STATUSES.map((s, i) => ({ name: splitWords(s), value: poStatusCounts[i].total })),
paymentStatusChart: PAYMENT_STATUSES.map((s, i) => ({ name: splitWords(s), value: paymentStatusCounts[i].total })),
movementTypeChart: Array.from(movementCounts, ([type, value]) => ({ name: splitWords(type), value })).sort((a, b) => b.value - a.value),
monthlySales: buildMonthlySales(getPaginatedItems(recentInvoices)),
pendingPOCount: 0, awaitingConfirmCount: 0, totalPOCount: 0, fulfilledPOCount: 0,
openRides: [],
plannedSheetsCount: 0, confirmedSheetsCount: 0,
pendingTasksCount: 0, partialTasksCount: 0,
lowStock: [], movements: [], warehouseBalances: [],
outstandingAmount: 0, outstandingInvoiceCount: 0,
draftInvoiceCount: 0, printedInvoiceCount: 0, finalizedInvoiceCount: 0,
poStatusChart: [], paymentStatusChart: [], movementTypeChart: [], monthlySales: [],
}
}
function CategoryPill({ cat }: { cat: Category }) {
const meta = CATEGORY_META[cat]
async function loadDashboardData(activeIds: Set<string>): Promise<DashboardData> {
const data = emptyDashboardData()
const fetches: Promise<void>[] = []
if (activeIds.has('pendingPO') || activeIds.has('awaitingConfirm') || activeIds.has('fulfillRate')) {
fetches.push(
Promise.all([
shopPos.list({ status: 'Pending', pageSize: 1 }),
shopPos.list({ confirmed: true, status: 'Pending', pageSize: 1 }),
shopPos.list({ pageSize: 1 }),
shopPos.list({ status: 'Fulfilled', pageSize: 1 }),
]).then(([pending, awaiting, all, fulfilled]) => {
data.pendingPOCount = pending.total
data.awaitingConfirmCount = awaiting.total
data.totalPOCount = all.total
data.fulfilledPOCount = fulfilled.total
}).catch(() => {})
)
}
if (activeIds.has('openRides')) {
fetches.push(
rides.list({ status: 'Open', pageSize: 5 })
.then(res => {
data.openRides = getPaginatedItems(res).map(r => ({
id: r.id, vehicleNumberPlate: r.vehicleNumberPlate, driverFullName: r.driverFullName,
}))
})
.catch(() => {})
)
}
if (activeIds.has('loadingSheetsByStatus')) {
fetches.push(
Promise.all([
loadingSheets.list({ status: 'Planned', pageSize: 1 }),
loadingSheets.list({ status: 'Confirmed', pageSize: 1 }),
]).then(([planned, confirmed]) => {
data.plannedSheetsCount = planned.total
data.confirmedSheetsCount = confirmed.total
}).catch(() => {})
)
}
if (activeIds.has('deliveryTasks')) {
fetches.push(
Promise.all([
deliveryTasks.list({ status: 'Pending', pageSize: 1 }),
deliveryTasks.list({ status: 'PartiallyDelivered', pageSize: 1 }),
]).then(([pending, partial]) => {
data.pendingTasksCount = pending.total
data.partialTasksCount = partial.total
}).catch(() => {})
)
}
if (activeIds.has('lowStock')) {
fetches.push(
stock.lowStock()
.then(res => { data.lowStock = getPaginatedItems(res).slice(0, 5) })
.catch(() => {})
)
}
if (activeIds.has('stockMovements')) {
fetches.push(
stock.movements({ pageSize: 5 })
.then(res => { data.movements = getPaginatedItems(res) })
.catch(() => {})
)
}
if (activeIds.has('warehouseBalance')) {
fetches.push(
stock.balances({ locationType: 'Warehouse', pageSize: 300 })
.then(res => {
const byWarehouse = new Map<string, WarehouseBalanceRow>()
for (const b of getPaginatedItems(res)) {
const existing = byWarehouse.get(b.locationId)
if (existing) existing.quantity += b.quantity
else byWarehouse.set(b.locationId, { locationId: b.locationId, name: b.locationName, quantity: b.quantity })
}
data.warehouseBalances = Array.from(byWarehouse.values())
.sort((a, b) => b.quantity - a.quantity)
.slice(0, 5)
})
.catch(() => {})
)
}
if (activeIds.has('outstandingPay')) {
fetches.push(
invoices.outstandingSummary()
.then(res => {
data.outstandingAmount = res.outstandingAmount
data.outstandingInvoiceCount = res.invoiceCount
})
.catch(() => {})
)
}
if (activeIds.has('invoiceStatus')) {
fetches.push(
Promise.all([
invoices.list({ status: 'Draft', pageSize: 1 }),
invoices.list({ status: 'Printed', pageSize: 1 }),
invoices.list({ status: 'Finalized', pageSize: 1 }),
]).then(([draft, printed, finalized]) => {
data.draftInvoiceCount = draft.total
data.printedInvoiceCount = printed.total
data.finalizedInvoiceCount = finalized.total
}).catch(() => {})
)
}
await Promise.all(fetches)
return data
}
const STAT_IDS = ['pendingPO', 'awaitingConfirm', 'fulfillRate', 'deliveryTasks', 'outstandingPay', 'invoiceStatus']
function StatTile({ title, value, sub, children }: { title: string; value: string; sub?: string; children?: React.ReactNode }) {
return (
<span className={`inline-block rounded-full px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide ${meta.text} ${meta.bg}`}>
{meta.label}
</span>
<div className="relative flex h-[76px] flex-col justify-between overflow-hidden rounded-xl border bg-card px-3 py-2 shadow-xs transition-shadow hover:shadow-md">
<div>
<div className="truncate text-[11px] font-medium text-muted-foreground">{title}</div>
<div className="truncate text-lg font-bold leading-tight text-foreground">{value}</div>
</div>
<div>
{sub && <div className="truncate text-[10px] text-muted-foreground">{sub}</div>}
{children}
</div>
</div>
)
}
function StatStrip({ ids, data }: { ids: string[]; data: DashboardData }) {
const pct = data.totalPOCount > 0 ? Math.round((data.fulfilledPOCount / data.totalPOCount) * 100) : 0
const invTotal = data.draftInvoiceCount + data.printedInvoiceCount + data.finalizedInvoiceCount
const seg = (n: number) => (invTotal > 0 ? `${(n / invTotal) * 100}%` : '0%')
const tiles: Record<string, React.ReactNode> = {
pendingPO: <StatTile title="Pending Shop POs" value={String(data.pendingPOCount)} sub={`${data.totalPOCount} total orders`} />,
awaitingConfirm: <StatTile title="Awaiting Confirmation" value={String(data.awaitingConfirmCount)} sub="Confirmed, not yet loaded" />,
fulfillRate: (
<StatTile title="Fulfillment Rate" value={`${pct}%`} sub={`${data.fulfilledPOCount} of ${data.totalPOCount} fulfilled`}>
<div className="mt-1 h-1 overflow-hidden rounded-full bg-muted"><div className="h-full rounded-full bg-primary" style={{ width: `${pct}%` }} /></div>
</StatTile>
),
deliveryTasks: <StatTile title="Pending Delivery Tasks" value={String(data.pendingTasksCount)} sub={`${data.partialTasksCount} partially delivered`} />,
outstandingPay: <StatTile title="Outstanding Payments" value={fmtMoney(data.outstandingAmount)} sub={`${data.outstandingInvoiceCount} invoices`} />,
invoiceStatus: (
<StatTile title="Invoices by Status" value={String(invTotal)} sub={`${data.draftInvoiceCount} draft · ${data.printedInvoiceCount} printed · ${data.finalizedInvoiceCount} final`}>
<div className="mt-1 flex h-1 overflow-hidden rounded-full bg-muted">
<div className="bg-primary/30" style={{ width: seg(data.draftInvoiceCount) }} />
<div className="bg-primary/60" style={{ width: seg(data.printedInvoiceCount) }} />
<div className="bg-primary" style={{ width: seg(data.finalizedInvoiceCount) }} />
</div>
</StatTile>
),
}
return (
<div className="grid grid-cols-2 gap-3 md:grid-cols-3 xl:grid-cols-6">
{STAT_IDS.filter(id => ids.includes(id)).map(id => <div key={id}>{tiles[id]}</div>)}
</div>
)
}
@@ -336,14 +352,14 @@ function WidgetBody({ id, data }: { id: string; data: DashboardData }) {
case 'pendingPO':
return (
<div>
<div className="text-3xl font-bold text-foreground">{data.pendingPOCount}</div>
<div className="text-2xl font-bold text-foreground">{data.pendingPOCount}</div>
<div className="mt-1.5 text-xs text-muted-foreground">{data.totalPOCount} total orders</div>
</div>
)
case 'awaitingConfirm':
return (
<div>
<div className="text-3xl font-bold text-foreground">{data.awaitingConfirmCount}</div>
<div className="text-2xl font-bold text-foreground">{data.awaitingConfirmCount}</div>
<div className="mt-1.5 text-xs text-muted-foreground">Confirmed, not yet loaded</div>
</div>
)
@@ -362,7 +378,7 @@ function WidgetBody({ id, data }: { id: string; data: DashboardData }) {
<div className="text-sm font-medium text-foreground">{r.vehicleNumberPlate}</div>
<div className="text-xs text-muted-foreground">{r.driverFullName}</div>
</div>
<span className="rounded-full bg-violet-600 px-2.5 py-1 text-[11px] font-semibold text-white">Open</span>
<span className="rounded-full bg-emerald-100 px-2.5 py-1 text-[11px] font-semibold text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300">Open</span>
</div>
))}
</div>
@@ -380,7 +396,7 @@ function WidgetBody({ id, data }: { id: string; data: DashboardData }) {
case 'deliveryTasks':
return (
<div>
<div className="text-3xl font-bold text-foreground">{data.pendingTasksCount}</div>
<div className="text-2xl font-bold text-foreground">{data.pendingTasksCount}</div>
<div className="mt-1.5 text-xs text-muted-foreground">{data.partialTasksCount} partially delivered</div>
</div>
)
@@ -425,7 +441,7 @@ function WidgetBody({ id, data }: { id: string; data: DashboardData }) {
case 'outstandingPay':
return (
<div>
<div className="text-3xl font-bold text-foreground">{fmtMoney(data.outstandingAmount)}</div>
<div className="text-2xl font-bold text-foreground">{fmtMoney(data.outstandingAmount)}</div>
<div className="mt-1.5 text-xs text-muted-foreground">{data.outstandingInvoiceCount} invoices</div>
</div>
)
@@ -467,171 +483,146 @@ function WidgetBody({ id, data }: { id: string; data: DashboardData }) {
}
}
function mergeLayoutsChange(
full: Record<Breakpoint, LayoutItem[]>,
changed: Partial<Record<Breakpoint, Layout>>,
): Record<Breakpoint, LayoutItem[]> {
const next = { ...full }
for (const bp of BREAKPOINT_ORDER) {
const changedArr = changed[bp]
if (!changedArr) continue
next[bp] = full[bp].map(item => {
const updated = changedArr.find(c => c.i === item.i)
return updated ? { ...item, x: updated.x, y: updated.y, w: updated.w, h: updated.h } : item
})
}
return next
function toIsoDate(d: Date) {
const pad = (n: number) => String(n).padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
}
type RangePreset = '7d' | '1m' | '3m' | '1y' | 'custom'
const RANGE_PRESETS: Array<{ key: RangePreset; label: string }> = [
{ key: '7d', label: 'Last 7 days' },
{ key: '1m', label: '1 month' },
{ key: '3m', label: '3 months' },
{ key: '1y', label: '1 year' },
{ key: 'custom', label: 'Custom' },
]
function presetRange(preset: Exclude<RangePreset, 'custom'>): DateRange {
const to = new Date()
const from = new Date()
if (preset === '7d') from.setDate(from.getDate() - 6)
else if (preset === '1m') from.setMonth(from.getMonth() - 1)
else if (preset === '3m') from.setMonth(from.getMonth() - 3)
else { from.setFullYear(from.getFullYear() - 1); from.setDate(from.getDate() + 1) }
return { from: toIsoDate(from), to: toIsoDate(to) }
}
function minFromDate(to: string) {
const d = new Date(`${to}T00:00:00`)
d.setDate(d.getDate() - 365)
return toIsoDate(d)
}
export function DashboardClient() {
const { hasPermission } = useAuth()
const [data, setData] = useState<DashboardData | null>(null)
const [loading, setLoading] = useState(true)
const [state, setState] = useState<DashboardLayoutState>(defaultLayoutState)
const [editMode, setEditMode] = useState(false)
const [showPicker, setShowPicker] = useState(false)
const [category, setCategory] = useState<'all' | Category>('all')
const [range, setRange] = useState<DateRange>(() => presetRange('1m'))
const [preset, setPreset] = useState<RangePreset>('1m')
const { width, containerRef, mounted } = useContainerWidth({ initialWidth: 1200 })
useEffect(() => {
setState(loadStoredLayoutState())
}, [])
const allowedIds = useMemo(
() => new Set(WIDGET_META.filter(w => hasPermission(w.permission)).map(w => w.id)),
[hasPermission],
)
const persist = useCallback((next: DashboardLayoutState) => {
setState(next)
try {
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next))
} catch {
// localStorage unavailable (private browsing, etc.) — layout just won't persist
}
}, [])
const permittedActiveIds = useMemo(
() => DEFAULT_ACTIVE.filter(id => allowedIds.has(id)),
[allowedIds],
)
const fetchData = useCallback(async () => {
setLoading(true)
try {
setData(await loadDashboardData())
setData(await loadDashboardData(new Set(permittedActiveIds)))
} catch (err) {
toast.add({ title: 'Failed to load dashboard', description: getApiError(err), type: 'error' })
} finally {
setLoading(false)
}
}, [])
}, [permittedActiveIds])
useEffect(() => {
fetchData()
}, [fetchData])
function toggleWidget(id: string, checked: boolean) {
if (checked) {
const meta = WIDGET_META.find(w => w.id === id)
if (!meta || state.activeIds.includes(id)) return
const layouts = { ...state.layouts }
for (const bp of BREAKPOINT_ORDER) layouts[bp] = appendWidget(layouts[bp], meta, bp)
persist({ activeIds: [...state.activeIds, id], layouts })
} else {
const layouts = { ...state.layouts }
for (const bp of BREAKPOINT_ORDER) layouts[bp] = layouts[bp].filter(l => l.i !== id)
persist({ activeIds: state.activeIds.filter(x => x !== id), layouts })
}
}
function handleLayoutChange(_layout: Layout, changedLayouts: Partial<Record<Breakpoint, Layout>>) {
setState(prev => {
const next = { ...prev, layouts: mergeLayoutsChange(prev.layouts, changedLayouts) }
try {
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next))
} catch {
// localStorage unavailable — position just won't persist
}
return next
})
}
const visibleWidgets = useMemo(
() => state.activeIds
() => permittedActiveIds
.map(id => WIDGET_META.find(w => w.id === id))
.filter((w): w is WidgetMeta => Boolean(w))
.filter(w => category === 'all' || w.cat === category),
[state.activeIds, category],
.filter(w => !STAT_IDS.includes(w.id)),
[permittedActiveIds],
)
const visibleLayouts = useMemo(() => {
const visibleIds = new Set(visibleWidgets.map(w => w.id))
return Object.fromEntries(
BREAKPOINT_ORDER.map(bp => [bp, state.layouts[bp].filter(l => visibleIds.has(l.i))]),
BREAKPOINT_ORDER.map(bp => [bp, generateFlowLayout(Array.from(visibleIds), bp)]),
) as Record<Breakpoint, LayoutItem[]>
}, [state.layouts, visibleWidgets])
}, [visibleWidgets])
const filters: Array<{ key: 'all' | Category; label: string }> = [
{ key: 'all', label: 'All widgets' },
{ key: 'sales', label: CATEGORY_META.sales.label },
{ key: 'ops', label: CATEGORY_META.ops.label },
{ key: 'stock', label: CATEGORY_META.stock.label },
{ key: 'finance', label: CATEGORY_META.finance.label },
]
const canSales = hasPermission('orders.view')
const canInventory = hasPermission('stock.view')
return (
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-3">
<div className="flex flex-wrap items-start justify-between gap-4">
<div>
<h1 className="text-2xl font-semibold text-foreground">Dashboard</h1>
<h1 className="text-xl font-semibold text-foreground">Dashboard</h1>
<p className="mt-1 text-sm text-muted-foreground">
{editMode ? 'Drag to move, drag a corner to resize, or tick which widgets show.' : 'Add, remove, drag and resize widgets to make this view yours.'}
Sales, inventory, shop orders, rides and loading sheets, deliveries, stock alerts, invoices and payments
</p>
</div>
</div>
<div className="relative flex items-center gap-2">
{editMode && (
<Button variant="outline" size="sm" onClick={() => setShowPicker(v => !v)}>
<HugeiconsIcon icon={Add01Icon} size={14} />
Widgets
</Button>
)}
<Button variant={editMode ? 'default' : 'outline'} size="sm" onClick={() => { setEditMode(v => !v); setShowPicker(false) }}>
{editMode ? 'Done' : 'Customize Dashboard'}
</Button>
{showPicker && (
<div className="absolute right-0 top-full z-20 mt-2 w-72 rounded-2xl border bg-popover p-3 shadow-lg">
<div className="mb-2 flex items-center justify-between">
<span className="text-sm font-semibold text-foreground">Widgets</span>
<button onClick={() => setShowPicker(false)} aria-label="Close" className="rounded-full bg-muted p-1 text-muted-foreground">
<HugeiconsIcon icon={Cancel01Icon} size={12} />
{(canSales || canInventory) && (
<div className="flex flex-wrap items-center justify-between gap-3 pt-2">
<span />
<div className="flex flex-wrap items-center gap-2 text-sm">
<div className="inline-flex rounded-lg border bg-muted/50 p-0.5">
{RANGE_PRESETS.map(p => (
<button
key={p.key}
onClick={() => { setPreset(p.key); if (p.key !== 'custom') setRange(presetRange(p.key)) }}
className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${
preset === p.key ? 'bg-primary text-primary-foreground shadow-xs' : 'text-muted-foreground hover:text-foreground'
}`}
>
{p.label}
</button>
</div>
<div className="flex flex-col gap-1">
{WIDGET_META.map(w => {
const checked = state.activeIds.includes(w.id)
return (
<label
key={w.id}
className="flex cursor-pointer items-center gap-2.5 rounded-lg px-2 py-1.5 hover:bg-muted"
>
<Checkbox checked={checked} onCheckedChange={(v) => toggleWidget(w.id, v === true)} />
<span className="text-sm text-foreground">{w.title}</span>
</label>
)
})}
</div>
))}
</div>
)}
{preset === 'custom' && (
<div className="flex items-center gap-1.5">
<input
type="date" value={range.from} min={minFromDate(range.to)} max={range.to} aria-label="From date"
onChange={e => e.target.value && setRange(r => ({ ...r, from: e.target.value }))}
className="rounded-lg border bg-background px-2 py-1 text-xs"
/>
<span className="text-xs text-muted-foreground">to</span>
<input
type="date" value={range.to} min={range.from} max={toIsoDate(new Date())} aria-label="To date"
onChange={e => e.target.value && setRange(r => ({ ...r, to: e.target.value }))}
className="rounded-lg border bg-background px-2 py-1 text-xs"
/>
</div>
)}
</div>
</div>
</div>
<div className="flex flex-wrap gap-2">
{filters.map(f => (
<button
key={f.key}
onClick={() => setCategory(f.key)}
className={`rounded-full border px-3.5 py-1.5 text-xs font-semibold transition-colors ${
category === f.key
? 'border-foreground bg-foreground text-background'
: 'border-border bg-background text-muted-foreground hover:bg-muted'
}`}
>
{f.label}
</button>
))}
</div>
)}
{canSales && (
<section className="flex flex-col gap-3">
<h3 className="flex items-center gap-2 text-sm font-semibold text-foreground"><span className="h-2 w-2 rounded-full bg-primary" />Sales</h3>
<SalesSection range={range} />
</section>
)}
{canInventory && (
<section className="flex flex-col gap-3">
<h3 className="flex items-center gap-2 text-sm font-semibold text-foreground"><span className="h-2 w-2 rounded-full bg-primary" />Inventory</h3>
<InventorySection range={range} />
</section>
)}
{loading || !data ? (
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
@@ -639,11 +630,9 @@ export function DashboardClient() {
<Skeleton key={i} className="h-40 rounded-2xl" />
))}
</div>
) : visibleWidgets.length === 0 ? (
<div className="rounded-2xl border border-dashed p-12 text-center text-sm text-muted-foreground">
No widgets on this dashboard yet. Click &ldquo;Widgets&rdquo; to add some.
</div>
) : (
<>
<StatStrip ids={permittedActiveIds} data={data} />
<div ref={containerRef} className="w-full">
{mounted && (
<ResponsiveGridLayout
@@ -655,25 +644,18 @@ export function DashboardClient() {
margin={GRID_MARGIN}
containerPadding={[0, 0]}
maxRows={Infinity}
dragConfig={{ enabled: editMode }}
resizeConfig={{ enabled: editMode, handles: ['se'] }}
dragConfig={{ enabled: false }}
resizeConfig={{ enabled: false }}
autoSize
onLayoutChange={handleLayoutChange}
>
{visibleWidgets.map(w => (
<div key={w.id} className="relative flex flex-col overflow-auto rounded-2xl border bg-card p-5">
{editMode && (
<button
onClick={() => toggleWidget(w.id, false)}
aria-label="Remove widget"
className="absolute right-3 top-3 flex h-6 w-6 items-center justify-center rounded-full border bg-background text-muted-foreground hover:text-foreground"
>
<HugeiconsIcon icon={Cancel01Icon} size={12} />
</button>
)}
<div className="mb-3.5 shrink-0">
<div className="text-sm font-semibold text-foreground">{w.title}</div>
<div className="mt-1"><CategoryPill cat={w.cat} /></div>
<div key={w.id} className="relative flex flex-col overflow-auto rounded-xl border bg-card p-3 shadow-xs transition-shadow hover:shadow-md">
<div className="mb-2 shrink-0">
<div className="flex items-center gap-1.5 text-sm font-semibold text-foreground">
<span className="h-3.5 w-1 rounded-full bg-primary" />
{w.title}
</div>
</div>
<div className="min-h-0 flex-1">
<WidgetBody id={w.id} data={data} />
@@ -683,6 +665,7 @@ export function DashboardClient() {
</ResponsiveGridLayout>
)}
</div>
</>
)}
</div>
)
@@ -120,7 +120,7 @@ export function GrnTaxCard() {
setSettings(s => ({ ...s, [field]: value }))
setPending(p => ({ ...p, [configKey]: true }))
try {
await sysConfig.set(configKey, String(value), user.id)
await sysConfig.set(configKey, String(value), user?.userId)
} catch (err) {
setSettings(s => ({ ...s, [field]: previous }))
toast.add({ title: 'Failed to update configuration', description: getApiError(err), type: 'error' })
@@ -92,7 +92,7 @@ export function ProductCapabilitiesCard() {
setForm(f => ({ ...f, [formKey]: value }))
setPendingKeys(p => ({ ...p, [configKey]: true }))
try {
await sysConfig.set(configKey, String(value), user.id)
await sysConfig.set(configKey, String(value), user?.userId)
} catch (err) {
setForm(f => ({ ...f, [formKey]: previous }))
toast.add({ title: 'Failed to update configuration', description: getApiError(err), type: 'error' })
@@ -107,7 +107,7 @@ export function ProductCapabilitiesCard() {
if (value === previous) return
setPendingKeys(p => ({ ...p, [ITEM_TRACKING_KEYS.defaultWarrantyPeriodDays]: true }))
try {
await sysConfig.set(ITEM_TRACKING_KEYS.defaultWarrantyPeriodDays, String(value), user.id)
await sysConfig.set(ITEM_TRACKING_KEYS.defaultWarrantyPeriodDays, String(value), user?.userId)
} catch (err) {
setForm(f => ({ ...f, defaultWarrantyPeriodDays: previous }))
toast.add({ title: 'Failed to update configuration', description: getApiError(err), type: 'error' })
@@ -60,7 +60,7 @@ export function DriverSheet({ open, onClose, driver, onSuccess }: DriverSheetPro
useEffect(() => {
if (open) {
usersApi.list({ pageSize: 100 }).then((res) => setUsersList(getPaginatedItems(res))).catch((err) =>
usersApi.list().then((res) => setUsersList(res)).catch((err) =>
toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' })
)
@@ -1,6 +1,7 @@
import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar'
import { AppSidebar } from '@/components/layout/app-sidebar'
import { BottomNav } from '@/components/layout/bottom-nav'
import { ThemeToggle } from '@/components/layout/theme-toggle'
export default function DashboardLayout({
children,
@@ -13,6 +14,9 @@ export default function DashboardLayout({
<SidebarInset>
<header className="flex h-14 shrink-0 items-center gap-2 border-b border-border px-4">
<SidebarTrigger className="-ml-1 hidden md:flex" />
<div className="ml-auto">
<ThemeToggle />
</div>
</header>
<main className="flex flex-1 flex-col gap-4 p-4 pb-20 md:pb-4">
{children}
@@ -89,11 +89,11 @@ export function RegionManageEntrySheet({ open, onClose, onSuccess, initial }: Re
Promise.all([
regionsApi.list({ page: 1, pageSize: 200 }),
usersApi.list({ page: 1, pageSize: 200 }),
usersApi.list(),
])
.then(([r, u]) => {
setRegionsList(getPaginatedItems(r).filter((x) => x.isActive))
setAgencyUsers(getPaginatedItems(u).filter((x) => x.roleName === 'RegionalAgency'))
setAgencyUsers(u.filter((x) => x.roleName === 'RegionalAgency'))
})
.catch((err) => toast.add({ title: 'Failed to load reference data', description: getApiError(err), type: 'error' }))
}, [open, initial])
@@ -81,8 +81,8 @@ export function RegionManageListClient() {
}, [fetchData])
useEffect(() => {
usersApi.list({ page: 1, pageSize: 200 })
.then((res) => setAgencyUsers(getPaginatedItems(res)))
usersApi.list()
.then((res) => setAgencyUsers(res))
.catch(() => toast.add({ title: 'Failed to load users', type: 'error' }))
}, [])
@@ -45,13 +45,13 @@ export function RegionManagerDialog({ open, onClose, region }: RegionManagerDial
setCurrent(null)
Promise.all([
regionsApi.getManager(region.id).catch(() => null), // 404 = no manager yet
usersApi.list({ pageSize: 500 }),
usersApi.list(),
])
.then(([manager, userRes]) => {
if (cancelled) return
setCurrent(manager)
setSelected(manager?.userId ?? '')
setCandidates(getPaginatedItems(userRes).filter((u) => u.isActive && u.roleName === MANAGER_ROLE))
setCandidates(userRes.filter((u) => u.isActive && u.roleName === MANAGER_ROLE))
})
.catch((err) => toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' }))
.finally(() => !cancelled && setLoading(false))
@@ -50,7 +50,9 @@ export function RegionSheet({ open, onClose, region, readOnly = false, onSuccess
.then((res) => {
if (!form.getValues('code')) form.setValue('code', res.code)
})
.catch(() => {})
.catch(() => {
toast.add({ title: 'Could not suggest a code — enter one manually', type: 'warning' })
})
}
}
}, [open, region])
@@ -46,8 +46,8 @@ export function RouteManageSheet({ open, onClose, route, onSuccess }: RouteManag
setOwnerUserId(route.ownerUserId ?? '')
setStoreFilter('')
usersApi.list({ page: 1, pageSize: 200 })
.then((res) => setSalesReps(getPaginatedItems(res).filter((u) => u.roleName === 'SalesRep')))
usersApi.list()
.then((res) => setSalesReps(res.filter((u) => u.roleName === 'SalesRep')))
.catch(() => toast.add({ title: 'Failed to load sales reps', type: 'error' }))
storesApi.list({ page: 1, pageSize: 200 })
@@ -46,10 +46,10 @@ export function RoutesClient() {
}, [fetchData, page, pageSize])
useEffect(() => {
usersApi.list({ page: 1, pageSize: 200 })
usersApi.list()
.then((res) => {
const map: Record<string, string> = {}
for (const u of getPaginatedItems(res)) map[u.id] = u.fullName
for (const u of res) map[u.id] = u.fullName
setUserNameById(map)
})
.catch(() => toast.add({ title: 'Failed to load users', type: 'error' }))
@@ -48,8 +48,8 @@ export function ConfirmLoadingSheetDialog({ open, onClose, onSuccess, sheet }: C
useEffect(() => {
if (!open) return
form.reset({ confirmedByUserId: '' })
usersApi.list({ pageSize: 200 })
.then((res) => setUsersList(getPaginatedItems(res)))
usersApi.list()
.then((res) => setUsersList(res))
.catch((err) => toast.add({ title: 'Failed to load users', description: getApiError(err), type: 'error' }))
}, [open])

Some files were not shown because too many files have changed in this diff Show More