Booking Creation - Finish initial implement.

- Check and update availability.
- Set prices.
- Generate booking refNumber.
This commit is contained in:
2024-05-10 21:31:24 +02:00
parent 528d1a39ab
commit ed4ba9d82f
3 changed files with 109 additions and 12 deletions
+46 -7
View File
@@ -7,6 +7,8 @@ use App\Entity\BookingCustomer;
use App\Entity\BookingRoom; use App\Entity\BookingRoom;
use App\Repository\BookingRepository; use App\Repository\BookingRepository;
use App\Repository\RoomCategoryRepository; use App\Repository\RoomCategoryRepository;
use App\Repository\RoomAvailabilityRepository;
use App\Service\PricesService;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
@@ -41,13 +43,16 @@ class BookingController extends AbstractController
} }
#[Route('/api/booking/create', name: 'app_booking_create')] #[Route('/api/booking/create', name: 'app_booking_create')]
public function newBooking(Request $request, BookingRepository $repoBooking, EntityManagerInterface $entityManager, RoomCategoryRepository $repoCat): JsonResponse public function newBooking(Request $request, BookingRepository $repoBooking, EntityManagerInterface $entityManager,
RoomCategoryRepository $repoCat, RoomAvailabilityRepository $repoAvailability,
PricesService $priceSrv): JsonResponse
{ {
$payload = $request->toArray(); $payload = $request->toArray();
if (\is_null($payload)) { if (\is_null($payload)) {
throw new \Exception('Invalid Payload', 400); throw new \Exception('Invalid Payload', 400);
} }
$booking = new Booking(); $booking = new Booking();
try { try {
$reqArrivalDate = $payload["arrivalDate"]; $reqArrivalDate = $payload["arrivalDate"];
@@ -65,11 +70,17 @@ class BookingController extends AbstractController
$currentTime = new \DateTime(); $currentTime = new \DateTime();
// Create booking from request data. // Create booking from request data.
//$booking = new Booking();
$booking->setBookingTime($currentTime); $booking->setBookingTime($currentTime);
$booking->setArrivalDate($arrivalDate); $booking->setArrivalDate($arrivalDate);
$booking->setDepartureDate($departureDate); $booking->setDepartureDate($departureDate);
$booking->setRefNumber($currentTime->format("Y") . "001");
$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); $entityManager->persist($booking);
@@ -89,22 +100,50 @@ class BookingController extends AbstractController
throw new HttpException(400, "Se debe indicar al menos una habitación"); throw new HttpException(400, "Se debe indicar al menos una habitación");
} }
// Create each room.
foreach ($reqRoomList as $roomItem) { foreach ($reqRoomList as $roomItem) {
$room = new BookingRoom(); $room = new BookingRoom();
$room->setBooking($booking); $room->setBooking($booking);
//Get Room category. //Get Room category.
$roomCategory = $repoCat->find($roomItem["roomCategory"]); $roomCategory = $repoCat->find($roomItem["roomCategory"]);
if($roomCategory == null) { if ($roomCategory == null) {
throw new HttpException(400, "La RoomCategory no es válida."); throw new HttpException(400, "La RoomCategory no es válida.");
} }
//Check room availability.
$amountAvailable = $repoAvailability->getAvailabilityForCategoryInPeriod($roomCategory, $arrivalDate, $departureDate);
$selectedAmount = $roomItem['amount'];
$selectedGuestAmount = $roomItem["guestNumber"];
if($amountAvailable == null || $selectedAmount > $amountAvailable) {
throw new HttpException(400, "No se pueden reservar más habitaciones de las disponibles.");
}
$room->setRoomCategory($roomCategory); $room->setRoomCategory($roomCategory);
$room->setGuestNumber($roomItem["guestNumber"]); $room->setGuestNumber($selectedGuestAmount);
$room->setAmount($roomItem["amount"]); $room->setAmount($selectedAmount);
$room->setRoomPrice(5000);
//Get Price for period.
$priceList = $priceSrv->getFinalPricesForSearch($roomCategory, $arrivalDate, $departureDate);
$priceFound = false;
foreach ($priceList as $key => $value) {
if($key == $selectedGuestAmount) {
$room->setRoomPrice($value);
$priceFound = true;
break;
}
}
if(!$priceFound) {
throw new HttpException(500,
"No se puedo obtener el precio para la categoría: " . $roommCategory->getId() . " , guests: " . $selecctedGuestAmount);
}
$entityManager->persist($room); $entityManager->persist($room);
//If booking is nice, let's update current availability.
$repoAvailability->updateAvailabilityForRoomCategoryOnPeriod($roomCategory, $arrivalDate, $departureDate, $selectedAmount, true); //Update using "diff" mode.
} }
$entityManager->commit(); $entityManager->commit();
+4
View File
@@ -57,4 +57,8 @@ class RoomAvailability
return $this; return $this;
} }
public function modNumAvailable(int $diffAmount):void {
$this->numAvailable -= $diffAmount;
}
} }
+59 -5
View File
@@ -3,6 +3,7 @@
namespace App\Repository; namespace App\Repository;
use App\Entity\RoomAvailability; use App\Entity\RoomAvailability;
use App\Entity\RoomCategory;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
@@ -34,7 +35,6 @@ class RoomAvailabilityRepository extends ServiceEntityRepository
->getResult(); ->getResult();
} }
/** /**
* @param \DateTimeInterface Period start (included in range). * @param \DateTimeInterface Period start (included in range).
* @param \DateTimeInterface Period end (not included in range). * @param \DateTimeInterface Period end (not included in range).
@@ -53,8 +53,30 @@ class RoomAvailabilityRepository extends ServiceEntityRepository
->setParameter('startDate', $strStartDate) ->setParameter('startDate', $strStartDate)
->setParameter('endDate', $strEndDate) ->setParameter('endDate', $strEndDate)
->getQuery() ->getQuery()
->getArrayResult() ->getArrayResult();
; }
/**
* @param \DateTimeInterface Period start (included in range).
* @param \DateTimeInterface Period end (not included in range).
* @return int Returns number of available room of that category on selected period.
*/
public function getAvailabilityForCategoryInPeriod(RoomCategory $roomCategory, \DateTimeInterface $startDate, \DateTimeInterface $endDate): int|null
{
$strStartDate = $startDate->format('Y-m-d');
$strEndDate = $endDate->format('Y-m-d');
$roomCatId = $roomCategory->getId();
return $this->createQueryBuilder('ra')
->select('MIN(ra.numAvailable) as availability')
->andWhere('ra.day >= :startDate')
->andWhere('ra.day < :endDate')
->andWhere('ra.roomCategory = :roomCategory')
->setParameter('roomCategory', $roomCatId)
->setParameter('startDate', $strStartDate)
->setParameter('endDate', $strEndDate)
->getQuery()
->getSingleScalarResult();
} }
public function getAvailabilityForPeriodDetails(\DateTimeInterface $startDate, \DateTimeInterface $endDate): array public function getAvailabilityForPeriodDetails(\DateTimeInterface $startDate, \DateTimeInterface $endDate): array
@@ -68,7 +90,39 @@ class RoomAvailabilityRepository extends ServiceEntityRepository
->setParameter('startDate', $strStartDate) ->setParameter('startDate', $strStartDate)
->setParameter('endDate', $strEndDate) ->setParameter('endDate', $strEndDate)
->getQuery() ->getQuery()
->getArrayResult() ->getArrayResult();
; }
/**
* Updates All Availability of selected roomCategory during period. It can operate in 2 modes, normal and diff mode.
* - Normal mode -> Sets value.
* - Diff mode -> apply value as sum ( currentAvailability += diff )
* NOTE: A Flush is needed after this operation.
*/
public function updateAvailabilityForRoomCategoryOnPeriod(RoomCategory $roomCategory, \DateTimeInterface $startDate, \DateTimeInterface $endDate, int $amount, bool $isDiff = false): void
{
$strStartDate = $startDate->format('Y-m-d');
$strEndDate = $endDate->format('Y-m-d');
$roomCatId = $roomCategory->getId();
$availabilityItemList = $this->createQueryBuilder('ra')
->andWhere('ra.day >= :startDate')
->andWhere('ra.day < :endDate')
->andWhere('ra.roomCategory = :roomCategory')
->setParameter('roomCategory', $roomCatId)
->setParameter('startDate', $strStartDate)
->setParameter('endDate', $strEndDate)
->getQuery()
->getResult();
$em = $this->getEntityManager();
foreach ($availabilityItemList as $item) {
if ($isDiff) {
$item->modNumAvailable($amount);
} else {
$item->setNumAvailable($amount);
}
}
} }
} }