Files
Verde-Web/app/Http/Controllers/Api/V1/Admin/AdminDumpsiteController.php

174 lines
6.4 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1\Admin;
use App\Http\Controllers\Api\V1\ApiController;
use App\Http\Requests\Dumpsite\StoreDumpsiteRequest;
use App\Http\Requests\Dumpsite\UpdateDumpsiteRequest;
use App\Http\Resources\DumpsiteResource;
use App\Models\Dumpsite;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use MatanYadaev\EloquentSpatial\Objects\LineString;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Objects\Polygon;
class AdminDumpsiteController extends ApiController
{
public function index(Request $request): JsonResponse
{
$request->validate([
'status' => ['nullable', 'in:active,maintenance,closed'],
'city_municipality_id' => ['nullable', 'integer'],
'q' => ['nullable', 'string', 'max:100'],
'per_page' => ['nullable', 'integer', 'min:1', 'max:500'],
]);
$perPage = (int) $request->input('per_page', 25);
$dumpsites = Dumpsite::query()
->with('cityMunicipality')
->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status')))
->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(fn ($qq) => $qq->where('name', 'like', $term)
->orWhere('code', 'like', $term)
->orWhere('address_line', 'like', $term));
})
->orderBy('name')
->paginate($perPage);
return $this->ok(
DumpsiteResource::collection($dumpsites),
null,
[
'page' => $dumpsites->currentPage(),
'per_page' => $dumpsites->perPage(),
'total' => $dumpsites->total(),
'last_page' => $dumpsites->lastPage(),
],
);
}
public function store(StoreDumpsiteRequest $request): JsonResponse
{
$data = $request->validated();
$payload = $this->mapPayload($data);
$payload['name'] = $data['name'];
$payload['code'] = $data['code'];
$payload['address_line'] = $data['address_line'];
$payload['city_municipality_id'] = $data['city_municipality_id'] ?? null;
$payload['accepted_waste_types'] = $data['accepted_waste_types'] ?? null;
$payload['operating_hours'] = $data['operating_hours'] ?? null;
$payload['capacity_tons'] = $data['capacity_tons'] ?? null;
$payload['contact_person'] = $data['contact_person'] ?? null;
$payload['contact_phone'] = $data['contact_phone'] ?? null;
$payload['permit_number'] = $data['permit_number'] ?? null;
$payload['status'] = $data['status'] ?? Dumpsite::STATUS_ACTIVE;
$dumpsite = Dumpsite::create($payload);
return $this->created(
new DumpsiteResource($dumpsite->fresh()->load('cityMunicipality')),
'Dumpsite created',
);
}
public function show(Dumpsite $dumpsite): JsonResponse
{
$dumpsite->load('cityMunicipality.province.region');
return $this->ok(new DumpsiteResource($dumpsite));
}
public function update(UpdateDumpsiteRequest $request, Dumpsite $dumpsite): JsonResponse
{
$data = $request->validated();
$payload = $this->mapPayload($data);
// Carry through scalar/json fields that mapPayload doesn't touch.
foreach ([
'name', 'code', 'address_line', 'city_municipality_id',
'accepted_waste_types', 'operating_hours', 'capacity_tons',
'contact_person', 'contact_phone', 'permit_number', 'status',
] as $key) {
if (array_key_exists($key, $data)) {
$payload[$key] = $data[$key];
}
}
$oldStatus = $dumpsite->status;
$newStatus = $payload['status'] ?? $oldStatus;
DB::transaction(function () use ($dumpsite, $payload, $oldStatus, $newStatus) {
$dumpsite->update($payload);
if ($newStatus !== Dumpsite::STATUS_ACTIVE && $oldStatus === Dumpsite::STATUS_ACTIVE) {
$trips = \App\Models\Trip::where('dumpsite_id', $dumpsite->id)
->whereIn('status', [\App\Models\Trip::STATUS_SCHEDULED, \App\Models\Trip::STATUS_IN_PROGRESS, \App\Models\Trip::STATUS_AT_DUMPSITE])
->get();
foreach ($trips as $trip) {
$trip->update([
'status' => \App\Models\Trip::STATUS_CANCELLED,
'notes' => trim(($trip->notes ?? '') . "\nSystem: Trip cancelled because the dumpsite was moved to " . $newStatus . " status."),
]);
}
}
});
return $this->ok(
new DumpsiteResource($dumpsite->fresh()->load('cityMunicipality')),
'Dumpsite updated',
);
}
public function destroy(Dumpsite $dumpsite): JsonResponse
{
$dumpsite->delete();
return $this->ok(null, 'Dumpsite deleted');
}
/**
* Translate lat/lng + boundary_polygon[{lat,lng}, ...] inputs into
* spatial Polygon/Point objects suitable for assignment to the model.
*/
private function mapPayload(array $data): array
{
$payload = [];
if (isset($data['lat'], $data['lng'])) {
$payload['coordinates'] = new Point((float) $data['lat'], (float) $data['lng'], 4326);
}
if (array_key_exists('geofence_wkt', $data)) {
$payload['boundary_polygon'] = !empty($data['geofence_wkt']) ? \MatanYadaev\EloquentSpatial\Objects\Polygon::fromJson($data['geofence_wkt'], 4326) : null;
}
return $payload;
}
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);
}
}