findOneBy(["refNumber" => $detailsRequest->refNumber]); if (\is_null($selectedBooking)) { throw new NotFoundHttpException('Booking not found'); } if ($selectedBooking->getBookingCustomer()->getEmail() != $detailsRequest->email) { throw new NotFoundHttpException('Booking not found'); } return $this->json($selectedBooking); } /** * Create a new Booking. */ #[Route('/api/booking/create', name: 'app_booking_create', methods: ["POST"], format: "json")] #[OA\Tag(name: "Booking")] #[OA\Response( response: 200, description: 'Returns booking details', content: new OA\JsonContent( type: 'object', ref: new Model(type: BookingCreateResponse::class) ) )] #[OA\RequestBody( content: new OA\JsonContent( type: 'object', ref: new Model(type: BookingCreateRequest::class), ) )] public function newBooking( Request $request, EntityManagerInterface $entityManager, RoomCategoryRepository $repoCat, RoomAvailabilityRepository $repoAvailability, PricesService $priceSrv, #[MapRequestPayload()] BookingCreateRequest $createRequest ): JsonResponse { if (\is_null($createRequest)) { throw new ApiErrorException( new ApiErrorMessage(400, ApiErrorMessage::TYPE_INVALID_REQUEST_BODY_FORMAT) ); } $booking = new Booking(); try { if ($createRequest->arrivalDate >= $createRequest->departureDate) { throw new ApiErrorException( new ApiErrorMessage(422, ApiErrorMessage::TYPE_INVALID_DATE), 'Arrival cant be before departure', ); } $entityManager->beginTransaction(); $currentTime = new \DateTime("now"); // Create booking from request data. $booking->setBookingTime($currentTime); $booking->setArrivalDate($createRequest->arrivalDate); $booking->setDepartureDate($createRequest->departureDate); $booking->setBookingCustomer($createRequest->customerDetails); //TODOME: Improve refNumber generation. $highest_id = $entityManager->createQueryBuilder() ->select('MAX(e.id)') ->from('App\Entity\Booking', 'e') ->getQuery() ->getSingleScalarResult(); $booking->setRefNumber($currentTime->format("Y") . $highest_id + 1); $entityManager->persist($booking); if (\count($createRequest->rooms) == 0) { throw new ApiErrorException( new ApiErrorMessage(422, ApiErrorMessage::TYPE_VALIDATION_ERROR), 'Booking must contain rooms', ); } // Create each room. foreach ($createRequest->rooms as $roomItem) { $room = new BookingRoom(); $room->setBooking($booking); //Get Room category. $roomCategory = $repoCat->find($roomItem->roomCategory); if ($roomCategory == null) { throw new ApiErrorException( new ApiErrorMessage(422, ApiErrorMessage::TYPE_VALIDATION_ERROR), 'Invalid RoomCategory: ' . $roomItem->roomCategory, ); } //Check room availability. $amountAvailable = $repoAvailability->getAvailabilityForCategoryInPeriod($roomCategory, $createRequest->arrivalDate, $createRequest->departureDate); $selectedAmount = $roomItem->amount; $selectedGuestAmount = $roomItem->guestNumber; if ($amountAvailable == null || $selectedAmount > $amountAvailable) { throw new ApiErrorException( new ApiErrorMessage(400, ApiErrorMessage::TYPE_LOGICAL_ERROR), 'Not enought rooms available for category: ' . $roomItem->roomCategory, ); } $room->setRoomCategory($roomCategory); $room->setGuestNumber($selectedGuestAmount); $room->setAmount($selectedAmount); //Get Price for period. $priceList = $priceSrv->getFinalPricesForSearch($roomCategory, $createRequest->arrivalDate, $createRequest->departureDate); $priceFound = false; foreach ($priceList as $key => $value) { if ($key == $selectedGuestAmount) { $room->setRoomPrice($value); $priceFound = true; break; } } if (!$priceFound) { throw new ApiErrorException( new ApiErrorMessage(422, ApiErrorMessage::TYPE_LOGICAL_ERROR), 'Price not found for category: ' . $roomCategory->getId() . ', guests: ' . $selectedGuestAmount, ); } $entityManager->persist($room); //If booking is nice, let's update current availability. $repoAvailability->updateAvailabilityForRoomCategoryOnPeriod($roomCategory, $createRequest->arrivalDate, $createRequest->departureDate, $selectedAmount, true); //Update using "diff" mode. } $entityManager->commit(); $entityManager->flush(); } catch (\Throwable $th) { $entityManager->rollback(); throw $th; } $results = ["refNumber" => $booking->getRefNumber()]; return $this->json($results); } }