49 lines
3.2 KiB
PHP
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']);
|
|
});
|
|
}
|
|
}
|