wip: insurance booking

This commit is contained in:
Björn Fromme
2025-09-29 19:54:20 +02:00
parent 0809f07d46
commit 90ae78262a
19 changed files with 807 additions and 128 deletions
+49 -14
View File
@@ -19,6 +19,7 @@ class InsuranceParser extends AbstractParser
* Parses insurance XML nodes into Insurance objects.
*
* @param Crawler $xmlContent The XML crawler containing insurance data
*
* @return array<string|int, Insurance> Array of Insurance objects indexed by id
*/
public function parse(Crawler $xmlContent): array
@@ -28,25 +29,29 @@ class InsuranceParser extends AbstractParser
// First pass: collect referenced insurance IDs from packages
$referencedIds = $this->collectReferencedInsuranceIds($xmlContent);
// Parse individual insurances with conditional filtering
// Second pass: Parse individual insurances with conditional filtering
$individualInsurances = [];
$xmlContent->filterXPath('//versicherungen/versicherung')
->each(function (Crawler $node) use (&$insurances, $referencedIds) {
->each(function (Crawler $node) use (&$individualInsurances, &$insurances, $referencedIds) {
$id = (int) $node->attr('idbuspro'); // Individual insurances have int IDs
$isZusatz = $this->getBoolAttributeValue($node->attr('zusatzversicherung'));
$isAdditional = $this->getBoolAttributeValue($node->attr('zusatzversicherung'));
// Include if: not zusatzversicherung OR referenced by package
if (!$isZusatz || in_array($id, $referencedIds, true)) {
$insurance = $this->parseInsuranceNode($node, false);
if (null !== $insurance && null !== $insurance->id) {
// Parse all individual insurances for reference lookup
$insurance = $this->parseInsuranceNode($node, false);
if (null !== $insurance && null !== $insurance->id) {
$individualInsurances[$insurance->id] = $insurance;
// Include if: not additional insurance OR referenced by package
if (!$isAdditional || in_array($id, $referencedIds, true)) {
$insurances[$insurance->id] = $insurance;
}
}
});
// Parse packages (no filtering needed)
// Third pass: Parse packages with family detection based on contained insurances
$xmlContent->filterXPath('//versicherungspakete/versicherungspaket')
->each(function (Crawler $node) use (&$insurances) {
$insurance = $this->parseInsuranceNode($node, true);
->each(function (Crawler $node) use (&$insurances, $individualInsurances) {
$insurance = $this->parseInsuranceNode($node, true, $individualInsurances);
if (null !== $insurance && null !== $insurance->id) {
// Parse contained insurance IDs
$insurance->containedInsuranceIds = $this->parseContainedInsuranceIds($node);
@@ -57,14 +62,37 @@ class InsuranceParser extends AbstractParser
return $insurances;
}
/**
* Determines if a package contains any family insurances.
*
* @param Crawler $packageNode The package XML node
* @param array<int, Insurance> $individualInsurances Parsed individual insurances for reference
*
* @return bool True if any contained insurance is a family insurance
*/
private function isPackageFamilyInsurance(Crawler $packageNode, array $individualInsurances): bool
{
// Check if any contained insurance is a family insurance
$containedInsuranceIds = $this->parseContainedInsuranceIds($packageNode);
foreach ($containedInsuranceIds as $containedId) {
if (isset($individualInsurances[$containedId]) && true === $individualInsurances[$containedId]->familyInsurance) {
return true;
}
}
return false;
}
/**
* Parses a single insurance or package node.
*
* @param Crawler $node The XML node to parse
* @param bool $isPackage Whether this is a package node
* @param Crawler $node The XML node to parse
* @param bool $isPackage Whether this is a package node
* @param array<int, Insurance> $individualInsurances Individual insurances for package family detection
*
* @return Insurance|null The parsed insurance object
*/
private function parseInsuranceNode(Crawler $node, bool $isPackage): ?Insurance
private function parseInsuranceNode(Crawler $node, bool $isPackage, array $individualInsurances = []): ?Insurance
{
$insurance = new Insurance();
$insurance->package = $isPackage;
@@ -79,6 +107,11 @@ class InsuranceParser extends AbstractParser
$this->stringToFloat($node->attr('preis')) : null;
$insurance->familyInsurance = $this->stringToBool($node->attr('familienversicherung'));
// For packages, check if any contained insurances are family insurances
if ($isPackage && !$insurance->familyInsurance && !empty($individualInsurances)) {
$insurance->familyInsurance = $this->isPackageFamilyInsurance($node, $individualInsurances);
}
// Date constraints
$insurance->travelDateFrom = $node->attr('reisedatumvon') ?
$this->stringToDate($node->attr('reisedatumvon')) : null;
@@ -115,6 +148,7 @@ class InsuranceParser extends AbstractParser
* Collects all insurance IDs referenced by packages.
*
* @param Crawler $xmlContent The XML content to scan
*
* @return array<int> Array of referenced insurance IDs
*/
private function collectReferencedInsuranceIds(Crawler $xmlContent): array
@@ -135,6 +169,7 @@ class InsuranceParser extends AbstractParser
* Parses contained insurance IDs from a package node.
*
* @param Crawler $node The package XML node
*
* @return array<int> Array of contained insurance IDs (always int, as they reference individual insurances)
*/
private function parseContainedInsuranceIds(Crawler $node): array
@@ -152,4 +187,4 @@ class InsuranceParser extends AbstractParser
{
return !empty($value) && $this->stringToBool($value);
}
}
}