diff --git a/app/Enums/Permission.php b/app/Enums/Permission.php new file mode 100644 index 0000000..5131b9d --- /dev/null +++ b/app/Enums/Permission.php @@ -0,0 +1,184 @@ +value; + } +} diff --git a/app/Enums/Role.php b/app/Enums/Role.php new file mode 100644 index 0000000..39872f7 --- /dev/null +++ b/app/Enums/Role.php @@ -0,0 +1,458 @@ + 'Developer', + self::OWNER => 'Owner', + self::ADMIN_TOKO => 'Admin Toko', + self::ADMIN_BAHAN_BAKU => 'Admin Bahan Baku', + self::DIREKTUR => 'Direktur', + self::MARKETING_OFFLINE => 'Marketing Offline', + self::MARKETING_ONLINE => 'Marketing Online', + self::CASHIER => 'Kasir', + self::NON_OPERATOR => 'Non Operator', + self::STOK_OPNAME => 'Stok Opname', + }; + } + + public function permissions(): array + { + return match ($this) { + self::DEVELOPER, self::OWNER => array_values(array_filter( + Permission::cases(), + fn (Permission $permission) => ! in_array($permission, [ + Permission::ATTENDANCES_CREATE, + Permission::ATTENDANCES_DELETE, + + Permission::STOK_OPNAMES_SUBMIT, + + Permission::ROLES_VIEW, + Permission::ROLES_CREATE, + Permission::ROLES_UPDATE, + Permission::ROLES_DELETE, + ], true) + )), + + self::DIREKTUR => [ + Permission::DASHBOARD_VIEW, + Permission::DASHBOARD_ATTENDANCE, + Permission::DASHBOARD_REVENUE, + Permission::DASHBOARD_EXPENSE, + Permission::DASHBOARD_ORDERS_CHANNEL, + Permission::DASHBOARD_ORDERS_PAYMENT, + Permission::DASHBOARD_ORDERS_MARKETING, + Permission::DASHBOARD_ORDERS_STATUS, + Permission::ANALYSIS_VIEW, + + Permission::ANALYSIS_ATTENDANCE, + Permission::ANALYSIS_CASH, + Permission::ANALYSIS_PRODUCT_STOCK, + Permission::ANALYSIS_REVENUE, + Permission::ANALYSIS_EXPENSE, + Permission::ANALYSIS_BUSY_HOURS, + Permission::ANALYSIS_PROFIT_ORDERS, + Permission::ANALYSIS_PROFIT_HPP, + Permission::ANALYSIS_PROFIT_GROSS, + Permission::ANALYSIS_PROFIT_MARGIN, + Permission::ANALYSIS_TOP_CUSTOMERS, + Permission::ANALYSIS_TOP_PRODUCTS, + Permission::ANALYSIS_MARKETING_SALES, + + Permission::EMPLOYEES_VIEW, + + Permission::ATTENDANCES_VIEW, + Permission::ATTENDANCES_CREATE, + Permission::ATTENDANCES_DELETE, + Permission::ATTENDANCES_MANAGE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_DELETE, + + Permission::CATEGORIES_VIEW, + + Permission::CUSTOMERS_VIEW, + + Permission::PRODUCTS_VIEW, + Permission::STOCKS_VIEW, + + Permission::ORDERS_VIEW, + + Permission::CUTTINGS_VIEW, + + Permission::CASH_VIEW, + + Permission::EXPENSES_VIEW, + + Permission::ACTIVITY_LOGS_VIEW, + + Permission::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::PAYROLL_VIEW, + ], + + self::ADMIN_TOKO => [ + Permission::DASHBOARD_VIEW, + Permission::DASHBOARD_REVENUE, + Permission::DASHBOARD_EXPENSE, + Permission::DASHBOARD_ORDERS_CHANNEL, + Permission::DASHBOARD_ORDERS_PAYMENT, + Permission::DASHBOARD_ORDERS_MARKETING, + Permission::DASHBOARD_ORDERS_STATUS, + + Permission::ANALYSIS_VIEW, + Permission::ANALYSIS_ATTENDANCE, + Permission::ANALYSIS_CASH, + Permission::ANALYSIS_PRODUCT_STOCK, + Permission::ANALYSIS_REVENUE, + Permission::ANALYSIS_EXPENSE, + Permission::ANALYSIS_BUSY_HOURS, + Permission::ANALYSIS_PROFIT_ORDERS, + Permission::ANALYSIS_PROFIT_HPP, + Permission::ANALYSIS_PROFIT_GROSS, + Permission::ANALYSIS_TOP_CUSTOMERS, + Permission::ANALYSIS_TOP_PRODUCTS, + Permission::ANALYSIS_MARKETING_SALES, + + Permission::STOCKS_VIEW, + + Permission::STOK_OPNAMES_VIEW, + + Permission::ATTENDANCES_VIEW, + Permission::ATTENDANCES_CREATE, + Permission::ATTENDANCES_DELETE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_DELETE, + + Permission::RESTOCKS_VIEW, + Permission::RESTOCKS_CREATE, + Permission::RESTOCKS_UPDATE, + Permission::RESTOCKS_DELETE, + + Permission::CUSTOMERS_VIEW, + Permission::CUSTOMERS_CREATE, + Permission::CUSTOMERS_UPDATE, + Permission::CUSTOMERS_DELETE, + + Permission::PRODUCTS_VIEW, + Permission::PRODUCTS_CREATE, + Permission::PRODUCTS_UPDATE, + Permission::PRODUCTS_DELETE, + Permission::PRODUCTS_TOGGLE_STATUS, + Permission::STOCKS_VIEW, + + Permission::OWNER_VERIFICATIONS_VIEW, + + Permission::ORDERS_VIEW, + Permission::ORDERS_CREATE, + Permission::ORDERS_UPDATE, + Permission::ORDERS_DELETE, + Permission::ORDERS_SEND, + Permission::ORDERS_COMPLETE, + Permission::ORDERS_CANCEL, + + Permission::CASH_VIEW, + Permission::CASH_DEPOSIT, + Permission::CASH_WITHDRAW, + Permission::CASH_UPDATE, + Permission::CASH_DELETE, + + Permission::EXPENSES_VIEW, + Permission::EXPENSES_CREATE, + Permission::EXPENSES_UPDATE, + Permission::EXPENSES_DELETE, + + Permission::ACTIVITY_LOGS_VIEW, + + Permission::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::PAYROLL_VIEW, + Permission::PAYROLL_ADJUST, + + Permission::SETTINGS_VIEW_SYSTEM, + Permission::SETTINGS_UPDATE_SYSTEM, + Permission::SETTINGS_VIEW_SOCIAL_MEDIA, + Permission::SETTINGS_UPDATE_SOCIAL_MEDIA, + Permission::SETTINGS_VIEW_MARKETPLACE, + Permission::SETTINGS_UPDATE_MARKETPLACE, + Permission::SETTINGS_VIEW_HR, + Permission::SETTINGS_UPDATE_HR, + Permission::SETTINGS_VIEW_HOMEPAGE, + Permission::SETTINGS_UPDATE_HOMEPAGE, + + Permission::EMPLOYEES_VIEW, + Permission::EMPLOYEES_CREATE, + Permission::EMPLOYEES_UPDATE, + Permission::EMPLOYEES_TOGGLE_STATUS, + Permission::EMPLOYEES_DELETE, + ], + + self::CASHIER => [ + Permission::DASHBOARD_VIEW, + Permission::DASHBOARD_REVENUE, + Permission::DASHBOARD_ORDERS_CHANNEL, + Permission::DASHBOARD_ORDERS_PAYMENT, + Permission::DASHBOARD_ORDERS_STATUS, + + Permission::ANALYSIS_VIEW, + Permission::ANALYSIS_ATTENDANCE, + Permission::ANALYSIS_REVENUE, + Permission::ANALYSIS_PROFIT_ORDERS, + Permission::ANALYSIS_TOP_CUSTOMERS, + Permission::ANALYSIS_TOP_PRODUCTS, + + Permission::ATTENDANCES_VIEW, + Permission::ATTENDANCES_CREATE, + Permission::ATTENDANCES_DELETE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_DELETE, + + Permission::CUSTOMERS_VIEW, + Permission::CUSTOMERS_CREATE, + Permission::CUSTOMERS_UPDATE, + Permission::CUSTOMERS_DELETE, + + Permission::PRODUCTS_VIEW, + + Permission::ORDERS_VIEW, + Permission::ORDERS_CREATE, + Permission::ORDERS_UPDATE, + Permission::ORDERS_DELETE, + Permission::ORDERS_SEND, + Permission::ORDERS_COMPLETE, + Permission::ORDERS_CANCEL, + + Permission::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::PAYROLL_VIEW, + Permission::PAYROLL_ADJUST, + ], + + self::ADMIN_BAHAN_BAKU => [ + Permission::DASHBOARD_VIEW, + + Permission::EMPLOYEES_VIEW, + Permission::EMPLOYEES_CREATE, + Permission::EMPLOYEES_UPDATE, + Permission::EMPLOYEES_TOGGLE_STATUS, + Permission::EMPLOYEES_DELETE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_DELETE, + + Permission::CATEGORIES_VIEW, + Permission::CATEGORIES_CREATE, + Permission::CATEGORIES_UPDATE, + Permission::CATEGORIES_DELETE, + + Permission::SUPPLIERS_VIEW, + Permission::SUPPLIERS_CREATE, + Permission::SUPPLIERS_UPDATE, + Permission::SUPPLIERS_DELETE, + + Permission::RAW_MATERIALS_VIEW, + Permission::RAW_MATERIALS_CREATE, + Permission::RAW_MATERIALS_UPDATE, + Permission::RAW_MATERIALS_TOGGLE_STATUS, + Permission::STOCKS_VIEW, + + Permission::OWNER_VERIFICATIONS_VIEW, + + Permission::PRODUCTS_VIEW, + Permission::PRODUCTS_CREATE, + Permission::PRODUCTS_UPDATE, + Permission::PRODUCTS_DELETE, + Permission::PRODUCTS_TOGGLE_STATUS, + + Permission::CUTTINGS_VIEW, + Permission::CUTTINGS_CREATE, + Permission::CUTTINGS_UPDATE, + Permission::CUTTINGS_DELETE, + Permission::CUTTINGS_COMPLETE, + Permission::PURCHASES_VIEW, + Permission::PURCHASES_CREATE, + Permission::PURCHASES_UPDATE, + Permission::PURCHASES_DELETE, + + Permission::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::ACTIVITY_LOGS_VIEW, + + Permission::PAYROLL_VIEW, + ], + + self::MARKETING_OFFLINE, self::MARKETING_ONLINE => [ + Permission::DASHBOARD_VIEW, + Permission::DASHBOARD_REVENUE, + Permission::DASHBOARD_ORDERS_CHANNEL, + Permission::DASHBOARD_ORDERS_PAYMENT, + Permission::DASHBOARD_ORDERS_MARKETING, + Permission::DASHBOARD_ORDERS_STATUS, + + Permission::ANALYSIS_VIEW, + Permission::ANALYSIS_ATTENDANCE, + Permission::ANALYSIS_REVENUE, + Permission::ANALYSIS_PROFIT_ORDERS, + Permission::ANALYSIS_TOP_PRODUCTS, + Permission::ANALYSIS_TOP_CUSTOMERS, + + Permission::ATTENDANCES_VIEW, + Permission::ATTENDANCES_CREATE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_DELETE, + + Permission::PRODUCTS_VIEW, + + Permission::ORDERS_VIEW, + + Permission::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::PAYROLL_VIEW, + ], + + self::NON_OPERATOR => [ + Permission::DASHBOARD_VIEW, + + Permission::ANALYSIS_VIEW, + Permission::ANALYSIS_ATTENDANCE, + + Permission::ATTENDANCES_VIEW, + Permission::ATTENDANCES_CREATE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_DELETE, + + Permission::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::PAYROLL_VIEW, + ], + + self::STOK_OPNAME => [ + Permission::DASHBOARD_VIEW, + + Permission::ATTENDANCES_VIEW, + Permission::ATTENDANCES_CREATE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_DELETE, + + Permission::PRODUCTS_VIEW, + Permission::STOCKS_VIEW, + + Permission::STOK_OPNAMES_VIEW, + Permission::STOK_OPNAMES_CREATE, + Permission::STOK_OPNAMES_UPDATE, + Permission::STOK_OPNAMES_DELETE, + Permission::STOK_OPNAMES_SUBMIT, + + Permission::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::PAYROLL_VIEW, + ], + }; + } + + public function isAssignable(): bool + { + return $this !== self::DEVELOPER; + } + + /** + * @return list + */ + public static function assignableSelectOptions(): array + { + return collect(self::cases()) + ->filter(fn (self $role) => $role->isAssignable()) + ->map(fn (self $role) => [ + 'value' => $role->value, + 'label' => $role->label(), + ]) + ->values() + ->all(); + } + + /** + * @return list + */ + public static function assignableValues(): array + { + return collect(self::cases()) + ->filter(fn (self $role) => $role->isAssignable()) + ->map(fn (self $role) => $role->value) + ->values() + ->all(); + } + + /** + * @return list + */ + public static function values(): array + { + return array_column(self::cases(), 'value'); + } +} diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 6f5a55b..0473a06 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -40,7 +40,9 @@ public function share(Request $request): array 'name' => config('app.name'), 'auth' => [ 'user' => $request->user() - ? $request->user()->load('userProfile', 'roles', 'permissions') + ? tap($request->user()->load('userProfile', 'roles'), function ($user) { + $user->setRelation('permissions', $user->getAllPermissions()); + }) : null, ], 'sidebarOpen' => ! $request->hasCookie('sidebar_state') || $request->cookie('sidebar_state') === 'true', diff --git a/database/seeders/RolePermissionSeeder.php b/database/seeders/RolePermissionSeeder.php index 36e20d1..ed4d3fd 100644 --- a/database/seeders/RolePermissionSeeder.php +++ b/database/seeders/RolePermissionSeeder.php @@ -14,25 +14,30 @@ public function run(): void app()[PermissionRegistrar::class]->forgetCachedPermissions(); $permissions = [ - 'user' => ['view', 'create', 'update', 'delete', 'toggle-active', 'reset-password'], - 'category' => ['view', 'create', 'update', 'delete'], - 'supplier' => ['view', 'create', 'update', 'delete'], - 'customer' => ['view', 'create', 'update', 'delete'], - 'cash-account' => ['view', 'deposit', 'withdrawal', 'update', 'delete'], - 'expense' => ['view', 'create', 'update', 'delete'], - 'employee-advance' => ['view', 'create', 'update', 'delete', 'approve', 'pay'], - 'payroll-period' => ['view', 'show', 'current', 'close', 'reopen'], - 'payroll' => ['pay', 'cancel'], - 'payroll-adjustment' => ['create', 'delete'], - 'leave-request' => ['view', 'create', 'update', 'delete', 'approve', 'reject'], - 'attendance' => ['view', 'check-in', 'check-out', 'by-date'], - 'settings' => ['view', 'update-system', 'update-homepage', 'update-social-media', 'update-marketplace', 'update-hr'], - 'purchase' => ['view', 'create', 'update', 'delete'], - 'cutting' => ['view', 'create', 'update', 'delete'], - 'restock' => ['view', 'create', 'update', 'delete'], - 'transaction' => ['view', 'create', 'update', 'delete'], - 'dashboard' => ['attendance', 'revenue', 'expense', 'orders_channel', 'orders_payment', 'orders_marketing', 'orders_status'], - 'analysis' => ['attendance', 'cash', 'raw_materials', 'product_stock', 'revenue', 'expense', 'profit_gross', 'profit_hpp', 'profit_orders', 'marketing_sales', 'top_suppliers', 'top_products', 'top_customers', 'busy_hours'], + 'dashboard' => ['view', 'attendance', 'revenue', 'expense', 'orders_channel', 'orders_payment', 'orders_marketing', 'orders_status', 'cash'], + 'analysis' => ['view', 'attendance', 'cash', 'product_stock', 'revenue', 'expense', 'busy_hours', 'profit_orders', 'profit_hpp', 'profit_gross', 'profit_margin', 'top_customers', 'top_products', 'marketing_sales', 'raw_materials'], + 'employees' => ['view', 'create', 'update', 'delete', 'toggle_status', 'reset_password'], + 'attendances' => ['view', 'create', 'delete', 'manage'], + 'leave_requests' => ['view', 'create', 'update', 'delete', 'verify'], + 'categories' => ['view', 'create', 'update', 'delete'], + 'customers' => ['view', 'create', 'update', 'delete'], + 'products' => ['view', 'create', 'update', 'delete', 'toggle_status'], + 'stocks' => ['view'], + 'orders' => ['view', 'create', 'update', 'delete', 'send', 'complete', 'cancel'], + 'cuttings' => ['view', 'create', 'update', 'delete', 'complete'], + 'cash' => ['view', 'deposit', 'withdraw', 'update', 'delete'], + 'expenses' => ['view', 'create', 'update', 'delete'], + 'activity_logs' => ['view'], + 'employee_advances' => ['view', 'create', 'update', 'delete', 'pay', 'verify'], + 'payroll' => ['view', 'pay', 'cancel', 'adjust'], + 'owner_verifications' => ['view', 'verify', 'reject'], + 'restocks' => ['view', 'create', 'update', 'delete'], + 'raw_materials' => ['view', 'create', 'update', 'delete', 'toggle_status'], + 'suppliers' => ['view', 'create', 'update', 'delete'], + 'purchases' => ['view', 'create', 'update', 'delete'], + 'stok_opnames' => ['view', 'create', 'update', 'delete', 'submit', 'verify'], + 'roles' => ['view', 'create', 'update', 'delete'], + 'settings' => ['view_system', 'update_system', 'view_homepage', 'update_homepage', 'view_social_media', 'update_social_media', 'view_marketplace', 'update_marketplace', 'view_hr', 'update_hr'], ]; foreach ($permissions as $module => $actions) { @@ -43,81 +48,416 @@ public function run(): void $allPermissions = Permission::all()->pluck('name')->toArray(); + $excludedFromDeveloperOwner = [ + 'attendances.create', + 'attendances.delete', + 'stok_opnames.submit', + 'roles.view', + 'roles.create', + 'roles.update', + 'roles.delete', + ]; + + $developerOwnerPerms = array_values(array_filter( + $allPermissions, + fn($p) => ! in_array($p, $excludedFromDeveloperOwner, true) + )); + $rolePermissions = [ - 'Developer' => $allPermissions, + 'developer' => $developerOwnerPerms, - 'Owner' => array_filter($allPermissions, fn ($p) => ! str_starts_with($p, 'settings.update-')), + 'owner' => $developerOwnerPerms, - 'Direktur' => array_filter($allPermissions, function ($p) { - return str_ends_with($p, '.view') - || str_starts_with($p, 'payroll-period.') - || $p === 'payroll.pay' - || $p === 'leave-request.approve' - || $p === 'leave-request.reject' - || $p === 'attendance.by-date'; - }), + 'admin-toko' => array_values(array_filter($allPermissions, function ($p) { + return in_array($p, [ + 'dashboard.view', + 'dashboard.revenue', + 'dashboard.expense', + 'dashboard.orders_channel', + 'dashboard.orders_payment', + 'dashboard.orders_marketing', + 'dashboard.orders_status', - 'Admin Bahan Baku' => array_filter($allPermissions, function ($p) { - return str_starts_with($p, 'supplier.') - || str_starts_with($p, 'purchase.') - || str_starts_with($p, 'cutting.') - || str_starts_with($p, 'restock.') - || $p === 'category.view' - || $p === 'customer.view' - || $p === 'cash-account.view'; - }), + 'analysis.view', + 'analysis.attendance', + 'analysis.cash', + 'analysis.product_stock', + 'analysis.revenue', + 'analysis.expense', + 'analysis.busy_hours', + 'analysis.profit_orders', + 'analysis.profit_hpp', + 'analysis.profit_gross', + 'analysis.top_customers', + 'analysis.top_products', + 'analysis.marketing_sales', - 'Admin Toko' => array_filter($allPermissions, function ($p) { - return str_starts_with($p, 'category.') - || str_starts_with($p, 'customer.') - || str_starts_with($p, 'expense.') - || str_starts_with($p, 'restock.') - || $p === 'cash-account.view' - || $p === 'leave-request.view' - || $p === 'leave-request.create' - || str_starts_with($p, 'attendance.'); - }), + 'stocks.view', + 'stok_opnames.view', - 'Marketing Offline' => array_filter($allPermissions, function ($p) { - return str_starts_with($p, 'customer.') - || $p === 'category.view' - || $p === 'supplier.view' - || $p === 'leave-request.view' - || $p === 'leave-request.create' - || $p === 'attendance.check-in' - || $p === 'attendance.check-out'; - }), + 'attendances.view', + 'attendances.create', + 'attendances.delete', - 'Marketing Online' => array_filter($allPermissions, function ($p) { - return str_starts_with($p, 'customer.') - || $p === 'category.view' - || $p === 'supplier.view' - || $p === 'leave-request.view' - || $p === 'leave-request.create' - || $p === 'attendance.check-in' - || $p === 'attendance.check-out'; - }), + 'leave_requests.view', + 'leave_requests.create', + 'leave_requests.update', + 'leave_requests.delete', - 'Kasir' => array_filter($allPermissions, function ($p) { - return str_starts_with($p, 'cash-account.') - || $p === 'expense.view' - || $p === 'leave-request.view' - || $p === 'leave-request.create' - || $p === 'attendance.check-in' - || $p === 'attendance.check-out'; - }), + 'restocks.view', + 'restocks.create', + 'restocks.update', + 'restocks.delete', - 'Stok Opname' => array_filter($allPermissions, function ($p) { - return str_starts_with($p, 'supplier.') - || $p === 'category.view' - || $p === 'cash-account.view' - || $p === 'leave-request.view' - || $p === 'leave-request.create' - || $p === 'attendance.check-in' - || $p === 'attendance.check-out'; - }), + 'categories.view', + 'categories.create', + 'categories.update', + 'categories.delete', - 'Non Operator' => array_filter($allPermissions, fn ($p) => str_ends_with($p, '.view')), + 'customers.view', + 'customers.create', + 'customers.update', + 'customers.delete', + + 'products.view', + 'products.create', + 'products.update', + 'products.delete', + 'products.toggle_status', + + 'owner_verifications.view', + + 'orders.view', + 'orders.create', + 'orders.update', + 'orders.delete', + 'orders.send', + 'orders.complete', + 'orders.cancel', + + 'cash.view', + 'cash.deposit', + 'cash.withdraw', + 'cash.update', + 'cash.delete', + + 'expenses.view', + 'expenses.create', + 'expenses.update', + 'expenses.delete', + + 'activity_logs.view', + + 'employee_advances.view', + 'employee_advances.create', + 'employee_advances.update', + 'employee_advances.delete', + 'employee_advances.pay', + + 'payroll.view', + 'payroll.adjust', + + 'settings.view_system', + 'settings.update_system', + 'settings.view_social_media', + 'settings.update_social_media', + 'settings.view_marketplace', + 'settings.update_marketplace', + 'settings.view_hr', + 'settings.update_hr', + 'settings.view_homepage', + 'settings.update_homepage', + + 'employees.view', + 'employees.create', + 'employees.update', + 'employees.toggle_status', + 'employees.delete', + ], true); + })), + + 'cashier' => array_values(array_filter($allPermissions, function ($p) { + return in_array($p, [ + 'dashboard.view', + 'dashboard.revenue', + 'dashboard.orders_channel', + 'dashboard.orders_payment', + 'dashboard.orders_status', + + 'analysis.view', + 'analysis.attendance', + 'analysis.revenue', + 'analysis.profit_orders', + 'analysis.top_customers', + 'analysis.top_products', + + 'attendances.view', + 'attendances.create', + 'attendances.delete', + + 'leave_requests.view', + 'leave_requests.create', + 'leave_requests.update', + 'leave_requests.delete', + + 'customers.view', + 'customers.create', + 'customers.update', + 'customers.delete', + + 'products.view', + + 'orders.view', + 'orders.create', + 'orders.update', + 'orders.delete', + 'orders.send', + 'orders.complete', + 'orders.cancel', + + 'employee_advances.view', + 'employee_advances.create', + 'employee_advances.update', + 'employee_advances.delete', + 'employee_advances.pay', + + 'payroll.view', + 'payroll.adjust', + ], true); + })), + + 'admin-bahan-baku' => array_values(array_filter($allPermissions, function ($p) { + return in_array($p, [ + 'dashboard.view', + + 'employees.view', + 'employees.create', + 'employees.update', + 'employees.toggle_status', + 'employees.delete', + + 'leave_requests.view', + 'leave_requests.create', + 'leave_requests.update', + 'leave_requests.delete', + + 'categories.view', + 'categories.create', + 'categories.update', + 'categories.delete', + + 'suppliers.view', + 'suppliers.create', + 'suppliers.update', + 'suppliers.delete', + + 'raw_materials.view', + 'raw_materials.create', + 'raw_materials.update', + 'raw_materials.toggle_status', + 'stocks.view', + + 'owner_verifications.view', + + 'products.view', + 'products.create', + 'products.update', + 'products.delete', + 'products.toggle_status', + + 'cuttings.view', + 'cuttings.create', + 'cuttings.update', + 'cuttings.delete', + 'cuttings.complete', + 'purchases.view', + 'purchases.create', + 'purchases.update', + 'purchases.delete', + + 'employee_advances.view', + 'employee_advances.create', + 'employee_advances.update', + 'employee_advances.delete', + 'employee_advances.pay', + + 'activity_logs.view', + + 'payroll.view', + ], true); + })), + + 'marketing-offline' => array_values(array_filter($allPermissions, function ($p) { + return in_array($p, [ + 'dashboard.view', + 'dashboard.revenue', + 'dashboard.orders_channel', + 'dashboard.orders_payment', + 'dashboard.orders_marketing', + 'dashboard.orders_status', + + 'analysis.view', + 'analysis.attendance', + 'analysis.revenue', + 'analysis.profit_orders', + 'analysis.top_products', + 'analysis.top_customers', + + 'attendances.view', + 'attendances.create', + + 'leave_requests.view', + 'leave_requests.create', + 'leave_requests.update', + 'leave_requests.delete', + + 'products.view', + + 'orders.view', + + 'employee_advances.view', + 'employee_advances.create', + 'employee_advances.update', + 'employee_advances.delete', + 'employee_advances.pay', + + 'payroll.view', + ], true); + })), + + 'marketing-online' => array_values(array_filter($allPermissions, function ($p) { + return in_array($p, [ + 'dashboard.view', + 'dashboard.revenue', + 'dashboard.orders_channel', + 'dashboard.orders_payment', + 'dashboard.orders_marketing', + 'dashboard.orders_status', + + 'analysis.view', + 'analysis.attendance', + 'analysis.revenue', + 'analysis.profit_orders', + 'analysis.top_products', + 'analysis.top_customers', + + 'attendances.view', + 'attendances.create', + + 'leave_requests.view', + 'leave_requests.create', + 'leave_requests.update', + 'leave_requests.delete', + + 'products.view', + + 'orders.view', + + 'employee_advances.view', + 'employee_advances.create', + 'employee_advances.update', + 'employee_advances.delete', + 'employee_advances.pay', + + 'payroll.view', + ], true); + })), + + 'direktur' => array_values(array_filter($allPermissions, function ($p) { + return in_array($p, [ + 'dashboard.view', + 'dashboard.attendance', + 'dashboard.revenue', + 'dashboard.expense', + 'dashboard.orders_channel', + 'dashboard.orders_payment', + 'dashboard.orders_marketing', + 'dashboard.orders_status', + 'analysis.view', + 'analysis.attendance', + 'analysis.cash', + 'analysis.product_stock', + 'analysis.revenue', + 'analysis.expense', + 'analysis.busy_hours', + 'analysis.profit_orders', + 'analysis.profit_hpp', + 'analysis.profit_gross', + 'analysis.profit_margin', + 'analysis.top_customers', + 'analysis.top_products', + 'analysis.marketing_sales', + 'employees.view', + 'attendances.view', + 'attendances.create', + 'attendances.delete', + 'attendances.manage', + 'leave_requests.view', + 'leave_requests.create', + 'leave_requests.update', + 'leave_requests.delete', + 'categories.view', + 'customers.view', + 'products.view', + 'stocks.view', + 'orders.view', + 'cuttings.view', + 'cash.view', + 'expenses.view', + 'activity_logs.view', + 'employee_advances.view', + 'employee_advances.create', + 'employee_advances.update', + 'employee_advances.delete', + 'employee_advances.pay', + 'payroll.view', + ], true); + })), + + 'non-operator' => array_values(array_filter($allPermissions, function ($p) { + return in_array($p, [ + 'dashboard.view', + 'analysis.view', + 'analysis.attendance', + 'attendances.view', + 'attendances.create', + 'leave_requests.view', + 'leave_requests.create', + 'leave_requests.update', + 'leave_requests.delete', + 'employee_advances.view', + 'employee_advances.create', + 'employee_advances.update', + 'employee_advances.delete', + 'employee_advances.pay', + 'payroll.view', + ], true); + })), + + 'stok-opname' => array_values(array_filter($allPermissions, function ($p) { + return in_array($p, [ + 'dashboard.view', + 'attendances.view', + 'attendances.create', + 'leave_requests.view', + 'leave_requests.create', + 'leave_requests.update', + 'leave_requests.delete', + 'products.view', + 'stocks.view', + 'stok_opnames.view', + 'stok_opnames.create', + 'stok_opnames.update', + 'stok_opnames.delete', + 'stok_opnames.submit', + 'employee_advances.view', + 'employee_advances.create', + 'employee_advances.update', + 'employee_advances.delete', + 'employee_advances.pay', + 'payroll.view', + ], true); + })), ]; foreach ($rolePermissions as $roleName => $perms) { diff --git a/resources/js/components/app-sidebar.tsx b/resources/js/components/app-sidebar.tsx index 1a1ffd8..e5fb634 100644 --- a/resources/js/components/app-sidebar.tsx +++ b/resources/js/components/app-sidebar.tsx @@ -1,3 +1,35 @@ +import AppLogo from '@/components/app-logo'; +import { + Sidebar, + SidebarContent, + SidebarGroup, + SidebarGroupLabel, + SidebarHeader, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + useSidebar, +} from '@/components/ui/sidebar'; +import { useCan } from '@/hooks/use-can'; +import { useCurrentUrl } from '@/hooks/use-current-url'; +import { dashboard } from '@/routes'; +import { index as cashAccountsIndex } from '@/routes/admin/finance/cash-accounts'; +import { index as employeeAdvancesIndex } from '@/routes/admin/finance/employee-advances'; +import { index as expensesIndex } from '@/routes/admin/finance/expenses'; +import { current as payrollCurrent } from '@/routes/admin/finance/payroll-periods'; +import { index as attendancesIndex } from '@/routes/admin/hr/attendances'; +import { index as employeesIndex } from '@/routes/admin/hr/employees'; +import { index as leaveRequestsIndex } from '@/routes/admin/hr/leave-requests'; +import { index as cuttingsIndex } from '@/routes/admin/manage/cuttings'; +import { index as purchasesIndex } from '@/routes/admin/manage/purchases'; +import { index as restocksIndex } from '@/routes/admin/manage/restocks'; +import { index as transactionsIndex } from '@/routes/admin/manage/transactions'; +import { index as categoriesIndex } from '@/routes/admin/master/categories'; +import { index as customersIndex } from '@/routes/admin/master/customers'; +import { index as productsIndex } from '@/routes/admin/master/products'; +import { index as rawMaterialsIndex } from '@/routes/admin/master/raw-materials'; +import { index as suppliersIndex } from '@/routes/admin/master/suppliers'; +import { index as rolesIndex } from '@/routes/admin/settings/roles'; import { Link, router } from '@inertiajs/react'; import type { LucideIcon } from 'lucide-react'; import { @@ -24,40 +56,8 @@ import { Wallet, } from 'lucide-react'; import React from 'react'; -import AppLogo from '@/components/app-logo'; -import { - Sidebar, - SidebarContent, - SidebarGroup, - SidebarGroupLabel, - SidebarHeader, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, - useSidebar, -} from '@/components/ui/sidebar'; -import { useCurrentUrl } from '@/hooks/use-current-url'; -import { dashboard } from '@/routes'; -import admin from '@/routes/admin'; -import { index as cashAccountsIndex } from '@/routes/admin/finance/cash-accounts'; -import { index as employeeAdvancesIndex } from '@/routes/admin/finance/employee-advances'; -import { index as expensesIndex } from '@/routes/admin/finance/expenses'; -import { current as payrollCurrent } from '@/routes/admin/finance/payroll-periods'; -import { index as attendancesIndex } from '@/routes/admin/hr/attendances'; -import { index as employeesIndex } from '@/routes/admin/hr/employees'; -import { index as leaveRequestsIndex } from '@/routes/admin/hr/leave-requests'; -import { index as cuttingsIndex } from '@/routes/admin/manage/cuttings'; -import { index as purchasesIndex } from '@/routes/admin/manage/purchases'; -import { index as restocksIndex } from '@/routes/admin/manage/restocks'; -import { index as transactionsIndex } from '@/routes/admin/manage/transactions'; -import { index as categoriesIndex } from '@/routes/admin/master/categories'; -import { index as customersIndex } from '@/routes/admin/master/customers'; -import { index as productsIndex } from '@/routes/admin/master/products'; -import { index as rawMaterialsIndex } from '@/routes/admin/master/raw-materials'; -import { index as suppliersIndex } from '@/routes/admin/master/suppliers'; -import { index as rolesIndex } from '@/routes/admin/settings/roles'; -type NavMenuItem = { title: string; href: string; icon: LucideIcon }; +type NavMenuItem = { title: string; href: string; icon: LucideIcon; permission?: string | string[] }; const dasborItem: NavMenuItem = { title: 'Dasbor', @@ -72,48 +72,57 @@ const analisaItem: NavMenuItem = { }; const masterItems: NavMenuItem[] = [ - { title: 'Kategori', href: categoriesIndex.url(), icon: Tags }, - { title: 'Produk', href: productsIndex.url(), icon: Package }, - { title: 'Bahan Baku', href: rawMaterialsIndex.url(), icon: Boxes }, - { title: 'Supplier', href: suppliersIndex.url(), icon: Truck }, - { title: 'Customer', href: customersIndex.url(), icon: Users }, + { title: 'Kategori', href: categoriesIndex.url(), icon: Tags, permission: 'categories.view' }, + { title: 'Produk', href: productsIndex.url(), icon: Package, permission: 'products.view' }, + { title: 'Bahan Baku', href: rawMaterialsIndex.url(), icon: Boxes, permission: 'raw_materials.view' }, + { title: 'Supplier', href: suppliersIndex.url(), icon: Truck, permission: 'suppliers.view' }, + { title: 'Customer', href: customersIndex.url(), icon: Users, permission: 'customers.view' }, ]; const kelolaItems: NavMenuItem[] = [ - { title: 'Belanja', href: purchasesIndex.url(), icon: ShoppingCart }, - { title: 'Cutting', href: cuttingsIndex.url(), icon: Scissors }, - { title: 'Transaksi', href: transactionsIndex.url(), icon: ShoppingCart }, - { title: 'Restock', href: restocksIndex.url(), icon: RefreshCw }, - { title: 'Stok Opname', href: '#', icon: ClipboardCheck }, + { title: 'Belanja', href: purchasesIndex.url(), icon: ShoppingCart, permission: 'purchases.view' }, + { title: 'Cutting', href: cuttingsIndex.url(), icon: Scissors, permission: 'cuttings.view' }, + { title: 'Transaksi', href: transactionsIndex.url(), icon: ShoppingCart, permission: 'orders.view' }, + { title: 'Restock', href: restocksIndex.url(), icon: RefreshCw, permission: 'restocks.view' }, + { title: 'Stok Opname', href: '#', icon: ClipboardCheck, permission: 'stok_opnames.view' }, ]; const keuanganItems: NavMenuItem[] = [ - { title: 'Kas Toko', href: cashAccountsIndex.url(), icon: Wallet }, - { title: 'Pengeluaran', href: expensesIndex.url(), icon: ArrowUpFromLine }, - { title: 'Kasbon', href: employeeAdvancesIndex.url(), icon: HandCoins }, - { title: 'Gaji', href: payrollCurrent.url(), icon: DollarSign }, + { title: 'Kas Toko', href: cashAccountsIndex.url(), icon: Wallet, permission: 'cash.view' }, + { title: 'Pengeluaran', href: expensesIndex.url(), icon: ArrowUpFromLine, permission: 'expenses.view' }, + { title: 'Kasbon', href: employeeAdvancesIndex.url(), icon: HandCoins, permission: 'employee_advances.view' }, + { title: 'Gaji', href: payrollCurrent.url(), icon: DollarSign, permission: 'payroll.view' }, ]; const hrItems: NavMenuItem[] = [ - { title: 'Pegawai', href: employeesIndex.url(), icon: UserCircle }, - { title: 'Presensi', href: attendancesIndex.url(), icon: CalendarCheck }, - { title: 'Cuti', href: leaveRequestsIndex.url(), icon: CalendarDays }, + { title: 'Pegawai', href: employeesIndex.url(), icon: UserCircle, permission: 'employees.view' }, + { title: 'Presensi', href: attendancesIndex.url(), icon: CalendarCheck, permission: 'attendances.view' }, + { title: 'Cuti', href: leaveRequestsIndex.url(), icon: CalendarDays, permission: 'leave_requests.view' }, ]; const sistemItems: NavMenuItem[] = [ - { title: 'Pengaturan', href: '/admin/settings', icon: Settings }, - { title: 'Role & Permission', href: rolesIndex.url(), icon: Shield }, - { title: 'Log Aktivitas', href: '#', icon: Activity }, + { title: 'Pengaturan', href: '/admin/settings', icon: Settings, permission: ['settings.view_system', 'settings.view_homepage', 'settings.view_social_media', 'settings.view_marketplace', 'settings.view_hr'] }, + { title: 'Role & Permission', href: rolesIndex.url(), icon: Shield, permission: 'roles.view' }, + { title: 'Log Aktivitas', href: '#', icon: Activity, permission: 'activity_logs.view' }, ]; function MenuGroup({ label, items }: { label: string; items: NavMenuItem[] }) { const { isCurrentUrl } = useCurrentUrl(); + const { can, canAny } = useCan(); + + const filtered = items.filter((item) => { + if (!item.permission) return true; + if (Array.isArray(item.permission)) return canAny(...item.permission); + return can(item.permission); + }); + + if (filtered.length === 0) return null; return ( {label} - {items.map((item) => ( + {filtered.map((item) => ( { if (!isMobile) { -return; -} + return; + } const cleanup = router.on('finish', () => { setOpenMobile(false); diff --git a/resources/js/hooks/use-can.ts b/resources/js/hooks/use-can.ts index 707c613..f1a3eff 100644 --- a/resources/js/hooks/use-can.ts +++ b/resources/js/hooks/use-can.ts @@ -34,6 +34,12 @@ export function useCan() { return permissionNames.includes(permission); } + function canAny(...permissions: string[]): boolean { + if (!user) return false; + if (roleNames.includes('developer') || roleNames.includes('owner')) return true; + return permissions.some((p) => permissionNames.includes(p)); + } + function hasRole(role: string): boolean { if (!user) return false; return roleNames.includes(role); @@ -44,5 +50,5 @@ export function useCan() { return roles.some((role) => roleNames.includes(role)); } - return { can, hasRole, hasAnyRole }; + return { can, canAny, hasRole, hasAnyRole }; } diff --git a/routes/web.php b/routes/web.php index 08b93bd..830655e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -38,93 +38,93 @@ Route::inertia('dashboard', 'dashboard')->name('dashboard'); Route::prefix('admin/master')->name('admin.master.')->group(function () { - Route::resource('categories', CategoryController::class)->except(['show', 'create', 'edit']); + Route::resource('categories', CategoryController::class)->except(['show', 'create', 'edit'])->middleware('permission:categories.view|categories.create|categories.update|categories.delete'); - Route::resource('products', ProductController::class)->except(['show']); - Route::post('products/{product}/toggle-status', [ProductController::class, 'toggleStatus'])->name('products.toggle-status'); - Route::delete('products/{product}/variants/{variant}', [ProductVariantController::class, 'destroy'])->name('products.variants.destroy'); - Route::get('products/{product}/variants/{variant}/edit', [ProductVariantController::class, 'edit'])->name('products.variants.edit'); - Route::put('products/{product}/variants/{variant}', [ProductVariantController::class, 'update'])->name('products.variants.update'); - Route::post('products/{product}/variants/{variant}/transfer-stock', [ProductVariantController::class, 'transferStock'])->name('products.variants.transfer-stock'); - Route::get('products/{product}/variants/{variant}/stock-mutations', [StockMutationController::class, 'index'])->name('products.variants.stock-mutations'); + Route::resource('products', ProductController::class)->except(['show'])->middleware('permission:products.view|products.create|products.update|products.delete'); + Route::post('products/{product}/toggle-status', [ProductController::class, 'toggleStatus'])->name('products.toggle-status')->middleware('permission:products.toggle_status'); + Route::delete('products/{product}/variants/{variant}', [ProductVariantController::class, 'destroy'])->name('products.variants.destroy')->middleware('permission:products.delete'); + Route::get('products/{product}/variants/{variant}/edit', [ProductVariantController::class, 'edit'])->name('products.variants.edit')->middleware('permission:products.update'); + Route::put('products/{product}/variants/{variant}', [ProductVariantController::class, 'update'])->name('products.variants.update')->middleware('permission:products.update'); + Route::post('products/{product}/variants/{variant}/transfer-stock', [ProductVariantController::class, 'transferStock'])->name('products.variants.transfer-stock')->middleware('permission:products.update'); + Route::get('products/{product}/variants/{variant}/stock-mutations', [StockMutationController::class, 'index'])->name('products.variants.stock-mutations')->middleware('permission:products.view'); - Route::resource('raw-materials', RawMaterialController::class)->except(['show']); - Route::post('raw-materials/{rawMaterial}/toggle-status', [RawMaterialController::class, 'toggleStatus'])->name('raw-materials.toggle-status'); - Route::get('raw-materials/{rawMaterial}/variants/{variant}/edit', [RawMaterialVariantController::class, 'edit'])->name('raw-materials.variants.edit'); - Route::put('raw-materials/{rawMaterial}/variants/{variant}', [RawMaterialVariantController::class, 'update'])->name('raw-materials.variants.update'); - Route::delete('raw-materials/{rawMaterial}/variants/{variant}', [RawMaterialVariantController::class, 'destroy'])->name('raw-materials.variants.destroy'); - - Route::resource('suppliers', SupplierController::class)->except(['show', 'create', 'edit']); - - Route::resource('customers', CustomerController::class)->except(['show', 'create', 'edit']); + Route::resource('raw-materials', RawMaterialController::class)->except(['show'])->middleware('permission:raw_materials.view|raw_materials.create|raw_materials.update|raw_materials.delete'); + Route::post('raw-materials/{rawMaterial}/toggle-status', [RawMaterialController::class, 'toggleStatus'])->name('raw-materials.toggle-status')->middleware('permission:raw_materials.toggle_status'); + Route::get('raw-materials/{rawMaterial}/variants/{variant}/edit', [RawMaterialVariantController::class, 'edit'])->name('raw-materials.variants.edit')->middleware('permission:raw_materials.update'); + Route::put('raw-materials/{rawMaterial}/variants/{variant}', [RawMaterialVariantController::class, 'update'])->name('raw-materials.variants.update')->middleware('permission:raw_materials.update'); + Route::delete('raw-materials/{rawMaterial}/variants/{variant}', [RawMaterialVariantController::class, 'destroy'])->name('raw-materials.variants.destroy')->middleware('permission:raw_materials.delete'); + + Route::resource('suppliers', SupplierController::class)->except(['show', 'create', 'edit'])->middleware('permission:suppliers.view|suppliers.create|suppliers.update|suppliers.delete'); + + Route::resource('customers', CustomerController::class)->except(['show', 'create', 'edit'])->middleware('permission:customers.view|customers.create|customers.update|customers.delete'); }); Route::prefix('admin/manage')->name('admin.manage.')->group(function () { - Route::resource('purchases', PurchaseController::class)->except(['show'])->middleware('permission:purchase.view|purchase.create|purchase.update|purchase.delete'); - - Route::resource('cuttings', CuttingController::class)->except(['show'])->middleware('permission:cutting.view|cutting.create|cutting.update|cutting.delete'); - - Route::resource('transactions', TransactionController::class)->except(['show'])->middleware('permission:transaction.view|transaction.create|transaction.update|transaction.delete'); - - Route::resource('restocks', RestockController::class)->except(['show'])->middleware('permission:restock.view|restock.create|restock.update|restock.delete'); + Route::resource('purchases', PurchaseController::class)->except(['show'])->middleware('permission:purchases.view|purchases.create|purchases.update|purchases.delete'); + + Route::resource('cuttings', CuttingController::class)->except(['show'])->middleware('permission:cuttings.view|cuttings.create|cuttings.update|cuttings.delete'); + + Route::resource('transactions', TransactionController::class)->except(['show'])->middleware('permission:orders.view|orders.create|orders.update|orders.delete'); + + Route::resource('restocks', RestockController::class)->except(['show'])->middleware('permission:restocks.view|restocks.create|restocks.update|restocks.delete'); }); Route::prefix('admin/finance')->name('admin.finance.')->group(function () { - Route::get('cash-accounts', [CashAccountController::class, 'index'])->name('cash-accounts.index')->middleware('permission:cash-account.view'); - Route::post('cash-accounts/deposit', [CashAccountController::class, 'deposit'])->name('cash-accounts.deposit')->middleware('permission:cash-account.deposit'); - Route::post('cash-accounts/withdrawal', [CashAccountController::class, 'withdrawal'])->name('cash-accounts.withdrawal')->middleware('permission:cash-account.withdrawal'); - Route::put('cash-accounts/transactions/{transaction}', [CashAccountController::class, 'update'])->name('cash-accounts.transactions.update')->middleware('permission:cash-account.update'); - Route::delete('cash-accounts/transactions/{transaction}', [CashAccountController::class, 'destroy'])->name('cash-accounts.transactions.destroy')->middleware('permission:cash-account.delete'); + Route::get('cash-accounts', [CashAccountController::class, 'index'])->name('cash-accounts.index')->middleware('permission:cash.view'); + Route::post('cash-accounts/deposit', [CashAccountController::class, 'deposit'])->name('cash-accounts.deposit')->middleware('permission:cash.deposit'); + Route::post('cash-accounts/withdrawal', [CashAccountController::class, 'withdrawal'])->name('cash-accounts.withdrawal')->middleware('permission:cash.withdraw'); + Route::put('cash-accounts/transactions/{transaction}', [CashAccountController::class, 'update'])->name('cash-accounts.transactions.update')->middleware('permission:cash.update'); + Route::delete('cash-accounts/transactions/{transaction}', [CashAccountController::class, 'destroy'])->name('cash-accounts.transactions.destroy')->middleware('permission:cash.delete'); - Route::resource('expenses', ExpenseController::class)->except(['show', 'create', 'edit'])->middleware('permission:expense.view|expense.create|expense.update|expense.delete'); + Route::resource('expenses', ExpenseController::class)->except(['show', 'create', 'edit'])->middleware('permission:expenses.view|expenses.create|expenses.update|expenses.delete'); - Route::resource('employee-advances', EmployeeAdvanceController::class)->except(['show', 'create', 'edit'])->middleware('permission:employee-advance.view|employee-advance.create|employee-advance.update|employee-advance.delete'); - Route::post('employee-advances/{employeeAdvance}/approve', [EmployeeAdvanceController::class, 'approve'])->name('employee-advances.approve')->middleware('permission:employee-advance.approve'); - Route::post('employee-advances/{employeeAdvance}/pay', [EmployeeAdvanceController::class, 'pay'])->name('employee-advances.pay')->middleware('permission:employee-advance.pay'); + Route::resource('employee-advances', EmployeeAdvanceController::class)->except(['show', 'create', 'edit'])->middleware('permission:employee_advances.view|employee_advances.create|employee_advances.update|employee_advances.delete'); + Route::post('employee-advances/{employeeAdvance}/approve', [EmployeeAdvanceController::class, 'approve'])->name('employee-advances.approve')->middleware('permission:employee_advances.verify'); + Route::post('employee-advances/{employeeAdvance}/pay', [EmployeeAdvanceController::class, 'pay'])->name('employee-advances.pay')->middleware('permission:employee_advances.pay'); - Route::get('payroll-periods/current', [PayrollPeriodController::class, 'current'])->name('payroll-periods.current')->middleware('permission:payroll-period.current'); - Route::resource('payroll-periods', PayrollPeriodController::class)->only(['index', 'show'])->middleware('permission:payroll-period.view'); - Route::post('payroll-periods/{payrollPeriod}/close', [PayrollPeriodController::class, 'close'])->name('payroll-periods.close')->middleware('permission:payroll-period.close'); - Route::post('payroll-periods/{payrollPeriod}/reopen', [PayrollPeriodController::class, 'reopen'])->name('payroll-periods.reopen')->middleware('permission:payroll-period.reopen'); + Route::get('payroll-periods/current', [PayrollPeriodController::class, 'current'])->name('payroll-periods.current')->middleware('permission:payroll.view'); + Route::resource('payroll-periods', PayrollPeriodController::class)->only(['index', 'show'])->middleware('permission:payroll.view'); + Route::post('payroll-periods/{payrollPeriod}/close', [PayrollPeriodController::class, 'close'])->name('payroll-periods.close')->middleware('permission:payroll.view'); + Route::post('payroll-periods/{payrollPeriod}/reopen', [PayrollPeriodController::class, 'reopen'])->name('payroll-periods.reopen')->middleware('permission:payroll.view'); Route::post('payrolls/{payroll}/pay', [PayrollController::class, 'pay'])->name('payrolls.pay')->middleware('permission:payroll.pay'); Route::post('payrolls/{payroll}/cancel', [PayrollController::class, 'cancel'])->name('payrolls.cancel')->middleware('permission:payroll.cancel'); - Route::post('payrolls/{payroll}/adjustments', [PayrollAdjustmentController::class, 'store'])->name('payrolls.adjustments.store')->middleware('permission:payroll-adjustment.create'); - Route::delete('payroll-adjustments/{payrollAdjustment}', [PayrollAdjustmentController::class, 'destroy'])->name('payroll-adjustments.destroy')->middleware('permission:payroll-adjustment.delete'); + Route::post('payrolls/{payroll}/adjustments', [PayrollAdjustmentController::class, 'store'])->name('payrolls.adjustments.store')->middleware('permission:payroll.adjust'); + Route::delete('payroll-adjustments/{payrollAdjustment}', [PayrollAdjustmentController::class, 'destroy'])->name('payroll-adjustments.destroy')->middleware('permission:payroll.adjust'); }); Route::prefix('admin/hr')->name('admin.hr.')->group(function () { - Route::resource('employees', EmployeeController::class)->except(['show'])->parameters(['employees' => 'user'])->middleware('permission:user.view|user.create|user.update|user.delete'); - Route::post('employees/{user}/toggle-active', [EmployeeController::class, 'toggleActive'])->name('employees.toggle-active')->middleware('permission:user.toggle-active'); - Route::post('employees/{user}/reset-password', [EmployeeController::class, 'resetPassword'])->name('employees.reset-password')->middleware('permission:user.reset-password'); + Route::resource('employees', EmployeeController::class)->except(['show'])->parameters(['employees' => 'user'])->middleware('permission:employees.view|employees.create|employees.update|employees.delete'); + Route::post('employees/{user}/toggle-active', [EmployeeController::class, 'toggleActive'])->name('employees.toggle-active')->middleware('permission:employees.toggle_status'); + Route::post('employees/{user}/reset-password', [EmployeeController::class, 'resetPassword'])->name('employees.reset-password')->middleware('permission:employees.reset_password'); - Route::get('attendances', [AttendanceController::class, 'index'])->name('attendances.index')->middleware('permission:attendance.view'); - Route::post('attendances', [AttendanceController::class, 'store'])->name('attendances.store')->middleware('permission:attendance.check-in'); - Route::put('attendances/{attendance}', [AttendanceController::class, 'update'])->name('attendances.update')->middleware('permission:attendance.check-out'); - Route::get('attendances/by-date', [AttendanceController::class, 'byDate'])->name('attendances.by-date')->middleware('permission:attendance.by-date'); + Route::get('attendances', [AttendanceController::class, 'index'])->name('attendances.index')->middleware('permission:attendances.view'); + Route::post('attendances', [AttendanceController::class, 'store'])->name('attendances.store')->middleware('permission:attendances.manage'); + Route::put('attendances/{attendance}', [AttendanceController::class, 'update'])->name('attendances.update')->middleware('permission:attendances.manage'); + Route::get('attendances/by-date', [AttendanceController::class, 'byDate'])->name('attendances.by-date')->middleware('permission:attendances.view'); - Route::resource('leave-requests', LeaveRequestController::class)->except(['show', 'create', 'edit'])->middleware('permission:leave-request.view|leave-request.create|leave-request.update|leave-request.delete'); - Route::post('leave-requests/{leaveRequest}/approve', [LeaveRequestController::class, 'approve'])->name('leave-requests.approve')->middleware('permission:leave-request.approve'); - Route::post('leave-requests/{leaveRequest}/reject', [LeaveRequestController::class, 'reject'])->name('leave-requests.reject')->middleware('permission:leave-request.reject'); + Route::resource('leave-requests', LeaveRequestController::class)->except(['show', 'create', 'edit'])->middleware('permission:leave_requests.view|leave_requests.create|leave_requests.update|leave_requests.delete'); + Route::post('leave-requests/{leaveRequest}/approve', [LeaveRequestController::class, 'approve'])->name('leave-requests.approve')->middleware('permission:leave_requests.verify'); + Route::post('leave-requests/{leaveRequest}/reject', [LeaveRequestController::class, 'reject'])->name('leave-requests.reject')->middleware('permission:leave_requests.verify'); }); Route::prefix('admin/settings')->name('admin.settings.')->group(function () { - Route::get('/', [AdminSettingsController::class, 'index'])->name('index')->middleware('permission:settings.view'); - Route::put('system', [AdminSettingsController::class, 'updateSystem'])->name('update-system')->middleware('permission:settings.update-system'); - Route::put('homepage', [AdminSettingsController::class, 'updateHomepage'])->name('update-homepage')->middleware('permission:settings.update-homepage'); - Route::put('social-media', [AdminSettingsController::class, 'updateSocialMedia'])->name('update-social-media')->middleware('permission:settings.update-social-media'); - Route::put('marketplace', [AdminSettingsController::class, 'updateMarketplace'])->name('update-marketplace')->middleware('permission:settings.update-marketplace'); - Route::put('hr', [AdminSettingsController::class, 'updateHR'])->name('update-hr')->middleware('permission:settings.update-hr'); + Route::get('/', [AdminSettingsController::class, 'index'])->name('index')->middleware('permission:settings.view_system|settings.view_homepage|settings.view_social_media|settings.view_marketplace|settings.view_hr'); + Route::put('system', [AdminSettingsController::class, 'updateSystem'])->name('update-system')->middleware('permission:settings.update_system'); + Route::put('homepage', [AdminSettingsController::class, 'updateHomepage'])->name('update-homepage')->middleware('permission:settings.update_homepage'); + Route::put('social-media', [AdminSettingsController::class, 'updateSocialMedia'])->name('update-social-media')->middleware('permission:settings.update_social_media'); + Route::put('marketplace', [AdminSettingsController::class, 'updateMarketplace'])->name('update-marketplace')->middleware('permission:settings.update_marketplace'); + Route::put('hr', [AdminSettingsController::class, 'updateHR'])->name('update-hr')->middleware('permission:settings.update_hr'); }); Route::prefix('admin/settings')->name('admin.settings.')->group(function () { - Route::get('roles', [RoleController::class, 'index'])->name('roles.index')->middleware('permission:user.view'); - Route::get('roles/create', [RoleController::class, 'create'])->name('roles.create')->middleware('permission:user.create'); - Route::post('roles', [RoleController::class, 'store'])->name('roles.store')->middleware('permission:user.create'); - Route::get('roles/{role}/edit', [RoleController::class, 'edit'])->name('roles.edit')->middleware('permission:user.update'); - Route::put('roles/{role}', [RoleController::class, 'update'])->name('roles.update')->middleware('permission:user.update'); - Route::delete('roles/{role}', [RoleController::class, 'destroy'])->name('roles.destroy')->middleware('permission:user.delete'); + Route::get('roles', [RoleController::class, 'index'])->name('roles.index')->middleware('permission:roles.view'); + Route::get('roles/create', [RoleController::class, 'create'])->name('roles.create')->middleware('permission:roles.create'); + Route::post('roles', [RoleController::class, 'store'])->name('roles.store')->middleware('permission:roles.create'); + Route::get('roles/{role}/edit', [RoleController::class, 'edit'])->name('roles.edit')->middleware('permission:roles.update'); + Route::put('roles/{role}', [RoleController::class, 'update'])->name('roles.update')->middleware('permission:roles.update'); + Route::delete('roles/{role}', [RoleController::class, 'destroy'])->name('roles.destroy')->middleware('permission:roles.delete'); }); });