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]; } public function input(array $input): array { return Validator::make($input,['zone_id'=>'required|uuid','consulted_public_version'=>'required|integer|min:1'])->validate(); } 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']); }); } }