commit de armazens
tests / ci (push) Canceled after 0s

This commit is contained in:
2026-11-04 09:40:26 +02:00
parent e753f7a0a4
commit 63d20b10fc
245 changed files with 10847 additions and 230 deletions
@@ -6,10 +6,12 @@ use App\Models\CandidateAccount;
use App\Models\PeopleProcess;
use App\Models\Tenant;
use App\Models\User;
use App\Services\AdministrativeGeography;
use App\Services\CandidateAccess;
use App\Services\CandidateDocuments;
use App\Services\CandidateProfiles;
use App\Services\CandidateSubmissions;
use App\Services\CandidateTerritory;
use App\Services\CandidateTriage;
use App\Services\ConflictGuard;
use App\Services\CurrentActor;
@@ -17,6 +19,7 @@ use App\Services\OrganizationConfiguration;
use App\Services\RequisitionWorkflow;
use App\Services\SubmissionForms;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
@@ -117,12 +120,25 @@ class CandidatePortalController extends Controller
$scopedSelection = is_array($selection) && ($selection['company'] ?? null) === $company && ($selection['account'] ?? null) === $account->id && is_int($selection['id'] ?? null) && $selection['id'] > 0;
$selected = $this->rememberOpportunity($request, $account, $scopedSelection ? (int) $selection['id'] : null);
return $this->page($request, 'candidate/profile', ['companyId' => $company, 'email' => $account->email, 'profile' => $profiles->profile($account),
$profile = $profiles->profile($account);
return $this->page($request, 'candidate/profile', ['companyId' => $company, 'email' => $account->email, 'profile' => $profile,
'geographyEnabled' => app(AdministrativeGeography::class)->enabled(),
'availabilityGeography' => app(AdministrativeGeography::class)->describe($profile['data']['availability_reference'] ?? null),
'emailVerified' => $account->email_verified_at !== null, 'accessStatus' => $scopedSelection && $selected === null ? 'opportunity_unavailable' : $request->session()->get('candidate_access_status'), 'emailDeliveryAvailable' => app(CandidateAccess::class)->deliveryAvailable(),
'opportunities' => $opportunities->items(), 'opportunityPagination' => ['prev' => $opportunities->previousPageUrl(), 'next' => $opportunities->nextPageUrl()], 'selectedOpportunity' => $selected,
'submissions' => $receipts->items(), 'submissionPagination' => ['prev' => $receipts->previousPageUrl(), 'next' => $receipts->nextPageUrl(), 'total' => $receipts->total()]]);
}
public function geography(Request $request, int $company, AdministrativeGeography $geography): JsonResponse
{
abort_unless($this->account($request, $company) !== null, 401);
abort_unless($geography->enabled(), 503);
$data = $request->validate(['parent' => 'nullable|string|regex:/^[0-9]+$/D|max:20', 'page' => 'sometimes|integer|min:1|max:10000']);
return response()->json($geography->children($data['parent'] ?? null, (int) ($data['page'] ?? 1)), 200, ['Cache-Control' => 'private, no-store, max-age=0']);
}
public function save(Request $request, int $company, CandidateProfiles $profiles): Response
{
$account = $this->account($request, $company);
@@ -293,21 +309,42 @@ class CandidatePortalController extends Controller
$record = PeopleProcess::query()->where('tenant_id', $actor->tenant_id)->where('id', $process)->firstOrFail();
$triage = app(CandidateTriage::class);
abort_unless($triage->canRead($actor, $record), 403);
$filter = $request->validate(['submission' => 'nullable|integer|min:1']);
$rows = DB::table('candidate_submissions')->where('tenant_id', $actor->tenant_id)->where('people_process_id', $process)->orderBy('id')->paginate(20);
$filter = $request->validate(['submission' => 'nullable|integer|min:1', 'location' => 'nullable|string|regex:/^[0-9]+$/D|max:20', 'page' => 'sometimes|integer|min:1|max:1000000']);
$query = DB::table('candidate_submissions')->where('tenant_id', $actor->tenant_id)->where('people_process_id', $process);
if (isset($filter['submission'])) {
$rows = DB::table('candidate_submissions')->where('tenant_id', $actor->tenant_id)->where('people_process_id', $process)->where('id', $filter['submission'])->paginate(20)->withQueryString();
$query->where('id', $filter['submission']);
}
if (! empty($filter['location'])) {
app(CandidateTerritory::class)->apply($query, $filter['location']);
}
$rows = $query->orderBy('id')->paginate(20)->withQueryString();
$decisions = Schema::hasTable('candidate_triage') ? DB::table('candidate_triage')->where('tenant_id', $actor->tenant_id)->where('people_process_id', $process)->whereIn('candidate_submission_id', $rows->pluck('id'))->get(['candidate_submission_id', 'outcome', 'reason', 'public_message', 'created_at', 'people_application_id'])->keyBy('candidate_submission_id') : collect();
$rows->through(fn ($row) => ['id' => $row->id, 'reference' => $row->reference, 'received_at' => $row->created_at, 'snapshot' => json_decode($row->snapshot, true, 32, JSON_THROW_ON_ERROR), 'decision' => $decisions->get($row->id)]);
app(RequisitionWorkflow::class)->audit($actor, 'candidate_submissions.consulted', null, null, ['process_id' => $process]);
return $this->page($request, 'people/submissions', ['process' => ['id' => $record->id, 'title' => $record->title, 'version' => $record->version], 'publication' => $submissions->publication($record), 'submissions' => $rows,
'filters' => $filter, 'geographyEnabled' => app(AdministrativeGeography::class)->enabled() && in_array(DB::getDriverName(), ['sqlite', 'pgsql'], true),
'geographyFilter' => empty($filter['location']) ? null : app(AdministrativeGeography::class)->describe(['country' => 'MZ', 'catalogue' => config('geography.source_sha256'), 'record_id' => $filter['location']]),
'canPrepare' => $triage->canPrepare($actor, $record), 'canTriage' => Schema::hasTable('candidate_triage') && $triage->canPrepare($actor, $record) && in_array($record->status, ['open', 'assessment'], true),
'publicUrl' => '/candidaturas/'.$actor->tenant_id.'/oportunidades/'.$record->id]);
});
}
public function processGeography(Request $request, int $process, AdministrativeGeography $geography): JsonResponse
{
return DB::transaction(function () use ($request, $process, $geography) {
$actor = $this->staff($request);
app(ConflictGuard::class)->lockCompany($actor);
$actor = app(CurrentActor::class)->lock($actor);
$record = PeopleProcess::query()->where('tenant_id', $actor->tenant_id)->where('id', $process)->firstOrFail();
abort_unless(app(CandidateTriage::class)->canRead($actor, $record), 403);
abort_unless($geography->enabled(), 503);
$data = $request->validate(['parent' => 'nullable|string|regex:/^[0-9]+$/D|max:20', 'page' => 'sometimes|integer|min:1|max:10000']);
return response()->json($geography->children($data['parent'] ?? null, (int) ($data['page'] ?? 1)), 200, ['Cache-Control' => 'private, no-store, max-age=0']);
});
}
public function publish(Request $request, int $process, CandidateSubmissions $submissions): Response
{
$submissions->publish($this->staff($request), $process, $request->all());