fix: give chatbot pickups per-leg surcharges including the return leg

This commit is contained in:
fromme committed 2026-10-09 08:38:57 +02:00
1 parent ac5ca7b18b
commit 3cb1548f2f
8 files changed
+58 -7

No files matched your search

+1 -1
View File
@@ -14,7 +14,7 @@ use Mcp\Schema\ToolAnnotations;
#[McpTool(
name: 'get_trip',
description: 'Full details of one trip: description, included services, programme, hotel, all upcoming dates with rooms, prices per person in EUR and availability, pickup points and departure times, FAQs. Use after search_trips, or when the user names a specific trip or a booked date (date codes such as SSLMP061226 narrow the answer to that date). Prices and availability are a snapshot as of dataAsOf; the booking page is binding.',
description: 'Full details of one trip: description, included services, programme, hotel, all upcoming dates with rooms, prices per person in EUR and availability, pickup points and departure times, FAQs. Pickup surcharges are per person and per direction: surchargeOutbound for the way there, surchargeReturn for the way back, surchargeRoundTrip for both; quote the round trip unless the user travels one way only. Use after search_trips, or when the user names a specific trip or a booked date (date codes such as SSLMP061226 narrow the answer to that date). Prices and availability are a snapshot as of dataAsOf; the booking page is binding.',
annotations: new ToolAnnotations(readOnlyHint: true, openWorldHint: false),
)]
final class GetTripTool
+11 -1
View File
@@ -585,6 +585,11 @@ class TripCatalog
}
/**
* BusPro prices a boarding point per leg, so a customer travelling both ways pays the
* surcharge twice. Both legs and their sum are spelled out, because a single figure
* reads as the whole price. A leg listed without a price is billed nothing, so it is 0;
* the return is absent only where the point is not served on the way back.
*
* @param array<string, mixed> $row
*
* @return list<array<string, mixed>>
@@ -598,12 +603,17 @@ class TripCatalog
continue;
}
$outbound = (float) ($pickup['price'] ?? 0);
$return = ($pickup['returnLeg'] ?? false) ? (float) ($pickup['returnPrice'] ?? 0) : null;
$pickups[] = array_filter([
'city' => $pickup['city'],
'place' => $pickup['street'] ?? null,
// A clock reading without an offset, as BusPro states it.
'departure' => is_string($pickup['datetime'] ?? null) ? str_replace('T', ' ', substr($pickup['datetime'], 0, 16)) : null,
'surcharge' => $pickup['price'] ?? null,
'surchargeOutbound' => $outbound,
'surchargeReturn' => $return,
'surchargeRoundTrip' => null !== $return ? round($outbound + $return, 2) : null,
], static fn (mixed $value): bool => null !== $value);
}
+5 -1
View File
@@ -188,7 +188,8 @@ class ProductExportBuilder
}
/**
* Outbound boarding points joined against zustiege.xml, in source order.
* Outbound boarding points joined against zustiege.xml, in source order, each with the
* same point's return-leg entry. A point listed on the return leg only is not emitted.
*
* getPickups() resolves both zeit shapes and rolls a bare time past midnight onto the
* next day. Entries with id 0 are kept: the consumer drops them itself.
@@ -206,6 +207,7 @@ class ProductExportBuilder
{
$resolved = [];
$clockDate = new \DateTimeImmutable($dateFrom->format('Y-m-d'), new \DateTimeZone('UTC'));
$returnLegs = $this->travelParser->getPickups($this->productExportParser->children($dateNode, 'zustiege_rueck/zustieg_rueck'), null, false);
foreach ($this->travelParser->getPickups($this->productExportParser->children($dateNode, 'zustiege/zustieg'), $clockDate, true) as $pickup) {
$pickupId = (int) $pickup->id;
@@ -221,6 +223,8 @@ class ProductExportBuilder
'city' => $details?->city,
'street' => $details?->street,
'price' => $pickup->price,
'returnLeg' => isset($returnLegs[$pickupId]),
'returnPrice' => ($returnLegs[$pickupId] ?? null)?->price,
'datetime' => $pickup->time?->format('Y-m-d\TH:i:s'),
];
}