API - Search Prices - Improvements
- Use config variables for API responses.
This commit is contained in:
@@ -2,13 +2,16 @@
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Consts\ConfigVariableConsts;
|
||||
use App\Entity\FareTable;
|
||||
use App\Entity\RoomCategory;
|
||||
use App\Entity\RoomFare;
|
||||
use App\Repository\FareTableRepository;
|
||||
use App\Repository\RoomCategoryRepository;
|
||||
use App\Repository\RoomFareRepository;
|
||||
use App\Response\SearchPricesResponse;
|
||||
use App\Response\SearchPricesResponsePriceItem;
|
||||
use App\Util\PriceSelectionMethods;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Ds\Set;
|
||||
use Psr\Log\LoggerInterface;
|
||||
@@ -19,13 +22,19 @@ use Psr\Log\LoggerInterface;
|
||||
*/
|
||||
class PricesService
|
||||
{
|
||||
private string $configFareMethod;
|
||||
private string $configPriceMethod;
|
||||
|
||||
public function __construct(
|
||||
private RoomCategoryRepository $repoRoomCategory,
|
||||
private FareTableRepository $repoFareTable,
|
||||
private RoomFareRepository $repoRoomFares,
|
||||
private ConfigVariableService $configVarService,
|
||||
private LoggerInterface $logger
|
||||
) {}
|
||||
) {
|
||||
$this->configFareMethod = $configVarService->getVariableFromConst(ConfigVariableConsts::CONFIG_PRICES_FAREMETHOD)->getValue();
|
||||
$this->configPriceMethod = $configVarService->getVariableFromConst(ConfigVariableConsts::CONFIG_PRICES_PRICEMETHOD)->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcula los precios de la estancia para la categoría y periodo indicados.
|
||||
@@ -79,8 +88,6 @@ class PricesService
|
||||
* Calculate stay total price on each roomCategory for the given time period
|
||||
* Returns a list with all roomCategories, containing the total price by guestnumber.
|
||||
*
|
||||
* e. g. --> [ 2 => 120€, 3 => 180€ ]
|
||||
*
|
||||
* @return SearchPricesResponse[] Total prices for each guestnumber of each roomCategory.
|
||||
*/
|
||||
public function getRoomSearch(\DateTimeInterface $startDate, \DateTimeInterface $endDate): array
|
||||
@@ -125,6 +132,11 @@ class PricesService
|
||||
|
||||
$roomPrices = [];
|
||||
foreach ($roomPricesByGuestNum as $guestNum => $price) {
|
||||
if ($price == null) {
|
||||
$roomPrices = [];
|
||||
break;
|
||||
}
|
||||
|
||||
$item = new SearchPricesResponsePriceItem();
|
||||
$item->guestNumber = $guestNum;
|
||||
$item->price = $price;
|
||||
@@ -159,7 +171,8 @@ class PricesService
|
||||
for ($i = 0; $i < $daysDiff; $i++) {
|
||||
$strCurrentDate = $currentDate->format("Y-m-d");
|
||||
|
||||
//Obtenemos el tarifario que aplica --> TODOME: Buscar si se puede cachear esto, para no recarlcularlo para cada GuestNumber.
|
||||
//Get Faretable for current day.
|
||||
//TODO: Possible optimization - This data doesn't need to be recalculated so often.
|
||||
$currentFareTableList = \array_filter($fareTableList, function (FareTable $element) use ($currentDate) {
|
||||
return $element->isActiveOnDate($currentDate);
|
||||
});
|
||||
@@ -195,12 +208,12 @@ class PricesService
|
||||
return [];
|
||||
}
|
||||
|
||||
//Si sólo hay 1 tarifa, aplico esa, sino calculo la apropiada según condiciones.
|
||||
$fareAmount = null;
|
||||
if (count($roomFares) == 1) {
|
||||
$fareAmount = $roomFares->first()->getFareAmount();
|
||||
} else {
|
||||
$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) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$dailyPrices[$strCurrentDate] = $fareAmount;
|
||||
@@ -218,32 +231,76 @@ class PricesService
|
||||
* @param DateTimeInterface $fareCondDate Fecha utilizada para las condiciones.
|
||||
*
|
||||
*/
|
||||
private function calculateFareApplyingConditions(Collection $roomFareList, \DateTimeInterface $fareCondDate): int
|
||||
private function calculateFareApplyingConditions(Collection $roomFareList, \DateTimeInterface $fareCondDate): int|null
|
||||
{
|
||||
$currentDayOfWeek = $fareCondDate->format("w");
|
||||
|
||||
if (count($roomFareList) == 1) {
|
||||
return $roomFareList->first()->getFareAmount();
|
||||
}
|
||||
|
||||
//Comprobamos si a alguna de las tarifas se la aplica la condición de "DayType" y coincide con el actual.
|
||||
// Si es así, devolvemos su valor.
|
||||
foreach ($roomFareList as $roomFare) {
|
||||
$dayType = $roomFare->getDayType();
|
||||
$currentDayOfWeek = $fareCondDate->format("w");
|
||||
//Filter applicable fares.
|
||||
//TODO: Possible optimization - This data doesn't need to be recalculated so often; just once for each FareTable.
|
||||
/** @var RoomFare[] */
|
||||
$applFaresByDay = [];
|
||||
/** @var RoomFare[] */
|
||||
$applFaresNonCondition = [];
|
||||
foreach ($roomFareList as $fare) {
|
||||
$dayType = $fare->getDayType();
|
||||
if ($dayType == null || $dayType == "") {
|
||||
$applFaresNonCondition[] = $fare;
|
||||
continue;
|
||||
}
|
||||
if ($dayType == $currentDayOfWeek) {
|
||||
return $roomFare->getFareAmount();
|
||||
$applFaresByDay[] = $fare;
|
||||
}
|
||||
}
|
||||
|
||||
//TODOME: Si existen múltiples tarifas posibles, debería haber una estrategia para elegir una u otra. Variable de configuración para esto.
|
||||
$faresWithoutConditions = $roomFareList->filter(function ($element) {
|
||||
return $element->getDayType() == null;
|
||||
});
|
||||
//Return final fare value.
|
||||
//Use fares for current weekday.
|
||||
$finalFare = $this->getPriceFromRoomFareList($applFaresByDay);
|
||||
if ($finalFare != null) {
|
||||
return $finalFare;
|
||||
}
|
||||
|
||||
return $faresWithoutConditions->first()->getFareAmount();
|
||||
//Use non-conditional fares.
|
||||
$finalFare = $this->getPriceFromRoomFareList($applFaresNonCondition);
|
||||
if ($finalFare != null) {
|
||||
return $finalFare;
|
||||
}
|
||||
|
||||
//No valid fare found!
|
||||
$this->logger->error(
|
||||
"PricesService.calculateFareApplyingConditions: No RoomFare found. Price can't be calculated.",
|
||||
["RoomFareList" => $roomFareList, "Date" => $fareCondDate]
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fare with bigger priority from a list of fares.
|
||||
* @param RoomFare[] $roomFareList List of RoomFares.
|
||||
*/
|
||||
private function getPriceFromRoomFareList(array $roomFareList): int|null
|
||||
{
|
||||
$countFares = count($roomFareList);
|
||||
if ($roomFareList == null || $countFares == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($countFares == 1) {
|
||||
return $roomFareList[0]->getFareAmount();
|
||||
}
|
||||
|
||||
switch ($this->configFareMethod) {
|
||||
case 'HIGHER':
|
||||
return PriceSelectionMethods::selectFare_Highest($roomFareList);
|
||||
case 'LOWER':
|
||||
return PriceSelectionMethods::selectFare_Lowest($roomFareList);
|
||||
case 'AVERAGE':
|
||||
return PriceSelectionMethods::selectFare_Average($roomFareList);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,13 +330,19 @@ class PricesService
|
||||
* @param array $dailyPrices Array containing the price for each day.
|
||||
* @return int Total stay price.
|
||||
*/
|
||||
private function getTotalPriceForStay(array $dailyPrices): int
|
||||
private function getTotalPriceForStay(array $dailyPrices): int|null
|
||||
{
|
||||
// TODOME: Crear y configurar diversas estrategias de precios -> Por el momento utilizamos "Suma del precio de cada día".
|
||||
|
||||
$finalAmount = \array_reduce($dailyPrices, function ($acc, $element) {
|
||||
return $acc + $element;
|
||||
});
|
||||
return $finalAmount;
|
||||
switch ($this->configPriceMethod) {
|
||||
case 'SUM':
|
||||
return PriceSelectionMethods::priceMethod_Sum($dailyPrices);
|
||||
case 'AVERAGE':
|
||||
return PriceSelectionMethods::priceMethod_Average($dailyPrices);
|
||||
case 'HIGHER':
|
||||
return PriceSelectionMethods::priceMethod_Highest($dailyPrices);
|
||||
case 'LOWER':
|
||||
return PriceSelectionMethods::priceMethod_Lowest($dailyPrices);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user