*/ public function context(string $id, int $version): array { $zone = app(InvestmentZones::class)->visible()->where('category', 'industrial_park')->findOrFail($id); abort_unless((int) $zone->version_no === $version, 409, 'A ficha pública mudou. Consulte a versão atual e confirme novamente; a seleção anterior não foi substituída.'); return ['zone_id' => $zone->id, 'consulted_public_version' => (int) $zone->version_no, 'title' => $zone->name, 'href' => '/zonas/'.$zone->id, 'province' => $zone->province, 'district' => $zone->district, 'notice' => self::NOTICE]; } /** * @param array $input * @return array */ public function input(array $input): array { return Validator::make($input, ['zone_id' => 'required|uuid', 'consulted_public_version' => 'required|integer|min:1'])->validate(); } /** * @param array $input */ public function attach(User $actor, string $id, array $input): void { abort_unless(app(InvestorPath::class)->available(), 404); $data = Validator::make($input, ['zone_id' => 'required|uuid', 'consulted_public_version' => 'required|integer|min:1', 'version' => 'required|integer|min:1', 'confirm' => 'required|accepted'])->validate(); DB::transaction(function () use ($actor, $id, $data) { $desk = app(VirtualDesk::class); $case = $desk->case($actor, $id, true, true); abort_if($case->closed_at, 409, 'O dossier está encerrado.'); abort_unless(DB::table('investor_journeys')->where('id', $case->journey_id)->whereNotNull('path_definition_id')->whereNull('deleted_at')->exists(), 409, 'Este dossier conserva outro roteiro.'); $payload = $desk->decode($case->payload); foreach ($payload['investor_path']['zone_contexts'] ?? [] as $existing) { if ($existing['zone_id'] === $data['zone_id'] && (int) $existing['consulted_public_version'] === (int) $data['consulted_public_version']) { return; } } abort_unless((int) $case->version === (int) $data['version'], 409, 'O dossier mudou; recupere a versão atual.'); // Lock the public record while checking the consulted version and recording its reference. DB::table('investment_zones')->where('id', $data['zone_id'])->lockForUpdate()->firstOrFail(); $context = $this->context($data['zone_id'], (int) $data['consulted_public_version']); abort_unless(count($payload['investor_path']['zone_contexts'] ?? []) < 100, 422, 'Limite de referências deste dossier atingido.'); $payload['investor_path']['zone_contexts'][] = [...$context, 'selected_at' => now()->toIso8601String()]; DB::table('desk_cases')->where('id', $id)->update(['payload' => $desk->encode($payload), 'version' => $case->version + 1, 'updated_at' => now()]); $desk->event($desk->case($actor, $id), $actor, 'park_reference_selected', ['zone_id' => $context['zone_id'], 'consulted_public_version' => $context['consulted_public_version'], 'scope' => 'preparation_reference_only']); }); } }