Files
myep/docs/pickup-api-limitation.md
T
Björn Fromme 9471abce94 fix: revert pickup pricing to match current BusPro behavior
Reverts split pricing calculation to use outbound-only pricing,
matching BusPro's current behavior where pickup is only charged when
outbound transportation is BUS.

- Use pickup->price directly instead of calculateEffectivePrice()
- PKW+BUS scenario now correctly charges €0 (matches BusPro loophole)
- priceOutbound/priceInbound remain populated for future activation
- Updated documentation with current behavior and future plan
2026-01-21 17:18:09 +01:00

5.1 KiB

Pickup Pricing - Implementation Documentation

Current BusPro Behavior (January 2026)

BusPro currently only charges pickup price when the outbound transportation is BUS, regardless of the inbound selection.

Pricing Matrix (Current)

Outbound Inbound BusPro Charges Notes
BUS BUS Pickup price once Full price from outbound
BUS PKW Pickup price once Full price from outbound
PKW BUS €0 Known loophole in BusPro
PKW PKW €0 No pickup available

The "loophole" (PKW outbound + BUS inbound = no charge) exists on BusPro's side. Our portal must match this behavior to avoid price validation errors when submitting bookings.

XML Data Structure

Both travel sections contain pickup data with prices:

<!-- Outbound pickups -->
<zustiege>
    <zustieg id="3" idbuspro="4" preis="5,90" .../>
</zustiege>

<!-- Inbound pickups -->
<zustiege_rueck>
    <zustieg_rueck id="3" idbuspro="4" preis="5,90" .../>
</zustiege_rueck>

Currently, prices are duplicated in both sections. In the future, when BusPro supports split pricing, travels may be configured with different prices per direction (e.g., 2.95 each way instead of 5.90 outbound only).

Portal Implementation

Forward-Compatible Data Layer

The portal parses and stores both direction prices for future use:

  1. Pickup Model (src/BusProNet/Model/Pickup.php):

    • price: The outbound price (used for pricing calculations)
    • priceOutbound: Explicit outbound price (populated but not used yet)
    • priceInbound: Explicit inbound price (populated but not used yet)
    • calculateEffectivePrice(): Ready for future split pricing activation
  2. TravelParser (src/BusProNet/XmlParser/TravelParser.php):

    • Parses zustiege section and sets priceOutbound
    • Parses zustiege_rueck section and sets priceInbound
    • Merges inbound prices into outbound pickup objects by ID
  3. BookingDataProcessor (src/BusProNet/DataProcessor/BookingDataProcessor.php):

    • Enriches participant pickups with all price properties from travel data

Current Pricing Logic

The pricing calculators use simple outbound-only logic to match BusPro:

// Only charge if outbound is BUS - matches current BusPro behavior
$hasOutboundBus = null !== $participant->transportationOutbound
    && 'BUS' === $participant->transportationOutbound->subType;

if ($hasOutboundBus && null !== $participant->pickup && null !== $participant->pickup->price) {
    $serviceTotal += $participant->pickup->price;
}

This ensures portal prices always match BusPro responses, avoiding validation errors.

API Constraints

  • Pickups can only be submitted via the zustiege (outbound) XML section
  • There is no zustiege_rueck (inbound) equivalent for submission
  • Booking responses return pickups in the outbound section only
  • A future API update will support separate pickup/drop-off locations

Future Activation (When BusPro Supports Split Pricing)

When BusPro is updated to charge based on actual transportation selections, update the pricing calculators to use calculateEffectivePrice():

$hasOutboundBus = null !== $participant->transportationOutbound
    && 'BUS' === $participant->transportationOutbound->subType;
$hasInboundBus = null !== $participant->transportationInbound
    && 'BUS' === $participant->transportationInbound->subType;

if (null !== $participant->pickup) {
    $pickupPrice = $participant->pickup->calculateEffectivePrice($hasOutboundBus, $hasInboundBus);
    if (null !== $pickupPrice) {
        $serviceTotal += $pickupPrice;
    }
}

Important Caveat for Split Pricing Configuration

If travels are configured with split pricing (e.g., outbound=2.95, inbound=2.95) before BusPro supports it:

Scenario Portal Charges BusPro Charges Intended
BUS+BUS 2.95 2.95 5.90
BUS+PKW 2.95 2.95 2.95
PKW+BUS 0.00 0.00 2.95

Recommendation: Keep full price on outbound (preis="5,90") until BusPro supports split pricing, then reconfigure to true split values.

  • src/BusProNet/Model/Pickup.php - Pickup model with split pricing properties and calculation methods
  • src/BusProNet/XmlParser/TravelParser.php - Parses and merges pickup prices from XML
  • src/BusProNet/DataProcessor/BookingDataProcessor.php - Enriches pickups with travel data
  • src/BusProNet/DataProcessor/BookingPayloadBuilder.php - Pickup submission
  • src/BusProNet/Model/Booking.php - getPickupForParticipant() method
  • src/Form/Service/EditFieldStateProvider.php - Pickup field visibility
  • src/Form/Service/CreateFieldStateProvider.php - Pickup field visibility
  • src/Service/ParticipantPricingCalculator.php - Pickup pricing logic (individual)
  • src/Service/ServicePricingCalculator.php - Pickup pricing aggregation (summary)

Test Scenarios

  1. BUS + BUS: Charges pickup->price (outbound)
  2. BUS + PKW: Charges pickup->price (outbound)
  3. PKW + BUS: Charges €0 (matches BusPro loophole)
  4. PKW + PKW: No pickup available

Last updated: 2026-01-21