Files
Verde-Web/app/Http/Controllers/Api/V1/SuperAdmin/SuperAdminBarangayController.php

195 lines
7.1 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1\SuperAdmin;
use App\Http\Controllers\Api\V1\ApiController;
use App\Http\Requests\SuperAdmin\StoreBarangayRequest;
use App\Http\Requests\SuperAdmin\UpdateBarangayRequest;
use App\Http\Resources\BarangayResource;
use App\Models\Barangay;
use App\Models\CityMunicipality;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use MatanYadaev\EloquentSpatial\Objects\LineString;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Objects\Polygon;
class SuperAdminBarangayController extends ApiController
{
public function index(Request $request): JsonResponse
{
$request->validate([
'city_municipality_id' => ['nullable', 'integer'],
'q' => ['nullable', 'string', 'max:100'],
'per_page' => ['nullable', 'integer', 'min:1', 'max:100'],
]);
$perPage = (int) $request->input('per_page', 25);
$barangays = Barangay::query()
->with(['cityMunicipality.province'])
->withSum('households', 'household_size')
->when($request->filled('city_municipality_id'), fn ($q) => $q->where('city_municipality_id', $request->integer('city_municipality_id')))
->when($request->filled('q'), function ($q) use ($request) {
$term = '%'.$request->string('q').'%';
$q->where(function ($qq) use ($term) {
$qq->where('name', 'like', $term)
->orWhere('code', 'like', $term)
->orWhere('psgc_code', 'like', $term);
});
})
->orderBy('name')
->paginate($perPage);
return $this->ok(BarangayResource::collection($barangays));
}
public function store(StoreBarangayRequest $request): JsonResponse
{
$data = $request->validated();
$boundary = $this->buildPolygon($data['boundary']);
$centroid = $this->calculateCentroid($boundary);
// Spatial validation check removed as per user request
// Code auto-generation if empty
$cityId = $data['city_municipality_id'];
$city = CityMunicipality::findOrFail($cityId);
if (empty($data['psgc_code'])) {
$prefix = substr($city->psgc_code, 0, 9);
$maxLocal = Barangay::where('psgc_code', 'like', $prefix.'%')
->whereRaw('LENGTH(psgc_code) = 12')
->orderBy('psgc_code', 'desc')
->first();
$suffix = $maxLocal ? ((int) substr($maxLocal->psgc_code, -3) + 1) : 1;
$data['psgc_code'] = $prefix.str_pad($suffix, 3, '0', STR_PAD_LEFT);
}
if (empty($data['code'])) {
$prefix = substr($city->code, 0, 12);
$maxLocal = Barangay::where('code', 'like', $prefix.'%')
->orderBy('code', 'desc')
->first();
$suffix = $maxLocal ? ((int) substr(strrchr($maxLocal->code, '-'), 1) + 1) : 1;
$data['code'] = $prefix.'-'.str_pad($suffix, 3, '0', STR_PAD_LEFT);
}
$barangay = Barangay::create([
'name' => $data['name'],
'city_municipality_id' => $cityId,
'psgc_code' => $data['psgc_code'],
'code' => $data['code'],
'urban_rural' => $data['urban_rural'],
'population' => $data['population'],
'boundary' => $boundary,
'centroid' => $centroid,
]);
return $this->created(new BarangayResource($barangay), 'Barangay created successfully');
}
public function show(Barangay $barangay): JsonResponse
{
$barangay->load(['cityMunicipality.province']);
return $this->ok(new BarangayResource($barangay));
}
public function update(UpdateBarangayRequest $request, Barangay $barangay): JsonResponse
{
$data = $request->validated();
$boundary = $this->buildPolygon($data['boundary']);
$centroid = $this->calculateCentroid($boundary);
// Spatial validation check removed as per user request
// Code auto-generation if empty
$cityId = $data['city_municipality_id'];
$city = CityMunicipality::findOrFail($cityId);
if (empty($data['psgc_code'])) {
$prefix = substr($city->psgc_code, 0, 9);
$maxLocal = Barangay::where('psgc_code', 'like', $prefix.'%')
->whereRaw('LENGTH(psgc_code) = 12')
->orderBy('psgc_code', 'desc')
->first();
$suffix = $maxLocal ? ((int) substr($maxLocal->psgc_code, -3) + 1) : 1;
$data['psgc_code'] = $prefix.str_pad($suffix, 3, '0', STR_PAD_LEFT);
}
if (empty($data['code'])) {
$prefix = substr($city->code, 0, 12);
$maxLocal = Barangay::where('code', 'like', $prefix.'%')
->orderBy('code', 'desc')
->first();
$suffix = $maxLocal ? ((int) substr(strrchr($maxLocal->code, '-'), 1) + 1) : 1;
$data['code'] = $prefix.'-'.str_pad($suffix, 3, '0', STR_PAD_LEFT);
}
$barangay->update([
'name' => $data['name'],
'city_municipality_id' => $cityId,
'psgc_code' => $data['psgc_code'],
'code' => $data['code'],
'urban_rural' => $data['urban_rural'],
'population' => $data['population'],
'boundary' => $boundary,
'centroid' => $centroid,
]);
return $this->ok(new BarangayResource($barangay), 'Barangay updated successfully');
}
public function destroy(Barangay $barangay): JsonResponse
{
$barangay->delete();
return $this->ok(null, 'Barangay deleted successfully');
}
private function buildPolygon(array $points): Polygon
{
$ring = array_map(
fn ($p) => new Point((float) $p['lat'], (float) $p['lng'], 4326),
$points,
);
$first = $ring[0];
$last = $ring[count($ring) - 1];
if ($first->latitude !== $last->latitude || $first->longitude !== $last->longitude) {
$ring[] = new Point($first->latitude, $first->longitude, 4326);
}
return new Polygon([new LineString($ring)], 4326);
}
private function calculateCentroid(Polygon $polygon): Point
{
$res = DB::selectOne(
'SELECT ST_AsText(ST_SRID(ST_Centroid(ST_GeomFromText(?, 0)), 4326)) as wkt',
[$polygon->toWkt()]
);
if ($res && preg_match('/POINT\(([^ ]+) ([^ ]+)\)/', $res->wkt, $matches)) {
$lat = (float) $matches[1];
$lng = (float) $matches[2];
return new Point($lat, $lng, 4326);
}
$rings = $polygon->getGeometries();
$ring = $rings->first();
if ($ring) {
$coords = $ring->getGeometries();
$lats = $coords->map(fn ($p) => $p->latitude)->all();
$lngs = $coords->map(fn ($p) => $p->longitude)->all();
return new Point(array_sum($lats) / count($lats), array_sum($lngs) / count($lngs), 4326);
}
return new Point(0, 0, 4326);
}
}