Files
Investidor-V2/app/Services/InvestmentZonePathContext.php
T
nala cef6e201c7
tests / ci (push) Canceled after 0s
versao nrgocios 2
2026-10-16 20:11:05 +02:00

49 lines
3.2 KiB
PHP

<?php
namespace App\Services;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
class InvestmentZonePathContext
{
public const NOTICE='Referência para preparação; não constitui reserva de lote, confirmação de disponibilidade ou autorização de instalação.';
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];
}
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']);
});
}
}