can(Permissions::WORK_ORDERS_CREATE) */ class Permissions { // Clients public const CLIENTS_VIEW_ALL = 'clients.view_all'; public const CLIENTS_VIEW_OWN = 'clients.view_own'; public const CLIENTS_CREATE = 'clients.create'; public const CLIENTS_EDIT = 'clients.edit'; public const CLIENTS_DELETE = 'clients.delete'; public const CLIENTS_EXPORT = 'clients.export'; // Vehicles public const VEHICLES_VIEW_ALL = 'vehicles.view_all'; public const VEHICLES_CREATE = 'vehicles.create'; public const VEHICLES_EDIT = 'vehicles.edit'; public const VEHICLES_DELETE = 'vehicles.delete'; // Work orders (Fișe) public const WORK_ORDERS_VIEW_ALL = 'work_orders.view_all'; public const WORK_ORDERS_VIEW_OWN_ASSIGNED = 'work_orders.view_own_assigned'; public const WORK_ORDERS_CREATE = 'work_orders.create'; public const WORK_ORDERS_EDIT = 'work_orders.edit'; public const WORK_ORDERS_DELETE = 'work_orders.delete'; public const WORK_ORDERS_CHANGE_STATUS = 'work_orders.change_status'; public const WORK_ORDERS_APPROVE_DISCOUNT_5 = 'work_orders.approve_discount_5'; public const WORK_ORDERS_APPROVE_DISCOUNT_20 = 'work_orders.approve_discount_20'; public const WORK_ORDERS_APPROVE_DISCOUNT_ANY = 'work_orders.approve_discount_any'; public const WORK_ORDERS_PRINT = 'work_orders.print'; // Finance public const FINANCE_VIEW_OVERVIEW = 'finance.view_overview'; public const FINANCE_VIEW_PL = 'finance.view_pl'; public const FINANCE_CREATE_PAYMENT = 'finance.create_payment'; public const FINANCE_DELETE_PAYMENT = 'finance.delete_payment'; public const FINANCE_CREATE_EXPENSE = 'finance.create_expense'; public const FINANCE_EXPORT = 'finance.export'; // Salaries public const SALARIES_VIEW_OWN = 'salaries.view_own'; public const SALARIES_VIEW_ALL = 'salaries.view_all'; public const SALARIES_CALCULATE = 'salaries.calculate'; public const SALARIES_MARK_PAID = 'salaries.mark_paid'; // Inventory public const INVENTORY_VIEW = 'inventory.view'; public const INVENTORY_CREATE_PART = 'inventory.create_part'; public const INVENTORY_EDIT_PART = 'inventory.edit_part'; public const INVENTORY_DELETE_PART = 'inventory.delete_part'; public const INVENTORY_ADJUST_STOCK = 'inventory.adjust_stock'; public const INVENTORY_CREATE_PURCHASE = 'inventory.create_purchase'; public const INVENTORY_RECEIVE_GOODS = 'inventory.receive_goods'; // Suppliers public const SUPPLIERS_VIEW = 'suppliers.view'; public const SUPPLIERS_EDIT = 'suppliers.edit'; public const SUPPLIERS_DELETE = 'suppliers.delete'; // Admin public const ADMIN_USERS_VIEW = 'admin.users.view'; public const ADMIN_USERS_MANAGE = 'admin.users.manage'; public const ADMIN_ROLES_MANAGE = 'admin.roles.manage'; public const ADMIN_SETTINGS_EDIT = 'admin.settings.edit'; public const ADMIN_INTEGRATIONS = 'admin.settings.integrations'; public const ADMIN_API_TOKENS_MANAGE = 'admin.api_tokens.manage'; public const ADMIN_AUDIT_LOG_VIEW = 'admin.audit_log.view'; public const ADMIN_BACKUP_DOWNLOAD = 'admin.backup.download'; // AI & Analytics public const AI_ASSISTANT_USE = 'ai_assistant.use'; public const AI_ASSISTANT_CONFIGURE_KEYS = 'ai_assistant.configure_keys'; public const ANALYTICS_VIEW = 'analytics.view'; /** Full list — used by seeder. */ public static function all(): array { return [ self::CLIENTS_VIEW_ALL, self::CLIENTS_VIEW_OWN, self::CLIENTS_CREATE, self::CLIENTS_EDIT, self::CLIENTS_DELETE, self::CLIENTS_EXPORT, self::VEHICLES_VIEW_ALL, self::VEHICLES_CREATE, self::VEHICLES_EDIT, self::VEHICLES_DELETE, self::WORK_ORDERS_VIEW_ALL, self::WORK_ORDERS_VIEW_OWN_ASSIGNED, self::WORK_ORDERS_CREATE, self::WORK_ORDERS_EDIT, self::WORK_ORDERS_DELETE, self::WORK_ORDERS_CHANGE_STATUS, self::WORK_ORDERS_APPROVE_DISCOUNT_5, self::WORK_ORDERS_APPROVE_DISCOUNT_20, self::WORK_ORDERS_APPROVE_DISCOUNT_ANY, self::WORK_ORDERS_PRINT, self::FINANCE_VIEW_OVERVIEW, self::FINANCE_VIEW_PL, self::FINANCE_CREATE_PAYMENT, self::FINANCE_DELETE_PAYMENT, self::FINANCE_CREATE_EXPENSE, self::FINANCE_EXPORT, self::SALARIES_VIEW_OWN, self::SALARIES_VIEW_ALL, self::SALARIES_CALCULATE, self::SALARIES_MARK_PAID, self::INVENTORY_VIEW, self::INVENTORY_CREATE_PART, self::INVENTORY_EDIT_PART, self::INVENTORY_DELETE_PART, self::INVENTORY_ADJUST_STOCK, self::INVENTORY_CREATE_PURCHASE, self::INVENTORY_RECEIVE_GOODS, self::SUPPLIERS_VIEW, self::SUPPLIERS_EDIT, self::SUPPLIERS_DELETE, self::ADMIN_USERS_VIEW, self::ADMIN_USERS_MANAGE, self::ADMIN_ROLES_MANAGE, self::ADMIN_SETTINGS_EDIT, self::ADMIN_INTEGRATIONS, self::ADMIN_API_TOKENS_MANAGE, self::ADMIN_AUDIT_LOG_VIEW, self::ADMIN_BACKUP_DOWNLOAD, self::AI_ASSISTANT_USE, self::AI_ASSISTANT_CONFIGURE_KEYS, self::ANALYTICS_VIEW, ]; } /** Groups for UI rendering: module → list of permissions. */ public static function grouped(): array { $groups = []; foreach (self::all() as $slug) { [$module] = explode('.', $slug, 2); $groups[$module][] = $slug; } return $groups; } public static function labels(): array { return [ 'clients' => 'Clienți', 'vehicles' => 'Mașini', 'work_orders' => 'Fișe lucru', 'finance' => 'Finanțe', 'salaries' => 'Salarii', 'inventory' => 'Stoc', 'suppliers' => 'Furnizori', 'admin' => 'Administrare', 'ai_assistant' => 'AI Assistant', 'analytics' => 'Analitică', ]; } /** * Role-permission matrix per TZ §2.4. * Returns: ['owner' => [perm1, perm2, ...], ...] */ public static function roleMatrix(): array { $all = self::all(); $matrix = []; // owner = everything $matrix['owner'] = $all; // admin = everything except billing-only stuff (we don't have that yet, so = all) $matrix['admin'] = $all; // manager: operations + reporting, no destructive $matrix['manager'] = [ self::CLIENTS_VIEW_ALL, self::CLIENTS_CREATE, self::CLIENTS_EDIT, self::CLIENTS_EXPORT, self::VEHICLES_VIEW_ALL, self::VEHICLES_CREATE, self::VEHICLES_EDIT, self::WORK_ORDERS_VIEW_ALL, self::WORK_ORDERS_VIEW_OWN_ASSIGNED, self::WORK_ORDERS_CREATE, self::WORK_ORDERS_EDIT, self::WORK_ORDERS_CHANGE_STATUS, self::WORK_ORDERS_APPROVE_DISCOUNT_5, self::WORK_ORDERS_APPROVE_DISCOUNT_20, self::WORK_ORDERS_PRINT, self::FINANCE_VIEW_OVERVIEW, self::FINANCE_CREATE_PAYMENT, self::FINANCE_CREATE_EXPENSE, self::SALARIES_VIEW_OWN, self::INVENTORY_VIEW, self::INVENTORY_CREATE_PART, self::INVENTORY_EDIT_PART, self::INVENTORY_ADJUST_STOCK, self::INVENTORY_CREATE_PURCHASE, self::INVENTORY_RECEIVE_GOODS, self::SUPPLIERS_VIEW, self::SUPPLIERS_EDIT, self::AI_ASSISTANT_USE, self::ANALYTICS_VIEW, ]; // accountant: finance + reporting only $matrix['accountant'] = [ self::CLIENTS_VIEW_ALL, self::CLIENTS_EXPORT, self::VEHICLES_VIEW_ALL, self::WORK_ORDERS_VIEW_ALL, self::FINANCE_VIEW_OVERVIEW, self::FINANCE_VIEW_PL, self::FINANCE_CREATE_PAYMENT, self::FINANCE_DELETE_PAYMENT, self::FINANCE_CREATE_EXPENSE, self::FINANCE_EXPORT, self::SALARIES_VIEW_OWN, self::SALARIES_VIEW_ALL, self::SALARIES_CALCULATE, self::SALARIES_MARK_PAID, self::INVENTORY_VIEW, self::SUPPLIERS_VIEW, self::ANALYTICS_VIEW, self::AI_ASSISTANT_USE, ]; // receptionist: front-desk operations $matrix['receptionist'] = [ self::CLIENTS_VIEW_ALL, self::CLIENTS_CREATE, self::CLIENTS_EDIT, self::VEHICLES_VIEW_ALL, self::VEHICLES_CREATE, self::VEHICLES_EDIT, self::WORK_ORDERS_VIEW_ALL, self::WORK_ORDERS_CREATE, self::WORK_ORDERS_EDIT, self::WORK_ORDERS_CHANGE_STATUS, self::WORK_ORDERS_APPROVE_DISCOUNT_5, self::WORK_ORDERS_PRINT, self::FINANCE_CREATE_PAYMENT, self::SALARIES_VIEW_OWN, self::INVENTORY_VIEW, self::AI_ASSISTANT_USE, ]; // mechanic: only own WOs + inventory view $matrix['mechanic'] = [ self::WORK_ORDERS_VIEW_OWN_ASSIGNED, self::WORK_ORDERS_CHANGE_STATUS, self::INVENTORY_VIEW, self::SALARIES_VIEW_OWN, ]; // viewer: read-only $matrix['viewer'] = [ self::CLIENTS_VIEW_ALL, self::VEHICLES_VIEW_ALL, self::WORK_ORDERS_VIEW_ALL, self::INVENTORY_VIEW, self::SUPPLIERS_VIEW, self::AI_ASSISTANT_USE, ]; return $matrix; } public static function roleLabels(): array { return [ 'owner' => 'Proprietar', 'admin' => 'Administrator', 'manager' => 'Manager', 'accountant' => 'Contabil', 'receptionist' => 'Recepție', 'mechanic' => 'Mecanic', 'viewer' => 'Vizitator', ]; } }