Skip to content

Recalculate open checkouts when a discount's amounts/currency change #13208

Description

@stilla

DiscountFixed.get_discount_amount does a direct self.amounts[currency] lookup with no fallback. If a merchant edits a DiscountFixed discount (e.g. via DiscountService.update, especially through the legacy amount+currency fields, which replaces the whole amounts map) while an open, unconfirmed checkout still references that discount and a now-removed currency, the checkout ends up in an inconsistent state. DiscountService.update() only blocks the edit when redemptions_count > 0, which doesn't cover this case. Reading the checkout afterwards (e.g. GET /v1/checkouts/client/{client_secret}) then serializes discount_amount and crashes with an unhandled KeyError.

Example: SERVER-4VF, checkout 7e54d8a5-f92c-423e-aaf9-d04a9b48afd5, KeyError: 'czk'.

Instead of only guarding against the edit or patching the read path, DiscountService.update() should proactively reconcile any open checkouts referencing the discount when amounts/currency change: re-run the existing is_applicable(product, currency) check for each affected open checkout and, when it no longer holds, null out the checkout's discount and recompute its totals (net_amount, tax_amount, etc.) the same way _update_checkout already does. This keeps checkouts consistent immediately after the discount edit rather than deferring to (or crashing on) the next checkout read/update.

Related prior art: #13140 fixed the same underlying amounts[currency] indexing issue for the subscription resolve path only (feedback#171); #12339 fixed a similar currency-mismatch crash in checkout product/price updates. Neither covers a discount being edited out from under an already-open checkout.

Sent by @frankie567 from Stilla investigation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions