fix: map live service status to export wording

This commit is contained in:
fromme committed 2026-11-04 10:12:34 +01:00
1 parent d8fe9a3875
commit 09610889f3
7 files changed
+129 -11

No files matched your search

+4 -4
View File
@@ -307,10 +307,10 @@ class TravelLoader extends AbstractLoader
$availability = $serviceAvailabilities[$service->id];
$service->available = $availability->available;
// The live status is the only signal that a contingent has run out: BusPro moves a
// Leistung to 'Anfrage' without necessarily reporting frei="0". Only overwrite when the
// response actually carries one, so a response that omits the attribute does not wipe
// the value parsed from the XML export. Mirrors TravelSnapshotManager::applyExtendedToService().
// The live status is fresher than the nightly export's. The parser has already mapped it
// onto the export vocabulary. Only overwrite when the response actually carries one, so a
// response that omits the attribute does not wipe the value parsed from the XML export.
// Mirrors TravelSnapshotManager::applyExtendedToService().
if (null !== $availability->status && '' !== trim($availability->status)) {
$service->status = $availability->status;
}
@@ -2,6 +2,7 @@
namespace App\BusProNet\XmlParser;
use App\BusProNet\Constants;
use App\BusProNet\Traits\TypeConversionTrait;
use Symfony\Component\DomCrawler\Crawler;
@@ -9,6 +10,19 @@ abstract class AbstractParser
{
use TypeConversionTrait;
/**
* Live availability wording for a Leistung, mapped onto the XML export's.
*
* The availability endpoints answer "buchbar" or "ausgebucht", while every availability rule
* compares against the export's "Frei" / "Anfrage" / "Buchungsstop". "ausgebucht" also covers
* a Leistung that would still take an inquiry (anfragemoeglich="J"); that is not offered
* either, so it maps to the booking stop.
*/
private const LIVE_SERVICE_STATUS = [
'buchbar' => Constants::STATUS_AVAILABLE,
'ausgebucht' => Constants::STATUS_BLOCKED,
];
protected function getStringOrNullValue(Crawler $node): ?string
{
return 0 < $node->count() ? $node->text() : null;
@@ -87,4 +101,16 @@ abstract class AbstractParser
return $value;
}
/**
* Translates a live Leistung status into the export vocabulary; anything else passes through.
*/
protected function toServiceStatus(?string $liveStatus): ?string
{
if (null === $liveStatus) {
return null;
}
return self::LIVE_SERVICE_STATUS[strtolower(trim($liveStatus))] ?? $liveStatus;
}
}
@@ -19,7 +19,7 @@ class AvailabilitiesParser extends AbstractParser
->each(function (Crawler $node) use (&$availabilities) {
$availability = new Availability();
$availability->serviceId = (int) $node->attr('id');
$availability->status = $node->attr('status');
$availability->status = $this->toServiceStatus($node->attr('status'));
$availability->available = (int) $node->attr('frei');
$availability->price = $this->stringToFloat($node->attr('preis'));
@@ -30,7 +30,7 @@ class ExtendedAvailabilitiesParser extends AbstractParser
$availability = new ExtendedAvailability();
$availability->serviceId = $serviceId;
$availability->status = $node->attr('status');
$availability->status = $this->toServiceStatus($node->attr('status'));
$availability->available = (int) $node->attr('frei');
$availability->price = $this->stringToFloat($node->attr('preis'));
$availability->dateFrom = $this->stringToDate($node->attr('termin'));