Kaizen
Browse modulesPricingpricing/sharedTypes

Type Alias: BasePriceAction

type BasePriceAction = z.infer<typeof BasePriceAction>;

Defined in: shared/pricing/types/actions.ts:224

Establishes the starting price for a line item. Only legal in calculation_phase: "base" — PricingDomainConfig rejects this action type in any other phase at parse time. Greenfield consumers author one or more BASE_PRICE actions per priced line item so the rules engine is the single source of truth for pricing; legacy consumers may continue to provide base_price_cents on the LineItemContext directly and skip authoring base-phase rules entirely.

amount_cents is an integer for ergonomics — pricing arithmetic stays in whole cents until presentation, mirroring LineItemContext.base_price_cents.

unit carries the scaling unit alongside the amount so a base-phase rule fully specifies the price; downstream FEE / DISCOUNT actions with method: "percentage" then scale against the materialized subtotal without needing a separate unit on the line-item context.

per is the OPTIONAL second axis — the tier modal's "Duration" select (PLA-233 #2). With it, unit: "person", per: "hour" prices "per attendee per hour": the calculator multiplies the two resolved quantities (resolveQuantity in calculator.ts), so 2 attendees × 3 hours = 6. Omitting it keeps the single-axis behaviour PLA-276 established, which is why this is additive rather than a change in charged amounts for any existing rule.

Two constraints, both enforced here at parse time:

  1. per must be a duration (DurationPricingUnit), never a count.
  2. unit must be a count (PER_ELIGIBLE_UNITS) when per is set.

Together they make same-dimension multiplication unrepresentable: one axis is always a count, the other always a duration, and the two sets are disjoint.

Authoring per obliges the consumer's getQuantity to dispatch on its pricingUnit argument — the calculator calls the same resolver twice, once with unit and once with per. A resolver that ignores the argument and always returns the line's item count (a common shortcut, e.g. (line) => line.quantity) would square that count instead of multiplying by hours. getBookingQuantity dispatches correctly; check your own before authoring a per.