*/ private function reviewFilters(Request $request, AdministrativeGeography $geography): array { $actor = $request->user('web'); abort_unless($actor instanceof User, 403); app(OrganizationConfiguration::class)->administrator($actor); abort_unless($geography->enabled(), 503); $filters = $request->validate(['search' => 'nullable|string|max:120', 'issue' => ['nullable', Rule::in(array_keys(AdministrativeGeography::ISSUES))], 'page' => 'sometimes|integer|min:1|max:10000']); return ['search' => trim($filters['search'] ?? ''), 'issue' => $filters['issue'] ?? '', 'page' => (int) ($filters['page'] ?? 1)]; } public function review(Request $request, AdministrativeGeography $geography): Response { $filters = $this->reviewFilters($request, $geography); $rows = $geography->inconsistencies($filters); Inertia::encryptHistory(); $response = Inertia::render('company/geography-review', ['filters' => $filters, 'records' => array_slice($rows, ($filters['page'] - 1) * 50, 50), 'total' => count($rows), 'manifest' => $geography->catalogue()['manifest'], 'issues' => AdministrativeGeography::ISSUES])->toResponse($request); $response->headers->set('Cache-Control', 'private, no-store, max-age=0'); return $response; } public function exportReview(Request $request, AdministrativeGeography $geography): StreamedResponse { $filters = $this->reviewFilters($request, $geography); $rows = $geography->inconsistencies($filters); return response()->streamDownload(function () use ($rows) { $output = fopen('php://output', 'w'); if ($output === false) { throw new \RuntimeException('Não foi possível preparar a exportação.'); } $safe = fn ($value) => preg_match('/^[\s]*[=+@-]|^[\t\r\n]/u', $value) ? "'".$value : $value; fputcsv($output, ['Linha', 'ID', 'Provincia', 'Distrito', 'Posto_Administrativo', 'Localidade', 'Bairro_Urbano', 'Aldeia_Quarteirao', 'Designacao', 'Diagnosticos'], ',', '"', ''); foreach ($rows as $record) { $raw = $record['raw']; fputcsv($output, array_map($safe, [(string) $record['source_row'], $record['id'], ...array_values(array_diff_key($raw, ['ID' => true])), implode('; ', array_map(fn ($issue) => AdministrativeGeography::ISSUES[$issue], $record['issues']))]), ',', '"', ''); } fclose($output); }, 'sgc-cartografia-pendencias.csv', ['Content-Type' => 'text/csv; charset=UTF-8', 'Cache-Control' => 'private, no-store, max-age=0', 'X-Content-Type-Options' => 'nosniff']); } public function index(Request $request, AdministrativeGeography $geography): JsonResponse { abort_unless($request->user('web') instanceof User && $request->user('web')->tenant_id !== null, 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))); } public function company(Request $request, AdministrativeGeography $geography): RedirectResponse { abort_unless($geography->enabled(), 503); $data = $request->validate(['geography_reference' => 'present|nullable|array:country,catalogue,record_id', 'geography_reference.catalogue' => 'required_with:geography_reference|string|size:64', 'geography_reference.record_id' => 'required_with:geography_reference|string|regex:/^[0-9]+$/D|max:20', 'expected_reference' => 'present|nullable|array:country,catalogue,record_id']); $actor = $request->user('web'); abort_unless($actor instanceof User, 403); DB::transaction(function () use ($actor, $data, $geography) { app(ConflictGuard::class)->lockCompany($actor); $actor = app(OrganizationConfiguration::class)->administrator($actor); abort_if(app(OrganizationAccess::class)->maintenanceOnly($actor), 403); $company = Tenant::query()->lockForUpdate()->findOrFail($actor->tenant_id); if ($company->geography_reference != $data['expected_reference']) { throw ValidationException::withMessages(['geography_reference' => 'A localização foi alterada. Reabra a parametrização.']); } $before = $company->geography_reference; $after = $geography->canonical($data['geography_reference']); if ($before != $after) { $company->update(['geography_reference' => $after]); app(RequisitionWorkflow::class)->audit($actor, 'company.geography_updated', null, ['geography_reference' => $before], ['geography_reference' => $after]); } }); return back(); } }