Busflow Docs

Internal documentation portal

Skip to content

ADR-010: Input/Output Value Object Separation (PricingRule β†’ AppliedCondition) ​

Status: βœ… Approved β€” 2026-04-10 Origin: Kalkulations-Engine ProtocolImpacts: PRODUCT_domain-model.md Β§Embedded Value Objects, schema-backoffice.md Β§price_matrices


Context ​

The domain model defined a PricingCondition VO embedded in PriceMatrix.variants[]. This VO attempted to serve two incompatible purposes:

  1. Input β€” defining what pricing rules exist (demographics, seasons, early-bird tiers)
  2. Output β€” recording how the engine applied those rules to produce a specific variant's price

The result was three vague fields (type, value, validity_period) with no enums, no format contract, and no clear semantics. A coding agent reading PricingCondition cannot determine whether they are looking at a rule template or a resolved computation result.

Meanwhile, PricingRule (the input VO on TourTemplate) already had a well-specified design. Season and early-bird rules had no dedicated input VO at all β€” they implicitly lived in an undefined pricing configuration.

Decision ​

1. Retire PricingCondition ​

This ADR removes the PricingCondition VO from the domain model and replaces it with AppliedCondition, a pure output VO that records the audit trail of each computation step.

2. Input VOs (templates β€” what rules exist) ​

VOEmbedded InPurpose
PricingRuleTourTemplate.pricing_rules[]Demographic discounts (operator-defined segments with percentage/absolute adjustments). Unchanged.
SeasonConfigTourTemplate.pricing_configSeasonal tier definitions (key, label, date periods, absolute surcharge). New.
EarlyBirdTierTourTemplate.pricing_configEarly-bird stepped discount tiers (key, label, day-range boundaries, percentage discount). New.
PricingConfigTourTemplate.pricing_configContainer VO: room_surcharge, includes_accommodation, season_config[], early_bird_config[]. New.

3. Output VO (resolved β€” what the engine applied) ​

VOEmbedded InPurpose
AppliedConditionPriceMatrix.variants[].applied_conditions[]Per-step audit record: condition type, label, adjustment method, configured value, applied amount, running gross, validity window.

AppliedCondition uses a fixed enum: DEMOGRAPHIC_DISCOUNT | ROOM_SURCHARGE | SEASON_SURCHARGE | EARLY_BIRD_DISCOUNT, applied in this exact priority order.

4. Naming Convention ​

  • Input VOs use domain-noun names: PricingRule, SeasonConfig, EarlyBirdTier, PricingConfig
  • Output VOs use past-participle names: AppliedCondition

This convention makes the read direction unambiguous: if it has "Applied" or "Resolved" in the name, it is engine output.

Consequences ​

Positive:

  • Clean separation of template (mutable, editable) from computation result (immutable, auditable)
  • Each VO has a single responsibility β€” no more overloaded fields
  • New input VOs (SeasonConfig, EarlyBirdTier, PricingConfig) fill specification gaps that blocked implementation
  • AppliedCondition provides a full derivation chain for dispatcher transparency

Negative:

  • Maintainers must update or remove PricingCondition references in any existing documentation
  • More VOs to maintain (4 input + 1 output vs. the previous 2)

Neutral:

  • PricingRule stays the same β€” no migration impact for demographic rules

Internal documentation β€” Busflow