parser = new BookingResponseParser(); } public function testParseBookingResponseWithPurchaseVoucher(): void { $xmlContent = ' möglich 321530 755,00 '; $crawler = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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 = XmlCrawlerFactory::create($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()); } }