*
* möglich|erfolgt
* 321530
* ...
*
*
*
* 671,78
*
*
*
*
*
*/
class BookingResponseParser extends AbstractParser
{
public function parse(Crawler $node): BookingResponse
{
$status = $this->getStringOrNullValue($node->filterXPath('//buchung'));
if (null === $status || '' === $status) {
throw new \InvalidArgumentException('Missing required booking status in booking response.');
}
$bookingNumber = $this->getIntOrNullValue($node->filterXPath('//vorgang'));
$totalPrice = $this->getFloatOrNullValue($node->filterXPath('//gesamtpreis'));
$message = $this->getStringOrNullValue($node->filterXPath('//hinweis'));
$priceItems = $this->parsePriceItems($node);
$paymentTerms = $this->parsePaymentTerms($node);
return new BookingResponse(
status: $status,
bookingNumber: $bookingNumber,
priceItems: $priceItems,
totalPrice: $totalPrice,
paymentTerms: $paymentTerms,
message: $message,
);
}
/**
* Parses individual price items from the response.
*
* @return array
*/
private function parsePriceItems(Crawler $node): array
{
$priceItems = [];
$node->filterXPath('//preise/preis')->each(function (Crawler $priceNode) use (&$priceItems): void {
$position = (int) $this->getRequiredAttrValue($priceNode, 'position', 'booking response price item');
$type = $this->getRequiredAttrValue($priceNode, 'art', 'booking response price item');
$label = $this->getRequiredAttrValue($priceNode, 'bezeichnung', 'booking response price item');
$unitPrice = $this->stringToFloat($this->getRequiredAttrValue($priceNode, 'preis', 'booking response price item'));
$totalPrice = $this->stringToFloat($this->getRequiredAttrValue($priceNode, 'gesamtpreis', 'booking response price item'));
$priceItems[] = new PriceItem(
position: $position,
type: $type,
subType: $this->getAttrOrNullValue($priceNode, 'unterart'),
label: $label,
dateFrom: $this->getAttrOrNullValue($priceNode, 'terminvon'),
dateTo: $this->getAttrOrNullValue($priceNode, 'terminbis'),
quantity: (int) ($this->getAttrOrNullValue($priceNode, 'anzahl') ?? 0),
assignment: $this->getAttrOrNullValue($priceNode, 'zuordnung'),
unitPrice: $unitPrice,
totalPrice: $totalPrice,
id: $this->getAttrOrNullValue($priceNode, 'id')
);
});
return $priceItems;
}
/**
* Parses payment terms from the response.
*/
private function parsePaymentTerms(Crawler $node): ?PaymentTerms
{
$paymentNode = $node->filterXPath('//zahlungsbedingungen');
if (0 === $paymentNode->count()) {
return null;
}
$depositAmount = null;
$depositDate = null;
$finalPaymentAmount = null;
$finalPaymentDate = null;
$depositNode = $paymentNode->filterXPath('.//anzahlung');
if ($depositNode->count() > 0) {
$depositAmount = $this->stringToFloat($this->getAttrOrNullValue($depositNode, 'betrag'));
$depositDate = $this->getAttrOrNullValue($depositNode, 'termin');
}
$finalPaymentNode = $paymentNode->filterXPath('.//restzahlung');
if ($finalPaymentNode->count() > 0) {
$finalPaymentAmount = $this->stringToFloat($this->getAttrOrNullValue($finalPaymentNode, 'betrag'));
$finalPaymentDate = $this->getAttrOrNullValue($finalPaymentNode, 'termin');
}
// Parse purchase vouchers (kaufgutschein elements)
$appliedPurchaseVouchers = [];
$voucherNodes = $paymentNode->filterXPath('.//kaufgutschein');
$voucherNodes->each(function (Crawler $voucherNode) use (&$appliedPurchaseVouchers): void {
$amount = $this->getAttrOrNullValue($voucherNode, 'betrag');
$appliedPurchaseVouchers[] = [
'nummer' => $this->getAttrOrNullValue($voucherNode, 'nummer') ?? '',
'betrag' => $this->stringToFloat($amount),
];
});
return new PaymentTerms(
depositAmount: $depositAmount,
depositDate: $depositDate,
finalPaymentAmount: $finalPaymentAmount,
finalPaymentDate: $finalPaymentDate,
appliedPurchaseVouchers: $appliedPurchaseVouchers,
);
}
}