From b9851943d018e566ddd7af236cd5bd06224e9b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Wed, 30 Sep 2026 12:31:42 +0200 Subject: [PATCH] fix: key imported services by BusPro id and match selection groups by id --- .../Classes/Service/DateImportService.php | 73 +++++++++++++++---- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/public/typo3conf/ext/ep_products/Classes/Service/DateImportService.php b/public/typo3conf/ext/ep_products/Classes/Service/DateImportService.php index 39f69753..988f4ffe 100644 --- a/public/typo3conf/ext/ep_products/Classes/Service/DateImportService.php +++ b/public/typo3conf/ext/ep_products/Classes/Service/DateImportService.php @@ -50,6 +50,26 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface const STATUS_ON_REQUEST = 'Anfrage'; const STATUS_STOP = 'Buchungsstop'; + /** + * BusPro ids of the selection groups whose selections make up the included + * services. Matched by id rather than by label, so a group renamed upstream + * does not silently drop out of services_included. + */ + const SELECTION_GROUP_SKIPASS = 7; + const SELECTION_GROUP_OTHER = 8; + const SELECTION_GROUP_BOARD = 71; + const SELECTION_GROUP_ACCOMMODATION = 85; + const SELECTION_GROUP_PROGRAMME = 86; + const SELECTION_GROUP_COURSES = 87; + const SELECTION_GROUP_EVENTS = 89; + const SELECTION_GROUP_TRANSPORTATION = 90; + + /** + * 'Leistungen Personal' occurs in no export so far, so its id is unknown and + * it is still matched by label. Register its id once the warning fires. + */ + const SELECTION_GROUP_LABEL_PERSONNEL = 'Leistungen Personal'; + /** * @var ConfigurationManagerInterface */ @@ -375,15 +395,15 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface 'important' => $product['important'], ]; - $includedAccommodation = $this->parseSelectionGroup($xmlDate, 'Leistungen Übernachtung'); - $includedSkiPass = $this->parseSelectionGroup($xmlDate, 'Leistungen Skipass'); - $includedBoard = $this->parseSelectionGroup($xmlDate, 'Leistungen Verpflegung'); - $includedTransportation = $this->parseSelectionGroup($xmlDate, 'Leistungen Transport'); - $includedProgramme = $this->parseSelectionGroup($xmlDate, 'Leistungen Programm'); - $includedPersonnel = $this->parseSelectionGroup($xmlDate, 'Leistungen Personal'); - $includedEvents = $this->parseSelectionGroup($xmlDate, 'Leistungen Events'); - $includedOther = $this->parseSelectionGroup($xmlDate, 'Leistungen Sonstige'); - $includedCourses = $this->parseSelectionGroup($xmlDate, 'Leistungen Kurse'); + $includedAccommodation = $this->parseSelectionGroup($xmlDate, static::SELECTION_GROUP_ACCOMMODATION); + $includedSkiPass = $this->parseSelectionGroup($xmlDate, static::SELECTION_GROUP_SKIPASS); + $includedBoard = $this->parseSelectionGroup($xmlDate, static::SELECTION_GROUP_BOARD); + $includedTransportation = $this->parseSelectionGroup($xmlDate, static::SELECTION_GROUP_TRANSPORTATION); + $includedProgramme = $this->parseSelectionGroup($xmlDate, static::SELECTION_GROUP_PROGRAMME); + $includedPersonnel = $this->parsePersonnelSelectionGroup($xmlDate); + $includedEvents = $this->parseSelectionGroup($xmlDate, static::SELECTION_GROUP_EVENTS); + $includedOther = $this->parseSelectionGroup($xmlDate, static::SELECTION_GROUP_OTHER); + $includedCourses = $this->parseSelectionGroup($xmlDate, static::SELECTION_GROUP_COURSES); $includedServices = [ ...$includedAccommodation, @@ -748,7 +768,7 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface $data[$type] = []; } - $data[$type][(int)$service->attributes()['id']] = [ + $data[$type][(int)$service->attributes()['idbuspro']] = [ 'idBusPro' => (int) $service->attributes()['idbuspro'], 'label' => $label, 'price' => number_format($price, 2, ',', '.'), @@ -762,14 +782,39 @@ class DateImportService implements SingletonInterface, LoggerAwareInterface /** * @param \SimpleXMLElement $xmlDate - * @param string $label + * @param int $busProId * @return array */ - protected function parseSelectionGroup(\SimpleXMLElement $xmlDate, string $label): array + protected function parseSelectionGroup(\SimpleXMLElement $xmlDate, int $busProId): array + { + return $this->parseSelections($xmlDate->xpath('selektiongruppe[@idbuspro="' . $busProId . '"]/selektion')); + } + + /** + * @param \SimpleXMLElement $xmlDate + * @return array + */ + protected function parsePersonnelSelectionGroup(\SimpleXMLElement $xmlDate): array + { + $groups = $xmlDate->xpath('selektiongruppe[@bezeichnung="' . static::SELECTION_GROUP_LABEL_PERSONNEL . '"]'); + foreach ($groups as $group) { + $this->logger->warning( + 'selection group matched by label, register its id', + ['label' => static::SELECTION_GROUP_LABEL_PERSONNEL, 'idbuspro' => (int) $group->attributes()['idbuspro']] + ); + } + + return $this->parseSelections($xmlDate->xpath('selektiongruppe[@bezeichnung="' . static::SELECTION_GROUP_LABEL_PERSONNEL . '"]/selektion')); + } + + /** + * @param \SimpleXMLElement[] $selections + * @return array + */ + protected function parseSelections(array $selections): array { $data = []; - $selectionGroup = $xmlDate->xpath('selektiongruppe[@bezeichnung="' . $label . '"]/selektion'); - foreach ($selectionGroup as $selection) { + foreach ($selections as $selection) { $attributes = $selection->attributes(); if (null === $attributes) { continue;