109 lines
3.9 KiB
PHP
109 lines
3.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Booking;
|
|
use App\Models\Services;
|
|
use App\Models\EmployeeAvailability;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Str;
|
|
|
|
class BookingsController extends Controller
|
|
{
|
|
// POST api/bookings - создание брони (ТОЛЬКО клиенты)
|
|
public function store(Request $request)
|
|
{
|
|
$request->validate([
|
|
'service_id' => 'required|exists:services,id',
|
|
'employee_id' => 'required|exists:users,id',
|
|
'date' => 'required|date',
|
|
'starttime' => 'required'
|
|
]);
|
|
|
|
$clientId = auth()->id();
|
|
if (!$clientId) {
|
|
return response()->json(['error' => 'Авторизация обязательна'], 401);
|
|
}
|
|
|
|
// Проверить активную услугу
|
|
$service = Services::where('id', $request->service_id)
|
|
->where('isactive', true)
|
|
->first();
|
|
if (!$service) {
|
|
return response()->json(['error' => 'Услуга неактивна или не найдена'], 400);
|
|
}
|
|
|
|
$durationMinutes = $service->durationminutes;
|
|
$endtime = date('H:i:s', strtotime($request->starttime . " +{$durationMinutes} minutes"));
|
|
|
|
// Проверить доступность сотрудника
|
|
$availability = EmployeeAvailability::where('employee_id', $request->employee_id)
|
|
->where('date', $request->date)
|
|
->where('starttime', '<=', $request->starttime)
|
|
->where('endtime', '>=', $endtime)
|
|
->where('isavailable', true)
|
|
->first();
|
|
|
|
if (!$availability) {
|
|
return response()->json(['error' => 'Сотрудник недоступен в это время'], 400);
|
|
}
|
|
|
|
// Проверить уникальность слота
|
|
$bookingExists = Booking::where('employee_id', $request->employee_id)
|
|
->where('bookingdate', $request->date)
|
|
->where('starttime', $request->starttime)
|
|
->whereIn('status', ['confirmed', 'completed'])
|
|
->exists();
|
|
|
|
if ($bookingExists) {
|
|
return response()->json(['error' => 'Слот уже забронирован'], 400);
|
|
}
|
|
|
|
// Создать бронь
|
|
$bookingNumber = 'CL-' . date('Y') . '-' . str_pad(Booking::count() + 1, 4, '0', STR_PAD_LEFT);
|
|
|
|
$booking = Booking::create([
|
|
'bookingnumber' => $bookingNumber,
|
|
'client_id' => $clientId,
|
|
'employee_id' => $request->employee_id,
|
|
'service_id' => $request->service_id,
|
|
'bookingdate' => $request->date,
|
|
'starttime' => $request->starttime,
|
|
'endtime' => $endtime,
|
|
'status' => 'confirmed'
|
|
]);
|
|
|
|
return response()->json([
|
|
'booking' => $booking,
|
|
'message' => 'Бронирование создано №' . $bookingNumber
|
|
], 201);
|
|
}
|
|
|
|
// POST api/bookings/{id}/cancel - отмена клиентом
|
|
public function cancel(Request $request, $id)
|
|
{
|
|
$booking = Booking::findOrFail($id);
|
|
|
|
// Только автор брони может отменить
|
|
if ($booking->client_id != auth()->id()) {
|
|
return response()->json(['error' => 'Можете отменить только свою бронь'], 403);
|
|
}
|
|
|
|
// Только confirmed брони
|
|
if ($booking->status != 'confirmed') {
|
|
return response()->json(['error' => 'Можно отменить только подтвержденные'], 400);
|
|
}
|
|
|
|
$booking->update([
|
|
'status' => 'cancelled',
|
|
'cancelledby' => 'client',
|
|
'cancelreason' => $request->reason ?? null
|
|
]);
|
|
|
|
return response()->json([
|
|
'message' => 'Бронь отменена',
|
|
'booking' => $booking
|
|
]);
|
|
}
|
|
}
|