fix: always adopt outbound pickup price for inbound when set

This commit is contained in:
fromme committed 2026-09-28 16:33:36 +02:00
1 parent 29f295abf6
commit 0c6126010f
5 files changed
+203 -20

No files matched your search

+28 -12
View File
@@ -87,8 +87,8 @@ class TravelParser extends AbstractParser
$travel->pickups = $this->getPickups($node->filterXPath('.//zustiege/zustieg'), $dateFrom, true);
$travel->dropOffs = $this->getPickups($node->filterXPath('.//zustiege_rueck/zustieg_rueck'), $dateTo, false);
// Merge drop-off prices into pickups for split pricing support
$this->mergeDropOffPricesIntoPickups($travel->pickups, $travel->dropOffs);
// A boarding point costs the same in both directions
$this->levelBoardingPointPrices($travel->pickups, $travel->dropOffs);
$travel->guide = $this->getGuide($node);
@@ -453,22 +453,38 @@ class TravelParser extends AbstractParser
}
/**
* Merges drop-off prices into pickups for split pricing support.
* Levels the price of a boarding point across both travel directions.
*
* For each pickup, finds the matching drop-off by ID and copies
* the inbound price to the pickup's priceInbound property. This enables
* split pricing calculations where costs are distributed between outbound
* and inbound transportation.
* A boarding point is either free or costs the same in both directions:
* `ZustiegPreis` is keyed by (point, tariff scheme) and holds no per-leg price, so
* BusPro bills an `Abfahrtsortzuschlag` per leg at one and the same rate. An
* asymmetric pair is therefore always an export defect — on some products a
* `<zustieg_rueck>` carries no `preis` although the engine still charges the return
* leg — and the stated price is the one that applies to both legs.
*
* Where both directions state a price they agree in practice; the outbound one wins
* to keep the outcome deterministic. Points without a counterpart are left as they are.
*
* @param array<int, Pickup> $pickups Pickups indexed by ID (modified in place)
* @param array<int, Pickup> $dropOffs Drop-offs indexed by ID
* @param array<int, Pickup> $dropOffs Drop-offs indexed by ID (modified in place)
*/
private function mergeDropOffPricesIntoPickups(array &$pickups, array $dropOffs): void
private function levelBoardingPointPrices(array &$pickups, array $dropOffs): void
{
foreach ($pickups as $pickupId => $pickup) {
if (isset($dropOffs[$pickupId])) {
$pickup->priceInbound = $dropOffs[$pickupId]->priceInbound;
foreach ($dropOffs as $pickupId => $dropOff) {
if (false === isset($pickups[$pickupId])) {
continue;
}
$pickup = $pickups[$pickupId];
$price = $pickup->price ?? $dropOff->price;
$pickup->price = $price;
$pickup->priceOutbound = $price;
$pickup->priceInbound = $price;
$dropOff->price = $price;
$dropOff->priceOutbound = $price;
$dropOff->priceInbound = $price;
}
}