62 lines
4.5 KiB
PHP
62 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Opportunity;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Str;
|
|
|
|
class InvestmentCoordinatesController extends Controller
|
|
{
|
|
public function show(int $id): JsonResponse
|
|
{
|
|
Opportunity::findOrFail($id);
|
|
$point = DB::table('geo_locations as g')->join('geo_geometries as s', 's.geo_location_id', '=', 'g.id')
|
|
->where('g.source_system', 'investment-site-editor')->where('g.external_id', (string) $id)->whereNull('g.deleted_at')->whereNull('s.deleted_at')
|
|
->first(['s.version_no', 's.properties', DB::raw('ST_X(s.geom) as longitude'), DB::raw('ST_Y(s.geom) as latitude')]);
|
|
|
|
return response()->json(['version' => $point->version_no ?? 0, 'latitude' => $point?->latitude, 'longitude' => $point?->longitude,
|
|
'source_reference' => $point ? (json_decode($point->properties, true)['source_reference'] ?? '') : '']);
|
|
}
|
|
|
|
public function save(Request $request, int $id): JsonResponse
|
|
{
|
|
$data = $request->validate(['version' => ['required', 'integer', 'min:0'], 'latitude' => ['required', 'numeric', 'between:-90,90'],
|
|
'longitude' => ['required', 'numeric', 'between:-180,180'], 'source_reference' => ['required', 'string', 'min:10', 'max:2000'],
|
|
'confirmed_site' => ['accepted']]);
|
|
$version = DB::transaction(function () use ($data, $id, $request) {
|
|
DB::select('SELECT pg_advisory_xact_lock(280926, 150000)');
|
|
$opportunity = Opportunity::whereKey($id)->lockForUpdate()->firstOrFail();
|
|
$location = DB::table('geo_locations')->where('source_system', 'investment-site-editor')->where('external_id', (string) $id)->first();
|
|
abort_if($location && $location->deleted_at, 409, 'Local arquivado; requer reconciliação.');
|
|
abort_if($location && $location->data_classification !== 'public', 409, 'Local retirado de divulgação; requer revisão da classificação.');
|
|
$geometry = $location ? DB::table('geo_geometries')->where('geo_location_id', $location->id)->where('geometry_type', 'point')->first() : null;
|
|
abort_if($geometry && $geometry->deleted_at, 409, 'Geometria arquivada; requer reconciliação.');
|
|
abort_if($geometry && $geometry->data_classification !== 'public', 409, 'Geometria retirada de divulgação; requer revisão da classificação.');
|
|
abort_unless((int) ($geometry->version_no ?? 0) === $data['version'], 409, 'Coordenadas alteradas. Recarregue.');
|
|
$locationId = $location->id ?? (string) Str::uuid();
|
|
if (! $location) {
|
|
DB::table('geo_locations')->insert(['id' => $locationId, 'source_system' => 'investment-site-editor', 'external_id' => (string) $id,
|
|
'name' => $opportunity->title, 'location_type' => 'site', 'code' => 'SITE-OPP-'.$id, 'data_classification' => 'public', 'parent_id' => $opportunity->primary_territory_id]);
|
|
}
|
|
$version = $data['version'] + 1;
|
|
$geometryId = $geometry->id ?? (string) Str::uuid();
|
|
DB::statement("INSERT INTO geo_geometries(id,geo_location_id,geometry_type,geom,data_classification,version_no,properties)
|
|
VALUES(?,?,'point',ST_SetSRID(ST_MakePoint(?,?),4326),'public',?,?::jsonb)
|
|
ON CONFLICT(id) DO UPDATE SET geom=EXCLUDED.geom,version_no=EXCLUDED.version_no,properties=EXCLUDED.properties,updated_at=now()",
|
|
[$geometryId, $locationId, $data['longitude'], $data['latitude'], $version, json_encode(['source_reference' => $data['source_reference'], 'accuracy' => 'site_confirmed_by_editor'], JSON_THROW_ON_ERROR)]);
|
|
DB::table('opportunity_locations')->updateOrInsert(['opportunity_id' => $id, 'geo_location_id' => $locationId], []);
|
|
DB::table('audit_events')->insert(['source_system' => 'investment-coordinates', 'entity_type' => 'geo_geometries', 'entity_id' => $geometryId,
|
|
'actor_user_id' => $request->user()->id, 'action' => 'site_coordinates_saved',
|
|
'before_data' => $geometry ? json_encode(['version' => $geometry->version_no, 'geometry_hex' => $geometry->geom], JSON_THROW_ON_ERROR) : null,
|
|
'after_data' => json_encode(['opportunity_id' => $id, 'version' => $version, 'latitude' => $data['latitude'], 'longitude' => $data['longitude'], 'source_sha256' => hash('sha256', $data['source_reference'])], JSON_THROW_ON_ERROR)]);
|
|
|
|
return $version;
|
|
});
|
|
|
|
return response()->json(['version' => $version]);
|
|
}
|
|
}
|