fix(roles): keep only Admin + Cashier as system, demote others to custom + migration
После ревью UX оказалось что 6 системных ролей — перебор. Перешли на схему «два системных + остальные шаблоны»: - Администратор (IsSystem=true) — RolePermissions.All(). - Кассир (IsSystem=true) — POS-only набор: ProductsView + StocksView + RetailSalesOperate. Без RetailSalesRefund (админ включит при необходимости). Это маркер для будущего POS-app — не имеет доступа к веб-админке. - Менеджер / Кладовщик / Закупщик / Бухгалтер — IsSystem=false (кастомные). Можно удалить если не нужны или подкрутить под себя. Сидер на чистой БД сразу создаёт роли в правильных статусах. Для существующих установок миграция Phase4b_RolesSimplify идемпотентно делает UPDATE: демоутит лишние и приводит permissions Кассира к правильному набору. Down() — no-op (юзер мог переименовать). На стенде sql применил вручную + записал в __EFMigrationsHistory. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d2305b7d40
commit
1d9fd7297c
|
|
@ -187,12 +187,14 @@ private static async Task SeedEmployeeRolesAsync(AppDbContext db, Guid orgId, Ca
|
||||||
IsSystem = true, SortOrder = 0,
|
IsSystem = true, SortOrder = 0,
|
||||||
Permissions = RolePermissions.All(),
|
Permissions = RolePermissions.All(),
|
||||||
};
|
};
|
||||||
|
// Менеджер/Кладовщик/Закупщик/Бухгалтер — кастомные шаблоны (IsSystem=false),
|
||||||
|
// юзер может удалить или подкрутить под себя. Системные только Администратор + Кассир.
|
||||||
var manager = new EmployeeRole
|
var manager = new EmployeeRole
|
||||||
{
|
{
|
||||||
OrganizationId = orgId,
|
OrganizationId = orgId,
|
||||||
Name = "Менеджер",
|
Name = "Менеджер",
|
||||||
Description = "Управление каталогом, документами и контрагентами",
|
Description = "Управление каталогом, документами и контрагентами",
|
||||||
IsSystem = true, SortOrder = 10,
|
IsSystem = false, SortOrder = 10,
|
||||||
Permissions = new RolePermissions
|
Permissions = new RolePermissions
|
||||||
{
|
{
|
||||||
ProductsView = true, ProductsEdit = true, ProductGroupsManage = true, PriceTypesManage = true,
|
ProductsView = true, ProductsEdit = true, ProductGroupsManage = true, PriceTypesManage = true,
|
||||||
|
|
@ -206,7 +208,7 @@ private static async Task SeedEmployeeRolesAsync(AppDbContext db, Guid orgId, Ca
|
||||||
OrganizationId = orgId,
|
OrganizationId = orgId,
|
||||||
Name = "Кладовщик",
|
Name = "Кладовщик",
|
||||||
Description = "Приёмки, инвентаризация, остатки",
|
Description = "Приёмки, инвентаризация, остатки",
|
||||||
IsSystem = true, SortOrder = 20,
|
IsSystem = false, SortOrder = 20,
|
||||||
Permissions = new RolePermissions
|
Permissions = new RolePermissions
|
||||||
{
|
{
|
||||||
ProductsView = true,
|
ProductsView = true,
|
||||||
|
|
@ -218,12 +220,14 @@ private static async Task SeedEmployeeRolesAsync(AppDbContext db, Guid orgId, Ca
|
||||||
{
|
{
|
||||||
OrganizationId = orgId,
|
OrganizationId = orgId,
|
||||||
Name = "Кассир",
|
Name = "Кассир",
|
||||||
Description = "Продажи на кассе. Привязка к конкретной кассе обязательна.",
|
Description = "Только работа на кассе. Без доступа к веб-админке.",
|
||||||
IsSystem = true, SortOrder = 30,
|
IsSystem = true, SortOrder = 30,
|
||||||
Permissions = new RolePermissions
|
Permissions = new RolePermissions
|
||||||
{
|
{
|
||||||
ProductsView = true,
|
ProductsView = true,
|
||||||
RetailSalesOperate = true, RetailSalesRefund = true,
|
StocksView = true,
|
||||||
|
RetailSalesOperate = true,
|
||||||
|
// RetailSalesRefund по умолчанию false — админ включит при необходимости
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var buyer = new EmployeeRole
|
var buyer = new EmployeeRole
|
||||||
|
|
@ -231,7 +235,7 @@ private static async Task SeedEmployeeRolesAsync(AppDbContext db, Guid orgId, Ca
|
||||||
OrganizationId = orgId,
|
OrganizationId = orgId,
|
||||||
Name = "Закупщик",
|
Name = "Закупщик",
|
||||||
Description = "Заказы поставщикам и приёмка товара",
|
Description = "Заказы поставщикам и приёмка товара",
|
||||||
IsSystem = true, SortOrder = 40,
|
IsSystem = false, SortOrder = 40,
|
||||||
Permissions = new RolePermissions
|
Permissions = new RolePermissions
|
||||||
{
|
{
|
||||||
ProductsView = true,
|
ProductsView = true,
|
||||||
|
|
@ -244,7 +248,7 @@ private static async Task SeedEmployeeRolesAsync(AppDbContext db, Guid orgId, Ca
|
||||||
OrganizationId = orgId,
|
OrganizationId = orgId,
|
||||||
Name = "Бухгалтер",
|
Name = "Бухгалтер",
|
||||||
Description = "Просмотр всех данных и отчётов, без редактирования",
|
Description = "Просмотр всех данных и отчётов, без редактирования",
|
||||||
IsSystem = true, SortOrder = 50,
|
IsSystem = false, SortOrder = 50,
|
||||||
Permissions = new RolePermissions
|
Permissions = new RolePermissions
|
||||||
{
|
{
|
||||||
ProductsView = true,
|
ProductsView = true,
|
||||||
|
|
|
||||||
2000
src/food-market.infrastructure/Persistence/Migrations/20260427020000_Phase4b_RolesSimplify.Designer.cs
generated
Normal file
2000
src/food-market.infrastructure/Persistence/Migrations/20260427020000_Phase4b_RolesSimplify.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,34 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace foodmarket.Infrastructure.Persistence.Migrations
|
||||||
|
{
|
||||||
|
/// <summary>Идемпотентный фикс: системными остаются только «Администратор»
|
||||||
|
/// и «Кассир», остальные демоутятся в кастомные. Кассирский набор прав
|
||||||
|
/// перетряхивается на минимально-достаточный POS-набор. На чистой БД
|
||||||
|
/// сидер сразу создаст роли в правильных статусах; миграция нужна для
|
||||||
|
/// баз, где Phase4 уже отработал по старой схеме.</summary>
|
||||||
|
public partial class Phase4b_RolesSimplify : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder b)
|
||||||
|
{
|
||||||
|
b.Sql(@"
|
||||||
|
UPDATE public.employee_roles
|
||||||
|
SET ""IsSystem"" = false
|
||||||
|
WHERE ""Name"" NOT IN ('Администратор', 'Кассир');
|
||||||
|
");
|
||||||
|
b.Sql(@"
|
||||||
|
UPDATE public.employee_roles
|
||||||
|
SET permissions = '{""productsView"":true,""stocksView"":true,""retailSalesOperate"":true}'::jsonb
|
||||||
|
WHERE ""Name"" = 'Кассир' AND ""IsSystem"" = true;
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder b)
|
||||||
|
{
|
||||||
|
// No-op: возвращать роли в IsSystem=true автоматически нельзя,
|
||||||
|
// юзер мог переименовать или подкрутить permissions.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue