feat: add the product code to the travel export

This commit is contained in:
fromme committed 2026-10-15 17:26:12 +02:00
1 parent 6f6bf3695c
commit 6d2db1b258
3 files changed
+27

No files matched your search

+6
View File
@@ -172,6 +172,7 @@ an error: it returns `200` with an empty `data` array and the usual `meta`.
{
"busProId": 12794,
"code": "PCJSER261226",
"productCode": "PCJSER",
"product": "Semesterende - Portes du Soleil - Joliment",
"dateFrom": "2026-12-26",
"dateTo": "2026-12-30",
@@ -212,6 +213,11 @@ an error: it returns `200` with an empty `data` array and the usual `meta`.
is always an int and never null; `hotel` is always an object and never null; `pickups` is always an array, possibly
empty, never null.
**`productCode`** is the code of the travel (product) the date belongs to, e.g. `DKIWE`. Key on it to
recognise dates of the same product. Do not derive it from the date `code` by cutting off the date: some
products run dates under a different code (`DWWMP` runs `DWWMW…`), and group travels carry each group's own
code on the date. It is `null` for the few travels that have no code upstream.
**`meta` describes the whole export, not the page.** `total`, `totalPages`, `skipped`, `pickupsWithoutMasterData`,
`sourceGeneratedAt` and `generatedAt` are identical on every page, so you can read them once on page 1 and decide whether to walk the
rest. `total` is the row count **after** skips, and `totalPages` is `ceil(total / perPage)`.
+5
View File
@@ -157,9 +157,14 @@ class TravelExportBuilder
$pickupsWithoutMasterData,
);
// The product a date belongs to, from the enclosing <reise>. Not derivable from the
// date code: DWWMP runs dates coded DWWMW…, and group travels carry each group's code.
$productNode = $node->getNode(0)?->parentNode;
$travel = [
'busProId' => $travelId,
'code' => $node->attr('code'),
'productCode' => $productNode instanceof \DOMElement ? $this->trimOrNull($productNode->getAttribute('code')) : null,
'product' => $this->trimOrNull($this->getStringOrNullValue($node->filterXPath('.//text'))),
'dateFrom' => $dateFrom->format('Y-m-d'),
'dateTo' => $dateTo->format('Y-m-d'),
+16
View File
@@ -42,6 +42,7 @@ class TravelExportBuilderTest extends TestCase
self::assertSame(900, $row['busProId']);
self::assertIsInt($row['busProId']);
self::assertSame('SBW261226', $row['code']);
self::assertSame('SBW', $row['productCode']);
self::assertSame('Semesterende - Portes du Soleil', $row['product'], 'the product label is trimmed');
self::assertSame('2026-12-26', $row['dateFrom']);
self::assertSame('2026-12-30', $row['dateTo']);
@@ -56,6 +57,21 @@ class TravelExportBuilderTest extends TestCase
], $row['hotel']);
}
public function testCarriesTheProductCodeOfTheEnclosingTravelRatherThanTheDateCode(): void
{
$rows = $this->build('<?xml version="1.0"?><reisen><reise code="DWWMP "><termin idbuspro="1" termin="01.01.2027" bis="02.01.2027" code="DWWMW010127"><hotel idbuspro="1"/></termin></reise></reisen>')->rows;
self::assertSame('DWWMP', $rows[0]['productCode'], 'taken from <reise>, trimmed');
self::assertSame('DWWMW010127', $rows[0]['code']);
}
public function testTheProductCodeIsNullWhenTheTravelCarriesNone(): void
{
$rows = $this->build('<?xml version="1.0"?><reisen><reise code=""><termin idbuspro="1" termin="01.01.2027" bis="02.01.2027" code="SCE010127"><hotel idbuspro="1"/></termin></reise></reisen>')->rows;
self::assertNull($rows[0]['productCode']);
}
public function testResolvesBothZeitShapesAndRollsAnOvernightPickupOntoTheNextDay(): void
{
$pickups = array_column($this->rowFor('900-1')['pickups'], null, 'busProId');