Passed
Push — master ( abbe1f...f3d6e0 )
by Adam
06:34
created

ReservationController::add()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 46
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 4.9704

Importance

Changes 0
Metric Value
cc 4
eloc 28
nc 5
nop 2
dl 0
loc 46
ccs 17
cts 28
cp 0.6071
crap 4.9704
rs 8.6315
c 0
b 0
f 0
1
<?php
2
3
namespace App\Http\Controllers;
4
5
use App\Http\Interfaces\ManageTableInterface;
6
use App\Http\Requests\ReservationAddRequest;
7
use App\Http\Requests\ReservationEditRequest;
8
use App\Models\Guest;
9
use App\Models\Reservation;
10
use App\Models\Room;
11
use App\Services\GuestTableService;
12
use App\Services\ReservationTableService;
13
use App\Services\RoomTableService;
14
use Carbon\Carbon;
15
use Illuminate\Database\Eloquent\ModelNotFoundException;
16
use Illuminate\Support\Facades\DB;
17
use Illuminate\Support\Facades\Log;
18
use Illuminate\Support\Facades\Session;
19
20
class ReservationController extends Controller implements ManageTableInterface
21
{
22
    protected $reservationTableService;
23
24 14
    public function __construct(ReservationTableService $reservationTableService)
25
    {
26 14
        $this->reservationTableService = $reservationTableService;
27 14
    }
28
29 4
    public function index()
30
    {
31 4
        $title = trans('navigation.all_reservations');
32
33 4
        $dataset = Reservation::select('id', 'room_id', 'guest_id', 'date_start', 'date_end', 'people')
34 4
            ->with('guest:id,first_name,last_name')
35 4
            ->with('room:id,number')
36 4
            ->orderBy('date_end', 'DESC')
37 4
            ->paginate($this->getItemsPerPage());
38
39 4
        if ($dataset->isEmpty()) {
40 2
            $this->addFlashMessage(trans('general.no_reservations_in_database'), 'alert-danger');
41
        }
42
43
        $viewData = [
44 4
            'columns'       => $this->reservationTableService->getColumns(),
45 4
            'dataset'       => $dataset,
46 4
            'routeName'     => $this->reservationTableService->getRouteName(),
47 4
            'title'         => $title,
48
        ];
49
50 4
        return view('list', $viewData);
51
    }
52
53 2
    public function current()
54
    {
55 2
        $title = trans('navigation.current_reservations');
56
57 2
        $dataset = Reservation::select('id', 'room_id', 'guest_id', 'date_start', 'date_end', 'people')
58 2
            ->with('guest:id,first_name,last_name')
59 2
            ->with('room:id,number')
60 2
            ->getCurrentReservations()
61 2
            ->orderBy('date_end')
62 2
            ->paginate($this->getItemsPerPage());
63
64 2
        if ($dataset->isEmpty()) {
65 1
            $this->addFlashMessage(trans('general.no_reservations_in_database'), 'alert-danger');
66
        }
67
68
        $viewData = [
69 2
            'columns'       => $this->reservationTableService->getColumns(),
70 2
            'dataset'       => $dataset,
71 2
            'routeName'     => $this->reservationTableService->getRouteName(),
72 2
            'title'         => $title,
73
        ];
74
75 2
        return view('list', $viewData);
76
    }
77
78 2
    public function future()
79
    {
80 2
        $title = trans('navigation.future_reservations');
81
82 2
        $dataset = Reservation::select('id', 'room_id', 'guest_id', 'date_start', 'date_end', 'people')
83 2
            ->with('guest:id,first_name,last_name')
84 2
            ->with('room:id,number')
85 2
            ->getFutureReservations()
86 2
            ->orderBy('date_end')
87 2
            ->paginate($this->getItemsPerPage());
88
89 2
        if ($dataset->isEmpty()) {
90 1
            $this->addFlashMessage(trans('general.no_reservations_in_database'), 'alert-danger');
91
        }
92
93
        $viewData = [
94 2
            'columns'       => $this->reservationTableService->getColumns(),
95 2
            'dataset'       => $dataset,
96 2
            'routeName'     => $this->reservationTableService->getRouteName(),
97 2
            'title'         => $title,
98
        ];
99
100 2
        return view('list', $viewData);
101
    }
102
103 3
    public function chooseGuest(GuestTableService $guestTableService)
104
    {
105 3
        $title = trans('navigation.choose_guest');
106
107 3
        $dataset = Guest::select('id', 'first_name', 'last_name', 'address', 'zip_code', 'place', 'PESEL', 'contact')
108 3
            ->paginate($this->getItemsPerPage());
109
110 3
        if ($dataset->isEmpty()) {
111 1
            $this->addFlashMessage(trans('general.no_guests_in_database'), 'alert-danger');
112
        }
113
114
        $viewData = [
115 3
            'columns'         => $guestTableService->getColumns(),
116 3
            'dataset'         => $dataset,
117 3
            'routeName'       => $guestTableService->getRouteName(),
118 3
            'title'           => $title,
119 3
            'routeChooseName' => $this->reservationTableService->getRouteName().'.search_free_rooms',
120
        ];
121
122 3
        return view('list', $viewData);
123
    }
124
125 3
    public function searchFreeRooms($guestId)
126
    {
127
        try {
128 3
            $guest = Guest::select('id', 'first_name', 'last_name')->findOrFail($guestId);
129
        } catch (ModelNotFoundException $e) {
130
            return $this->returnBack([
131
                'message'     => trans('general.object_not_found'),
132
                'alert-class' => 'alert-danger',
133
            ]);
134
        }
135
136 3
        $dataset = new Reservation();
137 3
        $dataset->guest()->associate($guest);
138 3
        $title = trans('navigation.search_free_rooms');
139 3
        $submitRoute = route($this->reservationTableService->getRouteName().'.post_search_free_rooms', $dataset->guest->id);
0 ignored issues
show
Bug introduced by
$dataset->guest->id of type integer is incompatible with the type array expected by parameter $parameters of route(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

139
        $submitRoute = route($this->reservationTableService->getRouteName().'.post_search_free_rooms', /** @scrutinizer ignore-type */ $dataset->guest->id);
Loading history...
140
141 3
        $fiels = $this->getFields(true);
142 3
        array_unshift($fiels, $this->getGuestField());
143
144
        $viewData = [
145 3
            'dataset'     => $dataset,
146 3
            'fields'      => $fiels,
147 3
            'title'       => $title,
148 3
            'submitRoute' => $submitRoute,
149
        ];
150
151 3
        return view('addedit', $viewData);
152
    }
153
154 2
    public function postSearchFreeRooms(ReservationAddRequest $request, $guestId = null)
155
    {
156
        try {
157 2
            $guest = Guest::select('id')->findOrFail($guestId);
158
        } catch (ModelNotFoundException $e) {
159
            return $this->returnBack([
160
                'message'     => trans('general.object_not_found'),
161
                'alert-class' => 'alert-danger',
162
            ]);
163
        }
164
165 2
        $data = $request->only(['date_start', 'date_end', 'people']);
166
167 2
        return redirect()->route($this->reservationTableService->getRouteName().'.choose_free_room', $guest->id)
0 ignored issues
show
Bug introduced by
$guest->id of type integer is incompatible with the type array expected by parameter $parameters of Illuminate\Routing\Redirector::route(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

167
        return redirect()->route($this->reservationTableService->getRouteName().'.choose_free_room', /** @scrutinizer ignore-type */ $guest->id)
Loading history...
168 2
            ->with($data);
169
    }
170
171
    /**
172
     * @param RoomTableService $roomTableService
173
     * @param int              $guestId
174
     *
175
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\View\View
176
     */
177 2
    public function chooseFreeRoom(RoomTableService $roomTableService, $guestId)
178
    {
179 2
        if (!$this->isReservationDataInSessionCorrect()) {
180
            return $this->returnBack([
181
                'message'     => trans('general.object_not_found'),
182
                'alert-class' => 'alert-danger',
183
            ]);
184
        }
185
186
        try {
187 2
            $guest = Guest::select('id', 'first_name', 'last_name')->findOrFail($guestId);
188
        } catch (ModelNotFoundException $e) {
189
            Log::warning(__CLASS__.'::'.__FUNCTION__.' at '.__LINE__.': '.$e->getMessage());
190
191
            return $this->returnBack([
192
                'message'     => trans('general.object_not_found'),
193
                'alert-class' => 'alert-danger',
194
            ]);
195
        }
196
197 2
        $dateStart = Session::get('date_start');
198 2
        $dateEnd = Session::get('date_end');
199 2
        $people = Session::get('people');
200
201 2
        $dateStart = Carbon::parse($dateStart);
202 2
        $dateEnd = Carbon::parse($dateEnd);
203
204 2
        $title = trans('navigation.choose_room_for').' '.$guest->fullName;
0 ignored issues
show
Bug introduced by
Are you sure trans('navigation.choose_room_for') of type null|string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

204
        $title = /** @scrutinizer ignore-type */ trans('navigation.choose_room_for').' '.$guest->fullName;
Loading history...
205
206 2
        $dataset = Room::select('id', 'number', 'floor', 'capacity', 'price', 'comment')
207 2
            ->freeRoomsForReservation($dateStart, $dateEnd, $people)
208 2
            ->paginate($this->getItemsPerPage());
209
210 2
        if ($dataset->isEmpty()) {
211 1
            $this->addFlashMessage(trans('general.no_rooms_in_database'), 'alert-danger');
212
        }
213
214
        $viewData = [
215 2
            'columns'               => $roomTableService->getColumns(),
216 2
            'dataset'               => $dataset,
217 2
            'routeName'             => $roomTableService->getRouteName(),
218 2
            'title'                 => $title,
219 2
            'routeChooseName'       => $this->reservationTableService->getRouteName().'.add',
220 2
            'additionalRouteParams' => $guest->id,
221
        ];
222
223 2
        return view('list', $viewData);
224
    }
225
226 1
    public function add($guestId, $roomId)
227
    {
228 1
        if (!$this->isReservationDataInSessionCorrect()) {
229
            return $this->returnBack([
230
                'message'     => trans('general.object_not_found'),
231
                'alert-class' => 'alert-danger',
232
            ]);
233
        }
234
235 1
        $dateStart = Session::get('date_start');
236 1
        $dateEnd = Session::get('date_end');
237 1
        $people = Session::get('people');
238
239
        try {
240 1
            $guest = Guest::select('id')->findOrFail($guestId);
241 1
            $room = Room::select('id', 'capacity')->findOrFail($roomId);
242
        } catch (ModelNotFoundException $e) {
243
            Log::warning(__CLASS__.'::'.__FUNCTION__.' at '.__LINE__.': '.$e->getMessage());
244
245
            return $this->returnBack([
246
                'message'     => trans('general.object_not_found'),
247
                'alert-class' => 'alert-danger',
248
            ]);
249
        }
250
251 1
        if ($room->capacity < $people) {
252
            return $this->returnBack([
253
                'message'     => trans('general.people_exceeds_room_capacity'),
254
                'alert-class' => 'alert-danger',
255
            ]);
256
        }
257
258
        // TODO: Check if room is free
259
260 1
        $reservation = new Reservation();
261 1
        $reservation->guest_id = $guest->id;
262 1
        $reservation->room_id = $room->id;
263 1
        $reservation->date_start = $dateStart;
264 1
        $reservation->date_end = $dateEnd;
265 1
        $reservation->people = $people;
266
267 1
        $reservation->save();
268
269 1
        $this->addFlashMessage(trans('general.saved'), 'alert-success');
270
271 1
        return redirect()->route($this->reservationTableService->getRouteName().'.index');
272
    }
273
274
    public function postEdit(ReservationEditRequest $request, $objectId)
275
    {
276
        try {
277
            $object = Reservation::with('room:id,capacity')
278
                ->findOrFail($objectId);
279
        } catch (ModelNotFoundException $e) {
280
            return $this->returnBack([
281
                'message'     => trans('general.object_not_found'),
282
                'alert-class' => 'alert-danger',
283
            ]);
284
        }
285
286
        // Check room capacity for people in reservation
287
        if ($object->room->capacity < $request->input('people')) {
288
            return redirect()->back()->with([
289
                'message'     => trans('general.people_exceeds_room_capacity'),
290
                'alert-class' => 'alert-danger',
291
            ]);
292
        }
293
294
        $dateStart = Carbon::parse($request->input('date_start'));
295
        $dateEnd = Carbon::parse($request->input('date_end'));
296
297
        // Check if dates can be changed
298
        $reservationsIdsForDates = DB::table('reservations')
299
            ->where('room_id', $object->room_id)
300
            ->where('id', '!=', $object->id)
301
            ->where(function ($query) use ($dateStart, $dateEnd) {
302
                $query->where(function ($query) use ($dateStart, $dateEnd) {
303
                    $query->where('date_start', '<', $dateEnd)
304
                        ->where('date_end', '>', $dateStart);
305
                });
306
            })
307
            ->count();
308
309
        if ($reservationsIdsForDates > 0) {
310
            return redirect()->back()->with([
311
                'message'     => trans('general.dates_coincide_different_booking'),
312
                'alert-class' => 'alert-danger',
313
            ]);
314
        }
315
316
        $object->fill($request->all());
317
        $object->save();
318
319
        return redirect()->route($this->reservationTableService->getRouteName().'.index')
320
            ->with([
321
                'message'     => trans('general.saved'),
322
                'alert-class' => 'alert-success',
323
            ]);
324
    }
325
326 1
    public function delete($objectId)
327
    {
328
        try {
329 1
            $object = Reservation::findOrFail($objectId);
330
        } catch (ModelNotFoundException $e) {
331
            $data = ['class' => 'alert-danger', 'message' => trans('general.object_not_found')];
332
333
            return response()->json($data);
334
        }
335
336 1
        $object->delete();
337
338 1
        $data = ['class' => 'alert-success', 'message' => trans('general.deleted')];
339
340 1
        return response()->json($data);
341
    }
342
343 2
    public function showEditForm($objectId)
344
    {
345
        try {
346 2
            $dataset = Reservation::select('id', 'room_id', 'guest_id', 'date_start', 'date_end', 'people')
347 2
            ->with('guest:id,first_name,last_name')
348 2
            ->with('room:id,number')
349 2
            ->findOrFail($objectId);
350 1
        } catch (ModelNotFoundException $e) {
351 1
            return $this->returnBack([
352 1
                'message'     => trans('general.object_not_found'),
353 1
                'alert-class' => 'alert-danger',
354
            ]);
355
        }
356
357 1
        $title = trans('navigation.edit_reservation');
358 1
        $submitRoute = route($this->reservationTableService->getRouteName().'.postedit', $objectId);
359
360 1
        $fiels = $this->getFields();
361 1
        array_unshift($fiels, $this->getGuestField(), $this->getRoomField(), $this->getActionButtons());
362
363
        $viewData = [
364 1
            'dataset'     => $dataset,
365 1
            'fields'      => $fiels,
366 1
            'title'       => $title,
367 1
            'submitRoute' => $submitRoute,
368 1
            'routeName'   => $this->reservationTableService->getRouteName(),
369
        ];
370
371 1
        return view('addedit', $viewData);
372
    }
373
374
    public function editChooseGuest(GuestTableService $guestTableService, $reservationId)
375
    {
376
        try {
377
            $reservation = Reservation::select('id', 'guest_id')->findOrFail($reservationId);
378
        } catch (ModelNotFoundException $e) {
379
            return $this->returnBack([
380
                'message'     => trans('general.object_not_found'),
381
                'alert-class' => 'alert-danger',
382
            ]);
383
        }
384
385
        $title = trans('navigation.change_guest_for_reservation');
386
387
        $dataset = Guest::select('id', 'first_name', 'last_name', 'address', 'zip_code', 'place', 'PESEL', 'contact')
388
            ->whereNotIn('id', [$reservation->guest_id])
389
            ->paginate($this->getItemsPerPage());
390
391
        if ($dataset->isEmpty()) {
392
            $this->addFlashMessage(trans('general.no_guests_in_database'), 'alert-danger');
393
        }
394
395
        $viewData = [
396
            'columns'               => $guestTableService->getColumns(),
397
            'dataset'               => $dataset,
398
            'routeName'             => $guestTableService->getRouteName(),
399
            'title'                 => $title,
400
            'routeChooseName'       => $this->reservationTableService->getRouteName().'.edit_change_guest',
401
            'additionalRouteParams' => $reservation->id,
402
        ];
403
404
        return view('list', $viewData);
405
    }
406
407
    public function editChangeGuest($reservationId, $guestId)
408
    {
409
        try {
410
            $reservation = Reservation::select('id')->findOrFail($reservationId);
411
            $guest = Guest::select('id')->findOrFail($guestId);
412
        } catch (ModelNotFoundException $e) {
413
            return $this->returnBack([
414
                'message'     => trans('general.object_not_found'),
415
                'alert-class' => 'alert-danger',
416
            ]);
417
        }
418
419
        $reservation->guest_id = $guest->id;
420
        $reservation->save();
421
422
        return redirect()->route($this->reservationTableService->getRouteName().'.editform', $reservation->id)
0 ignored issues
show
Bug introduced by
$reservation->id of type integer is incompatible with the type array expected by parameter $parameters of Illuminate\Routing\Redirector::route(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

422
        return redirect()->route($this->reservationTableService->getRouteName().'.editform', /** @scrutinizer ignore-type */ $reservation->id)
Loading history...
423
            ->with([
424
                'message'     => trans('general.saved'),
425
                'alert-class' => 'alert-success',
426
            ]);
427
    }
428
429
    public function editChooseRoom(RoomTableService $roomTableService, $reservationId)
430
    {
431
        try {
432
            $reservation = Reservation::select('id', 'guest_id', 'date_start', 'date_end', 'people')
433
                ->findOrFail($reservationId);
434
        } catch (ModelNotFoundException $e) {
435
            return $this->returnBack([
436
                'message'     => trans('general.object_not_found'),
437
                'alert-class' => 'alert-danger',
438
            ]);
439
        }
440
441
        $dateStart = Carbon::parse($reservation->date_start);
442
        $dateEnd = Carbon::parse($reservation->date_end);
443
444
        $title = trans('navigation.change_room_for_reservation');
445
446
        $dataset = Room::select('id', 'number', 'floor', 'capacity', 'price', 'comment')
447
            ->freeRoomsForReservation($dateStart, $dateEnd, $reservation->people)
448
            ->paginate($this->getItemsPerPage());
449
450
        if ($dataset->isEmpty()) {
451
            $this->addFlashMessage(trans('general.no_rooms_in_database'), 'alert-danger');
452
        }
453
454
        $viewData = [
455
            'columns'               => $roomTableService->getColumns(),
456
            'dataset'               => $dataset,
457
            'routeName'             => $roomTableService->getRouteName(),
458
            'title'                 => $title,
459
            'routeChooseName'       => $this->reservationTableService->getRouteName().'.edit_change_room',
460
            'additionalRouteParams' => $reservation->id,
461
        ];
462
463
        return view('list', $viewData);
464
    }
465
466
    public function editChangeRoom($reservationId, $roomId)
467
    {
468
        try {
469
            $reservation = Reservation::select('id', 'people')->findOrFail($reservationId);
470
            $room = Room::select('id', 'capacity')->findOrFail($roomId);
471
        } catch (ModelNotFoundException $e) {
472
            return $this->returnBack([
473
                'message'     => trans('general.object_not_found'),
474
                'alert-class' => 'alert-danger',
475
            ]);
476
        }
477
478
        if ($room->capacity < $reservation->people) {
479
            return $this->returnBack([
480
                'message'     => trans('general.people_exceeds_room_capacity'),
481
                'alert-class' => 'alert-danger',
482
            ]);
483
        }
484
485
        // TODO: Check if room is free
486
487
        $reservation->room_id = $room->id;
488
        $reservation->save();
489
490
        return redirect()->route($this->reservationTableService->getRouteName().'.editform', $reservation->id)
0 ignored issues
show
Bug introduced by
$reservation->id of type integer is incompatible with the type array expected by parameter $parameters of Illuminate\Routing\Redirector::route(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

490
        return redirect()->route($this->reservationTableService->getRouteName().'.editform', /** @scrutinizer ignore-type */ $reservation->id)
Loading history...
491
            ->with([
492
                'message'     => trans('general.saved'),
493
                'alert-class' => 'alert-success',
494
            ]);
495
    }
496
497 4
    public function getGuestField()
498
    {
499
        return [
500 4
            'id'    => 'guest',
501 4
            'title' => trans('general.guest'),
502 4
            'value' => function (Reservation $data) {
503 4
                return $data->guest->full_name;
504 4
            },
505
            'optional' => [
506
                'readonly' => 'readonly',
507
            ],
508
        ];
509
    }
510
511 1
    public function getRoomField()
512
    {
513
        return [
514 1
            'id'    => 'room',
515 1
            'title' => trans('general.room'),
516 1
            'value' => function (Reservation $data) {
517 1
                return $data->room->number;
518 1
            },
519
            'optional' => [
520
                'readonly' => 'readonly',
521
            ],
522
        ];
523
    }
524
525 1
    public function getActionButtons()
526
    {
527
        return [
528 1
            'id'         => 'action_buttons',
529 1
            'type'       => 'buttons',
530
            'buttons'    => [
531
                [
532 1
                    'value' => function () {
533 1
                        return 'Zmień gościa';
534 1
                    },
535 1
                    'route_name'  => 'reservation.edit_choose_guest',
536 1
                    'route_param' => function (Reservation $data) {
537 1
                        return $data->id;
538 1
                    },
539
                    'optional' => [
540
                        'class' => 'btn btn-primary',
541
                    ],
542
                ],
543
                [
544 1
                    'value' => function () {
545 1
                        return 'Zmień pokój';
546 1
                    },
547 1
                    'route_name'  => 'reservation.edit_choose_room',
548 1
                    'route_param' => function (Reservation $data) {
549 1
                        return $data->id;
550 1
                    },
551
                    'optional' => [
552
                        'class' => 'btn btn-primary',
553
                    ],
554
                ],
555
            ],
556
        ];
557
    }
558
559 4
    public function getFields($forAdd = false)
560
    {
561
        return [
562
            [
563 4
                'id'    => 'date_start',
564 4
                'title' => trans('general.date_start'),
565 4
                'value' => function (Reservation $data) {
566 4
                    return $data->date_start;
567 4
                },
568 4
                'type'     => 'text',
569
                'optional' => [
570 4
                    'required'    => 'required',
571 4
                    'class'       => 'datepicker'. ($forAdd ? ' start-date' : null),
572 4
                    'placeholder' => 'dd.mm.rrrr',
573
                ],
574
            ],
575
            [
576 4
                'id'    => 'date_end',
577 4
                'title' => trans('general.date_end'),
578 4
                'value' => function (Reservation $data) {
579 4
                    return $data->date_end;
580 4
                },
581 4
                'type'     => 'text',
582
                'optional' => [
583 4
                    'required'    => 'required',
584 4
                    'class'       => 'datepicker'. ($forAdd ? ' end-date' : null),
585 4
                    'placeholder' => 'dd.mm.rrrr',
586
                ],
587
            ],
588
            [
589 4
                'id'    => 'people',
590 4
                'title' => trans('general.number_of_people'),
591 4
                'value' => function (Reservation $data) {
592 4
                    return $data->people ?: 1;
593 4
                },
594 4
                'type'     => 'number',
595
                'optional' => [
596
                    'required' => 'required',
597
                    'min'      => '1',
598
                ],
599
            ],
600
        ];
601
    }
602
603 2
    private function isReservationDataInSessionCorrect()
604
    {
605 2
        if (!Session::has(['date_start', 'date_end', 'people'])) {
606
            Log::error('Missing one of Session keys: date_start, date_end, people');
607
608
            return false;
609
        }
610
611 2
        Session::reflash();
612
613 2
        return true;
614
    }
615
}
616