diff --git a/app/Enums/Permission.php b/app/Enums/Permission.php index 58c7441..39d8516 100644 --- a/app/Enums/Permission.php +++ b/app/Enums/Permission.php @@ -222,4 +222,49 @@ public function label(): string self::ROLES_DELETE => 'Hapus Role', }; } + + public function group(): string + { + return match ($this) { + self::DASHBOARD_VIEW => 'Umum', + self::EMPLOYEES_VIEW, self::EMPLOYEES_CREATE, self::EMPLOYEES_UPDATE, + self::EMPLOYEES_DELETE, self::EMPLOYEES_RESET_PASSWORD, self::EMPLOYEES_TOGGLE_STATUS => 'Pegawai', + self::ATTENDANCES_VIEW, self::ATTENDANCES_CREATE, self::ATTENDANCES_DELETE, + self::ATTENDANCES_MANAGE => 'Presensi', + self::LEAVE_REQUESTS_VIEW, self::LEAVE_REQUESTS_CREATE, self::LEAVE_REQUESTS_UPDATE, + self::LEAVE_REQUESTS_DELETE, self::LEAVE_REQUESTS_VERIFY => 'Cuti', + self::CATEGORIES_VIEW, self::CATEGORIES_CREATE, self::CATEGORIES_UPDATE, + self::CATEGORIES_DELETE => 'Kategori', + self::SUPPLIERS_VIEW, self::SUPPLIERS_CREATE, self::SUPPLIERS_UPDATE, + self::SUPPLIERS_DELETE => 'Supplier', + self::CUSTOMERS_VIEW, self::CUSTOMERS_CREATE, self::CUSTOMERS_UPDATE, + self::CUSTOMERS_DELETE => 'Pelanggan', + self::PRODUCTS_VIEW, self::PRODUCTS_CREATE, self::PRODUCTS_UPDATE, + self::PRODUCTS_DELETE, self::PRODUCTS_TOGGLE_STATUS => 'Produk', + self::RAW_MATERIALS_VIEW, self::RAW_MATERIALS_CREATE, self::RAW_MATERIALS_UPDATE, + self::RAW_MATERIALS_DELETE, self::RAW_MATERIALS_TOGGLE_STATUS => 'Bahan Baku', + self::PURCHASES_VIEW, self::PURCHASES_CREATE, self::PURCHASES_UPDATE, + self::PURCHASES_DELETE => 'Belanja', + self::ORDERS_VIEW, self::ORDERS_CREATE, self::ORDERS_UPDATE, + self::ORDERS_DELETE, self::ORDERS_SEND, self::ORDERS_COMPLETE, + self::ORDERS_CANCEL => 'Pesanan', + self::CUTTINGS_VIEW, self::CUTTINGS_CREATE, self::CUTTINGS_UPDATE, + self::CUTTINGS_DELETE, self::CUTTINGS_COMPLETE, self::CUTTINGS_VERIFY, + self::CUTTINGS_REJECT => 'Cutting', + self::OWNER_VERIFICATIONS_VIEW, self::OWNER_VERIFICATIONS_VERIFY, + self::OWNER_VERIFICATIONS_REJECT => 'Verifikasi Owner', + self::STOCKS_VIEW => 'Stok', + self::CASH_VIEW, self::CASH_DEPOSIT, self::CASH_WITHDRAW, self::CASH_UPDATE, self::CASH_DELETE => 'Kas', + self::EXPENSES_VIEW, self::EXPENSES_CREATE, self::EXPENSES_UPDATE, + self::EXPENSES_DELETE => 'Pengeluaran', + self::EMPLOYEE_ADVANCES_VIEW, self::EMPLOYEE_ADVANCES_CREATE, self::EMPLOYEE_ADVANCES_UPDATE, + self::EMPLOYEE_ADVANCES_DELETE, self::EMPLOYEE_ADVANCES_VERIFY, + self::EMPLOYEE_ADVANCES_PAY => 'Kasbon', + self::PAYROLL_VIEW, self::PAYROLL_ADJUST => 'Gaji', + self::SETTINGS_VIEW, self::SETTINGS_UPDATE => 'Pengaturan Aplikasi', + self::ACTIVITY_LOGS_VIEW => 'Log Aktivitas', + self::ROLES_VIEW, self::ROLES_CREATE, self::ROLES_UPDATE, + self::ROLES_DELETE => 'Role & Permission', + }; + } } diff --git a/app/Enums/Role.php b/app/Enums/Role.php index d8019e5..eb7edce 100644 --- a/app/Enums/Role.php +++ b/app/Enums/Role.php @@ -30,4 +30,259 @@ public function label(): string self::NON_OPERATOR => 'Non Operator', }; } + + 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, + ], true) + )), + + self::DIREKTUR => [ + Permission::DASHBOARD_VIEW, + + Permission::EMPLOYEES_VIEW, + + Permission::STOCKS_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::SUPPLIERS_VIEW, + + Permission::CUSTOMERS_VIEW, + + Permission::PRODUCTS_VIEW, + + Permission::RAW_MATERIALS_VIEW, + + Permission::PURCHASES_VIEW, + + Permission::ORDERS_VIEW, + + Permission::CUTTINGS_VIEW, + + Permission::CASH_VIEW, + + Permission::EXPENSES_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::STOCKS_VIEW, + + Permission::CUTTINGS_VERIFY, + + 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::CATEGORIES_VIEW, + Permission::CATEGORIES_CREATE, + Permission::CATEGORIES_UPDATE, + Permission::CATEGORIES_DELETE, + + Permission::SUPPLIERS_VIEW, + Permission::SUPPLIERS_CREATE, + Permission::SUPPLIERS_UPDATE, + Permission::SUPPLIERS_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::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::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::CASHIER => [ + Permission::DASHBOARD_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::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::ATTENDANCES_VIEW, + Permission::ATTENDANCES_CREATE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_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_DELETE, + Permission::RAW_MATERIALS_TOGGLE_STATUS, + + Permission::PRODUCTS_VIEW, + + Permission::CUTTINGS_VIEW, + Permission::CUTTINGS_CREATE, + Permission::CUTTINGS_UPDATE, + Permission::CUTTINGS_DELETE, + Permission::CUTTINGS_COMPLETE, + Permission::CUTTINGS_VERIFY, + + 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::PAYROLL_VIEW, + ], + + self::MARKETING => [ + 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::CUSTOMERS_VIEW, + + 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::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::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::PAYROLL_VIEW, + ], + }; + } } diff --git a/app/Http/Controllers/Admin/System/RoleController.php b/app/Http/Controllers/Admin/System/RoleController.php index b4b9d6a..699df36 100644 --- a/app/Http/Controllers/Admin/System/RoleController.php +++ b/app/Http/Controllers/Admin/System/RoleController.php @@ -3,7 +3,6 @@ namespace App\Http\Controllers\Admin\System; use App\Enums\Permission as PermissionEnum; -use App\Enums\Role as EnumsRole; use App\Http\Controllers\Concerns\FlashesEntityMessage; use App\Http\Controllers\Concerns\ParsesDataTableQuery; use App\Http\Controllers\Controller; @@ -35,13 +34,11 @@ public function index(Request $request): Response public function create(): Response { - $permissionGroups = config('permissions.groups'); - $permissions = collect(PermissionEnum::cases()) ->map(fn (PermissionEnum $permission) => [ 'value' => $permission->value, 'label' => $permission->label(), - 'group' => $permissionGroups[$permission->value] ?? '-', + 'group' => $permission->group(), ]) ->values() ->all(); @@ -64,26 +61,20 @@ public function edit(Role $role): Response { $role->load('permissions'); - $permissionGroups = config('permissions.groups'); - $permissions = collect(PermissionEnum::cases()) ->map(fn (PermissionEnum $permission) => [ 'value' => $permission->value, 'label' => $permission->label(), - 'group' => $permissionGroups[$permission->value] ?? '-', + 'group' => $permission->group(), ]) ->values() ->all(); - // Check if role is developer or owner to protect it - $isProtected = in_array($role->name, [EnumsRole::DEVELOPER->value, EnumsRole::OWNER->value], true); - return Inertia::render('admin/system/roles/Edit', [ 'role' => [ 'id' => $role->id, 'name' => $role->name, 'permissions' => $role->permissions->pluck('name'), - 'is_protected' => $isProtected, ], 'permissions' => $permissions, ]); diff --git a/app/Services/System/ActivityLogService.php b/app/Services/System/ActivityLogService.php index 7a448e8..b2999d5 100644 --- a/app/Services/System/ActivityLogService.php +++ b/app/Services/System/ActivityLogService.php @@ -7,15 +7,11 @@ use App\Support\ActivityLog\ModelLabel; use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Collection; use Spatie\Activitylog\Models\Activity; class ActivityLogService { - /** - * @param array{search: string, sort: string, direction: 'asc'|'desc'} $tableQuery - */ public function paginateForIndex(array $tableQuery, string $event = '', string $subjectType = ''): LengthAwarePaginator { $query = Activity::query() @@ -42,53 +38,21 @@ public function paginateForIndex(array $tableQuery, string $event = '', string $ return $query ->paginate(10) ->withQueryString() - ->through(fn (Activity $activity) => $this->present($activity)); + ->through(fn (Activity $activity) => [ + 'id' => $activity->id, + 'description' => $activity->description, + 'event' => $activity->event, + 'event_label' => ActivityEventLabel::from($activity->event)->label(), + 'subject_type' => $activity->subject_type, + 'subject_label' => ModelLabel::for($activity->subject_type), + 'subject_id' => $activity->subject_id, + 'causer_name' => $activity->causer?->profile?->full_name ?? $activity->causer?->username ?? '-', + 'created_at' => $activity->created_at?->toIso8601String(), + 'created_at_formatted' => $activity->created_at?->translatedFormat('l, d F Y H:i'), + 'changes' => $this->formatChanges($activity->attribute_changes), + ]); } - /** - * @return array{ - * id: int, - * description: string, - * event: string|null, - * event_label: string, - * subject_type: string|null, - * subject_label: string, - * subject_id: int|null, - * causer_name: string, - * created_at: string|null, - * created_at_formatted: string|null, - * changes: list - * } - */ - private function present(Activity $activity): array - { - return [ - 'id' => $activity->id, - 'description' => $activity->description, - 'event' => $activity->event, - 'event_label' => ActivityEventLabel::labelFor($activity->event), - 'subject_type' => $activity->subject_type, - 'subject_label' => ModelLabel::for($activity->subject_type), - 'subject_id' => $activity->subject_id, - 'causer_name' => $this->resolveCauserName($activity->causer), - 'created_at' => $activity->created_at?->toIso8601String(), - 'created_at_formatted' => $activity->created_at?->translatedFormat('l, d F Y H:i'), - 'changes' => $this->formatChanges($activity->attribute_changes), - ]; - } - - private function resolveCauserName(?Model $causer): string - { - if (! $causer instanceof User) { - return '-'; - } - - return $causer->profile?->full_name ?? $causer->username ?? '-'; - } - - /** - * @return list - */ private function formatChanges(?Collection $changes): array { if ($changes === null || $changes->isEmpty()) { diff --git a/app/Services/System/RoleService.php b/app/Services/System/RoleService.php index 9a91a6b..c1bbd28 100644 --- a/app/Services/System/RoleService.php +++ b/app/Services/System/RoleService.php @@ -11,9 +11,6 @@ class RoleService { - /** - * @param array{search: string, sort: string, direction: 'asc'|'desc'} $tableQuery - */ public function paginateForIndex(array $tableQuery): LengthAwarePaginator { $query = Role::query() @@ -32,9 +29,6 @@ public function paginateForIndex(array $tableQuery): LengthAwarePaginator ->withQueryString(); } - /** - * @param array $validated - */ public function create(array $validated): void { DB::transaction(function () use ($validated): void { @@ -49,13 +43,9 @@ public function create(array $validated): void }); } - /** - * @param array $validated - */ public function update(Role $role, array $validated): void { DB::transaction(function () use ($role, $validated): void { - // Protect developer and owner names from changing $updateData = []; if (! in_array($role->name, [EnumsRole::DEVELOPER->value, EnumsRole::OWNER->value], true)) { $updateData['name'] = Str::slug($validated['name']); @@ -68,10 +58,6 @@ public function update(Role $role, array $validated): void public function delete(Role $role): void { - if (in_array($role->name, [EnumsRole::DEVELOPER->value, EnumsRole::OWNER->value], true)) { - throw new \InvalidArgumentException('Role developer atau owner tidak dapat dihapus.'); - } - $role->delete(); } diff --git a/database/seeders/RolePermissionSeeder.php b/database/seeders/RolePermissionSeeder.php index cb35c54..438437f 100644 --- a/database/seeders/RolePermissionSeeder.php +++ b/database/seeders/RolePermissionSeeder.php @@ -23,15 +23,11 @@ public function run(): void $registrar->forgetCachedPermissions(); - $rolePermissions = config('roles.permissions'); - foreach (RoleEnum::cases() as $role) { $roleModel = Role::findOrCreate($role->value, 'web'); - $rolePermissionsList = $rolePermissions[$role->value] ?? []; - $roleModel->syncPermissions( - collect($rolePermissionsList) + collect($role->permissions()) ->map(fn (PermissionEnum $permission) => $permissions[$permission->value]) ->all() ); diff --git a/resources/js/pages/admin/system/activity-logs/Index.vue b/resources/js/pages/admin/system/activity-logs/Index.vue index c720205..88c237c 100644 --- a/resources/js/pages/admin/system/activity-logs/Index.vue +++ b/resources/js/pages/admin/system/activity-logs/Index.vue @@ -1,14 +1,14 @@