namespace foodmarket.Domain.Organizations;
/// Набор флагов разрешений роли. Хранится JSON-колонкой
/// (owned by EmployeeRole). Семантика: false = доступ запрещён.
public class RolePermissions
{
// Каталог
public bool ProductsView { get; set; }
public bool ProductsEdit { get; set; }
public bool ProductsDelete { get; set; }
public bool ProductGroupsManage { get; set; }
public bool PriceTypesManage { get; set; }
public bool UnitsManage { get; set; }
// Закупки
public bool SuppliesView { get; set; }
public bool SuppliesEdit { get; set; }
public bool SuppliesPost { get; set; }
public bool SuppliesDelete { get; set; }
// Продажи (отгрузка контрагенту + POS)
public bool DemandsView { get; set; }
public bool DemandsEdit { get; set; }
public bool DemandsPost { get; set; }
public bool RetailSalesOperate { get; set; }
public bool RetailSalesRefund { get; set; }
// Контрагенты
public bool CounterpartiesView { get; set; }
public bool CounterpartiesEdit { get; set; }
public bool CounterpartiesDelete { get; set; }
// Склад / Остатки
public bool StocksView { get; set; }
public bool InventoryEdit { get; set; }
public bool LossEdit { get; set; }
public bool EnterEdit { get; set; }
public bool TransferEdit { get; set; }
// Отчёты
public bool ReportsView { get; set; }
public bool ReportsFinanceView { get; set; }
public bool ReportsStockView { get; set; }
// Настройки организации
public bool OrgSettingsManage { get; set; }
public bool EmployeesManage { get; set; }
public bool RolesManage { get; set; }
public bool StoresManage { get; set; }
public bool RetailPointsManage { get; set; }
public bool CashRegistersManage { get; set; }
public bool IntegrationsManage { get; set; }
// Sprint 9: лояльность и акции (Admin-only по умолчанию).
public bool LoyaltyManage { get; set; }
public bool PromotionsManage { get; set; }
// Sprint 33 (модуль «Деньги»):
// MoneyView — видеть счета, движения, отчёт «Деньги», долги.
// Кассир — да (видит выручку своей смены); Кладовщик — только через SuppliesView,
// увидит оплаченность приёмки, но не остатки по счетам.
// MoneyEdit — создавать/редактировать платежи, ордера, переводы,
// счета, статьи расходов, корректировки взаиморасчётов.
// Admin-only по умолчанию.
// CashShiftOperate — открыть/закрыть смену, вносить/выплачивать деньги
// в своей смене. Кассир — да.
public bool MoneyView { get; set; }
public bool MoneyEdit { get; set; }
public bool CashShiftOperate { get; set; }
/// Права, доступные только в расширенном режиме организации
/// (в простом режиме скрыты и на сервере, и в UI). Единый источник правды,
/// зеркалит контроллеры с [RequiresAdvancedMode]: Оптовые отгрузки,
/// Перемещения, Лояльность, Акции, Типы цен.
public static readonly IReadOnlySet AdvancedOnly = new HashSet(StringComparer.Ordinal)
{
nameof(DemandsView), nameof(DemandsEdit), nameof(DemandsPost),
nameof(TransferEdit), nameof(LoyaltyManage), nameof(PromotionsManage),
nameof(PriceTypesManage),
};
/// Все bool-флаги прав в виде словаря имя→значение (через рефлексию).
public Dictionary ToDictionary()
{
var dict = new Dictionary(StringComparer.Ordinal);
foreach (var p in typeof(RolePermissions).GetProperties())
if (p.PropertyType == typeof(bool) && p.CanRead)
dict[p.Name] = (bool)p.GetValue(this)!;
return dict;
}
/// Эффективные права текущего пользователя для клиента (моб./веб):
/// SuperAdmin — всё без ограничений; Admin — всё, но в простом режиме
/// advanced-only скрыты; обычная роль — её флаги, в простом режиме с
/// обнулением advanced-only. Единый источник, чтобы клиенты скрывали одно и то же.
public static Dictionary Effective(RolePermissions? role, bool isSuperAdmin, bool isAdmin, bool advancedMode)
{
var basePerms = (isSuperAdmin || isAdmin) ? All() : (role ?? new RolePermissions());
var dict = basePerms.ToDictionary();
// SuperAdmin обходит гейт расширенного режима; остальным в простом режиме
// advanced-only права выключаем.
if (!isSuperAdmin && !advancedMode)
foreach (var name in AdvancedOnly)
dict[name] = false;
return dict;
}
/// Полный набор всех true — для системной роли «Администратор».
public static RolePermissions All() => new()
{
ProductsView = true, ProductsEdit = true, ProductsDelete = true,
ProductGroupsManage = true, PriceTypesManage = true, UnitsManage = true,
SuppliesView = true, SuppliesEdit = true, SuppliesPost = true, SuppliesDelete = true,
DemandsView = true, DemandsEdit = true, DemandsPost = true,
RetailSalesOperate = true, RetailSalesRefund = true,
CounterpartiesView = true, CounterpartiesEdit = true, CounterpartiesDelete = true,
StocksView = true, InventoryEdit = true, LossEdit = true, EnterEdit = true, TransferEdit = true,
ReportsView = true, ReportsFinanceView = true, ReportsStockView = true,
OrgSettingsManage = true, EmployeesManage = true, RolesManage = true,
StoresManage = true, RetailPointsManage = true,
CashRegistersManage = true, IntegrationsManage = true,
LoyaltyManage = true, PromotionsManage = true,
MoneyView = true, MoneyEdit = true, CashShiftOperate = true,
};
}