-
Mahmoud Aglan authored
Two bugs meant no pricing rule has ever applied correctly: 1. Condition keys never matched. The engine reads min/max/values; the wizard wrote min_age/min_children/target_gender and the form blade wrote a third set. Ranges saw null bounds and list rules saw an empty allow-list, both of which passed, so every rule applied to every participant. 2. Percentages were 100x too small. applyAdjustment divides by 10000 (basis points) but both screens stored a plain percent, so "20%" discounted 0.2%. They masked each other, which is why the symptom looked like a broken engine rather than two bugs — and why everyone moved to the untyped super-admin price override instead. Engine - ConditionSchema is now the single owner of the conditions vocabulary; builder, engine, simulator and migration all read keys from it. - Percent handles all basis-point conversion; nothing else touches the raw column. - evaluateInList fails closed instead of treating an empty allow-list as "match everyone". - custom rules no longer auto-apply; they are picker-only. - enrollment_timing honours days_before_start (fails closed without a program start date instead of silently passing). - Global discount cap reads system_settings rather than a hardcoded constant with a TODO. - New: explain(), audience(), wouldApply(), and role-capped manual discounts. Per-branch - pricing_rule_branches pivot so one rule targets many branches, instead of one near-identical row per branch that drifts apart. Stacking - is_stackable now defaults to false; best-of-one is the normal case and stacking is an explicit opt-in. Authoring - The five-step column editor becomes a recipe gallery plus an Arabic sentence, with a live simulator on a real participant and an audience count that warns when a rule would hit everyone. Saving a conditionless rule is refused. Checkout - ManagesDiscounts trait plus <x-pricing.discount-picker>: branch-scoped, searchable, pinned favourites, replace-vs-stack inline, blocked rows show why. Wired into CollectPaymentWizard renewals; discount names are frozen onto invoice.metadata so receipts survive later rule changes. - NewRegistrationWizard now prices through the engine using a provisional context built from the form, since the participant row does not exist yet. The step-4 guard still checks the base price, so a 100% discount is not mistaken for an unpriced program. Migration - Rewrites conditions onto the canonical keys and scales percentages to basis points. Rules whose conditions cannot be mapped confidently are deactivated rather than guessed, with the old JSON kept in metadata.legacy_conditions. Also fixes list and coupon views that rendered the raw column (a 20% rule would have displayed as 2000%), and adds the [x-cloak] CSS rule that was missing app-wide. Co-Authored-By:Claude Opus 5 (1M context) <noreply@anthropic.com>
b3f127c8
| Name |
Last commit
|
Last update |
|---|---|---|
| .. | ||
| app.blade.php | ||
| guest.blade.php | ||
| parent.blade.php | ||
| wizard.blade.php |