wip: continue implemntation
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace App\BusProNet;
|
||||
|
||||
use App\BusProNet\ApiResponseParser\ResponseParser;
|
||||
use App\BusProNet\DataProcessor\BookingDataProcessor;
|
||||
use App\BusProNet\Exception\ApiClientException;
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\Booking;
|
||||
@@ -24,7 +25,7 @@ class ApiClient
|
||||
public const TYPE_NOTIFICATION = 'HINWEIS';
|
||||
public const TYPE_CUSTOMER_DATA = 'KUNDENKONTO';
|
||||
public const TYPE_BASE_DATA_COUNTRIES = 'STAMMLAENDER';
|
||||
public const TYPE_MUTABLE_FIELDS = 'MOEGLICHEAENDERUNGEN';
|
||||
public const TYPE_MUTABLE_DATA = 'MOEGLICHEAENDERUNGEN';
|
||||
public const TYPE_AVAILABILITY = 'VERFUEGBARKEIT';
|
||||
public const TYPE_BOOKING_UPDATE = 'BUCHUNGAENDERUNG';
|
||||
|
||||
@@ -113,15 +114,15 @@ class ApiClient
|
||||
|
||||
public function updateBooking(BookingData $formData, bool $dryRun = true): Notification|BookingUpdate
|
||||
{
|
||||
$booking = $formData->booking;
|
||||
$mode = $dryRun ? 'Anfrage' : 'Buchung';
|
||||
$payload = (new BookingDataProcessor())->createUpdateRequestPayload($formData);
|
||||
|
||||
$data = [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_BOOKING_UPDATE),
|
||||
'satz' => ['@typ' => static::TYPE_BOOKING_UPDATE],
|
||||
'buchungsart' => $mode,
|
||||
...$booking->toPayload($formData),
|
||||
...$payload,
|
||||
];
|
||||
|
||||
return $this->sendRequest(static::TYPE_BOOKING_UPDATE, $data);
|
||||
@@ -130,17 +131,17 @@ class ApiClient
|
||||
/**
|
||||
* @throws ApiClientException
|
||||
*/
|
||||
public function getMutableFields(int $id): Notification|BaseData
|
||||
public function getMutableData(int $id): Notification|BaseData
|
||||
{
|
||||
$data = [
|
||||
'user' => $this->config['bpn_username'],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_MUTABLE_FIELDS),
|
||||
'satz' => ['@typ' => static::TYPE_MUTABLE_FIELDS],
|
||||
'key' => $this->createKey($this->config['bpn_username'], $this->config['bpn_password'], static::TYPE_MUTABLE_DATA),
|
||||
'satz' => ['@typ' => static::TYPE_MUTABLE_DATA],
|
||||
'art' => 'Vorgang_Details',
|
||||
'idreise' => $id,
|
||||
];
|
||||
|
||||
return $this->sendRequest(static::TYPE_MUTABLE_FIELDS, $data);
|
||||
return $this->sendRequest(static::TYPE_MUTABLE_DATA, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,7 +230,7 @@ class ApiClient
|
||||
*/
|
||||
private function sendRequest(string $type, array $data): mixed
|
||||
{
|
||||
$requestId = Uuid::v7();
|
||||
$requestId = date(DATE_ATOM).uniqid();
|
||||
|
||||
$body = $this
|
||||
->serializer
|
||||
|
||||
@@ -6,8 +6,10 @@ use App\BusProNet\Model\Address;
|
||||
use App\BusProNet\Model\Booking;
|
||||
use App\BusProNet\Model\Communication;
|
||||
use App\BusProNet\Model\PersonalData;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Room;
|
||||
use App\BusProNet\Model\Service;
|
||||
use App\BusProNet\Model\Surcharge;
|
||||
|
||||
class BookingResponseParser
|
||||
{
|
||||
@@ -48,14 +50,20 @@ class BookingResponseParser
|
||||
|
||||
if ($xml->beförderungen) {
|
||||
$booking->transportationServices = $this
|
||||
->parseServices($xml->beförderungen->beförderung, Service::TYPE_TRANSPORTATION);
|
||||
->parseServices($xml->beförderungen->beförderung, Service::CATEGORY_TRANSPORTATION);
|
||||
}
|
||||
if ($xml->zusatzleistungen) {
|
||||
$booking->additionalServices = $this
|
||||
->parseServices($xml->zusatzleistungen->zusatzleistung, Service::TYPE_ADDITIONAL);
|
||||
->parseServices($xml->zusatzleistungen->zusatzleistung, Service::CATEGORY_ADDITIONAL);
|
||||
}
|
||||
if ($xml->ferienzielunterbringungen) {
|
||||
$booking->rooms = $this->parseRooms($xml->ferienzielunterbringungen->ferienzielunterbringung);
|
||||
$booking->rooms = $this->parseRooms($xml->ferienzielunterbringungen);
|
||||
}
|
||||
if ($xml->zustiege) {
|
||||
$booking->pickups = $this->parsePickups($xml->zustiege);
|
||||
}
|
||||
if ($xml->zuschlaege) {
|
||||
$booking->surcharges = $this->parseSurcharges($xml->zuschlaege);
|
||||
}
|
||||
|
||||
return $booking;
|
||||
@@ -135,8 +143,8 @@ class BookingResponseParser
|
||||
return $this->stringToFloat((string) $price);
|
||||
}, $this->stringToArray((string) $attributes['einzelpreis'], '/')
|
||||
);
|
||||
$service->individualPrice = $this->arrayToOneBased($individualPrices);
|
||||
if (Service::TYPE_TRANSPORTATION === $type) {
|
||||
$service->individualPrice = array_combine($mapping, $individualPrices);
|
||||
if (Service::CATEGORY_TRANSPORTATION === $type) {
|
||||
$service->direction = (string) $attributes['richtung'];
|
||||
}
|
||||
|
||||
@@ -150,7 +158,7 @@ class BookingResponseParser
|
||||
{
|
||||
$rooms = [];
|
||||
|
||||
foreach ($xml as $item) {
|
||||
foreach ($xml->ferienzielunterbringung as $item) {
|
||||
$attributes = $item->attributes();
|
||||
$id = (int) $attributes['idzimmer'];
|
||||
|
||||
@@ -173,10 +181,69 @@ class BookingResponseParser
|
||||
return $this->stringToFloat((string) $price);
|
||||
}, $this->stringToArray((string) $attributes['einzelpreis'], '/')
|
||||
);
|
||||
$room->individualPrice = $this->arrayToOneBased($individualPrices);
|
||||
$room->individualPrice = array_combine($mapping, $individualPrices);
|
||||
|
||||
$rooms[$id] = $room;
|
||||
}
|
||||
|
||||
return $rooms;
|
||||
}
|
||||
|
||||
private function parsePickups(\SimpleXMLElement $xml): array
|
||||
{
|
||||
$pickups = [];
|
||||
|
||||
foreach ($xml->zustieg as $item) {
|
||||
$attributes = $item->attributes();
|
||||
$pickupId = (int) $attributes['idzustieg'];
|
||||
$pickupDate = (string) $attributes['datum'];
|
||||
$pickupTime = (string) $attributes['zeit'];
|
||||
|
||||
$pickup = new Pickup();
|
||||
$pickup->id = $pickupId;
|
||||
$pickup->code = (string) $attributes['code'];
|
||||
$pickup->city = (string) $xml->ort;
|
||||
$pickup->postalCode = (string) $xml->plz;
|
||||
$pickup->street = (string) $xml->strasse;
|
||||
$pickup->time = $this->stringToDateTime($pickupDate.' '.$pickupTime);
|
||||
$pickup->price = $attributes['preis'] ? $this->stringToFloat((string) $attributes['preis']) : null;
|
||||
$mapping = $this->stringToArray((string) $attributes['zuordnung']);
|
||||
$pickup->mapping = array_map('intval', $mapping);
|
||||
|
||||
$pickups[$pickupId] = $pickup;
|
||||
}
|
||||
|
||||
return $pickups;
|
||||
}
|
||||
|
||||
private function parseSurcharges(\SimpleXMLElement $xml): array
|
||||
{
|
||||
$surcharges = [];
|
||||
|
||||
foreach ($xml->zuschlag as $item) {
|
||||
$attributes = $item->attributes();
|
||||
|
||||
$label = (string) $attributes['bezeichnung'];
|
||||
// Skip invalid entries
|
||||
if (empty($label)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$surcharge = new Surcharge();
|
||||
$surcharge->label = $label;
|
||||
$surcharge->totalPrice = $this->stringToFloat((string) $attributes['gesamtpreis']);
|
||||
$mapping = $this->stringToArray((string) $attributes['zuordnung']);
|
||||
$surcharge->mapping = array_map('intval', $mapping);
|
||||
$individualPrices = array_map(
|
||||
function ($price) {
|
||||
return $this->stringToFloat((string) $price);
|
||||
}, $this->stringToArray((string) $attributes['einzelpreis'], '/')
|
||||
);
|
||||
$surcharge->individualPrice = array_combine($mapping, $individualPrices);
|
||||
|
||||
$surcharges[] = $surcharge;
|
||||
}
|
||||
|
||||
return $surcharges;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\BusProNet\ApiResponseParser;
|
||||
|
||||
use App\BusProNet\Model\CrmAttribute;
|
||||
use App\BusProNet\Model\CrmAttributeGroup;
|
||||
use App\BusProNet\Model\CrmSelection;
|
||||
use App\BusProNet\Model\CrmSelectionGroup;
|
||||
use App\BusProNet\Model\CrmAttributes;
|
||||
|
||||
class CrmAttributesResponseParser
|
||||
@@ -21,14 +21,14 @@ class CrmAttributesResponseParser
|
||||
$hotelCode = null;
|
||||
|
||||
foreach ($xml->selektionsmerkmale->selektionsgruppe as $item) {
|
||||
$group = new CrmAttributeGroup();
|
||||
$group = new CrmSelectionGroup();
|
||||
$group->label = (string) $item->attributes()['bezeichnung'];
|
||||
$attributes = [];
|
||||
|
||||
foreach ($item->selektion as $subItem) {
|
||||
$subItemAttributes = $subItem->attributes();
|
||||
$attributeLabel = (string) $subItemAttributes['bezeichnung'];
|
||||
$attribute = new CrmAttribute();
|
||||
$attribute = new CrmSelection();
|
||||
$attribute->id = (int) $subItemAttributes['id'];
|
||||
$attribute->label = $attributeLabel;
|
||||
$attribute->selected = $this->stringToBool((string) $subItemAttributes['auswahl']);
|
||||
@@ -49,12 +49,12 @@ class CrmAttributesResponseParser
|
||||
|
||||
$attributes[] = $attribute;
|
||||
}
|
||||
$group->attributes = $attributes;
|
||||
$group->selections = $attributes;
|
||||
$groups[] = $group;
|
||||
}
|
||||
|
||||
$response = new CrmAttributes();
|
||||
$response->attributeGroups = $groups;
|
||||
$response->selectionGroups = $groups;
|
||||
$response->admin = $isAdmin;
|
||||
$response->manager = $isManager;
|
||||
$response->houseManager = $isHouseManager;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\ApiResponseParser;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\MutableData;
|
||||
|
||||
class MutableDataResponseParser
|
||||
{
|
||||
use ResponseParserTrait;
|
||||
|
||||
public function parse(\SimpleXMLElement $xml): BaseData
|
||||
{
|
||||
$mutableFields = [];
|
||||
|
||||
foreach ($xml->änderungen->änderung as $item) {
|
||||
$attributes = $item->attributes();
|
||||
|
||||
$category = match ((string) $attributes['art']) {
|
||||
'anzahl_teilnehmer' => MutableData::CATEGORY_PARTICIPANT_COUNT,
|
||||
'beförderung' => MutableData::CATEGORY_TRANSPORTATION,
|
||||
'zustieg' => MutableData::CATEGORY_PICKUP,
|
||||
'unterbringung' => MutableData::CATEGORY_ACCOMMODATION,
|
||||
'zusatzleistung' => MutableData::CATEGORY_ADDITIONAL_SERVICES,
|
||||
'teilnehmerdaten' => MutableData::CATEGORY_PARTICIPANT_DATA,
|
||||
default => false,
|
||||
};
|
||||
|
||||
if (false === $category) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mutableField = new MutableData($category, $this->stringToBool((string) $attributes['möglich']));
|
||||
|
||||
if ($attributes['möglichbiszum']) {
|
||||
$mutableField->mutableBefore = $this->stringToDate((string) $attributes['möglichbiszum']);
|
||||
}
|
||||
|
||||
$mutableFields[$category] = $mutableField;
|
||||
}
|
||||
|
||||
return new BaseData($mutableFields);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\ApiResponseParser;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\MutableField;
|
||||
|
||||
class MutableFieldsResponseParser
|
||||
{
|
||||
use ResponseParserTrait;
|
||||
|
||||
public function parse(\SimpleXMLElement $xml): BaseData
|
||||
{
|
||||
$mutableFields = [];
|
||||
|
||||
foreach ($xml->änderungen->änderung as $item) {
|
||||
$attributes = $item->attributes();
|
||||
|
||||
$type = match ((string) $attributes['art']) {
|
||||
'anzahl_teilnehmer' => 'participant_count',
|
||||
'beförderung' => 'transportation',
|
||||
'zustieg' => 'pickup',
|
||||
'unterbringung' => 'accommodation',
|
||||
'zusatzleistung' => 'services',
|
||||
'teilnehmerdaten' => 'participant_data',
|
||||
default => false,
|
||||
};
|
||||
|
||||
if (false === $type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mutableField = new MutableField($type, $this->stringToBool((string) $attributes['möglich']));
|
||||
|
||||
if ($attributes['möglichbiszum']) {
|
||||
$mutableField->mutableBefore = $this->stringToDate((string) $attributes['möglichbiszum']);
|
||||
}
|
||||
|
||||
$mutableFields[$type] = $mutableField;
|
||||
}
|
||||
|
||||
return new BaseData($mutableFields);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,10 @@ class ResponseParser
|
||||
{
|
||||
$xml = simplexml_load_string($content);
|
||||
|
||||
if (false === $xml) {
|
||||
throw new ResponseParserException('Empty response received from server');
|
||||
}
|
||||
|
||||
// Override type when present in XML to catch error responses
|
||||
$responseType = $type;
|
||||
$responseTypeXml = $xml->xpath('satz/@typ');
|
||||
@@ -45,8 +49,8 @@ class ResponseParser
|
||||
break;
|
||||
case ApiClient::TYPE_BASE_DATA_COUNTRIES:
|
||||
return (new CountriesResponseParser())->parse($xml);
|
||||
case ApiClient::TYPE_MUTABLE_FIELDS:
|
||||
return (new MutableFieldsResponseParser())->parse($xml);
|
||||
case ApiClient::TYPE_MUTABLE_DATA:
|
||||
return (new MutableDataResponseParser())->parse($xml);
|
||||
case ApiClient::TYPE_AVAILABILITY:
|
||||
return (new AvailabilitiesResponseParser())->parse($xml);
|
||||
case ApiClient::TYPE_BOOKING_UPDATE:
|
||||
|
||||
@@ -52,7 +52,7 @@ class PickupDataLoader extends AbstractDataLoader
|
||||
return $pickup;
|
||||
}
|
||||
|
||||
public function enrichPickupsData(Travel $travel): void
|
||||
public function patchPickupsDetails(Travel $travel): void
|
||||
{
|
||||
foreach ($travel->pickups as $pickupId => $pickup) {
|
||||
$pickupData = $this->loadById($pickupId);
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
namespace App\BusProNet\DataLoader;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\CrmAttribute;
|
||||
use App\BusProNet\Model\CrmAttributeGroup;
|
||||
use App\BusProNet\Model\CrmSelection;
|
||||
use App\BusProNet\Model\CrmSelectionGroup;
|
||||
use App\BusProNet\Model\MutableData;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Room;
|
||||
use App\BusProNet\Model\Service;
|
||||
@@ -71,17 +72,17 @@ class TravelDataLoader extends AbstractDataLoader
|
||||
|
||||
foreach ($xml->selektiongruppe as $item) {
|
||||
$groupId = (int) $item->attributes()['idbuspro'];
|
||||
$selectionGroup = new CrmAttributeGroup();
|
||||
$selectionGroup = new CrmSelectionGroup();
|
||||
$selectionGroup->id = $groupId;
|
||||
$selectionGroup->label = (string) $item->attributes()['bezeichnung'];
|
||||
|
||||
foreach ($item->selektion as $subItem) {
|
||||
$selectionId = (int) $subItem->attributes()['idbuspro'];
|
||||
$selection = new CrmAttribute();
|
||||
$selection = new CrmSelection();
|
||||
$selection->id = $selectionId;
|
||||
$selection->label = (string) $subItem->attributes()['bezeichnung'];
|
||||
$selectionGroups[$groupId]['selections'][$selectionId] = (string) $subItem->attributes()['bezeichnung'];
|
||||
$selectionGroup->attributes[] = $selection;
|
||||
$selectionGroup->selections[] = $selection;
|
||||
}
|
||||
|
||||
$selectionGroups[$groupId] = $selectionGroup;
|
||||
@@ -99,6 +100,7 @@ class TravelDataLoader extends AbstractDataLoader
|
||||
$serviceId = (int) $attributes['idbuspro'];
|
||||
|
||||
$service = new Service();
|
||||
$service->category = Service::CATEGORY_ADDITIONAL;
|
||||
$service->id = $serviceId;
|
||||
$service->subType = (string) $attributes['unterart'];
|
||||
$service->mandatory = $this->stringToBool((string) $attributes['pflicht']);
|
||||
@@ -123,6 +125,7 @@ class TravelDataLoader extends AbstractDataLoader
|
||||
$serviceId = (int) $attributes['idbuspro'];
|
||||
|
||||
$service = new Service();
|
||||
$service->category = Service::CATEGORY_TRANSPORTATION;
|
||||
$service->id = $serviceId;
|
||||
$service->subType = (string) $attributes['unterart'];
|
||||
$service->dateFrom = $this->stringToDate((string) $attributes['termin']);
|
||||
@@ -183,7 +186,34 @@ class TravelDataLoader extends AbstractDataLoader
|
||||
return $rooms;
|
||||
}
|
||||
|
||||
public function enrichServicesData(Travel $travel, BaseData $availabilities): void
|
||||
public function patchMutability(Travel $travel, BaseData $mutableData): void
|
||||
{
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_ADDITIONAL_SERVICES)) {
|
||||
$travel->additionalServicesMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_TRANSPORTATION)) {
|
||||
$travel->transportationServicesMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PICKUP)) {
|
||||
$travel->pickupsMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_ACCOMMODATION)) {
|
||||
$travel->roomsMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PARTICIPANT_COUNT)) {
|
||||
$travel->participantCountMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PARTICIPANT_DATA)) {
|
||||
$travel->participantDataMutable = $item->mutable;
|
||||
}
|
||||
}
|
||||
|
||||
public function patchAvailabilities(Travel $travel, BaseData $availabilities): void
|
||||
{
|
||||
$serviceAvailabilities = $availabilities->getItems();
|
||||
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\DataProcessor;
|
||||
|
||||
use App\Form\Model\BookingData;
|
||||
|
||||
class BookingDataProcessor
|
||||
{
|
||||
public function createUpdateRequestPayload(?BookingData $formData): array
|
||||
{
|
||||
$bookingData = $formData->booking;
|
||||
$travelData = $formData->travel;
|
||||
|
||||
// Reset mappings
|
||||
foreach ([...$bookingData->additionalServices, ...$bookingData->transportationServices, ...$bookingData->pickups] as $service) {
|
||||
$service->mapping = [];
|
||||
}
|
||||
// Update mappings, add services and pickups
|
||||
foreach ($formData->participants as $participant) {
|
||||
$servicesToMap = [
|
||||
...$participant->courses,
|
||||
...$participant->additionalServices,
|
||||
...$participant->skiPass,
|
||||
...$participant->board,
|
||||
...$participant->rentals,
|
||||
];
|
||||
foreach ($servicesToMap as $service) {
|
||||
if (false === isset($this->additionalServices[$service->id])) {
|
||||
$serviceToAdd = $travelData->additionalServices[$service->id];
|
||||
$bookingData->additionalServices[$service->id] = $serviceToAdd;
|
||||
$bookingData->additionalServices[$service->id]->individualPrice[$participant->index] = $serviceToAdd->price;
|
||||
}
|
||||
$bookingData->additionalServices[$service->id]->mapping[] = $participant->index;
|
||||
}
|
||||
foreach ([$participant->transportationServiceTo, $participant->transportationServiceFro] as $service) {
|
||||
if (false === isset($this->transportationServices[$service->id])) {
|
||||
$serviceToAdd = $travelData->transportationServices[$service->id];
|
||||
$bookingData->transportationServices[$service->id] = $serviceToAdd;
|
||||
$bookingData->transportationServices[$service->id]->individualPrice[$participant->index] = $serviceToAdd->price;
|
||||
}
|
||||
$bookingData->transportationServices[$service->id]->mapping[] = $participant->index;
|
||||
}
|
||||
if ('BUS' === $participant->transportationServiceTo->subType && null !== $selectedPickup = $participant->pickup) {
|
||||
if (false === isset($bookingData->pickups[$selectedPickup->id])) {
|
||||
$bookingData->pickups[$selectedPickup->id] = $selectedPickup;
|
||||
}
|
||||
$bookingData->pickups[$selectedPickup->id]->mapping[] = $participant->index;
|
||||
}
|
||||
}
|
||||
// Remove services/pickups with empty mappings
|
||||
foreach ($bookingData->additionalServices as $service) {
|
||||
if (0 === count($service->mapping)) {
|
||||
unset($bookingData->additionalServices[$service->id]);
|
||||
}
|
||||
}
|
||||
foreach ($bookingData->transportationServices as $service) {
|
||||
if (0 === count($service->mapping)) {
|
||||
unset($bookingData->transportationServices[$service->id]);
|
||||
}
|
||||
}
|
||||
foreach ($bookingData->pickups as $pickup) {
|
||||
if (0 === count($pickup->mapping)) {
|
||||
unset($bookingData->pickups[$pickup->id]);
|
||||
}
|
||||
}
|
||||
|
||||
// Update participants' personal data
|
||||
foreach ($formData->participants as $participant) {
|
||||
$bookingData->participants[$participant->index]->firstName = $participant->firstName;
|
||||
$bookingData->participants[$participant->index]->lastName = $participant->lastName;
|
||||
$bookingData->participants[$participant->index]->dateOfBirth = $participant->dateOfBirth;
|
||||
$bookingData->participants[$participant->index]->gender = $participant->gender;
|
||||
$bookingData->participants[$participant->index]->nationality = $participant->nationality;
|
||||
$bookingData->participants[$participant->index]->height = $participant->height;
|
||||
$bookingData->participants[$participant->index]->weight = $participant->weight;
|
||||
$bookingData->participants[$participant->index]->shoeSize = $participant->shoeSize;
|
||||
$bookingData->participants[$participant->index]->communication->email = $participant->email;
|
||||
$bookingData->participants[$participant->index]->communication->mobile = $participant->mobile;
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'idbuchung' => $bookingData->id,
|
||||
'status' => $bookingData->status,
|
||||
'idagentur' => $bookingData->agencyId,
|
||||
'idreise' => $bookingData->travelId,
|
||||
'idpartner' => $bookingData->hotelId,
|
||||
'anmelder' => $bookingData->applicant->toPayload(),
|
||||
'zahlung' => [
|
||||
'@idzahlungsart' => $bookingData->paymentId,
|
||||
'@bezeichnung' => $bookingData->paymentLabel,
|
||||
'@art' => $bookingData->paymentType,
|
||||
],
|
||||
'teilnehmerliste' => [
|
||||
'teilnehmer' => [],
|
||||
],
|
||||
'zusatzleistungen' => [
|
||||
'zusatzleistung' => [],
|
||||
],
|
||||
'beförderungen' => [
|
||||
'beförderung' => [],
|
||||
],
|
||||
'ferienzielunterbringungen' => [
|
||||
'ferienzielunterbringung' => [],
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($bookingData->participants as $index => $participant) {
|
||||
$payload['teilnehmerliste']['teilnehmer'][] = [
|
||||
'@id' => $index,
|
||||
'status' => $bookingData->participantsStatus[$index],
|
||||
...$participant->toPayload(),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($bookingData->additionalServices as $service) {
|
||||
$payload['zusatzleistungen']['zusatzleistung'][] = [
|
||||
'@idleistung' => $service->id,
|
||||
'@anzahl' => count($service->mapping),
|
||||
'@zuordnung' => implode(',', $service->mapping),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($bookingData->transportationServices as $service) {
|
||||
$payload['beförderungen']['beförderung'][] = [
|
||||
'@idleistung' => $service->id,
|
||||
'@anzahl' => count($service->mapping),
|
||||
'@zuordnung' => implode(',', $service->mapping),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($bookingData->rooms as $room) {
|
||||
$payload['ferienzielunterbringungen']['ferienzielunterbringung'][] = [
|
||||
'@idzimmer' => $room->id,
|
||||
'@kategorie' => $room->category,
|
||||
'@idverpflegung' => $room->boardId,
|
||||
'@anreise' => $room->dateFrom ? $room->dateFrom->format('d.m.Y') : null,
|
||||
'@abreise' => $room->dateTo ? $room->dateTo->format('d.m.Y') : null,
|
||||
'@anzahl' => count($room->mapping),
|
||||
'@zuordnung' => implode(',', $room->mapping),
|
||||
];
|
||||
}
|
||||
|
||||
if (0 < count($bookingData->pickups)) {
|
||||
$payload['zustiege']['zustieg'] = [];
|
||||
foreach ($bookingData->pickups as $pickup) {
|
||||
$payload['zustiege']['zustieg'][] = [
|
||||
'@idzustieg' => $pickup->id,
|
||||
'@anzahl' => count($pickup->mapping),
|
||||
'@zuordnung' => implode(',', $pickup->mapping),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,9 @@ class BaseData
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
|
||||
public function getItemByKey(string $key): mixed
|
||||
{
|
||||
return $this->items[$key] ?? null;
|
||||
}
|
||||
}
|
||||
+25
-153
@@ -2,14 +2,11 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
use App\Form\Model\BookingData;
|
||||
|
||||
class Booking
|
||||
{
|
||||
public ?int $id = null;
|
||||
public ?int $agencyId = null;
|
||||
public ?int $bookingNumber = null;
|
||||
public ?Travel $travelData = null;
|
||||
public ?string $status = null;
|
||||
public ?PersonalData $applicant = null;
|
||||
public ?int $participantCount = null;
|
||||
@@ -32,6 +29,7 @@ class Booking
|
||||
public array $additionalServices = [];
|
||||
public array $rooms = [];
|
||||
public array $pickups = [];
|
||||
public array $surcharges = [];
|
||||
public ?int $invoiceNumber = null;
|
||||
public ?float $totalPrice = null;
|
||||
|
||||
@@ -47,6 +45,7 @@ class Booking
|
||||
public function getAdditionalServicesByGroup(mixed $group): array
|
||||
{
|
||||
$group = (array) $group;
|
||||
|
||||
return array_filter($this->additionalServices, function (Service $service) use ($group) {
|
||||
return in_array($service->subType, $group);
|
||||
});
|
||||
@@ -54,9 +53,9 @@ class Booking
|
||||
|
||||
public function getAdditionalServicesForParticipantByGroup(int $participantIndex, mixed $group): array
|
||||
{
|
||||
$services = $this->getAdditionalServicesByGroup($group);
|
||||
$selectedServices = $this->getAdditionalServicesByGroup($group);
|
||||
|
||||
return array_filter($services, function (Service $service) use ($participantIndex) {
|
||||
return array_filter($selectedServices, function (Service $service) use ($participantIndex) {
|
||||
return in_array($participantIndex, $service->mapping);
|
||||
});
|
||||
}
|
||||
@@ -75,6 +74,17 @@ class Booking
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPickupForParticipant(int $participantIndex): ?Pickup
|
||||
{
|
||||
foreach ($this->pickups as $pickup) {
|
||||
if (in_array($participantIndex, $pickup->mapping)) {
|
||||
return $pickup;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRoomForParticipant(int $participantIndex): ?Room
|
||||
{
|
||||
foreach ($this->rooms as $room) {
|
||||
@@ -90,21 +100,22 @@ class Booking
|
||||
{
|
||||
$price = 0.0;
|
||||
|
||||
// Sum up all services
|
||||
foreach ([...$this->transportationServices, ...$this->additionalServices] as $service) {
|
||||
if (in_array($participantIndex, $service->mapping) && isset($service->individualPrice[$participantIndex])) {
|
||||
if (in_array($participantIndex, $service->mapping) || true === $service->mandatory) {
|
||||
$price += $service->individualPrice[$participantIndex];
|
||||
} elseif ($service->price) {
|
||||
$price += $service->price;
|
||||
}
|
||||
}
|
||||
|
||||
// Sum up all surcharges
|
||||
foreach ($this->surcharges as $surcharge) {
|
||||
if (in_array($participantIndex, $surcharge->mapping)) {
|
||||
$price += $surcharge->individualPrice[$participantIndex];
|
||||
}
|
||||
}
|
||||
|
||||
$room = $this->getRoomForParticipant($participantIndex);
|
||||
|
||||
if (isset($room->individualPrice[$participantIndex])) {
|
||||
$price += $room->individualPrice[$participantIndex];
|
||||
} elseif ($room->price) {
|
||||
$price += $room->price;
|
||||
}
|
||||
$price += $room->individualPrice[$participantIndex];
|
||||
|
||||
return $price;
|
||||
}
|
||||
@@ -113,143 +124,4 @@ class Booking
|
||||
{
|
||||
return $this->travelDate > new \DateTimeImmutable() && false === in_array($this->status, ['S', 'U']);
|
||||
}
|
||||
|
||||
public function toPayload(?BookingData $formData): array
|
||||
{
|
||||
// Reset mappings
|
||||
foreach ([...$this->additionalServices, ...$this->transportationServices, ...$this->pickups] as $service) {
|
||||
$service->mapping = [];
|
||||
}
|
||||
// Update mappings, add services and pickups
|
||||
foreach ($formData->participants as $participant) {
|
||||
$servicesToMap = [
|
||||
...$participant->courses,
|
||||
...$participant->additionalServices,
|
||||
...$participant->skiPass,
|
||||
...$participant->board,
|
||||
...$participant->rentals,
|
||||
];
|
||||
foreach ($servicesToMap as $service) {
|
||||
if (false === isset($this->additionalServices[$service->id])) {
|
||||
$serviceToAdd = $this->travelData->additionalServices[$service->id];
|
||||
$this->additionalServices[$service->id] = $serviceToAdd;
|
||||
$this->additionalServices[$service->id]->individualPrice[$participant->index] = $serviceToAdd->price;
|
||||
}
|
||||
$this->additionalServices[$service->id]->mapping[] = $participant->index;
|
||||
}
|
||||
foreach ([$participant->transportationServiceTo, $participant->transportationServiceFro] as $service) {
|
||||
if (false === isset($this->transportationServices[$service->id])) {
|
||||
$serviceToAdd = $this->travelData->transportationServices[$service->id];
|
||||
$this->transportationServices[$service->id] = $serviceToAdd;
|
||||
$this->transportationServices[$service->id]->individualPrice[$participant->index] = $serviceToAdd->price;
|
||||
}
|
||||
$this->transportationServices[$service->id]->mapping[] = $participant->index;
|
||||
}
|
||||
if ('BUS' === $participant->transportationServiceTo->subType && null !== $selectedPickup = $participant->pickup) {
|
||||
if (false === isset($this->pickups[$selectedPickup->id])) {
|
||||
$this->pickups[$selectedPickup->id] = $selectedPickup;
|
||||
}
|
||||
$this->pickups[$selectedPickup->id]->mapping[] = $participant->index;
|
||||
}
|
||||
}
|
||||
// Remove services with empty mappings
|
||||
foreach ($this->additionalServices as $service) {
|
||||
if (0 === count($service->mapping)) {
|
||||
unset($this->additionalServices[$service->id]);
|
||||
}
|
||||
}
|
||||
foreach ($this->transportationServices as $service) {
|
||||
if (0 === count($service->mapping)) {
|
||||
unset($this->transportationServices[$service->id]);
|
||||
}
|
||||
}
|
||||
// Update participants' personal data
|
||||
foreach ($formData->participants as $participant) {
|
||||
$this->participants[$participant->index]->firstName = $participant->firstName;
|
||||
$this->participants[$participant->index]->lastName = $participant->lastName;
|
||||
$this->participants[$participant->index]->dateOfBirth = $participant->dateOfBirth;
|
||||
$this->participants[$participant->index]->gender = $participant->gender;
|
||||
$this->participants[$participant->index]->nationality = $participant->nationality;
|
||||
$this->participants[$participant->index]->height = $participant->height;
|
||||
$this->participants[$participant->index]->weight = $participant->weight;
|
||||
$this->participants[$participant->index]->shoeSize = $participant->shoeSize;
|
||||
$this->participants[$participant->index]->communication->email = $participant->email;
|
||||
$this->participants[$participant->index]->communication->mobile = $participant->mobile;
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'idbuchung' => $this->id,
|
||||
'status' => $this->status,
|
||||
'idagentur' => $this->agencyId,
|
||||
'idreise' => $this->travelId,
|
||||
'idpartner' => $this->hotelId,
|
||||
'anmelder' => $this->applicant->toPayload(),
|
||||
'zahlung' => [
|
||||
'@idzahlungsart' => $this->paymentId,
|
||||
'@bezeichnung' => $this->paymentLabel,
|
||||
'@art' => $this->paymentType,
|
||||
],
|
||||
'teilnehmerliste' => [
|
||||
'teilnehmer' => [],
|
||||
],
|
||||
'zusatzleistungen' => [
|
||||
'zusatzleistung' => [],
|
||||
],
|
||||
'beförderungen' => [
|
||||
'beförderung' => [],
|
||||
],
|
||||
'ferienzielunterbringungen' => [
|
||||
'ferienzielunterbringung' => [],
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($this->participants as $index => $participant) {
|
||||
$payload['teilnehmerliste']['teilnehmer'][] = [
|
||||
'@id' => $index,
|
||||
'status' => $this->participantsStatus[$index],
|
||||
...$participant->toPayload(),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->additionalServices as $service) {
|
||||
$payload['zusatzleistungen']['zusatzleistung'][] = [
|
||||
'@idleistung' => $service->id,
|
||||
'@anzahl' => count($service->mapping),
|
||||
'@zuordnung' => implode(',', $service->mapping),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->transportationServices as $service) {
|
||||
$payload['beförderungen']['beförderung'][] = [
|
||||
'@idleistung' => $service->id,
|
||||
'@anzahl' => count($service->mapping),
|
||||
'@zuordnung' => implode(',', $service->mapping),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->rooms as $room) {
|
||||
$payload['ferienzielunterbringungen']['ferienzielunterbringung'][] = [
|
||||
'@idzimmer' => $room->id,
|
||||
'@kategorie' => $room->category,
|
||||
'@idverpflegung' => $room->boardId,
|
||||
'@anreise' => $room->dateFrom ? $room->dateFrom->format('d.m.Y') : null,
|
||||
'@abreise' => $room->dateTo ? $room->dateTo->format('d.m.Y') : null,
|
||||
'@anzahl' => count($room->mapping),
|
||||
'@zuordnung' => implode(',', $room->mapping),
|
||||
];
|
||||
}
|
||||
|
||||
if (0 < count($this->pickups)) {
|
||||
$payload['zustiege']['zustieg'] = [];
|
||||
foreach ($this->pickups as $pickup) {
|
||||
$payload['zustiege']['zustieg'][] = [
|
||||
'@idzustieg' => $pickup->id,
|
||||
'@anzahl' => count($pickup->mapping),
|
||||
'@zuordnung' => implode(',', $pickup->mapping),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class CrmAttributeGroup
|
||||
{
|
||||
public ?int $id = null;
|
||||
public ?string $label = null;
|
||||
public ?array $attributes = null;
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace App\BusProNet\Model;
|
||||
|
||||
class CrmAttributes
|
||||
{
|
||||
public ?array $attributeGroups = null;
|
||||
public ?array $selectionGroups = null;
|
||||
public bool $admin = false;
|
||||
public bool $manager = false;
|
||||
public bool $houseManager = false;
|
||||
@@ -15,13 +15,13 @@ class CrmAttributes
|
||||
{
|
||||
$crmSelections = [];
|
||||
|
||||
foreach ($this->attributeGroups as $group) {
|
||||
/** @var CrmAttributeGroup $group */
|
||||
foreach ($this->selectionGroups as $group) {
|
||||
/** @var CrmSelectionGroup $group */
|
||||
if (false === isset($crmSelections[$group->label])) {
|
||||
$crmSelections[$group->label] = [];
|
||||
}
|
||||
foreach ($group->attributes as $attribute) {
|
||||
/** @var CrmAttribute $attribute */
|
||||
foreach ($group->selections as $attribute) {
|
||||
/** @var CrmSelection $attribute */
|
||||
if (false === $attribute->selected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class CrmAttribute
|
||||
class CrmSelection
|
||||
{
|
||||
public ?int $id = null;
|
||||
public ?string $label = null;
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class CrmSelectionGroup
|
||||
{
|
||||
/**
|
||||
* Maps BusPro IDs of CRM selection groups representing
|
||||
* included services
|
||||
* @var array|string[]
|
||||
*/
|
||||
public static array $includedServicesMapping = [
|
||||
7 => 'Skipass',
|
||||
71 => 'Verpflegung',
|
||||
85 => 'Übernachtungen',
|
||||
86 => 'Programm',
|
||||
];
|
||||
|
||||
public ?int $id = null;
|
||||
public ?string $label = null;
|
||||
public ?array $selections = null;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class MutableData
|
||||
{
|
||||
public const CATEGORY_PARTICIPANT_COUNT = 'participant_count';
|
||||
public const CATEGORY_PARTICIPANT_DATA = 'participant_data';
|
||||
public const CATEGORY_TRANSPORTATION = 'transportation';
|
||||
public const CATEGORY_PICKUP = 'pickup';
|
||||
public const CATEGORY_ACCOMMODATION = 'accommodation';
|
||||
public const CATEGORY_ADDITIONAL_SERVICES = 'additional_services';
|
||||
|
||||
public function __construct(string $category, bool $mutable, ?\DateTimeImmutable $mutableUntil = null)
|
||||
{
|
||||
$this->category = $category;
|
||||
$this->mutable = $mutable;
|
||||
$this->mutableBefore = $mutableUntil;
|
||||
}
|
||||
|
||||
public ?string $category = null;
|
||||
public bool $mutable = false;
|
||||
public ?\DateTimeImmutable $mutableBefore = null;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class MutableField
|
||||
{
|
||||
public function __construct(string $type, bool $mutable, ?\DateTimeImmutable $mutableUntil = null)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->mutable = $mutable;
|
||||
$this->mutableBefore = $mutableUntil;
|
||||
}
|
||||
|
||||
public ?string $type = null;
|
||||
public bool $mutable = false;
|
||||
public ?\DateTimeImmutable $mutableBefore = null;
|
||||
}
|
||||
@@ -4,9 +4,8 @@ namespace App\BusProNet\Model;
|
||||
|
||||
class Service
|
||||
{
|
||||
public const TYPE_INCLUDED = 'included';
|
||||
public const TYPE_ADDITIONAL = 'additional';
|
||||
public const TYPE_TRANSPORTATION = 'transportation';
|
||||
public const CATEGORY_ADDITIONAL = 'additional';
|
||||
public const CATEGORY_TRANSPORTATION = 'transportation';
|
||||
|
||||
public const TOKEN_COURSES = 'KUR';
|
||||
public const TOKEN_SKI_PASS = 'SPA';
|
||||
@@ -15,6 +14,7 @@ class Service
|
||||
public const TOKEN_RENTALS = ['VER', 'VE2', 'VE3', 'VE4', 'VE5', 'VE6', 'VE7', 'VE8'];
|
||||
|
||||
public ?int $id = null;
|
||||
public ?string $category = null;
|
||||
public ?string $status = null;
|
||||
public bool $mandatory = false;
|
||||
public ?string $label = null;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\Model;
|
||||
|
||||
class Surcharge
|
||||
{
|
||||
public ?string $label = null;
|
||||
public array $mapping = [];
|
||||
public ?float $totalPrice = null;
|
||||
public array $individualPrice = [];
|
||||
}
|
||||
@@ -13,9 +13,15 @@ class Travel
|
||||
public ?float $priceFrom = null;
|
||||
public array $selectionGroups = [];
|
||||
public array $additionalServices = [];
|
||||
public bool $additionalServicesMutable = true;
|
||||
public array $transportationServices = [];
|
||||
public bool $transportationServicesMutable = true;
|
||||
public array $pickups = [];
|
||||
public bool $pickupsMutable = true;
|
||||
public array $rooms = [];
|
||||
public bool $roomsMutable = true;
|
||||
public bool $participantDataMutable = true;
|
||||
public bool $participantCountMutable = true;
|
||||
|
||||
public function getAdditionalServicesByGroup(mixed $group, bool $availableOnly = true): array
|
||||
{
|
||||
@@ -34,4 +40,17 @@ class Travel
|
||||
&& (false === $availableOnly || $service->available > 0);
|
||||
});
|
||||
}
|
||||
|
||||
public function getIncludedServices(): array
|
||||
{
|
||||
$services = [];
|
||||
|
||||
foreach (CrmSelectionGroup::$includedServicesMapping as $id => $label) {
|
||||
if (isset($this->selectionGroups[$id])) {
|
||||
$services[] = $this->selectionGroups[$id];
|
||||
}
|
||||
}
|
||||
|
||||
return $services;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user