3 Commits
Author SHA1 Message Date
Daniel-Garmig 3bb042462b Booking - Small improvements and fixes
CI / Docker Lint (push) Successful in 29s
2026-01-13 15:01:30 +01:00
Daniel-Garmig 52a4997497 Updated DateTime types. 2026-01-13 10:48:04 +01:00
Daniel-Garmig 708948fa15 Config Vars - General fixes and improvements. 2026-01-07 22:29:07 +01:00
16 changed files with 147 additions and 196 deletions
+41 -52
View File
@@ -5,9 +5,8 @@
- [Config implementation status](#config-implementation-status)
- [Company Information](#company-information)
- [Front-end Config](#front-end-config)
- [Var `NightAmountForContactDialog`](#var-nightamountforcontactdialog)
- [Var `NightCountForContactDialog`](#var-nightcountforcontactdialog)
- [Var `GuestNumberForContactDialog`](#var-guestnumberforcontactdialog)
- [Var `ContactDialogShowBehaviour`](#var-contactdialogshowbehaviour)
- [Var `ShowNonAvailableRooms`](#var-shownonavailablerooms)
- [Var `SomniaAttributionNotice`](#var-somniaattributionnotice)
- [Var `PhotoAspectRatio`](#var-photoaspectratio)
@@ -31,17 +30,16 @@ Variables are divided in sections. Some sections are ony accesible from SomniaRo
| [Company Information](#company-information) | COMPANY | Configure company information | Public |
| [Front-end config](#front-end-config) | FRONTEND_CONFIG | Configure front-end behaviour | Public |
| [Price API Management](#price-management) | API_PRICES | Configure how prices are calculated for a stay | Private |
| [API Config](#api-config) | API_CONFIG | Configure API | Private |
| [API Config](#api-config) | API_CONFIG | Configure API | Public |
### Config implementation status
Not all variables are fully implemented, some are experimental or have options that are.
Current status for a variable and it's options:
- New!: :sparkles:
- New/Experimental: :test_tube:
- Fully available: :heavy_check_mark:
- Partially available: :construction:
- Experimental: :bulb:
- Not yet: :x:
@@ -49,13 +47,15 @@ Current status for a variable and it's options:
Variables in this section contains information about the Company. Those are used to identify the business and to customize frontend.
| Variable | Type | Description | Constraints | Default Value | Status |
| :------------- | :----- | :-------------------- | :----------------------------------------------------------- | :------------ | :------------: |
| CompanyName | string | Company name | - | SomniaRooms | :construction: |
| CompanyWebsite | string | Company website URL | Valid URL to company website. | somnia.dev | :construction: |
| CompanyLogo | string | Company Logo URL | Valid URL to company logo. Somnia Backend system can be used | "" | :construction: |
| CompanyAddress | string | Company Address | - | "" | :construction: |
| CompanyEmail | string | Company email address | - | "" | :construction: |
| CompanyPhone | string | Company phone number | - | "" | :construction: |
| :-------------------- | :----- | :----------------------- | :----------------------------------------------------------- | :------------ | :----------------: |
| CompanyName | string | Company name | - | SomniaRooms | :heavy_check_mark: |
| CompanyWebsite | string | Company website URL | Valid URL to company website. | somnia.dev | :heavy_check_mark: |
| CompanyContactFormUrl | string | Company Contact form URL | A empty string or a URL to a page with a contact form. | "" | :heavy_check_mark: |
| CompanyLogo | string | Company Logo URL | Valid URL to company logo. Somnia Backend system can be used | "" | :heavy_check_mark: |
| CompanyLogoSize | string | Company Logo Size | A valid CSS size for the company logo. e.g. "96px" | "" | :heavy_check_mark: |
| CompanyAddress | string | Company Address | - | "" | :heavy_check_mark: |
| CompanyEmail | string | Company email address | - | "" | :heavy_check_mark: |
| CompanyPhone | string | Company phone number | - | "" | :heavy_check_mark: |
## Front-end Config
@@ -63,24 +63,23 @@ This variable set the behaviour of front-end app.
| Variable | Type | Description | Constraints | Default Value | Status |
| :-------------------------- | :------ | :------------------------------------------------- | :---------------------------------------------- | :------------ | :------------: |
| NightAmountForContactDialog | int | Set the amount of nights to show a contact dialog. | See [details](#var-nightamountforcontactdialog) | 10 | :construction: |
| NightCountForContactDialog | int | Set the amount of nights to show a contact dialog. | See [details](#var-NightCountForContactDialog) | 10 | :test_tube: |
| GuestNumberForContactDialog | int | Set the guest number to show a contact dialog. | See [details](#var-guestnumberforcontactdialog) | 6 | :construction: |
| ContactDialogShowBehaviour | options | Set how the contact dialog is shown | See [details](#var-contactdialogshowbehaviour) | show | :construction: |
| ShowNonAvailableRooms | bool | Show rooms without availability on search | See [details](#var-shownonavailablerooms) | true | :construction: |
| SomniaAttributionNotice | options | How SomniaRooms notice is shown. | See [details](#var-somniaattributionnotice) | full | :construction: |
| PhotoAspectRatio | string | Set the aspect ratio for photos | See [details](#var-photoaspectratio) | 4:3 | :construction: |
### Var `NightAmountForContactDialog`
### Var `NightCountForContactDialog`
Set the amount of nights to show a contact dialog. This dialog contains company contact information and may be used to get a custom price for long stays.
The contact dialog will be shown when night amount is equal or greater than configured amount.
**Options:**
| Option | Value | Usage | Status |
| :------------ | :---- | :-------------------------------------------------------- | :----: |
| Disabled | -1 | Disable this funcionality. Contact dialog won't be shown. | :x: |
| Always | 0 | Contact dialog is always shown. | :x: |
| Custom Amount | - | Set the minimun number of nights to show the dialog. | :x: |
| :------------ | :---- | :-------------------------------------------------------- | :---------: |
| Disabled | -1 | Disable this funcionality. Contact dialog won't be shown. | :test_tube: |
| Always | 0 | Contact dialog is always shown. | :test_tube: |
| Custom Amount | - | Set the minimun number of nights to show the dialog. | :test_tube: |
### Var `GuestNumberForContactDialog`
@@ -96,16 +95,6 @@ The contact dialog will be shown when guest number is equal or greater than conf
| Custom Amount | - | Set the minimun guest number to show the dialog. | :x: |
### Var `ContactDialogShowBehaviour`
How the contact dialog is shown to the user (when conditions are meet).
**Options:**
| Option | Value | Usage | Status |
| :----- | :---- | :------------------------------- | :----: |
| Show | SHOW | Show dialog on screen | :x: |
| Alert | ALERT | Show an alert to open the dialog | :x: |
### Var `ShowNonAvailableRooms`
Show rooms without availability on search.
Non-available rooms will be shown at the end of the list.
@@ -121,8 +110,8 @@ Configure how SomniaRooms attribution note is display.
**Options:**
| Option | Value | Usage | Status |
| :----- | :---- | :------------------------------------ | :----: |
| Full | FULL | Show the full message. Thanks :heart: | :x: |
| :----- | :---- | :------------------------------------ | :---------: |
| Full | FULL | Show the full message. Thanks :heart: | :test_tube: |
| Small | SMALL | Show a small notice :+1: | :x: |
| Hide | HIDE | SomniaRooms notice won't be shown. | :x: |
@@ -138,9 +127,9 @@ It's recommended that all photos have the same aspect-ratio to avoid scaling.
How SomniaRooms API services calculates prices for bookings.
| Variable | Type | Description | Constraints | Default Value | Status |
| :------------------ | :----- | :---------------------------------------------------- | :-------------------------------------- | :------------ | :----: |
| TotalPriceMethod | option | How total price is calculated for a stay | See [details](#var-totalpricemethod) | SUM | :x: |
| FareSelectionMethod | option | What fare to select when multiple fares are available | See [details](#var-fareselectionmethod) | HIGHER | :x: |
| :------------------ | :----- | :---------------------------------------------------- | :-------------------------------------- | :------------ | :---------: |
| TotalPriceMethod | option | How total price is calculated for a stay | See [details](#var-totalpricemethod) | SUM | :test_tube: |
| FareSelectionMethod | option | What fare to select when multiple fares are available | See [details](#var-fareselectionmethod) | HIGHER | :test_tube: |
### Var `TotalPriceMethod`.
@@ -150,11 +139,11 @@ The total price for a stay will be calculated from the price of the days that ma
**Options:**
| Option | Value | Usage | Status |
| :------------ | :------ | :----------------------------------------------------------------- | :----: |
| Lower Price | LOWER | The lower price will be apply for each day. | :x: |
| High Price | HIGHER | The highest price will be apply for each day. | :x: |
| Total Sum | SUM | Total price will be the sum of the price for each day. | :x: |
| Average Price | AVERAGE | The average for all days will be calculated and apply to each day. | :x: |
| :------------ | :------ | :----------------------------------------------------------------- | :---------: |
| Lower Price | LOWER | The lower price will be apply for each day. | :test_tube: |
| High Price | HIGHER | The highest price will be apply for each day. | :test_tube: |
| Total Sum | SUM | Total price will be the sum of the price for each day. | :test_tube: |
| Average Price | AVERAGE | The average for all days will be calculated and apply to each day. | :test_tube: |
### Var `FareSelectionMethod`
@@ -165,19 +154,19 @@ Note: RoomPrices have more priority than fares. So if a RoomPrice is available,
**Options:**
| Option | Value | Usage | Status |
| :------------ | :------ | :---------------------------------------------------------------- | :----: |
| Lower Price | LOWER | Lower price available will be used. | :x: |
| High Price | HIGHER | Higher available price will be used. | :x: |
| Average price | AVERAGE | Selected price will be the aritmetic average of available prices. | :x: |
| :------------ | :------ | :---------------------------------------------------------------- | :---------: |
| Lower Price | LOWER | Lower price available will be used. | :test_tube: |
| High Price | HIGHER | Higher available price will be used. | :test_tube: |
| Average price | AVERAGE | Selected price will be the aritmetic average of available prices. | :test_tube: |
## API Config.
Configuration for some API endpoints.
| Variable | Type | Description | Constraints | Default Value | Status |
| :-------------------- | :--- | :----------------------------------- | :---------------------------------------- | :------------ | :------------: |
| MaxAllowedNightAmount | int | Max night amount that can be booked. | See [details](#var-maxallowednightamount) | 20 | :construction: |
| MaxAllowedGuestNumber | int | Max guest number that can be booked. | See [details](#var-maxallowedguestnumber) | 20 | :construction: |
| :-------------------- | :--- | :----------------------------------- | :---------------------------------------- | :------------ | :---------: |
| MaxAllowedNightAmount | int | Max night amount that can be booked. | See [details](#var-maxallowednightamount) | 20 | :test_tube: |
| MaxAllowedGuestNumber | int | Max guest number that can be booked. | See [details](#var-maxallowedguestnumber) | 20 | :test_tube: |
@@ -186,15 +175,15 @@ Max number of nights that can be booked using the app. For longer stays the comp
**Options:**
| Option | Value | Usage | Status |
| :------------ | :---- | :---------------------------------------------------------- | :----: |
| Disabled | 0 | Disable this funcionality. No limit on booking will be set. | :x: |
| Custom Amount | - | Set the max number of nights allowed to book. | :x: |
| :------------ | :---- | :---------------------------------------------------------- | :---------: |
| Disabled | 0 | Disable this funcionality. No limit on booking will be set. | :test_tube: |
| Custom Amount | - | Set the max number of nights allowed to book. | :test_tube: |
### Var `MaxAllowedGuestNumber`
Max guest number that can be booked using the app. For bigger groups the company should be contacted.
**Options:**
| Option | Value | Usage | Status |
| :------------ | :---- | :---------------------------------------------------------- | :----: |
| Disabled | 0 | Disable this funcionality. No limit on booking will be set. | :x: |
| Custom Amount | - | Set the max guest number allowed to book. | :x: |
| :------------ | :---- | :---------------------------------------------------------- | :---------: |
| Disabled | 0 | Disable this funcionality. No limit on booking will be set. | :test_tube: |
| Custom Amount | - | Set the max guest number allowed to book. | :test_tube: |
+18 -3
View File
@@ -9,17 +9,23 @@ use App\Enum\ConfigVariableSectionEnum;
// --> This constants contains all defined Config Variables. For each one a array is stored as [varKey => [varSection, varDefaultValue]].
class ConfigVariableConsts
{
public const PUBLIC_SECTION_LIST = [
ConfigVariableSectionEnum::Company->value,
ConfigVariableSectionEnum::Frontend->value,
ConfigVariableSectionEnum::API_CONFIG->value,
];
public const CONFIG_COMPANY_NAME = ["CompanyName" => [ConfigVariableSectionEnum::Company, "SomniaRooms"]];
public const CONFIG_COMPANY_WEBSITE = ["CompanyWebsite" => [ConfigVariableSectionEnum::Company, "somnia.dev"]];
public const CONFIG_COMPANY_CONTACT_FORMURL = ["CompanyContactFormUrl" => [ConfigVariableSectionEnum::Company, "somnia.dev"]];
public const CONFIG_COMPANY_LOGO = ["CompanyLogo" => [ConfigVariableSectionEnum::Company, ""]];
public const CONFIG_COMPANY_LOGOSIZE = ["CompanyLogoSize" => [ConfigVariableSectionEnum::Company, ""]];
public const CONFIG_COMPANY_ADDRESS = ["CompanyAddress" => [ConfigVariableSectionEnum::Company, ""]];
public const CONFIG_COMPANY_EMAIL = ["CompanyEmail" => [ConfigVariableSectionEnum::Company, ""]];
public const CONFIG_COMPANY_PHONE = ["CompanyPhone" => [ConfigVariableSectionEnum::Company, ""]];
public const CONFIG_FRONTEND_NIGHTSFORCONTACT = ["NightAmountForContactDialog" => [ConfigVariableSectionEnum::Frontend, "10"]];
public const CONFIG_FRONTEND_NIGHTSFORCONTACT = ["NightCountForContactDialog" => [ConfigVariableSectionEnum::Frontend, "10"]];
public const CONFIG_FRONTEND_GUESTSFORCONTACT = ["GuestNumberForContactDialog" => [ConfigVariableSectionEnum::Frontend, "6"]];
public const CONFIG_FRONTEND_CONTACTDIALOGBEHAVIOUR = ["ContactDialogShowBehaviour" => [ConfigVariableSectionEnum::Frontend, "show"]];
public const CONFIG_FRONTEND_SHOWNONAVAILABLEROOMS = ["ShowNonAvailableRooms" => [ConfigVariableSectionEnum::Frontend, true]];
public const CONFIG_FRONTEND_SOMNIAATTRIBUTION = ["SomniaAttributionNotice" => [ConfigVariableSectionEnum::Frontend, "full"]];
public const CONFIG_FRONTEND_PHOTOASPECTRATIO = ["PhotoAspectRatio" => [ConfigVariableSectionEnum::Frontend, "4:3"]];
@@ -42,6 +48,7 @@ class ConfigVariableConsts
return array_merge(
ConfigVariableConsts::CONFIG_COMPANY_NAME,
ConfigVariableConsts::CONFIG_COMPANY_WEBSITE,
ConfigVariableConsts::CONFIG_COMPANY_CONTACT_FORMURL,
ConfigVariableConsts::CONFIG_COMPANY_LOGO,
ConfigVariableConsts::CONFIG_COMPANY_LOGOSIZE,
ConfigVariableConsts::CONFIG_COMPANY_ADDRESS,
@@ -49,7 +56,6 @@ class ConfigVariableConsts
ConfigVariableConsts::CONFIG_COMPANY_PHONE,
ConfigVariableConsts::CONFIG_FRONTEND_NIGHTSFORCONTACT,
ConfigVariableConsts::CONFIG_FRONTEND_GUESTSFORCONTACT,
ConfigVariableConsts::CONFIG_FRONTEND_CONTACTDIALOGBEHAVIOUR,
ConfigVariableConsts::CONFIG_FRONTEND_SHOWNONAVAILABLEROOMS,
ConfigVariableConsts::CONFIG_FRONTEND_SOMNIAATTRIBUTION,
ConfigVariableConsts::CONFIG_FRONTEND_PHOTOASPECTRATIO,
@@ -60,4 +66,13 @@ class ConfigVariableConsts
ConfigVariableConsts::CONFIG_INTERNAL_SETUP,
);
}
public static function IsSectionValuePublicForApi(string $sectionValue)
{
return in_array($sectionValue, ConfigVariableConsts::PUBLIC_SECTION_LIST);
}
public static function IsSectionPublicForApi(ConfigVariableSectionEnum $section)
{
return ConfigVariableConsts::IsSectionValuePublicForApi($section->value);
}
}
+35 -15
View File
@@ -3,6 +3,7 @@
namespace App\Controller;
use App\ApiErrorException;
use App\Consts\ConfigVariableConsts;
use App\DTO\ApiErrorMessage;
use App\Entity\Booking;
use App\Entity\BookingRoom;
@@ -12,7 +13,9 @@ use App\Repository\RoomAvailabilityRepository;
use App\Request\BookingCreateRequest;
use App\Request\BookingDetailsRequest;
use App\Response\BookingCreateResponse;
use App\Service\ConfigVariableService;
use App\Service\PricesService;
use Doctrine\DBAL\TransactionIsolationLevel;
use Doctrine\ORM\EntityManagerInterface;
use Nelmio\ApiDocBundle\Attribute\Model;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@@ -84,11 +87,10 @@ class BookingController extends AbstractController
RoomCategoryRepository $repoCat,
RoomAvailabilityRepository $repoAvailability,
PricesService $priceSrv,
ConfigVariableService $config,
#[MapRequestPayload()] BookingCreateRequest $createRequest
): JsonResponse {
$booking = new Booking();
try {
if ($createRequest->arrivalDate >= $createRequest->departureDate) {
throw new ApiErrorException(
new ApiErrorMessage(422, ApiErrorMessage::TYPE_INVALID_DATE),
@@ -96,9 +98,32 @@ class BookingController extends AbstractController
);
}
$entityManager->beginTransaction();
if (\count($createRequest->rooms) == 0) {
throw new ApiErrorException(
new ApiErrorMessage(422, ApiErrorMessage::TYPE_VALIDATION_ERROR),
'Booking must contain rooms',
);
}
$currentTime = new \DateTime("now");
$maxAllowedGuestNumber = $config->getVariableFromConst(ConfigVariableConsts::CONFIG_API_NAXGUESTS)?->getValue() ?? 0;
if ($maxAllowedGuestNumber > 0) {
$totalGuestNumber = array_reduce($createRequest->rooms, function ($carry, $item) {
return $carry += $item->guestNumber;
}, 0);
if ($totalGuestNumber > $maxAllowedGuestNumber) {
throw new ApiErrorException(
new ApiErrorMessage(422, ApiErrorMessage::TYPE_VALIDATION_ERROR),
'Max allowed guest number exceeded. Contact the company to complete the booking',
);
}
}
$currentTime = new \DateTimeImmutable("now");
$booking = new Booking();
try {
$entityManager->beginTransaction(TransactionIsolationLevel::REPEATABLE_READ);
// Create booking from request data.
$booking->setBookingTime($currentTime);
@@ -117,13 +142,6 @@ class BookingController extends AbstractController
$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();
@@ -157,9 +175,9 @@ class BookingController extends AbstractController
//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);
foreach ($priceList as $priceItem) {
if ($priceItem->guestNumber == $selectedGuestAmount) {
$room->setRoomPrice($priceItem->price);
$priceFound = true;
break;
}
@@ -178,10 +196,12 @@ class BookingController extends AbstractController
$repoAvailability->updateAvailabilityForRoomCategoryOnPeriod($roomCategory, $createRequest->arrivalDate, $createRequest->departureDate, $selectedAmount, true); //Update using "diff" mode.
}
$entityManager->commit();
$entityManager->flush();
$entityManager->commit();
} catch (\Throwable $th) {
if ($entityManager->getConnection()->isTransactionActive()) {
$entityManager->rollback();
}
throw $th;
}
+10 -65
View File
@@ -3,6 +3,7 @@
namespace App\Controller;
use App\ApiErrorException;
use App\Consts\ConfigVariableConsts;
use App\DTO\ApiErrorMessage;
use App\Entity\ConfigVariable;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@@ -11,6 +12,7 @@ use Symfony\Component\Routing\Attribute\Route;
use App\Repository\ConfigVariableRepository;
use Nelmio\ApiDocBundle\Attribute\Model;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ConfigVariableController extends AbstractController
{
@@ -36,71 +38,11 @@ class ConfigVariableController extends AbstractController
public function getAllVariables(ConfigVariableRepository $repo): Response
{
$varList = $repo->findAllVariables();
$filteredResults = array_filter($varList, function ($varItem) {
return ConfigVariableConsts::IsSectionPublicForApi($varItem->getSection());
});
return $this->json(['results' => $varList]);
}
#[Route('/api/config/section', name: 'app_config_sections', methods: ["GET"])]
#[OA\Tag(name: "Config")]
#[OA\Response(
response: 200,
description: 'Returns all public config sections.',
content: new OA\JsonContent(
type: 'object',
properties: [
new OA\Property(
property: "results",
type: "array",
items: new OA\Items(type: "string")
)
]
)
)]
public function getSections(ConfigVariableRepository $repo): Response
{
$sectionList = $repo->getAllSections();
$returnList = [];
foreach ($sectionList as $section) {
$sectionValue = $section["section"];
$returnList[] = $sectionValue;
}
return $this->json(['results' => $returnList]);
}
#[Route('/api/config/section/{section}', name: 'app_config_variableBySection', methods: ["GET"])]
#[OA\Tag(name: "Config")]
#[OA\Response(
response: 200,
description: 'Returns all public config variables for given section.',
content: new OA\JsonContent(
type: 'object',
properties: [
new OA\Property(
property: "results",
type: "array",
items: new OA\Items(ref: new Model(type: ConfigVariable::class))
)
]
)
)]
#[OA\Parameter(
name: 'section',
in: 'path',
description: 'Config section.',
schema: new OA\Schema(type: 'string')
)]
public function getVariablesBySection(ConfigVariableRepository $repo, string $section): Response
{
if(\is_null($section) || $section == '') {
throw new ApiErrorException(
new ApiErrorMessage(400, ApiErrorMessage::TYPE_INVALID_REQUEST_BODY_FORMAT)
);
}
$varList = $repo->findAllBySection($section);
return $this->json(['results' => $varList]);
return $this->json(['results' => array_values($filteredResults)]);
}
#[Route('/api/config/var/{key}', name: 'app_config_variable', methods: ["GET"])]
@@ -116,12 +58,15 @@ class ConfigVariableController extends AbstractController
#[OA\Parameter(
name: 'key',
in: 'path',
description: 'Variable key.',
description: 'Variable key. (Capital letters must match)',
schema: new OA\Schema(type: 'string')
)]
public function getByKey(ConfigVariableRepository $repo, string $key): Response
{
$var = $repo->findVariableByKey($key);
if (is_null($var)) {
throw new NotFoundHttpException('Config Variable not found!');
}
return $this->json($var);
}
+3 -3
View File
@@ -21,13 +21,13 @@ class Booking
#[ORM\Column(length: 20)]
private ?string $refNumber = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeInterface $arrivalDate = null;
#[ORM\Column(type : Types::DATE_MUTABLE)]
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
private ?\DateTimeInterface $departureDate = null;
#[ORM\Column(type : Types::DATETIMETZ_MUTABLE)]
#[ORM\Column(type: Types::DATETIMETZ_IMMUTABLE)]
private ?\DateTimeInterface $bookingTime = null;
#[ORM\OneToOne(mappedBy: 'booking', cascade: ['persist', 'remove'])]
+2 -2
View File
@@ -20,10 +20,10 @@ class FareTable
#[ORM\JoinColumn(nullable: false, onDelete: "CASCADE")]
private ?RoomCategory $roomCategory = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: false)]
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: false)]
private ?\DateTimeInterface $startDate = null;
#[ORM\Column(type : Types::DATETIME_MUTABLE, nullable: true)]
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)]
private ?\DateTimeInterface $endDate = null;
#[ORM\Column(length : 255, nullable: true)]
+2 -3
View File
@@ -3,7 +3,6 @@
namespace App\Entity;
use App\Repository\RoomAvailabilityRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: RoomAvailabilityRepository::class)]
@@ -22,9 +21,9 @@ class RoomAvailability
#[ORM\Column(nullable: false)]
private ?int $numAvailable = null;
public function getDay(): ?\DateTimeInterface
public function getDay(): ?\DateTimeImmutable
{
return new \DateTime($this->day);
return new \DateTimeImmutable($this->day);
}
public function setDay(\DateTimeInterface $day): static
+3 -3
View File
@@ -38,9 +38,9 @@ class RoomPrice
return $this;
}
public function getDate(): ?\DateTime
public function getDate(): ?\DateTimeImmutable
{
return new \DateTime($this->date);
return new \DateTimeImmutable($this->date);
}
public function getDateString(): ?string
@@ -48,7 +48,7 @@ class RoomPrice
return $this->date;
}
public function setDate(\DateTime $date): static
public function setDate(\DateTimeInterface $date): static
{
$this->date = $date->format('Y-m-d');
+4 -9
View File
@@ -24,11 +24,11 @@ class ConfigVariableRepository extends ServiceEntityRepository
/**
* Get all config variables for API.
* @return ConfigVariable[]
*/
public function findAllVariables(): array
{
return $this->createQueryBuilder('c')
->select('c.key, c.value, c.section')
->getQuery()
->getResult();
}
@@ -55,21 +55,16 @@ class ConfigVariableRepository extends ServiceEntityRepository
public function findVariableByKey($varKey): ConfigVariable|null
{
$rs = $this->createQueryBuilder('c')
->select('c.key, c.value, c.section')
->andWhere('c.key = :val')
->setParameter('val', $varKey)
->setMaxResults(1)
->getQuery()
->getResult();
// FIXME!!!
if (!$rs) {
if (count($rs) == 0) {
return null;
}
$var = new ConfigVariable();
$var->setKey($rs[0]["key"]);
$var->setValue($rs[0]["value"]);
$var->setSection($rs[0]["section"]);
return $var;
return $rs[0];
}
/**
@@ -106,6 +106,7 @@ class RoomAvailabilityRepository extends ServiceEntityRepository
$strEndDate = $endDate->format('Y-m-d');
$roomCatId = $roomCategory->getId();
/** @var RoomAvailability[] */
$availabilityItemList = $this->createQueryBuilder('ra')
->andWhere('ra.day >= :startDate')
->andWhere('ra.day < :endDate')
@@ -116,8 +117,6 @@ class RoomAvailabilityRepository extends ServiceEntityRepository
->getQuery()
->getResult();
$em = $this->getEntityManager();
foreach ($availabilityItemList as $item) {
if ($isDiff) {
$item->modNumAvailable($amount);
+3 -3
View File
@@ -3,7 +3,7 @@
namespace App\Request;
use App\Entity\BookingCustomer;
use DateTimeInterface;
use DateTimeImmutable;
use OpenApi\Attributes as OA;
use Symfony\Component\Validator\Constraints as Assert;
@@ -12,11 +12,11 @@ class BookingCreateRequest
#[OA\Property(description: 'Booking Arrival date')]
#[Assert\NotBlank]
#[Assert\GreaterThanOrEqual(value: 'today')]
public DateTimeInterface $arrivalDate;
public DateTimeImmutable $arrivalDate;
#[OA\Property(description: 'Booking departure date')]
#[Assert\NotBlank]
public DateTimeInterface $departureDate;
public DateTimeImmutable $departureDate;
#[OA\Property(
description: 'Booking customer details',
+3 -3
View File
@@ -2,7 +2,7 @@
namespace App\Request;
use DateTimeInterface;
use DateTimeImmutable;
use OpenApi\Attributes as OA;
use Symfony\Component\Validator\Constraints as Assert;
@@ -10,9 +10,9 @@ class SearchPeriodRequest
{
#[OA\Property(description: 'Period start date')]
#[Assert\NotBlank]
public DateTimeInterface $startDate;
public DateTimeImmutable $startDate;
#[OA\Property(description: 'Period end date')]
#[Assert\NotBlank]
public DateTimeInterface $endDate;
public DateTimeImmutable $endDate;
}
@@ -2,7 +2,7 @@
namespace App\Request;
use DateTimeInterface;
use DateTimeImmutable;
use OpenApi\Attributes as OA;
use Symfony\Component\Validator\Constraints as Assert;
@@ -14,9 +14,9 @@ class SearchPricesForCategoryRequest
#[OA\Property(description: 'Period start date')]
#[Assert\NotBlank]
public DateTimeInterface $startDate;
public DateTimeImmutable $startDate;
#[OA\Property(description: 'Period end date')]
#[Assert\NotBlank]
public DateTimeInterface $endDate;
public DateTimeImmutable $endDate;
}
+1 -1
View File
@@ -65,7 +65,7 @@ class ConfigVariableService
}
}
public function AddConfigVariable(string $key, string $value, ConfigVariableSectionEnum $section): void
private function AddConfigVariable(string $key, string $value, ConfigVariableSectionEnum $section): void
{
$var = new ConfigVariable();
$var->setKey($key);
+2 -13
View File
@@ -2,36 +2,25 @@
namespace App\Service;
use App\DTO\AppSetupConfig;
use App\DTO\ExampleDataConfig;
use App\Entity\BedType;
use App\Entity\ConfigVariable;
use App\Entity\FareTable;
use App\Entity\RoomCategory;
use App\Entity\RoomCategoryBedType;
use App\Entity\RoomFare;
use App\Entity\User;
use App\Enum\UserRoleEnum;
use App\Repository\ConfigVariableRepository;
use App\Repository\FareTableRepository;
use App\Repository\RoomAvailabilityRepository;
use App\Repository\RoomCategoryRepository;
use App\Repository\RoomFareRepository;
use App\Serializer\Normalizer\EntityByIdDenormalizer;
use DateTime;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use stdClass;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
/**
* Service for setup proccess.
@@ -163,7 +152,7 @@ class ExampleDataService
private function GenerateFares(ExampleDataConfig $config): bool
{
$generationTime = new DateTime();
$generationTime = new DateTimeImmutable();
$strGenTime = $generationTime->format('d-m-Y H:i:s');
$roomCategoryList = $this->roomCategoryRepository->findAll();
+1 -1
View File
@@ -43,7 +43,7 @@ class PricesService
*
* e. g. --> [ 2 => 120€, 3 => 180€ ]
*
* @return array Contiene los precios en función del número de personas.
* @return SearchPricesResponsePriceItem[] Contiene los precios en función del número de personas.
*/
public function getFinalPricesForSearch(RoomCategory $category, \DateTimeInterface $startDate, \DateTimeInterface $endDate): array
{