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

162 lines
6.2 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1\Admin;
use App\Http\Controllers\Api\V1\ApiController;
use App\Http\Requests\DropOff\StoreCapacityLogRequest;
use App\Http\Requests\DropOff\StoreDropOffPointRequest;
use App\Http\Requests\DropOff\UpdateDropOffPointRequest;
use App\Http\Resources\DropOffCapacityLogResource;
use App\Http\Resources\DropOffPointResource;
use App\Models\DropOffCapacityLog;
use App\Models\DropOffPoint;
use App\Services\DropOff\DropOffPointFinder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Objects\Polygon;
class AdminDropOffPointController extends ApiController
{
public function __construct(private readonly DropOffPointFinder $dopFinder) {}
public function index(Request $request): JsonResponse
{
$request->validate([
'status' => ['nullable', 'in:active,maintenance,closed'],
'barangay_id' => ['nullable', 'integer'],
'q' => ['nullable', 'string', 'max:100'],
'per_page' => ['nullable', 'integer', 'min:1', 'max:500'],
]);
$perPage = (int) $request->input('per_page', 25);
$points = DropOffPoint::query()
->with(['barangay', 'tenant'])
->when($request->filled('status'), fn ($q) => $q->where('status', $request->string('status')))
->when($request->filled('barangay_id'), fn ($q) => $q->where('barangay_id', $request->integer('barangay_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(
DropOffPointResource::collection($points),
null,
[
'page' => $points->currentPage(),
'per_page' => $points->perPage(),
'total' => $points->total(),
'last_page' => $points->lastPage(),
],
);
}
public function store(StoreDropOffPointRequest $request): JsonResponse
{
$data = $request->validated();
$point = $this->makePoint($data);
$dop = DropOffPoint::create([
'name' => $data['name'],
'code' => $data['code'],
'barangay_id' => $data['barangay_id'] ?? null,
'coordinates' => $point,
'address_line' => $data['address_line'],
'capacity_kg' => $data['capacity_kg'] ?? null,
'operating_hours' => $data['operating_hours'] ?? null,
'accepted_waste_types' => $data['accepted_waste_types'] ?? null,
'status' => $data['status'] ?? DropOffPoint::STATUS_ACTIVE,
'photo_path' => $data['photo_path'] ?? null,
'contact_person' => $data['contact_person'] ?? null,
'contact_phone' => $data['contact_phone'] ?? null,
'geofence' => ! empty($data['geofence_wkt']) ? Polygon::fromJson($data['geofence_wkt'], 4326) : null,
]);
return $this->created(new DropOffPointResource($dop->load('barangay')), 'Drop-off point created');
}
public function show(DropOffPoint $dropOffPoint): JsonResponse
{
$dropOffPoint->load('barangay.cityMunicipality');
$dropOffPoint->loadMissing(['capacityLogs' => fn ($q) => $q->latest('recorded_at')->limit(20)]);
return $this->ok([
'drop_off_point' => new DropOffPointResource($dropOffPoint),
'recent_capacity_logs' => DropOffCapacityLogResource::collection($dropOffPoint->capacityLogs),
]);
}
public function update(UpdateDropOffPointRequest $request, DropOffPoint $dropOffPoint): JsonResponse
{
$data = $request->validated();
$oldStatus = $dropOffPoint->status;
$newStatus = $data['status'] ?? $oldStatus;
if (isset($data['lat'], $data['lng'])) {
$data['coordinates'] = $this->makePoint($data);
}
unset($data['lat'], $data['lng']);
if (array_key_exists('geofence_wkt', $data)) {
$data['geofence'] = ! empty($data['geofence_wkt']) ? Polygon::fromJson($data['geofence_wkt'], 4326) : null;
unset($data['geofence_wkt']);
}
DB::transaction(function () use ($dropOffPoint, $data, $oldStatus, $newStatus) {
$dropOffPoint->update($data);
if ($newStatus !== DropOffPoint::STATUS_ACTIVE && $oldStatus === DropOffPoint::STATUS_ACTIVE) {
$households = $dropOffPoint->households;
foreach ($households as $household) {
$nearest = $this->dopFinder->nearest(
$household->coordinates->latitude,
$household->coordinates->longitude
);
$household->update(['assigned_drop_off_point_id' => $nearest?->id]);
}
}
});
return $this->ok(
new DropOffPointResource($dropOffPoint->fresh()->load('barangay')),
'Drop-off point updated',
);
}
public function destroy(DropOffPoint $dropOffPoint): JsonResponse
{
$dropOffPoint->delete();
return $this->ok(null, 'Drop-off point deleted');
}
public function logCapacity(StoreCapacityLogRequest $request, DropOffPoint $dropOffPoint): JsonResponse
{
$data = $request->validated();
$log = DropOffCapacityLog::create([
'drop_off_point_id' => $dropOffPoint->id,
'fill_percent' => $data['fill_percent'],
'recorded_at' => $data['recorded_at'] ?? now(),
'recorded_by_user_id' => $request->user()->id,
'notes' => $data['notes'] ?? null,
]);
return $this->created(
new DropOffCapacityLogResource($log->load('recordedBy')),
'Capacity reading recorded',
);
}
private function makePoint(array $data): Point
{
return new Point((float) $data['lat'], (float) $data['lng'], 4326);
}
}