108 lines
4.8 KiB
PHP
108 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Enums\PurchasingRole;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class OrganizationAccess
|
|
{
|
|
public const PERMISSIONS = [
|
|
'requester' => '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<string> */
|
|
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<PurchasingRole|string> $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<string> $fields
|
|
* @return array<string,mixed>
|
|
*/
|
|
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;
|
|
}
|
|
}
|