Я пишу тесты, чтобы удостовериться, что новое бронирование не может быть зарезервировано дважды над другим. Я прочитал, хотя и бесчисленное количество других SO-тем, и теперь я в замешательстве и не уверен, что все делаю правильно. Я специально использую Laravel в своем проекте, а также в этом примере.
Миграция. php
...
$table->date('date'); // 2020-01-01
$table->time('time_start'); // 15:00:00
$table->time('time_end'); // 17:00:00
...
Я работал с dateTime
или timezone
. Я попадаю в ловушку: «Мне не нужна дата , просто время. Я сохраняю дату в другом месте». Затем я найду ветку, предлагающую сохранить как timestamp
, и сравню там дату.
У меня есть фабрика резервирования для генерации (среди прочих деталей) date
, time_start
и time_end
:
Factory. php
'date' => date('Y-m-d'),
'time_start' => '15:00:00',
'time_end' => '17:00:00',
Большинство прочитанных мной тем предлагают сравнение с использованием strtotime
. Что-то вроде:
'time_start' => strtotime('15:00:00'), // 1582210800
Это имеет смысл. Но потом я прочитал, что сохранение как dateTime
или timezone
лучше из-за часового пояса.
В моем контроллере я проверяю существующее резервирование, как это:
Controller. php
...
$existing = DB::table('reservations')
->where('asset_id', '=', $request->asset_id)
->whereDate('date', '=', $request->date)
->whereTime('time_start', '>=', $request->time_start) // or use $request->strtotime('time_start')
->whereTime('time_end', '<=', $request->time_end)
->where(function ($query) {
$query
->where('status', '=', 'created')
->orWhere('status', '=', 'pending')
->orWhere('status', '=', 'completed');
})
->get();
if ($existing->count() > 0) {
// Not allowed
} else {
// OK to proceed
}
...
Использование whereTime выглядит именно так, как мне нужно:
->whereTime('created_at', '=', '11:20:45')
Похоже, что это будет сохранено как time
столбец. В своих тестах я проверяю, что я получаю 400
обратно, если он не может быть создан.
Тест. php
...
$http->assertStatus(400)
->assertJsonStructure([
'type', 'data' => [
'reason'
]])
->assertJson([
'type' => 'reservations',
'data' => [
'reason' => 'Asset is no longer available.',
],
]);
Это работает Великий. Если я создаю бронирование с 15:00:00
до 17:00:00
той же даты / актив и т. Д. 1107 *. Мой тест проходит. Я получаю ошибку 400 точно так, как я ожидаю. Однако, если я пройду 15:01:00
, мой тест не пройден. Не удивлен, но это говорит о том, что я не правильно сравниваю данные. Кажется, что я нахожусь на финишной линии sh, но тогда обе туфли развязались.
Интерфейс пользователя будет просто выпадать из понятных человеку времен. Я планировал просто сохранить значения как 24-часовое время. Например, 15:00:00
. Я не уверен, как еще это сделать ...
Буду признателен за предложения, чтобы лучше понять, как:
- Лучше всего сэкономить время (я)
time
, timestamp
, datetime
? - Использовать
strtotime
(или нет). Если да, то какой тип данных идеален? timestamp
, datetime
? - Используйте соответствующий ответ об ошибке; 400 идеально?
Большое спасибо за любые мысли.
ОБНОВЛЕНИЕ
Следуя совету @ miken32 - я сделал уже установили отношения таким образом, чтобы это имело смысл.
Теперь я сохраняю time_start
и time_end
как поле dateTime
в моей миграции.
Контроллер. php
$asset = Asset::find($request->asset_id);
$existing = $asset->reservations()
->where(function ($query) use ($request) {
$start_dt = new Carbon($request->time_start);
$end_dt = new Carbon($request->time_end);
$query->where('time_start', '>=', $start_dt)
->where('time_end', '<=', $end_dt);
})
->whereIn('status', ['created', 'pending', 'completed'])
->get();
if ($existing->count() > 0) {
// Log::info('CANNOT MAKE RESERVATION FOR: ' . $request->first_name . ' ' . $request->last_name);
return response()->json(['type' => 'reservations', 'data' => ['reason' => 'Asset is no longer available.']], 409);
} else {
$reservation = new Reservation();
...
// Log::info('RESERVATION MADE FOR: ' . $reservation->first_name . ' ' . $reservation->last_name);
Пользователи будут иметь возможность выбирать только предварительно определенное время. Как только временной интервал зарезервирован для любого данного актива, этот блок становится недоступным. Я уверен, что, по сути, я уверен, что кто-то не может (каким-то образом) переопределить запрос POST
другим значением.
Надеюсь, это поможет кому-то еще. Если моя реализация выключена, пожалуйста, дайте мне знать, чтобы я мог исправить это для всех остальных.