feat: expose hotel cost unit and iso country code via the api

The Teamer app groups hotels by cost unit and renders a flag per
destination, and cannot derive either from what /api/hotels returns
today.

costUnit is the raw kostenstelle and stays a string: only 281 of 1931
hotels carry one and some hold a space-separated list such as "84 85".

countryCode goes through CountryCodeMapper, whose table is part of the
API contract: BusPro's land column mixes ISO-2, ISO-3 and European
vehicle registration codes for the same country, and a wrong entry
mislabels a destination's flag silently. An unmappable token is null and
warns on the bpn channel, never a guess. country itself is untouched --
it remains the join key into /api/countries[].token.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
frommeandClaude Opus 5 committed 2026-09-29 12:07:13 +02:00
1 parent 65c1a7bd12
commit f3745f918e
7 files changed
+322 -2

No files matched your search

@@ -3,9 +3,11 @@
namespace App\Tests\BusProNet\DataLoader;
use App\BusProNet\Model\Hotel;
use App\BusProNet\Utility\CountryCodeMapper;
use App\BusProNet\XmlLoader\HotelLoader;
use League\Flysystem\FilesystemOperator;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
@@ -34,7 +36,7 @@ class HotelDataLoaderTest extends TestCase
->willReturn($xmlContent);
$cache = new TagAwareAdapter(new ArrayAdapter());
$loader = new HotelLoader($cache, $filesystem);
$loader = new HotelLoader(new CountryCodeMapper(new NullLogger()), $cache, $filesystem);
$hotels = $loader->loadAll();
@@ -50,5 +52,7 @@ class HotelDataLoaderTest extends TestCase
$this->assertEquals('F', $hotel->country);
$this->assertEquals('Rue des Lacs', $hotel->street);
$this->assertEquals('', $hotel->phone);
$this->assertEquals('fr', $hotel->countryCode);
$this->assertNull($hotel->costUnit);
}
}