fix: offer/auction cart charges agreed price, not list price
total_discounted_price_in_cents summed line items and ignored the cart_offer / cart_auction override. is_discounted then reported True (agreed ≠ list), so total_in_cents — what the charge path reads — returned the list price. UI strikethroughed the agreed price and charged the list price. Short-circuit the discounted path on override, the same way total_price_in_cents does. An offer/auction is a negotiated price, not a discount, so coupons and gift-card balances do not stack on top of it. Extended both override tests to assert total_in_cents, total_discounted_price_in_cents, and is_discounted — the gap that let this ship.
This commit is contained in:
parent
6119489c40
commit
c58b6b27a7
2 changed files with 24 additions and 0 deletions
|
|
@ -395,7 +395,18 @@ class Cart(RBase, Base):
|
|||
def total_discounted_price_in_cents(self):
|
||||
"""
|
||||
Calculate the total discounted price in cents, including handling cost and gift card purchases.
|
||||
MPS-20 + MPS-21: an auction-won or offer-accepted cart pays the
|
||||
agreed amount; coupons and gift-card balances do not stack on top
|
||||
of a negotiated price.
|
||||
"""
|
||||
override = self.auction_offer_override_in_cents
|
||||
if override is not None:
|
||||
total = override
|
||||
total += self.gift_card_purchases_total_in_cents
|
||||
if self.handling_cost_in_cents:
|
||||
total += self.handling_cost_in_cents
|
||||
return total
|
||||
|
||||
total = sum(self.discounted_shop_totals_in_cents.values())
|
||||
total += self.gift_card_purchases_total_in_cents
|
||||
if self.handling_cost_in_cents:
|
||||
|
|
|
|||
|
|
@ -4942,6 +4942,12 @@ class TestCartTotalOverride(DatabaseIntegrationTests):
|
|||
# Override: $42 not $100.
|
||||
self.assertEqual(cart.auction_offer_override_in_cents, 4200)
|
||||
self.assertEqual(cart.total_price_in_cents, 4200)
|
||||
# The charge path (total_in_cents) and the discounted path must
|
||||
# both honor the override — otherwise the cart strikethroughs the
|
||||
# agreed price and charges the list price.
|
||||
self.assertEqual(cart.total_discounted_price_in_cents, 4200)
|
||||
self.assertEqual(cart.total_in_cents, 4200)
|
||||
self.assertFalse(cart.is_discounted)
|
||||
|
||||
def test_offer_override_uses_current_amount(self):
|
||||
from ..models.cart import Cart
|
||||
|
|
@ -4974,6 +4980,13 @@ class TestCartTotalOverride(DatabaseIntegrationTests):
|
|||
# Override: $80 not $100.
|
||||
self.assertEqual(cart.auction_offer_override_in_cents, 8000)
|
||||
self.assertEqual(cart.total_price_in_cents, 8000)
|
||||
# Cart logic was built for coupons (a discount on top of list
|
||||
# price). Offers are a negotiated price, not a discount — both
|
||||
# totals must agree, so is_discounted is False and the buyer is
|
||||
# charged the offer amount, not the list price.
|
||||
self.assertEqual(cart.total_discounted_price_in_cents, 8000)
|
||||
self.assertEqual(cart.total_in_cents, 8000)
|
||||
self.assertFalse(cart.is_discounted)
|
||||
|
||||
|
||||
class TestAuctionTickIntegration(DatabaseIntegrationTests):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue