'Solicitar e acompanhar compras próprias', 'department_head' => 'Supervisão e aprovação do departamento', 'procurement' => 'Preparação e gestão operacional de compras', 'finance' => 'Conferência e operações financeiras', 'warehouse' => 'Recepção e operações de armazém', 'admin' => 'Administrar a empresa, utilizadores e parametrização', 'people_service_prepare' => 'Preparar contratação de prestadores individuais', 'people_service_review' => 'Avaliar e conferir contratação de prestadores individuais', 'people_staff_prepare' => 'Preparar recrutamento de trabalhadores', 'people_staff_review' => 'Avaliar e conferir recrutamento de trabalhadores', 'people_registry_read' => 'Consultar cadastro partilhado de pessoas da empresa', 'people_registry_manage' => 'Criar e actualizar cadastro partilhado de pessoas da empresa', ]; public function active(?int $tenant): bool { return $tenant !== null && Schema::hasTable('organization_access') && DB::table('organization_access')->where('tenant_id', $tenant)->where('active', true)->exists(); } /** @return list */ public function permissions(User $user): array { if ($user->tenant_id === null) { return []; } if (! $this->active($user->tenant_id)) { return $user->purchasing_role === null || $user->purchasing_role === PurchasingRole::Configured ? [] : [$user->purchasing_role->value]; } $rows = DB::table('organization_memberships as m')->join('organization_profiles as p', 'p.id', '=', 'm.profile_id') ->where('m.tenant_id', $user->tenant_id)->where('p.tenant_id', $user->tenant_id)->where('m.user_id', $user->id) ->where(fn ($q) => $q->whereNull('m.expires_at')->orWhere('m.expires_at', '>', now()))->get(['p.permissions']); $permissions = []; foreach ($rows as $row) { $permissions = [...$permissions, ...json_decode($row->permissions, true, 32, JSON_THROW_ON_ERROR)]; } return array_values(array_unique($permissions)); } /** @param list $functions */ public function allows(User $user, array $functions): bool { $requested = array_map(fn ($f) => $f instanceof PurchasingRole ? $f->value : $f, $functions); return $user->tenant_id !== null && count(array_intersect($this->permissions($user), $requested)) > 0; } public function maintenanceOnly(User $user): bool { if (! $this->active($user->tenant_id)) { return false; } $valid = DB::table('organization_memberships')->where('tenant_id', $user->tenant_id)->where('user_id', $user->id)->where(fn ($q) => $q->whereNull('expires_at')->orWhere('expires_at', '>', now())); return (clone $valid)->where('maintenance', true)->exists() && ! (clone $valid)->where('maintenance', false)->exists(); } public function departmentScoped(User $user): bool { $permissions = $this->permissions($user); return in_array('department_head', $permissions, true) && ! array_intersect($permissions, ['admin', 'procurement', 'finance']); } public function canRequest(User $user): bool { return $user->tenant_id !== null && ($this->active($user->tenant_id) ? $this->allows($user, ['requester']) : ($user->purchasing_role !== null && $user->purchasing_role !== PurchasingRole::Configured)); } public function profileLabel(User $user): string { if (! $this->active($user->tenant_id)) { return $user->purchasing_role?->label() ?? 'Utilizador'; } return DB::table('organization_memberships as m')->join('organization_profiles as p', 'p.id', '=', 'm.profile_id')->where('m.tenant_id', $user->tenant_id)->where('p.tenant_id', $user->tenant_id)->where('m.user_id', $user->id) ->where(fn ($q) => $q->whereNull('m.expires_at')->orWhere('m.expires_at', '>', now()))->orderBy('p.name')->pluck('p.name')->unique()->implode(' · '); } /** @param list $fields * @return array */ public function actorSnapshot(User $user, array $fields): array { $snapshot = $user->only($fields); if ($this->active($user->tenant_id)) { if (array_key_exists('purchasing_role', $snapshot)) { $snapshot['purchasing_role'] = $user->purchasing_role->value ?? ''; } $snapshot['profile_label'] = $this->profileLabel($user); } return $snapshot; } }