where('uuid', $uuid) ->with('establishment') ->firstOrFail(); return $this->success([ 'machine' => new MachineResource($machine), ]); } public function availability(Request $request, string $uuid): JsonResponse { $machine = Machine::query() ->where('uuid', $uuid) ->with('establishment') ->firstOrFail(); $date = $request->filled('date') ? Carbon::parse($request->string('date')->toString())->startOfDay() : now()->startOfDay(); $slotDuration = $request->integer('slot_minutes', 60); $dayStart = $date->copy()->setTime(7, 0); $dayEnd = $date->copy()->setTime(22, 0); $bookings = Booking::query() ->where('machine_id', $machine->id) ->whereIn('status', ['pending', 'confirmed', 'active']) ->where('slot_start', '<', $dayEnd) ->where('slot_end', '>', $dayStart) ->get(['slot_start', 'slot_end']); $slots = []; $cursor = $dayStart->copy(); while ($cursor->copy()->addMinutes($slotDuration)->lte($dayEnd)) { $slotEnd = $cursor->copy()->addMinutes($slotDuration); $isAvailable = $cursor->isFuture() && ! in_array($machine->status, ['offline', 'maintenance', 'out_of_order'], true); if ($isAvailable) { foreach ($bookings as $booking) { if ($booking->slot_start < $slotEnd && $booking->slot_end > $cursor) { $isAvailable = false; break; } } } if ($isAvailable) { $slots[] = [ 'start' => $cursor->toIso8601String(), 'end' => $slotEnd->toIso8601String(), ]; } $cursor->addMinutes($slotDuration); } return $this->success([ 'machine_uuid' => $machine->uuid, 'date' => $date->toDateString(), 'slots' => $slots, ]); } public function pricing(string $uuid): JsonResponse { $machine = Machine::query() ->where('uuid', $uuid) ->with('establishment') ->firstOrFail(); $price = $this->pricingService->getActivePrice($machine); return $this->success([ 'machine_uuid' => $machine->uuid, 'price' => $price, 'currency' => 'EUR', ]); } }