parser = new BookingResponseParser();
}
public function testParseBookingResponseWithPurchaseVoucher(): void
{
$xmlContent = '
möglich
321530
755,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
$this->assertTrue($response->isInquiryValid());
$this->assertEquals(321530, $response->bookingNumber);
$this->assertEquals(755.0, $response->totalPrice);
// Verify purchase voucher is parsed
$this->assertNotNull($response->paymentTerms);
$this->assertCount(1, $response->paymentTerms->appliedPurchaseVouchers);
$this->assertEquals('G1263', $response->paymentTerms->appliedPurchaseVouchers[0]['nummer']);
$this->assertEquals(100.0, $response->paymentTerms->appliedPurchaseVouchers[0]['betrag']);
$this->assertEquals(100.0, $response->paymentTerms->getPurchaseVoucherDiscount());
$this->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'));
$this->assertTrue($response->isInquiryValid());
$this->assertEquals(615.2, $response->totalPrice);
// Verify price items include promotional voucher
$this->assertCount(2, $response->priceItems);
$voucherItem = $response->priceItems[1];
$this->assertEquals('AKTION', $voucherItem->type);
$this->assertEquals('TESTERINO1', $voucherItem->label);
$this->assertEquals(-100.0, $voucherItem->totalPrice);
// Verify voucher discount extraction
$voucherDiscounts = $response->getVoucherDiscountsFromPrices();
$this->assertCount(1, $voucherDiscounts);
$this->assertEquals(100.0, $response->getVoucherDiscountFromPrices());
$this->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'));
$this->assertTrue($response->isInquiryValid());
$this->assertEquals(0.0, $response->totalPrice);
// Verify goodwill voucher is parsed
$voucherDiscounts = $response->getVoucherDiscountsFromPrices();
$this->assertCount(1, $voucherDiscounts);
$goodwillVoucher = array_values($voucherDiscounts)[0];
$this->assertEquals('KULANZGUTSCHEIN', $goodwillVoucher->type);
$this->assertEquals('Kulanzgutschein K1904', $goodwillVoucher->label);
$this->assertEquals(-679.0, $goodwillVoucher->totalPrice);
$this->assertEquals(679.0, $response->getVoucherDiscountFromPrices());
$this->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
$this->assertEquals(80.0, $response->getVoucherDiscountFromPrices()); // 50 + 30
$this->assertEquals(100.0, $response->getPurchaseVoucherDiscount());
$this->assertEquals(180.0, $response->getTotalVoucherDiscount()); // 50 + 30 + 100
// Verify price item vouchers
$voucherDiscounts = $response->getVoucherDiscountsFromPrices();
$this->assertCount(2, $voucherDiscounts);
}
public function testParseBookingResponseWithNoVouchers(): void
{
$xmlContent = '
möglich
321530
679,00
';
$crawler = new Crawler($xmlContent);
$response = $this->parser->parse($crawler->filter('ergebnis'));
$this->assertTrue($response->isInquiryValid());
$this->assertEquals(679.0, $response->totalPrice);
// Verify no voucher discounts
$this->assertCount(0, $response->getVoucherDiscountsFromPrices());
$this->assertEquals(0.0, $response->getVoucherDiscountFromPrices());
$this->assertEquals(0.0, $response->getPurchaseVoucherDiscount());
$this->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
$this->assertNotNull($response->paymentTerms);
$this->assertCount(2, $response->paymentTerms->appliedPurchaseVouchers);
$this->assertEquals(125.0, $response->paymentTerms->getPurchaseVoucherDiscount()); // 50 + 75
$this->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'));
$this->assertTrue($response->isInquiryValid());
$this->assertEquals(3972.0, $response->totalPrice);
// Verify Gruppenrabatt is NOT counted as voucher discount
$this->assertCount(0, $response->getVoucherDiscountsFromPrices());
$this->assertEquals(0.0, $response->getVoucherDiscountFromPrices());
// Verify Gruppenrabatt IS counted as API-applied discount
$apiAppliedDiscounts = $response->getApiAppliedDiscounts();
$this->assertCount(1, $apiAppliedDiscounts);
$gruppenrabatt = array_values($apiAppliedDiscounts)[0];
$this->assertEquals('ERM', $gruppenrabatt->type);
$this->assertEquals('GRU', $gruppenrabatt->subType);
$this->assertEquals('Gruppenrabatt', $gruppenrabatt->label);
$this->assertEquals(-90.0, $gruppenrabatt->totalPrice);
$this->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
$this->assertEquals(20.0, $response->getVoucherDiscountFromPrices());
// API-applied discount should only include ERM (Gruppenrabatt)
$this->assertEquals(50.0, $response->getApiAppliedDiscountTotal());
// Verify they are separate and don't overlap
$voucherDiscounts = $response->getVoucherDiscountsFromPrices();
$apiDiscounts = $response->getApiAppliedDiscounts();
$this->assertCount(1, $voucherDiscounts);
$this->assertCount(1, $apiDiscounts);
$this->assertEquals('AKTION', array_values($voucherDiscounts)[0]->type);
$this->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
$this->assertCount(0, $response->getApiAppliedDiscounts());
$this->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'));
$this->assertTrue($response->isInquiryValid());
$this->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
$this->assertCount(0, $response->getApiAppliedDiscounts());
$this->assertEquals(0.0, $response->getApiAppliedDiscountTotal());
// Verify no voucher discounts either
$this->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();
$this->assertCount(1, $apiAppliedDiscounts);
$gruppenrabatt = array_values($apiAppliedDiscounts)[0];
$this->assertEquals('ERM', $gruppenrabatt->type);
$this->assertEquals(-100.0, $gruppenrabatt->totalPrice);
// Total API-applied discount should only include Gruppenrabatt (100), not transportation (300)
$this->assertEquals(100.0, $response->getApiAppliedDiscountTotal());
}
}