API - Search Prices - Added RoomPrices

This commit is contained in:
2025-10-21 19:58:00 +02:00
parent f703727ccb
commit c9e1f95c81
5 changed files with 287 additions and 65 deletions
+85 -60
View File
@@ -9,6 +9,7 @@ use App\Entity\RoomFare;
use App\Repository\FareTableRepository;
use App\Repository\RoomCategoryRepository;
use App\Repository\RoomFareRepository;
use App\Repository\RoomPriceRepository;
use App\Response\SearchPricesResponse;
use App\Response\SearchPricesResponsePriceItem;
use App\Util\PriceSelectionMethods;
@@ -28,7 +29,7 @@ class PricesService
public function __construct(
private RoomCategoryRepository $repoRoomCategory,
private FareTableRepository $repoFareTable,
private RoomFareRepository $repoRoomFares,
private RoomPriceRepository $repoRoomPrices,
private ConfigVariableService $configVarService,
private LoggerInterface $logger
) {
@@ -53,35 +54,40 @@ class PricesService
}
$fareTablesForPeriod = $this->repoFareTable->findFareTable($category->getId(), $startDate, $endDate);
$roomPriceList = $this->repoRoomPrices->getListForPeriod($startDate, $endDate, $category->getId());
//"Organize" RoomPrices.
$filteredRoomPriceList = [];
foreach ($roomPriceList as $roomPrice) {
$priceDate = $roomPrice->getDateString();
$filteredRoomPriceList[$roomPrice->getGuestNumber()][$priceDate] = $roomPrice->getPrice();
}
//Obtenemos el número de personas permitido por todos los tarifarios activos.
$allowedGuestNumbers = $this->getAllowedGuestNumberFromFaretableList($fareTablesForPeriod);
$allowedGuestNumberList = $this->getAllowedGuestNumberFromFaretableList($fareTablesForPeriod);
$rs = [];
//Calculate stay price for each allowed GuestNumber.
$priceItems = [];
foreach ($allowedGuestNumberList as $currentGuestNumber) {
//Calculamos los precios para cada GuestNumber permitido.
foreach ($allowedGuestNumbers as $currentGuestNumber) {
//Get RoomPrices for current GuestNumber.
$roomPricesForGuestNum = [];
if (array_key_exists($currentGuestNumber, $filteredRoomPriceList)) {
$roomPricesForGuestNum = $filteredRoomPriceList[$currentGuestNumber];
}
//Calculamos el precio de cada día.
// e.g. --> [ "2024-04-30" => 20, "2024-05-01" => 28, "2024-05-02" => 20, ...].
$dailyPrices = $this->getDailyPricesForSearch($startDate, $endDate, $currentGuestNumber, $fareTablesForPeriod);
//Calculate the price for each day.
$dailyPrices = $this->getDailyPricesForSearch($startDate, $endDate, $currentGuestNumber, $fareTablesForPeriod, $roomPricesForGuestNum);
$rs[$currentGuestNumber] = $dailyPrices;
$stayPrice = $this->getTotalPriceForStay($dailyPrices);
$item = new SearchPricesResponsePriceItem();
$item->guestNumber = $currentGuestNumber;
$item->price = $stayPrice;
$priceItems[] = $item;
}
//Aplicamos la estrategia de precios configurada para calcular el precio final de la estancia.
// TODOME: Crear y configurar diversas estrategias de precios -> Por el momento utilizamos "Suma del precio de cada día".
$finalResult = [];
foreach ($rs as $guestNum => $priceArray) {
$finalAmount = \array_reduce($priceArray, function ($acc, $element) {
return $acc + $element;
});
$finalResult[$guestNum] = $finalAmount;
}
return $finalResult;
return $priceItems;
}
/**
@@ -107,46 +113,57 @@ class PricesService
$faretablesByRoomCategory[$faretable->getRoomCategory()->getId()][] = $faretable;
}
//Get and filter prices.
$priceList = $this->repoRoomPrices->getListForPeriod($startDate, $endDate);
$filteredPrices = [];
foreach ($priceList as $price) {
$priceDate = $price->getDateString();
//Store price in multi-level array by: RoomCategoryId, GuestNumber and Date.
$filteredPrices[$price->getRoomCategory()->getId()][$price->getGuestNumber()][$priceDate] = $price->getPrice();
}
foreach ($roomCategoryList as $roomCat) {
$currentRoomCategoryId = $roomCat->getId();
//Get Faretables for RoomCategory.
$roomFaretables = [];
if (array_key_exists($roomCat->getId(), $faretablesByRoomCategory)) {
$roomFaretables = $faretablesByRoomCategory[$roomCat->getId()];
if (array_key_exists($currentRoomCategoryId, $faretablesByRoomCategory)) {
$roomFaretables = $faretablesByRoomCategory[$currentRoomCategoryId];
}
//Get RoomPrices for current RoomCategory.
$roomPricesForCategory = [];
if (array_key_exists($currentRoomCategoryId, $filteredPrices)) {
$roomPricesForCategory = $filteredPrices[$currentRoomCategoryId];
}
//Calculate distinct GuestNumber for RoomCategory by it's faretables.
$allowedGuestNumberList = $this->getAllowedGuestNumberFromFaretableList($roomFaretables);
//Calculate stay price for each allowed GuestNumber.
$roomPricesByGuestNum = [];
$priceItems = [];
foreach ($allowedGuestNumberList as $currentGuestNumber) {
//Get RoomPrices for current GuestNumber.
$roomPricesForGuestNum = [];
if (array_key_exists($currentGuestNumber, $roomPricesForCategory)) {
$roomPricesForGuestNum = $roomPricesForCategory[$currentGuestNumber];
}
//Calculate the price for each day.
$dailyPrices = $this->getDailyPricesForSearch($startDate, $endDate, $currentGuestNumber, $roomFaretables);
$dailyPrices = $this->getDailyPricesForSearch($startDate, $endDate, $currentGuestNumber, $roomFaretables, $roomPricesForGuestNum);
$stayPrice = $this->getTotalPriceForStay($dailyPrices);
$roomPricesByGuestNum[$currentGuestNumber] = $stayPrice;
}
$roomPrices = [];
foreach ($roomPricesByGuestNum as $guestNum => $price) {
if ($price == null) {
$roomPrices = [];
break;
}
$item = new SearchPricesResponsePriceItem();
$item->guestNumber = $guestNum;
$item->price = $price;
$roomPrices[] = $item;
$item->guestNumber = $currentGuestNumber;
$item->price = $stayPrice;
$priceItems[] = $item;
}
$roomItem = new SearchPricesResponse();
$roomItem->roomCategoryId = $roomCat->getId();
$roomItem->prices = $roomPrices;
$roomItem->prices = $priceItems;
$rs[] = $roomItem;
}
@@ -162,7 +179,7 @@ class PricesService
* @param array $fareTableList Array con los tarifarios que aplican en el periodo indicado.
* @return array Devuelve un array con los precios: e.g. --> [ "2024-04-30" => 2500, "2024-05-01" => 3500, "2024-05-02" => 3000, ...].
*/
private function getDailyPricesForSearch(\DateTimeInterface $startDate, \DateTimeInterface $endDate, int $guestNumber, array $fareTableList): array
private function getDailyPricesForSearch(\DateTimeInterface $startDate, \DateTimeInterface $endDate, int $guestNumber, array $fareTableList, array $roomPricesByGuestNum): array
{
$daysDiff = $startDate->diff($endDate)->days;
@@ -190,33 +207,41 @@ class PricesService
return [];
}
$currentFareTable = array_values($currentFareTableList)[0];
//TODOME: -> Obtener precio específico (RoomPrices).
//Check for Prices.
$roomPrice = null;
if (array_key_exists($strCurrentDate, $roomPricesByGuestNum)) {
$roomPrice = $roomPricesByGuestNum[$strCurrentDate];
}
//Si no hay precio, calcular mediante tarifarios.
$roomFares = $currentFareTable->getRoomFaresByGuestNumber($guestNumber);
if (count($roomFares) < 1) {
$this->logger->error(
"PricesService.getDailyPricesForSearch: Can't calculate prices: Found faretable without fares",
[
"currentFareTable" => $currentFareTable,
"guestNumber" => $guestNumber,
"roomFaresForGuestNumber" => $roomFares
]
);
return [];
}
$fareAmount = null;
if ($roomPrice == null) {
//Get Faretables for guestNumber.
$currentFareTable = array_values($currentFareTableList)[0];
$roomFares = $currentFareTable->getRoomFaresByGuestNumber($guestNumber);
if (count($roomFares) < 1) {
$this->logger->error(
"PricesService.getDailyPricesForSearch: Can't calculate prices: Found faretable without fares",
[
"currentFareTable" => $currentFareTable,
"guestNumber" => $guestNumber,
"roomFaresForGuestNumber" => $roomFares
]
);
return [];
}
//Calculate RoomFare.
$fareAmount = $this->calculateFareApplyingConditions($roomFares, $currentDate);
//Calculate RoomFare.
$fareAmount = $this->calculateFareApplyingConditions($roomFares, $currentDate);
}
//If any price can't be calculated, NO price should be returned.
if ($fareAmount == null) {
if ($roomPrice == null && $fareAmount == null) {
return [];
}
$dailyPrices[$strCurrentDate] = $fareAmount;
$dailyPrices[$strCurrentDate] = $roomPrice ?? $fareAmount;
//Add 1 day to current date.
$currentDate->add(new \DateInterval("P1D"));