PriceService + XDEBUG.
- Arreglados problemas que impedian el funcionamiento de xdebug para hacer debug. - Correción errores PriceService.
This commit is contained in:
Vendored
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"port": 9003,
|
"port": 9003,
|
||||||
"pathMappings": {
|
"pathMappings": {
|
||||||
"/app" : "/src"
|
"/app" : "${workspaceFolder}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# InstantRooms
|
# SomniaRooms
|
||||||
|
|
||||||
A Hotel Room booking system.
|
A Hotel Room booking system.
|
||||||
|
|
||||||
Powered by:
|
Powered by:
|
||||||
- PHP Synfony.
|
- PHP Symfony.
|
||||||
- Easyadmin
|
- Easyadmin.
|
||||||
|
|
||||||
## Commands:
|
## Commands:
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@ docker compose build --no-cache
|
|||||||
Start Containers:
|
Start Containers:
|
||||||
```
|
```
|
||||||
docker compose up --pull always -d --wait
|
docker compose up --pull always -d --wait
|
||||||
|
docker compose --env-file .\.env.local up -d --watch
|
||||||
```
|
```
|
||||||
|
|
||||||
Stop containers
|
Stop containers
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# SomniaRooms - App Configuration Variables.
|
||||||
|
|
||||||
|
This document contains a list of all config variables of SomniaRooms. Variables are stored in DB (table _`config_variable`_) and can be configured from admin panel.
|
||||||
|
|
||||||
|
Variables are divided in sections. Some sections are ony accesible from SomniaRoom, but others can be retrieved by anyone using config endpoint (_`/config`_).
|
||||||
|
|
||||||
|
## List of sections:
|
||||||
|
|
||||||
|
WIP
|
||||||
|
|
||||||
|
TODO -> Add default table with basic information to all sections.
|
||||||
|
|
||||||
|
### **Company**
|
||||||
|
Variables in this section contains information about the Hotel.
|
||||||
|
|
||||||
|
- SectionName -> company
|
||||||
|
- Availability -> public
|
||||||
|
- Nº variables -> X
|
||||||
|
|
||||||
|
**Variable list:**
|
||||||
|
|
||||||
|
- Name - Name of hotel.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### **Price Management**
|
||||||
|
Configure how backend services calculates prices for bookings.
|
||||||
|
|
||||||
|
- SectionName -> price_mng
|
||||||
|
- Availability -> internal
|
||||||
|
- Nº variables -> X
|
||||||
|
|
||||||
|
**Variable list:**
|
||||||
|
|
||||||
|
WIP
|
||||||
|
|
||||||
|
#### FinalPriceCalculation.
|
||||||
|
Establece cómo se deben tratar los precios de cada día para generar el precio final de la estancia.
|
||||||
|
|
||||||
|
Algunos algoritmos para estos serán:
|
||||||
|
- Precio más alto.
|
||||||
|
- Precio más bajo.
|
||||||
|
- Suma de precios. --> Por defecto.
|
||||||
|
- Media de precios.
|
||||||
|
|
||||||
|
#### MultipleRoomFareValid
|
||||||
|
Estrategia de selección de tarifa en caso de que haya varias válidas (mientras no exista un sistema de prioridad de tarifas...)
|
||||||
|
|
||||||
|
Posibles algoritmos:
|
||||||
|
- Precio más alto.
|
||||||
|
- Precio más bajo.
|
||||||
|
- Media.
|
||||||
|
|
||||||
|
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
; See https://github.com/docker/for-linux/issues/264
|
; See https://github.com/docker/for-linux/issues/264
|
||||||
; The `client_host` below may optionally be replaced with `discover_client_host=yes`
|
; The `client_host` below may optionally be replaced with `discover_client_host=yes`
|
||||||
; Add `start_with_request=yes` to start debug session on each request
|
; Add `start_with_request=yes` to start debug session on each request
|
||||||
xdebug.client_host = host.docker.internal
|
xdebug.client_host=host.docker.internal
|
||||||
xdebug.start_with_request=yes
|
xdebug.start_with_request=yes
|
||||||
xdebug.mode=debug
|
;xdebug.mode=debug
|
||||||
|
xdebug.discover_client_host=1
|
||||||
|
xdebug.idekey=docker
|
||||||
|
;xdebug.log=/dev/stdout
|
||||||
@@ -9,7 +9,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
|
|||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\MoneyField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\MoneyField;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
|
||||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
|
use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
|
||||||
|
|
||||||
class RoomFareCrudController extends AbstractCrudController
|
class RoomFareCrudController extends AbstractCrudController
|
||||||
{
|
{
|
||||||
@@ -29,8 +29,8 @@ class RoomFareCrudController extends AbstractCrudController
|
|||||||
yield NumberField::new ('guestNumber');
|
yield NumberField::new ('guestNumber');
|
||||||
yield MoneyField::new ('fareAmount')->setCurrency('EUR');
|
yield MoneyField::new ('fareAmount')->setCurrency('EUR');
|
||||||
|
|
||||||
yield TextField::new('dayType')->setMaxLength(2);
|
$dayTypeList = ["MONDAY" => 1, "TUESDAY" => 2, "WEDNESDAY" => 3, "THURSDAY" => 4, "FRIDAY" => 5, "SATURDAY" => 6, "SUNDAY" => 0];
|
||||||
|
yield ChoiceField::new('dayType')->setChoices($dayTypeList);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,11 +79,10 @@ class SearchRoomsController extends AbstractController
|
|||||||
$fareTable[] = $repoFareTable->find(2);
|
$fareTable[] = $repoFareTable->find(2);
|
||||||
$cat = $repoCat->find(4);
|
$cat = $repoCat->find(4);
|
||||||
|
|
||||||
//$rs = $repoFareTable->getAllowedGuestNumberOnFareTableList($fareTable);
|
$startDate = new \DateTime("2024-04-27");
|
||||||
$startDate = new \DateTime("2024-04-20");
|
$endDate = new \DateTime("2024-05-02");
|
||||||
$endDate = new \DateTime("2024-04-21");
|
|
||||||
|
|
||||||
$rs = $priceService->getCategoryPricesForSearch($cat, $startDate, $endDate);
|
$rs = $priceService->getFinalPricesForSearch($cat, $startDate, $endDate);
|
||||||
|
|
||||||
return $this->json($rs);
|
return $this->json($rs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ use App\Entity\RoomCategory;
|
|||||||
use App\Repository\FareTableRepository;
|
use App\Repository\FareTableRepository;
|
||||||
use App\Repository\RoomFareRepository;
|
use App\Repository\RoomFareRepository;
|
||||||
|
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Servicio para calcular los precios de las estancias.
|
* Servicio para calcular los precios de las estancias.
|
||||||
* En un futuro este servicio deberá admitir múltiples estrategias de cálculo de precios finales.
|
* En un futuro este servicio deberá admitir múltiples estrategias de cálculo de precios finales.
|
||||||
@@ -28,7 +30,7 @@ class PricesService
|
|||||||
*
|
*
|
||||||
* @return array Contiene los precios en función del número de personas.
|
* @return array Contiene los precios en función del número de personas.
|
||||||
*/
|
*/
|
||||||
public function getCategoryPricesForSearch(RoomCategory $category, \DateTimeInterface $startDate, \DateTimeInterface $endDate): array
|
public function getFinalPricesForSearch(RoomCategory $category, \DateTimeInterface $startDate, \DateTimeInterface $endDate): array
|
||||||
{
|
{
|
||||||
$daysDiff = $startDate->diff($endDate)->days;
|
$daysDiff = $startDate->diff($endDate)->days;
|
||||||
if (!$daysDiff) {
|
if (!$daysDiff) {
|
||||||
@@ -47,50 +49,109 @@ class PricesService
|
|||||||
|
|
||||||
//Calculamos el precio de cada día.
|
//Calculamos el precio de cada día.
|
||||||
// e.g. --> [ "2024-04-30" => 20, "2024-05-01" => 28, "2024-05-02" => 20, ...].
|
// e.g. --> [ "2024-04-30" => 20, "2024-05-01" => 28, "2024-05-02" => 20, ...].
|
||||||
$dailyPrices = [];
|
$dailyPrices = $this->getDailyPricesForSearch($startDate, $endDate, $currentGuestNumber, $fareTablesForPeriod);
|
||||||
$currentDate = $startDate; //TODOME: Comprobar si es tipo referencia y está cambiando.
|
|
||||||
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.
|
|
||||||
$currentFareTableList = \array_filter($fareTablesForPeriod, function (FareTable $element) use ($currentDate) {
|
|
||||||
return $element->isActiveOnDate($currentDate);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (count($currentFareTableList) != 1) {
|
|
||||||
//ERROR
|
|
||||||
$dailyPrices[$strCurrentDate] = "ERROR - Number of FareTable found: " . count($currentFareTableList);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$currentFareTable = $currentFareTableList[0];
|
|
||||||
|
|
||||||
//TODOME: -> Obtener precio específico (RoomPrices).
|
|
||||||
|
|
||||||
//Si no hay precio, calcular mediante tarifarios.
|
|
||||||
$roomFares = $currentFareTable->getRoomFaresByGuestNumber($currentGuestNumber);
|
|
||||||
if (count($roomFares) < 1) {
|
|
||||||
//ERROR
|
|
||||||
$dailyPrices[$strCurrentDate] = "ERROR - Invalid RoomFares found";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODOME: -> Handle conditions...
|
|
||||||
$fareAmount = $roomFares->first()->getFareAmount();
|
|
||||||
$dailyPrices[$strCurrentDate] = $fareAmount;
|
|
||||||
|
|
||||||
//Add 1 day to current date.
|
|
||||||
$currentDate->add(new \DateInterval("P1D"));
|
|
||||||
}
|
|
||||||
|
|
||||||
$rs[$currentGuestNumber] = $dailyPrices;
|
$rs[$currentGuestNumber] = $dailyPrices;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Aplicamos la estrategia de precios configurada para calcular el precio final de la estancia.
|
//Aplicamos la estrategia de precios configurada para calcular el precio final de la estancia.
|
||||||
// TODOME: ...
|
// TODOME: Crear y configurar diversas estrategias de precios -> Por el momento utilizamos "Suma del precio de cada día".
|
||||||
|
|
||||||
return $rs;
|
$finalResult = [];
|
||||||
|
foreach ($rs as $guestNum => $priceArray) {
|
||||||
|
$finalAmount = \array_reduce($priceArray, function ($acc, $element) {
|
||||||
|
return $acc + $element;
|
||||||
|
});
|
||||||
|
|
||||||
|
$finalResult[$guestNum] = $finalAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $finalResult;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dado un número de huéspedes, calcula el precio de cada día del periodo indicado.
|
||||||
|
* @param \DateTimeInterface $startDate Fecha de inicio del periodo.
|
||||||
|
* @param \DateTimeInterface $endDate Fecha fin del periodo.
|
||||||
|
* @param int $guestNumber Número de huéspedes para los que calcular los precios.
|
||||||
|
* @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, ...].
|
||||||
|
*/
|
||||||
|
public function getDailyPricesForSearch(\DateTimeInterface $startDate, \DateTimeInterface $endDate, int $guestNumber, array $fareTableList): array
|
||||||
|
{
|
||||||
|
$daysDiff = $startDate->diff($endDate)->days;
|
||||||
|
|
||||||
|
$dailyPrices = [];
|
||||||
|
$currentDate = new \DateTime($startDate->format("Y-m-d")); //TODOME: Comprobar si es tipo referencia y está cambiando.
|
||||||
|
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.
|
||||||
|
$currentFareTableList = \array_filter($fareTableList, function (FareTable $element) use ($currentDate) {
|
||||||
|
return $element->isActiveOnDate($currentDate);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (count($currentFareTableList) != 1) {
|
||||||
|
$dailyPrices[$strCurrentDate] = "ERROR - Number of FareTable found: " . count($currentFareTableList);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentFareTable = array_values($currentFareTableList)[0];
|
||||||
|
|
||||||
|
//TODOME: -> Obtener precio específico (RoomPrices).
|
||||||
|
|
||||||
|
//Si no hay precio, calcular mediante tarifarios.
|
||||||
|
$roomFares = $currentFareTable->getRoomFaresByGuestNumber($guestNumber);
|
||||||
|
if (count($roomFares) < 1) {
|
||||||
|
$dailyPrices[$strCurrentDate] = "ERROR - Invalid RoomFares found";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dailyPrices[$strCurrentDate] = $fareAmount;
|
||||||
|
|
||||||
|
//Add 1 day to current date.
|
||||||
|
$currentDate->add(new \DateInterval("P1D"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dailyPrices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcula el precio a aplicar según las condiciones de las tarifas.
|
||||||
|
* @param RoomFare[] $roomFareList Lista con las posibles tarifas.
|
||||||
|
* @param DateTimeInterface $fareCondDate Fecha utilizada para las condiciones.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function calculateFareApplyingConditions(ArrayCollection $roomFareList, \DateTimeInterface $fareCondDate): int
|
||||||
|
{
|
||||||
|
$currentDayOfWeek = $fareCondDate->format("w");
|
||||||
|
|
||||||
|
//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();
|
||||||
|
if ($dayType == null || $dayType == "") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if($dayType == $currentDayOfWeek) {
|
||||||
|
return $roomFare->getFareAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//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 $faresWithoutConditions->first()->getFareAmount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user