100 lines
4.0 KiB
PHP
100 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Opportunity;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
final class InvestmentCorridorContext
|
|
{
|
|
public function key(Opportunity $record): ?string
|
|
{
|
|
$name = data_get($record->workflow_context, 'corridor_agribusiness.corridor');
|
|
foreach (config('investment_corridors') as $key => $entry) {
|
|
if ($entry['name'] === $name) {
|
|
return $key;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/** Reuse Tempo's approved provincial context; never infer a district or master link.
|
|
* @return array<array-key, mixed>
|
|
*/
|
|
public function catalogueProvinces(Opportunity $record): array
|
|
{
|
|
if (data_get($record->workflow_context, 'corridor_agribusiness.source_sha256') !== CorridorAgribusinessOpportunities::SOURCE_HASH) {
|
|
return [];
|
|
}
|
|
if ($record->primary_territory_id || $record->additionalTerritories()->exists()) {
|
|
return [];
|
|
}
|
|
$key = $this->key($record);
|
|
|
|
return $key ? $this->provinces($key) : [];
|
|
}
|
|
|
|
/**
|
|
* @return array<array-key, mixed>
|
|
*/
|
|
public function provinces(string $key): array
|
|
{
|
|
$entry = config('investment_corridors.'.$key);
|
|
abort_unless(is_array($entry), 422, 'Seleccione um corredor disponível.');
|
|
$records = app(InvestmentGeography::class)->publicReferences()->where('location_type', 'province')
|
|
->whereIn('source_code', $entry['provinces'])->get(['id', 'name', 'parent_id', 'location_type', 'source_code'])->all();
|
|
if (! (count($records) === count($entry['provinces']))) {
|
|
abort(503, 'Não foi possível recuperar todas as províncias deste corredor. Tente novamente.');
|
|
}
|
|
|
|
return $records;
|
|
}
|
|
|
|
public function compatible(string $key, ?string $territory): bool
|
|
{
|
|
if (! $territory) {
|
|
return true;
|
|
}
|
|
$path = app(InvestmentGeography::class)->path($territory);
|
|
|
|
return $path !== [] && in_array($path[0]->id, array_column($this->provinces($key), 'id'), true);
|
|
}
|
|
|
|
/** Both membership in the selected area and documented public zone coverage are required.
|
|
* @return array<array-key, mixed>
|
|
*/
|
|
public function parks(?string $key, ?string $territory): array
|
|
{
|
|
if (! $key || ! $territory) {
|
|
return [];
|
|
}
|
|
abort_unless($this->compatible($key, $territory), 422, 'A localização não pertence ao corredor escolhido.');
|
|
$selectedPath = array_column(app(InvestmentGeography::class)->path($territory), 'id');
|
|
$candidates = app(InvestmentZones::class)->visible()->whereIn('category', ['industrial_park', 'zee', 'zfi'])->orderBy('name')->get();
|
|
$result = [];
|
|
foreach ($candidates as $zone) {
|
|
$ids = DB::table('investment_zone_locations')->where('zone_id', $zone->id)->where('validation_status', 'validated')
|
|
->whereIn('scope_type', ['legal_scope', 'administrative', 'site'])
|
|
->where(fn ($q) => $q->whereNull('valid_from')->orWhereDate('valid_from', '<=', today()))
|
|
->where(fn ($q) => $q->whereNull('valid_until')->orWhereDate('valid_until', '>=', today()))->get(['geo_location_id', 'scope_type'])->all();
|
|
if ($zone->primary_territory_id) {
|
|
$ids[] = (object) ['geo_location_id' => $zone->primary_territory_id, 'scope_type' => 'site'];
|
|
}
|
|
foreach ($ids as $link) {
|
|
$id = $link->geo_location_id;
|
|
if (! $this->compatible($key, $id)) {
|
|
continue;
|
|
}
|
|
$path = array_column(app(InvestmentGeography::class)->path($id), 'id');
|
|
if (in_array($territory, $path, true) || ($link->scope_type === 'legal_scope' && in_array($id, $selectedPath, true))) {
|
|
$result[] = $zone->only(['id', 'name', 'category', 'version_no']);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
}
|