feat: api endpoints
This commit is contained in:
@@ -2,13 +2,28 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
|
||||
class Hotel
|
||||
{
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $id = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $code = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $name = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $city = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $street = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $phone = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $country = null;
|
||||
}
|
||||
@@ -2,14 +2,34 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
use Symfony\Component\Serializer\Attribute\Context;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
||||
|
||||
class Pickup
|
||||
{
|
||||
#[Groups(['api:list'])]
|
||||
public ?int $id = null;
|
||||
|
||||
#[Groups(['api:list'])]
|
||||
public ?string $code = null;
|
||||
|
||||
#[Groups(['api:list'])]
|
||||
public ?string $city = null;
|
||||
|
||||
#[Groups(['api:list'])]
|
||||
public ?string $postalCode = null;
|
||||
|
||||
#[Groups(['api:list'])]
|
||||
public ?string $street = null;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d H:i'])]
|
||||
public ?\DateTimeImmutable $time = null;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public ?float $price = null;
|
||||
|
||||
#[Groups(['api:booking'])]
|
||||
public array $mapping = [];
|
||||
}
|
||||
@@ -2,24 +2,65 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
use Symfony\Component\Serializer\Attribute\Context;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
||||
|
||||
class Room
|
||||
{
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $id = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $category = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $boardId = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $code = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $label = null;
|
||||
|
||||
#[Groups(['booking'])]
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||
public ?\DateTimeImmutable $dateFrom = null;
|
||||
|
||||
#[Groups(['booking'])]
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||
public ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
#[Groups(['booking'])]
|
||||
public ?int $totalCount = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $minPax = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $maxPax = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $nights = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $status = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $available = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $board = null;
|
||||
|
||||
#[Groups(['booking'])]
|
||||
public array $mapping = [];
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?float $price = null;
|
||||
|
||||
#[Groups(['booking'])]
|
||||
public ?float $totalPrice = null;
|
||||
|
||||
#[Groups(['booking'])]
|
||||
public array $individualPrice = [];
|
||||
}
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
use Symfony\Component\Serializer\Attribute\Context;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
||||
|
||||
class Service
|
||||
{
|
||||
public const SOURCE_TRAVEL = 'travel';
|
||||
@@ -16,20 +20,50 @@ class Service
|
||||
public const TOKEN_BOARD = 'VPF';
|
||||
public const TOKEN_RENTALS = ['VER', 'VE2', 'VE3', 'VE4', 'VE5', 'VE6', 'VE7', 'VE8'];
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?int $id = null;
|
||||
public ?string $source = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?string $category = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?string $status = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public bool $mandatory = false;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?string $label = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||
public ?\DateTimeImmutable $dateFrom = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||
public ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?string $subType = null;
|
||||
|
||||
#[Groups(['booking'])]
|
||||
public ?int $totalCount = null;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public array $mapping = [];
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?float $price = null;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public ?float $totalPrice = null;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public array $individualPrice = [];
|
||||
public ?string $direction = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?int $available = null;
|
||||
|
||||
#[Groups(['api:single', 'api:list'])]
|
||||
public ?string $source = null;
|
||||
}
|
||||
@@ -2,25 +2,72 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
use Symfony\Component\Serializer\Attribute\Context;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
||||
|
||||
class Travel
|
||||
{
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $id = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $code = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $label = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?int $hotelId = null;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public ?Hotel $hotel = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||
public ?\DateTimeImmutable $dateFrom = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
|
||||
public ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?string $type = null;
|
||||
|
||||
#[Groups(['api:list', 'api:single'])]
|
||||
public ?float $priceFrom = null;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public array $selectionGroups = [];
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public array $additionalServices = [];
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public bool $additionalServicesMutable = true;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public array $transportationServices = [];
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public bool $transportationServicesMutable = true;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public array $pickups = [];
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public bool $pickupsMutable = true;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public array $rooms = [];
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public bool $roomsMutable = true;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public bool $participantDataMutable = true;
|
||||
|
||||
#[Groups(['api:single'])]
|
||||
public bool $participantCountMutable = true;
|
||||
|
||||
public function getAdditionalServicesByGroup(mixed $group, bool $availableOnly = true): array
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataLoader;
|
||||
namespace App\BusProNet\XmlLoader;
|
||||
|
||||
use App\BusProNet\TypeConversionTrait;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
|
||||
abstract class AbstractDataLoader
|
||||
abstract class AbstractXmlLoader
|
||||
{
|
||||
use TypeConversionTrait;
|
||||
|
||||
+10
-2
@@ -1,12 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataLoader;
|
||||
namespace App\BusProNet\XmlLoader;
|
||||
|
||||
use App\BusProNet\Model\Hotel;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use Psr\Cache\InvalidArgumentException;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class HotelDataLoader extends AbstractDataLoader
|
||||
class HotelXmlLoader extends AbstractXmlLoader
|
||||
{
|
||||
public function loadAll(?string $filename = 'hotel.xml'): array
|
||||
{
|
||||
@@ -72,4 +73,11 @@ class HotelDataLoader extends AbstractDataLoader
|
||||
|
||||
return $hotel;
|
||||
}
|
||||
|
||||
public function patchHotelDetails(Travel $travel): void
|
||||
{
|
||||
$hotelId = $travel->hotelId;
|
||||
$hotel = $this->loadById($hotelId);
|
||||
$travel->hotel = $hotel;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataLoader;
|
||||
namespace App\BusProNet\XmlLoader;
|
||||
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use Psr\Cache\InvalidArgumentException;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class PickupDataLoader extends AbstractDataLoader
|
||||
class PickupXmlLoader extends AbstractXmlLoader
|
||||
{
|
||||
public function loadAll(?string $filename = 'zustiege.xml'): array
|
||||
{
|
||||
+30
-15
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataLoader;
|
||||
namespace App\BusProNet\XmlLoader;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\CrmSelection;
|
||||
@@ -14,12 +14,12 @@ use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class TravelDataLoader extends AbstractDataLoader
|
||||
class TravelXmlLoader extends AbstractXmlLoader
|
||||
{
|
||||
public function __construct(
|
||||
private readonly HotelDataLoader $hotelDataLoader,
|
||||
CacheInterface $cache,
|
||||
?string $xmlPath = null
|
||||
private readonly HotelXmlLoader $hotelDataLoader,
|
||||
CacheInterface $cache,
|
||||
?string $xmlPath = null
|
||||
) {
|
||||
parent::__construct($cache, $xmlPath);
|
||||
}
|
||||
@@ -67,24 +67,24 @@ class TravelDataLoader extends AbstractDataLoader
|
||||
});
|
||||
}
|
||||
|
||||
public function loadById(int $id, ?string $filename = null): ?Travel
|
||||
public function loadById(int $travelId, ?int $hotelId = null, ?string $filename = null): ?Travel
|
||||
{
|
||||
if (null !== $filename) {
|
||||
return $this->loadXml($id, $filename);
|
||||
return $this->loadXml($travelId, $hotelId, $filename);
|
||||
}
|
||||
|
||||
$mapping = $this->generateMapping();
|
||||
|
||||
if (false === isset($mapping[$id])) {
|
||||
if (false === isset($mapping[$travelId])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$file = $mapping[$id]['file'];
|
||||
$file = $mapping[$travelId]['file'];
|
||||
|
||||
return $this->loadXml($id, $file);
|
||||
return $this->loadXml($travelId, $hotelId, $file);
|
||||
}
|
||||
|
||||
private function loadXml(int $id, string $filename): ?Travel
|
||||
private function loadXml(int $id, ?int $hotelId, string $filename): ?Travel
|
||||
{
|
||||
$xml = simplexml_load_file($filename);
|
||||
|
||||
@@ -94,16 +94,19 @@ class TravelDataLoader extends AbstractDataLoader
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->parseXml($travelXml[0]);
|
||||
return $this->parseXml($travelXml[0], $hotelId);
|
||||
}
|
||||
|
||||
public function parseXml(\SimpleXMLElement $xml): Travel
|
||||
public function parseXml(\SimpleXMLElement $xml, ?int $hotelId): Travel
|
||||
{
|
||||
$hotelXml = $this->getHotelXml($xml, $hotelId);
|
||||
|
||||
$attributes = $xml->attributes();
|
||||
|
||||
$travel = new Travel();
|
||||
$travel->id = (int) $attributes['idbuspro'];
|
||||
$travel->label = (string) $xml->text;
|
||||
$travel->hotelId = $hotelId;
|
||||
$travel->dateFrom = $this->stringToDate((string) $attributes['termin']);
|
||||
$travel->dateTo = $this->stringToDate((string) $attributes['bis']);
|
||||
$travel->code = (string) $attributes['code'];
|
||||
@@ -112,7 +115,7 @@ class TravelDataLoader extends AbstractDataLoader
|
||||
$travel->selectionGroups = $this->getSelectionGroups($xml);
|
||||
$travel->additionalServices = $this->getAdditionalServices($xml);
|
||||
$travel->transportationServices = $this->getTransportationServices($xml);
|
||||
$travel->rooms = $this->getRooms($xml);
|
||||
$travel->rooms = $this->getRooms($hotelXml);
|
||||
$travel->pickups = $this->getPickups($xml);
|
||||
|
||||
return $travel;
|
||||
@@ -213,11 +216,23 @@ class TravelDataLoader extends AbstractDataLoader
|
||||
return $pickups;
|
||||
}
|
||||
|
||||
public function getHotelXml(\SimpleXMLElement $xml, ?int $hotelId): ?\SimpleXMLElement
|
||||
{
|
||||
// In case not hotel id is provided, take the first hotel node (which is most probably the only one)
|
||||
if (null === $hotelId) {
|
||||
return $xml->hotel;
|
||||
}
|
||||
|
||||
$hotelXml = $xml->xpath(sprintf('//hotel[@idbuspro="%d"]', $hotelId));
|
||||
|
||||
return $hotelXml[0] ?? null;
|
||||
}
|
||||
|
||||
public function getRooms(\SimpleXMLElement $xml): array
|
||||
{
|
||||
$rooms = [];
|
||||
|
||||
foreach ($xml->hotel->zimmer->preis as $item) {
|
||||
foreach ($xml->zimmer->preis as $item) {
|
||||
$attributes = $item->attributes();
|
||||
$roomId = (int) $attributes['idbuspro_zimmer'];
|
||||
|
||||
Reference in New Issue
Block a user