Concept: Compliance Rule Engine β
Status: Idea / Future Feature (Phase 2+)
Problem Statement β
Bus operators in the DACH region operate under strict consumer protection laws, primarily the BGB (BΓΌrgerliches Gesetzbuch) for German package tours (Pauschalreisen) and the PAngV (Preisangabenverordnung).
Currently, the Busflow platform enforces safety through hardcoded defaults (e.g., a system default deposit of 20% to comply with Β§ 651a BGB). However, operators can override these defaults per template or per tenant. If an operator sets a deposit of 50% without a valid legal justification, the platform silently processes it, exposing the operator to Abmahnungen (legal warnings) from consumer protection agencies.
Proposed Solution β
Introduce a Compliance Rule Engine that validates operator configurations against known legal boundaries and surfaces non-blocking π‘ Warnings or blocking π΄ Errors in the Backoffice UI.
Rules must be jurisdiction-localizable: Busflow should not bake German law into the product as the only truth. Legal thresholds, required documents, checkout disclosures, tax handling, and enforcement severity should be configurable by country and legal regime, resolved from the operator's country plus per-tour context when needed. The German BGB/PAngV rules below are the first jurisdiction profile, not the global model.
This may force a rule engine earlier than the phase label suggests. International trips can cross multiple legal contexts in one itinerary, so compliance may depend on route countries, sales country, operator country, destination country, and passenger-facing checkout obligations rather than a single tenant-wide default.
Identified Rules (Initial Set) β
Maximum Deposit (Anzahlung):
- Rule: Under German law, advance payments usually cannot exceed 20% of the travel price.
- Trigger: If
deposit_config.percentage > 20. - Action: Show π‘ Warning in the TourTemplate editor: "A deposit exceeding 20% may violate Β§ 651a BGB unless specific high advance costs (e.g., flights) justify it."
Final Payment Timing (Restzahlung):
- Rule: Final payments generally cannot be demanded earlier than 28-30 days before departure (unless the Sicherungsschein has been provided).
- Trigger: If
final_payment_config.reminder_days_before_start > 30. - Action: Show π‘ Warning: "Requesting final payment earlier than 30 days before departure may be legally contestable."
Fee Pass-Through Disclosure (PAngV):
- Rule: If the operator enables the "Fee Pass-Through" option (shifting the platform booking fee to the passenger), this surcharge must be explicitly declared before checkout.
- Trigger: If
fee_pass_through = true. - Action: Show βΉοΈ Info: "Ensure your AGBs reflect this surcharge. The booking widget will automatically display this as an explicit line item to comply with PAngV."
Sicherungsschein Requirement:
- Rule: If a trip is marked as a package tour (
is_pauschalreise = true), a Sicherungsschein must be provided if the deposit exceeds 20% or final payment is collected before the trip ends. - Trigger: If
is_pauschalreise = trueANDoperator_settings.sicherungsschein_url IS NULL. - Action: Show π΄ Error: "Cannot publish a Pauschalreise without a configured insolvency insurance certificate (Sicherungsschein)."
- Rule: If a trip is marked as a package tour (
Implementation Architecture β
- Stateless Validation: The rule engine should run as a stateless utility service within the NestJS backend, evaluating the
TourTemplateandOperatorSettingsJSONB payloads duringUPDATEmutations. - Jurisdiction Profiles: Rule definitions should be versioned and scoped by jurisdiction (e.g.,
DE,AT,CH,EU) so country-specific legal defaults can evolve independently without changing business workflows or historical audit snapshots. International trips should be able to compose multiple applicable profiles from the itinerary and sales context. - UI Bubbling: The GraphQL mutations should return an
warningsarray alongside the mutated entity, which the Quasar frontend displays as inline alerts within the configuration forms.