fix: reduce snapshot payloads via serializer group and hydration
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes travel_snapshot.payload from TEXT to LONGTEXT so large
|
||||||
|
* plain JSON snapshot payloads can be stored safely.
|
||||||
|
*/
|
||||||
|
final class Version20260324120000 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Change travel_snapshot.payload from TEXT to LONGTEXT for plain JSON snapshot payloads';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE travel_snapshot CHANGE payload payload LONGTEXT NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE travel_snapshot CHANGE payload payload TEXT NOT NULL');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,15 +15,15 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
|||||||
*/
|
*/
|
||||||
class CrmSelection
|
class CrmSelection
|
||||||
{
|
{
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?int $id = null;
|
public ?int $id = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?string $label = null;
|
public ?string $label = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public bool $mutable = false;
|
public bool $mutable = false;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public bool $selected = false;
|
public bool $selected = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,16 +32,16 @@ class CrmSelectionGroup
|
|||||||
90 => 'Transport',
|
90 => 'Transport',
|
||||||
];
|
];
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?int $id = null;
|
public ?int $id = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?string $label = null;
|
public ?string $label = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<int, CrmSelection>|null
|
* @var array<int, CrmSelection>|null
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?array $selections = null;
|
public ?array $selections = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
|||||||
*/
|
*/
|
||||||
class Guide
|
class Guide
|
||||||
{
|
{
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?string $phone = null;
|
public ?string $phone = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,24 +15,24 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
|||||||
*/
|
*/
|
||||||
class Hotel
|
class Hotel
|
||||||
{
|
{
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $id = null;
|
public ?int $id = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $code = null;
|
public ?string $code = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $city = null;
|
public ?string $city = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $street = null;
|
public ?string $street = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $phone = null;
|
public ?string $phone = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $country = null;
|
public ?string $country = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,32 +17,32 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
|||||||
*/
|
*/
|
||||||
class Pickup
|
class Pickup
|
||||||
{
|
{
|
||||||
#[Groups(['api:list'])]
|
#[Groups(['api:list', 'snapshot'])]
|
||||||
public ?int $id = null;
|
public ?int $id = null;
|
||||||
|
|
||||||
#[Groups(['api:list'])]
|
#[Groups(['api:list', 'snapshot'])]
|
||||||
public ?string $code = null;
|
public ?string $code = null;
|
||||||
|
|
||||||
#[Groups(['api:list'])]
|
#[Groups(['api:list', 'snapshot'])]
|
||||||
public ?string $city = null;
|
public ?string $city = null;
|
||||||
|
|
||||||
#[Groups(['api:list'])]
|
#[Groups(['api:list', 'snapshot'])]
|
||||||
public ?string $postalCode = null;
|
public ?string $postalCode = null;
|
||||||
|
|
||||||
#[Groups(['api:list'])]
|
#[Groups(['api:list', 'snapshot'])]
|
||||||
public ?string $street = null;
|
public ?string $street = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i'])]
|
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i'])]
|
||||||
public ?\DateTimeImmutable $time = null;
|
public ?\DateTimeImmutable $time = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?float $price = null;
|
public ?float $price = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?float $priceOutbound = null;
|
public ?float $priceOutbound = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?float $priceInbound = null;
|
public ?float $priceInbound = null;
|
||||||
|
|
||||||
#[Groups(['api:booking'])]
|
#[Groups(['api:booking'])]
|
||||||
|
|||||||
@@ -20,19 +20,19 @@ class Room
|
|||||||
public const SELECTION_TYPE_BY_PAX = 'by_pax';
|
public const SELECTION_TYPE_BY_PAX = 'by_pax';
|
||||||
public const SELECTION_TYPE_BY_ROOM = 'by_room';
|
public const SELECTION_TYPE_BY_ROOM = 'by_room';
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $id = null;
|
public ?int $id = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $category = null;
|
public ?string $category = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $boardId = null;
|
public ?int $boardId = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $code = null;
|
public ?string $code = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $label = null;
|
public ?string $label = null;
|
||||||
|
|
||||||
#[Groups(['booking'])]
|
#[Groups(['booking'])]
|
||||||
@@ -46,19 +46,19 @@ class Room
|
|||||||
#[Groups(['booking'])]
|
#[Groups(['booking'])]
|
||||||
public ?int $totalCount = null;
|
public ?int $totalCount = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $minPax = null;
|
public ?int $minPax = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $maxPax = null;
|
public ?int $maxPax = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $nights = null;
|
public ?int $nights = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $status = null;
|
public ?string $status = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $available = null;
|
public ?int $available = null;
|
||||||
|
|
||||||
#[Groups(['booking'])]
|
#[Groups(['booking'])]
|
||||||
@@ -67,7 +67,7 @@ class Room
|
|||||||
#[Groups(['booking'])]
|
#[Groups(['booking'])]
|
||||||
public array $mapping = [];
|
public array $mapping = [];
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?float $price = null;
|
public ?float $price = null;
|
||||||
|
|
||||||
#[Groups(['booking'])]
|
#[Groups(['booking'])]
|
||||||
|
|||||||
@@ -17,78 +17,78 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
|||||||
*/
|
*/
|
||||||
class Service
|
class Service
|
||||||
{
|
{
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?int $id = null;
|
public ?int $id = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $category = null;
|
public ?string $category = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $status = null;
|
public ?string $status = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public bool $mandatory = false;
|
public bool $mandatory = false;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public bool $autoBook = false;
|
public bool $autoBook = false;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $label = null;
|
public ?string $label = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||||
public ?\DateTimeImmutable $dateFrom = null;
|
public ?\DateTimeImmutable $dateFrom = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $timeFrom = null;
|
public ?string $timeFrom = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $dayTime = null;
|
public ?string $dayTime = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||||
public ?\DateTimeImmutable $dateTo = null;
|
public ?\DateTimeImmutable $dateTo = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $subType = null;
|
public ?string $subType = null;
|
||||||
|
|
||||||
#[Groups(['booking'])]
|
#[Groups(['booking'])]
|
||||||
public ?int $totalCount = null;
|
public ?int $totalCount = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $mapping = [];
|
public array $mapping = [];
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?float $price = null;
|
public ?float $price = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?float $totalPrice = null;
|
public ?float $totalPrice = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $individualPrice = [];
|
public array $individualPrice = [];
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?int $available = null;
|
public ?int $available = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $source = null;
|
public ?string $source = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $direction = null;
|
public ?string $direction = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?int $ageFrom = null;
|
public ?int $ageFrom = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?int $ageTo = null;
|
public ?int $ageTo = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?int $birthYearFrom = null;
|
public ?int $birthYearFrom = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?int $birthYearTo = null;
|
public ?int $birthYearTo = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $ageConstraintType = null;
|
public ?string $ageConstraintType = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single'])]
|
||||||
@@ -97,7 +97,7 @@ class Service
|
|||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single'])]
|
||||||
public ?string $rawAgeConstraintData = null;
|
public ?string $rawAgeConstraintData = null;
|
||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public ?string $description = null;
|
public ?string $description = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,6 +107,6 @@ class Service
|
|||||||
* When false, this service's price is excluded when determining which insurance
|
* When false, this service's price is excluded when determining which insurance
|
||||||
* tier is appropriate for a participant.
|
* tier is appropriate for a participant.
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list', 'snapshot'])]
|
||||||
public bool $includeInInsuranceCalculation = true;
|
public bool $includeInInsuranceCalculation = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,43 +20,43 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
|||||||
class Travel
|
class Travel
|
||||||
{
|
{
|
||||||
use SortByPriceTrait;
|
use SortByPriceTrait;
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $id = null;
|
public ?int $id = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $code = null;
|
public ?string $code = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $productCode = null;
|
public ?string $productCode = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $productId = null;
|
public ?int $productId = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $label = null;
|
public ?string $label = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?int $hotelId = null;
|
public ?int $hotelId = null;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?Hotel $hotel = null;
|
public ?Hotel $hotel = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||||
public ?\DateTimeImmutable $dateFrom = null;
|
public ?\DateTimeImmutable $dateFrom = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||||
public ?\DateTimeImmutable $dateTo = null;
|
public ?\DateTimeImmutable $dateTo = null;
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?string $type = null;
|
public ?string $type = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Travel booking status from BusProNet API.
|
* Travel booking status from BusProNet API.
|
||||||
* Possible values: 'Frei', 'Anfrage', 'Buchungsstop'.
|
* Possible values: 'Frei', 'Anfrage', 'Buchungsstop'.
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?string $status = null;
|
public ?string $status = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,67 +65,67 @@ class Travel
|
|||||||
*
|
*
|
||||||
* @var array<string>
|
* @var array<string>
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $allowedBookingStatus = [];
|
public array $allowedBookingStatus = [];
|
||||||
|
|
||||||
#[Groups(['api:list', 'api:single'])]
|
#[Groups(['api:list', 'api:single', 'snapshot'])]
|
||||||
public ?float $priceFrom = null;
|
public ?float $priceFrom = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<int, CrmSelectionGroup>
|
* @var array<int, CrmSelectionGroup>
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $selectionGroups = [];
|
public array $selectionGroups = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<int, Service>
|
* @var array<int, Service>
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $additionalServices = [];
|
public array $additionalServices = [];
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public bool $additionalServicesMutable = true;
|
public bool $additionalServicesMutable = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<int, Service>
|
* @var array<int, Service>
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $transportationServices = [];
|
public array $transportationServices = [];
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public bool $transportationServicesMutable = true;
|
public bool $transportationServicesMutable = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<int, Pickup>
|
* @var array<int, Pickup>
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $pickups = [];
|
public array $pickups = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<int, Pickup>
|
* @var array<int, Pickup>
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $dropOffs = [];
|
public array $dropOffs = [];
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public bool $pickupsMutable = true;
|
public bool $pickupsMutable = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<int, Room>
|
* @var array<int, Room>
|
||||||
*/
|
*/
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public array $rooms = [];
|
public array $rooms = [];
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public bool $roomsMutable = true;
|
public bool $roomsMutable = true;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public bool $participantDataMutable = true;
|
public bool $participantDataMutable = true;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public bool $participantCountMutable = true;
|
public bool $participantCountMutable = true;
|
||||||
|
|
||||||
#[Groups(['api:single'])]
|
#[Groups(['api:single', 'snapshot'])]
|
||||||
public ?Guide $guide = null;
|
public ?Guide $guide = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class InsuranceLoader extends AbstractLoader
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return $this->cache->get('bpn_insurances', function (ItemInterface $item) use ($filename) {
|
return $this->cache->get('bpn_insurances', function (ItemInterface $item) use ($filename) {
|
||||||
$item->expiresAfter(3 * 60 * 60);
|
$item->expiresAfter(24 * 60 * 60);
|
||||||
|
|
||||||
$crawler = $this->loadXml($filename);
|
$crawler = $this->loadXml($filename);
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ class BpnXmlSyncCommand extends Command
|
|||||||
'bpn_travels_mapping',
|
'bpn_travels_mapping',
|
||||||
'bpn_hotels',
|
'bpn_hotels',
|
||||||
'bpn_pickups',
|
'bpn_pickups',
|
||||||
'bpn_insurances',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ class TravelSnapshot
|
|||||||
#[ORM\Column(type: 'date_immutable', nullable: true)]
|
#[ORM\Column(type: 'date_immutable', nullable: true)]
|
||||||
private ?\DateTimeImmutable $dateTo = null;
|
private ?\DateTimeImmutable $dateTo = null;
|
||||||
|
|
||||||
/** Full JSON-serialized Travel aggregate. */
|
/** Full serialized Travel aggregate stored as JSON text. */
|
||||||
#[ORM\Column(type: 'text')]
|
#[ORM\Column(type: 'text', columnDefinition: 'LONGTEXT NOT NULL')]
|
||||||
private string $payload;
|
private string $payload;
|
||||||
|
|
||||||
/** SHA-256 of payload; compared before every write to skip no-op flushes. */
|
/** SHA-256 of payload; compared before every write to skip no-op flushes. */
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ class TravelDataService
|
|||||||
?? $this->getTravelDataFromXml($dateId, $hotelId);
|
?? $this->getTravelDataFromXml($dateId, $hotelId);
|
||||||
|
|
||||||
if (null !== $travel) {
|
if (null !== $travel) {
|
||||||
|
$this->patchInsuranceData($travel);
|
||||||
$this->hydrateInsurancePackageRelationships($travel->insurances);
|
$this->hydrateInsurancePackageRelationships($travel->insurances);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,7 +761,6 @@ class TravelDataService
|
|||||||
try {
|
try {
|
||||||
$this->pickupLoader->patchPickupsDetails($travel);
|
$this->pickupLoader->patchPickupsDetails($travel);
|
||||||
$this->hotelLoader->patchHotelDetails($travel);
|
$this->hotelLoader->patchHotelDetails($travel);
|
||||||
$this->patchInsuranceData($travel);
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->logger->warning('Failed to enrich travel data', [
|
$this->logger->warning('Failed to enrich travel data', [
|
||||||
'travelId' => $travel->id,
|
'travelId' => $travel->id,
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class TravelSnapshotService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$payload = $this->serializer->serialize($travel, 'json');
|
$payload = $this->serializer->serialize($travel, 'json', ['groups' => ['snapshot']]);
|
||||||
$payloadHash = hash('sha256', $payload);
|
$payloadHash = hash('sha256', $payload);
|
||||||
$snapshot = $this->snapshotRepository->findByDateAndHotel($travel->id, $travel->hotelId);
|
$snapshot = $this->snapshotRepository->findByDateAndHotel($travel->id, $travel->hotelId);
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ class TravelSnapshotService
|
|||||||
|
|
||||||
$this->applyExtendedAvailability($travel, $response);
|
$this->applyExtendedAvailability($travel, $response);
|
||||||
|
|
||||||
$payload = $this->serializer->serialize($travel, 'json');
|
$payload = $this->serializer->serialize($travel, 'json', ['groups' => ['snapshot']]);
|
||||||
$payloadHash = hash('sha256', $payload);
|
$payloadHash = hash('sha256', $payload);
|
||||||
if ($payloadHash !== $snapshot->getPayloadHash()) {
|
if ($payloadHash !== $snapshot->getPayloadHash()) {
|
||||||
$snapshot->setPayload($payload)->setPayloadHash($payloadHash);
|
$snapshot->setPayload($payload)->setPayloadHash($payloadHash);
|
||||||
|
|||||||
@@ -313,13 +313,20 @@ class TravelDataServiceTest extends TestCase
|
|||||||
$this->assertSame($travel, $result);
|
$this->assertSame($travel, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetTravelDataFromLocalRehydratesInsurancePackagesFromSnapshot(): void
|
public function testGetTravelDataFromLocalHydratesInsurancePackagesFromLoaderAfterSnapshotLoad(): void
|
||||||
{
|
{
|
||||||
$dateId = 12345;
|
$dateId = 12345;
|
||||||
$hotelId = 67890;
|
$hotelId = 67890;
|
||||||
|
|
||||||
// Simulate a deserialized snapshot state: containedInsuranceIds are present but
|
$travel = new Travel();
|
||||||
// containedInsurances is empty (circular-reference prevention strips it during serialization).
|
$travel->id = $dateId;
|
||||||
|
$travel->hotelId = $hotelId;
|
||||||
|
|
||||||
|
// Snapshot-provided insurances are intentionally replaced by InsuranceLoader data.
|
||||||
|
$staleSnapshotInsurance = new Insurance();
|
||||||
|
$staleSnapshotInsurance->id = 'stale';
|
||||||
|
$travel->insurances = [$staleSnapshotInsurance];
|
||||||
|
|
||||||
$individual = new Insurance();
|
$individual = new Insurance();
|
||||||
$individual->id = '10';
|
$individual->id = '10';
|
||||||
$individual->package = false;
|
$individual->package = false;
|
||||||
@@ -328,12 +335,7 @@ class TravelDataServiceTest extends TestCase
|
|||||||
$package->id = '20';
|
$package->id = '20';
|
||||||
$package->package = true;
|
$package->package = true;
|
||||||
$package->containedInsuranceIds = ['10'];
|
$package->containedInsuranceIds = ['10'];
|
||||||
$package->containedInsurances = []; // as it arrives after deserialization
|
$package->containedInsurances = [];
|
||||||
|
|
||||||
$travel = new Travel();
|
|
||||||
$travel->id = $dateId;
|
|
||||||
$travel->hotelId = $hotelId;
|
|
||||||
$travel->insurances = [$individual, $package];
|
|
||||||
|
|
||||||
$this->travelSnapshotService
|
$this->travelSnapshotService
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
@@ -341,9 +343,15 @@ class TravelDataServiceTest extends TestCase
|
|||||||
->with($dateId, $hotelId)
|
->with($dateId, $hotelId)
|
||||||
->willReturn($travel);
|
->willReturn($travel);
|
||||||
|
|
||||||
|
$this->insuranceLoader
|
||||||
|
->expects($this->once())
|
||||||
|
->method('loadAll')
|
||||||
|
->willReturn([$individual, $package]);
|
||||||
|
|
||||||
$result = $this->service->getTravelDataFromLocal($dateId, $hotelId);
|
$result = $this->service->getTravelDataFromLocal($dateId, $hotelId);
|
||||||
|
|
||||||
$this->assertSame($travel, $result);
|
$this->assertSame($travel, $result);
|
||||||
|
$this->assertSame([$individual, $package], array_values($travel->insurances));
|
||||||
$this->assertCount(1, $package->containedInsurances);
|
$this->assertCount(1, $package->containedInsurances);
|
||||||
$this->assertSame($individual, $package->containedInsurances[0]);
|
$this->assertSame($individual, $package->containedInsurances[0]);
|
||||||
}
|
}
|
||||||
@@ -393,8 +401,8 @@ class TravelDataServiceTest extends TestCase
|
|||||||
$dateId = 12345;
|
$dateId = 12345;
|
||||||
$hotelId = 67890;
|
$hotelId = 67890;
|
||||||
|
|
||||||
// insuranceLoader->loadAll() returns these during enrichTravelData(); the package's
|
// InsuranceLoader supplies the canonical insurance list for local reads; the package's
|
||||||
// containedInsurances starts empty (as it would from a fresh XML load before hydration).
|
// containedInsurances starts empty and is rebuilt after hydration.
|
||||||
$individual = new Insurance();
|
$individual = new Insurance();
|
||||||
$individual->id = '10';
|
$individual->id = '10';
|
||||||
$individual->package = false;
|
$individual->package = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user