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_VIEW_INTERNAL_MARGIN = 'finance.view_internal_margin'; 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'; // Injector diagnostic protocols public const INJECTOR_PROTOCOLS_VIEW = 'injector_protocols.view'; public const INJECTOR_PROTOCOLS_CONCLUDE = 'injector_protocols.conclude'; /** 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_VIEW_INTERNAL_MARGIN, 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, self::INJECTOR_PROTOCOLS_VIEW, self::INJECTOR_PROTOCOLS_CONCLUDE, ]; } /** 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ă', 'injector_protocols' => 'Protocol forsunki', ]; } /** Human-readable label for each permission slug. Used by role editor + audit UI. */ public static function permissionLabels(): array { return [ 'clients.view_all' => 'Vezi toți clienții', 'clients.view_own' => 'Vezi doar clienții proprii', 'clients.create' => 'Adaugă client', 'clients.edit' => 'Editează client', 'clients.delete' => 'Șterge client', 'clients.export' => 'Exportă clienți (CSV)', 'vehicles.view_all' => 'Vezi toate mașinile', 'vehicles.create' => 'Adaugă mașină', 'vehicles.edit' => 'Editează mașină', 'vehicles.delete' => 'Șterge mașină', 'work_orders.view_all' => 'Vezi toate fișele', 'work_orders.view_own_assigned' => 'Vezi doar fișele proprii asignate', 'work_orders.create' => 'Deschide fișă nouă', 'work_orders.edit' => 'Editează fișă', 'work_orders.delete' => 'Șterge fișă', 'work_orders.change_status' => 'Schimbă statusul fișei', 'work_orders.approve_discount_5' => 'Aprobă discount ≤ 5%', 'work_orders.approve_discount_20' => 'Aprobă discount ≤ 20%', 'work_orders.approve_discount_any' => 'Aprobă discount fără limită', 'work_orders.print' => 'Tipărește / PDF fișă', 'finance.view_overview' => 'Vezi panou finanțe', 'finance.view_pl' => 'Vezi profit & pierdere (P&L)', 'finance.view_internal_margin' => 'Vezi marja internă (baza de salariu)', 'finance.create_payment' => 'Înregistrează plată', 'finance.delete_payment' => 'Șterge plată', 'finance.create_expense' => 'Înregistrează cheltuială', 'finance.export' => 'Exportă rapoarte financiare', 'salaries.view_own' => 'Vezi propriul salariu', 'salaries.view_all' => 'Vezi salariile tuturor', 'salaries.calculate' => 'Calculează salarii', 'salaries.mark_paid' => 'Marchează salariul ca plătit', 'inventory.view' => 'Vezi stoc (piese)', 'inventory.create_part' => 'Adaugă piesă în catalog', 'inventory.edit_part' => 'Editează piesă', 'inventory.delete_part' => 'Șterge piesă', 'inventory.adjust_stock' => 'Ajustează stocul manual', 'inventory.create_purchase' => 'Creează comandă de aprovizionare', 'inventory.receive_goods' => 'Recepționează marfă', 'suppliers.view' => 'Vezi furnizori', 'suppliers.edit' => 'Editează furnizor', 'suppliers.delete' => 'Șterge furnizor', 'admin.users.view' => 'Vezi utilizatori', 'admin.users.manage' => 'Gestionează utilizatori (creează/blochează)', 'admin.roles.manage' => 'Editează roluri & drepturi', 'admin.settings.edit' => 'Editează setările companiei', 'admin.settings.integrations' => 'Configurează integrări externe', 'admin.api_tokens.manage' => 'Gestionează tokene API', 'admin.audit_log.view' => 'Vezi jurnalul de audit', 'admin.backup.download' => 'Descarcă backup', 'ai_assistant.use' => 'Folosește AI Assistant', 'ai_assistant.configure_keys' => 'Configurează chei API pentru AI', 'analytics.view' => 'Vezi rapoarte & analitică', 'injector_protocols.view' => 'Vezi protocoalele de diagnostic forsunki', 'injector_protocols.conclude' => 'Completează Заключение (concluzii + semnătură)', ]; } /** * 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_VIEW_INTERNAL_MARGIN, 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, self::INJECTOR_PROTOCOLS_VIEW, self::INJECTOR_PROTOCOLS_CONCLUDE, ]; // 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, self::INJECTOR_PROTOCOLS_VIEW, ]; // 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, self::INJECTOR_PROTOCOLS_VIEW, self::INJECTOR_PROTOCOLS_CONCLUDE, ]; // 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', ]; } }