parser = new BookingResponseParser();
}
public function testParseBookingResponseWithPurchaseVoucher(): void
{
$xmlContent = '
möglich
321530
755,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
self::assertTrue($response->isInquiryValid());
self::assertEquals(321530, $response->bookingNumber);
self::assertEquals(755.0, $response->totalPrice);
// Verify purchase voucher is parsed
self::assertNotNull($response->paymentTerms);
self::assertCount(1, $response->paymentTerms->appliedPurchaseVouchers);
self::assertEquals('G1263', $response->paymentTerms->appliedPurchaseVouchers[0]['nummer']);
self::assertEquals(100.0, $response->paymentTerms->appliedPurchaseVouchers[0]['betrag']);
self::assertEquals(100.0, $response->paymentTerms->getPurchaseVoucherDiscount());
self::assertEquals(655.0, $response->paymentTerms->finalPaymentAmount);
}
public function testParseBookingResponseWithPromotionalVoucher(): void
{
$xmlContent = '
möglich
321530
615,20
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
self::assertTrue($response->isInquiryValid());
self::assertEquals(615.2, $response->totalPrice);
// Verify price items include promotional voucher
self::assertCount(2, $response->priceItems);
$voucherItem = $response->priceItems[1];
self::assertEquals('AKTION', $voucherItem->type);
self::assertEquals('TESTERINO1', $voucherItem->label);
self::assertEquals(-100.0, $voucherItem->totalPrice);
// Verify voucher discount extraction
$voucherDiscounts = $response->getVoucherDiscountsFromPrices();
self::assertCount(1, $voucherDiscounts);
self::assertEquals(100.0, $response->getVoucherDiscountFromPrices());
self::assertEquals(100.0, $response->getTotalVoucherDiscount());
}
public function testParseBookingResponseWithGoodwillVoucher(): void
{
$xmlContent = '
möglich
321530
0,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
self::assertTrue($response->isInquiryValid());
self::assertEquals(0.0, $response->totalPrice);
// Verify goodwill voucher is parsed
$voucherDiscounts = $response->getVoucherDiscountsFromPrices();
self::assertCount(1, $voucherDiscounts);
$goodwillVoucher = array_values($voucherDiscounts)[0];
self::assertEquals('KULANZGUTSCHEIN', $goodwillVoucher->type);
self::assertEquals('Kulanzgutschein K1904', $goodwillVoucher->label);
self::assertEquals(-679.0, $goodwillVoucher->totalPrice);
self::assertEquals(679.0, $response->getVoucherDiscountFromPrices());
self::assertEquals(679.0, $response->getTotalVoucherDiscount());
}
public function testParseBookingResponseWithMultipleVouchers(): void
{
$xmlContent = '
möglich
321530
499,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
// Verify all voucher types are parsed
self::assertEquals(80.0, $response->getVoucherDiscountFromPrices()); // 50 + 30
self::assertEquals(100.0, $response->getPurchaseVoucherDiscount());
self::assertEquals(180.0, $response->getTotalVoucherDiscount()); // 50 + 30 + 100
// Verify price item vouchers
$voucherDiscounts = $response->getVoucherDiscountsFromPrices();
self::assertCount(2, $voucherDiscounts);
}
public function testParseBookingResponseWithNoVouchers(): void
{
$xmlContent = '
möglich
321530
679,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
self::assertTrue($response->isInquiryValid());
self::assertEquals(679.0, $response->totalPrice);
// Verify no voucher discounts
self::assertCount(0, $response->getVoucherDiscountsFromPrices());
self::assertEquals(0.0, $response->getVoucherDiscountFromPrices());
self::assertEquals(0.0, $response->getPurchaseVoucherDiscount());
self::assertEquals(0.0, $response->getTotalVoucherDiscount());
}
public function testParseBookingResponseWithMultiplePurchaseVouchers(): void
{
$xmlContent = '
möglich
321530
679,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
// Verify multiple purchase vouchers are parsed
self::assertNotNull($response->paymentTerms);
self::assertCount(2, $response->paymentTerms->appliedPurchaseVouchers);
self::assertEquals(125.0, $response->paymentTerms->getPurchaseVoucherDiscount()); // 50 + 75
self::assertEquals(125.0, $response->getTotalVoucherDiscount());
}
public function testParseBookingResponseWithGruppenrabatt(): void
{
$xmlContent = '
möglich
321530
3972,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
self::assertTrue($response->isInquiryValid());
self::assertEquals(3972.0, $response->totalPrice);
// Verify Gruppenrabatt is NOT counted as voucher discount
self::assertCount(0, $response->getVoucherDiscountsFromPrices());
self::assertEquals(0.0, $response->getVoucherDiscountFromPrices());
// Verify Gruppenrabatt IS counted as API-applied discount
$apiAppliedDiscounts = $response->getApiAppliedDiscounts();
self::assertCount(1, $apiAppliedDiscounts);
$gruppenrabatt = array_values($apiAppliedDiscounts)[0];
self::assertEquals('ERM', $gruppenrabatt->type);
self::assertEquals('GRU', $gruppenrabatt->subType);
self::assertEquals('Gruppenrabatt', $gruppenrabatt->label);
self::assertEquals(-90.0, $gruppenrabatt->totalPrice);
self::assertEquals(90.0, $response->getApiAppliedDiscountTotal());
}
public function testParseBookingResponseWithGruppenrabattAndVouchers(): void
{
$xmlContent = '
möglich
321530
430,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
// Voucher discount should only include AKTION
self::assertEquals(20.0, $response->getVoucherDiscountFromPrices());
// API-applied discount should only include ERM (Gruppenrabatt)
self::assertEquals(50.0, $response->getApiAppliedDiscountTotal());
// Verify they are separate and don't overlap
$voucherDiscounts = $response->getVoucherDiscountsFromPrices();
$apiDiscounts = $response->getApiAppliedDiscounts();
self::assertCount(1, $voucherDiscounts);
self::assertCount(1, $apiDiscounts);
self::assertEquals('AKTION', array_values($voucherDiscounts)[0]->type);
self::assertEquals('ERM', array_values($apiDiscounts)[0]->type);
}
public function testParseBookingResponseWithNoApiAppliedDiscounts(): void
{
$xmlContent = '
möglich
321530
679,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
// Verify no API-applied discounts
self::assertCount(0, $response->getApiAppliedDiscounts());
self::assertEquals(0.0, $response->getApiAppliedDiscountTotal());
}
public function testParseBookingResponseWithTransportationDiscountNotCountedAsApiApplied(): void
{
$xmlContent = '
möglich
321530
1682,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
self::assertTrue($response->isInquiryValid());
self::assertEquals(1682.0, $response->totalPrice);
// Transportation discount (BEF with negative price) should NOT be counted as API-applied discount
// because it's already handled by the local price calculator
self::assertCount(0, $response->getApiAppliedDiscounts());
self::assertEquals(0.0, $response->getApiAppliedDiscountTotal());
// Verify no voucher discounts either
self::assertEquals(0.0, $response->getVoucherDiscountFromPrices());
}
public function testParseBookingResponseWithBothTransportationAndGruppenrabatt(): void
{
$xmlContent = '
möglich
321530
1600,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
// Only ERM (Gruppenrabatt) should be counted as API-applied discount
// BEF transportation discount should NOT be counted
$apiAppliedDiscounts = $response->getApiAppliedDiscounts();
self::assertCount(1, $apiAppliedDiscounts);
$gruppenrabatt = array_values($apiAppliedDiscounts)[0];
self::assertEquals('ERM', $gruppenrabatt->type);
self::assertEquals(-100.0, $gruppenrabatt->totalPrice);
// Total API-applied discount should only include Gruppenrabatt (100), not transportation (300)
self::assertEquals(100.0, $response->getApiAppliedDiscountTotal());
}
}