-
Mahmoud Aglan authored
The terminal read products.selling_price and never called the pricing engine, so a product priced per membership type — a member rate and a walk-in rate, which is how base_prices has always modelled it — sold at whichever single number the catalogue carried. Members were charged the non-member price and nothing on the receipt showed it had happened. Every product line now comes from PricingService, which resolves the base price for THIS buyer and then applies the academy's rules to it. selling_price stays the fallback for a product nobody has priced through the engine: it is the price the catalogue advertises, and refusing the sale outright would close the shop over a configuration gap. Cashiers scan first and identify the customer afterwards at least as often as the other way round, so selecting or clearing a participant re-prices what is already in the cart, and the product grid shows that buyer's price with the list price struck through beside it — a rate the cashier cannot quote out loud is a rate that gets argued about at the counter. Checkout prices everything again before it believes any of it. The cart is a public Livewire property, so the unit prices arriving at checkout are whatever the browser last sent; if the engine's answer differs from what the cashier is looking at, the sale stops rather than charging a total nobody saw. Verified against a restored copy of the live tenant: with member/non-member base prices on a real product, member 900, non-member 1,200, walk-in 1,200, and a product with no base price falls back to its catalogue 8,000. Co-Authored-By:Claude Opus 5 (1M context) <noreply@anthropic.com>
55b03a06