97 lines
7.0 KiB
PHP
97 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\PeopleProcess;
|
|
use App\Models\User;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class PeopleWorkdesk
|
|
{
|
|
public const STATES = ['draft', 'open', 'assessment', 'selection_review', 'selected', 'contract_draft'];
|
|
|
|
/** @param Builder<PeopleProcess> $query
|
|
* @return array<string,mixed>
|
|
*/
|
|
public function build(Builder $query, User $actor): array
|
|
{
|
|
$tasks = [];
|
|
$approvals = [];
|
|
$alerts = [];
|
|
$total = 0;
|
|
$active = 0;
|
|
$contractDrafts = 0;
|
|
$workflow = app(PeopleHiring::class);
|
|
$access = app(PeopleAccess::class);
|
|
$maintenance = app(OrganizationAccess::class)->maintenanceOnly($actor);
|
|
foreach ((clone $query)->orderBy('id')->lazyById(100) as $record) {
|
|
$total++;
|
|
// Preparing a draft does not close a hiring process or prove a signed contract.
|
|
$active++;
|
|
$contractDrafts += $record->status === 'contract_draft' ? 1 : 0;
|
|
$scopes = $access->scopes($actor, $record);
|
|
$prepare = ! $maintenance && in_array('prepare', $scopes, true) && $workflow->allowed($actor, $record->kind, 'prepare');
|
|
$review = ! $maintenance && in_array('review', $scopes, true) && $workflow->allowed($actor, $record->kind, 'review');
|
|
$approve = ! $maintenance && in_array('approve', $scopes, true) && $workflow->allowed($actor, $record->kind, 'review');
|
|
$contract = ! $maintenance && in_array('contract', $scopes, true) && $workflow->allowed($actor, $record->kind, 'prepare');
|
|
$base = ['process_id' => $record->id, 'reference' => 'PES-'.$record->id, 'title' => $record->title, 'kind' => $record->kind, 'status' => $record->status];
|
|
$pendingTriage = in_array($record->status, ['open', 'assessment'], true) ? app(CandidateTriage::class)->pending($record) : 0;
|
|
$item = fn (string $action, string $label, ?string $due = null, ?int $application = null) => [...$base,
|
|
'id' => $record->id.':'.$action.($application === null ? '' : ':'.$application), 'action' => $action, 'label' => $label, 'due_on' => $due,
|
|
'href' => '/pessoas/'.$record->id.($application === null ? '' : '?candidatura='.$application).'#people-'.$action];
|
|
if (in_array($record->status, ['draft', 'open'], true) && $record->closes_on < today()->toDateString()) {
|
|
$alerts[] = [...$base, 'id' => $record->id.':reception', 'label' => 'Prazo de candidaturas vencido', 'due_on' => $record->closes_on, 'href' => '/pessoas/'.$record->id];
|
|
}
|
|
if ($pendingTriage > 0) {
|
|
if ($prepare) {
|
|
$tasks[] = [...$item('triage', 'Triar candidaturas electrónicas ('.$pendingTriage.')'), 'href' => '/pessoas/'.$record->id.'/recebidas'];
|
|
}
|
|
} elseif ($record->status === 'draft' && $review && $actor->id !== $record->created_by && $record->closes_on >= today()->toDateString()) {
|
|
$approvals[] = $item('open', 'Conferir abertura', $record->closes_on);
|
|
} elseif ($record->status === 'open' && $prepare) {
|
|
$tasks[] = today()->toDateString() >= $record->closes_on ? $item('close', 'Encerrar recepção e iniciar avaliação', $record->closes_on) : $item('apply', 'Gerir recepção de candidaturas', $record->closes_on);
|
|
} elseif ($record->status === 'assessment' && ($prepare || $review)) {
|
|
$rows = $workflow->matrix($record);
|
|
if ($review && $actor->id !== $record->created_by) {
|
|
foreach ($rows as $row) {
|
|
if ($row['registered_by'] !== $actor->id && ! in_array($actor->id, array_column($row['reviews'], 'reviewed_by'), true) && $row['evaluation_count'] < $record->rules['minimum_reviews']) {
|
|
$tasks[] = $item('evaluate', 'Avaliar candidatura #'.$row['id'], null, $row['id']);
|
|
}
|
|
}
|
|
}
|
|
if ($prepare && $rows !== [] && ! in_array(null, array_column($rows, 'score_minor'), true)) {
|
|
$tasks[] = $item('select', 'Preparar proposta de selecção');
|
|
}
|
|
} elseif ($record->status === 'selection_review' && $approve && ! in_array($actor->id, $workflow->decisionContributors($record), true)) {
|
|
$approvals[] = $item('confirm', 'Conferir selecção ou devolver para análise');
|
|
} elseif ($record->status === 'selected' && $contract) {
|
|
$tasks[] = $item('contract', 'Preparar minuta contratual');
|
|
}
|
|
if (Schema::hasTable('people_clarifications')) {
|
|
$clarifications = app(PeopleClarifications::class);
|
|
foreach ($clarifications->sources($actor, $record) as $source) {
|
|
$tasks[] = [...$base, 'id' => 'clarification-source-'.$source['review_id'].'-'.$source['criterion_index'], 'action' => 'clarification_assign',
|
|
'label' => 'Atribuir esclarecimento da avaliação #'.$source['review_id'].' · critério '.($source['criterion_index'] + 1), 'due_on' => null,
|
|
'href' => '/pessoas/'.$record->id.'#clarification-source-'.$source['review_id'].'-'.$source['criterion_index']];
|
|
}
|
|
foreach (DB::table('people_clarifications')->where('tenant_id', $record->tenant_id)->where('people_process_id', $record->id)->where('status', '!=', 'resolved')->orderBy('id')->get() as $clarification) {
|
|
$link = '/pessoas/'.$record->id.'#clarification-'.$clarification->id;
|
|
if ($clarification->due_on < today()->toDateString()) {
|
|
$alerts[] = [...$base, 'id' => 'clarification-'.$clarification->id, 'label' => 'Esclarecimento #'.$clarification->id.' com prazo vencido', 'due_on' => $clarification->due_on, 'href' => $link];
|
|
}
|
|
if ($clarifications->canRespond($actor, $record, $clarification)) {
|
|
$tasks[] = [...$base, 'id' => 'clarification-'.$clarification->id.':respond', 'action' => 'clarification_respond', 'label' => 'Responder ao esclarecimento #'.$clarification->id, 'due_on' => $clarification->due_on, 'href' => $link];
|
|
} elseif ($clarification->status === 'responded' && $clarifications->canReview($actor, $record, $clarification)) {
|
|
$tasks[] = [...$base, 'id' => 'clarification-'.$clarification->id.':review', 'action' => 'clarification_review', 'label' => 'Conferir esclarecimento #'.$clarification->id, 'due_on' => $clarification->due_on, 'href' => $link];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ['updated_at' => now()->toIso8601String(), 'counts' => ['processes' => $total, 'active' => $active, 'contract_drafts' => $contractDrafts, 'tasks' => count($tasks), 'approvals' => count($approvals), 'overdue' => count($alerts)],
|
|
'tasks' => $tasks, 'approvals' => $approvals, 'alerts' => $alerts];
|
|
}
|
|
}
|