From 7dc82dda50c319be516c1923c1353de977d192ae Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Wed, 13 May 2026 10:09:16 -0400 Subject: [PATCH] fix: offer checkout is one-shot; seller copy says so MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two coupled fixes on the accepted-offer flow: 1. Single redemption. offer_checkout was creating a fresh cart on every POST. While offer.state == ACCEPTED, a buyer could spawn N parallel carts on one offer; mark_paid is idempotent on the offer but the *other* carts still carried the override and could each complete checkout, double-charging the buyer. Now: if any cart_offer already exists for the offer, reuse that cart (and re-activate it). Only one cart_offer row can ever exist per offer. 2. Seller copy on the "Awaiting payment" panel said "they need to sign in and pay from this same page — send them the link", which implied the seller had to manually deliver the link. The system already emails the buyer on accept (send_offer_accepted_email is wired in views/offer.py for both auto-accept and manual paths). The copy now reflects that: "We emailed them a one-time checkout link — this offer can be redeemed only once." The shareable link stays as a fallback for if the buyer asks for it again. Functional test test_offer_checkout_is_single_redemption asserts three consecutive POSTs to /o/{id}/checkout redirect to the same cart URL and produce exactly one cart_offer row. Existing test_accepted_offer_seller_sees_pay_link_to_share extended to assert the new copy ("emailed", "one-time checkout link"). --- make_post_sell/templates/offer.j2 | 3 ++- make_post_sell/tests/test_functional.py | 33 +++++++++++++++++++++++++ make_post_sell/views/offer.py | 32 +++++++++++++++++------- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/make_post_sell/templates/offer.j2 b/make_post_sell/templates/offer.j2 index 5ffa80e..cdd9cc1 100644 --- a/make_post_sell/templates/offer.j2 +++ b/make_post_sell/templates/offer.j2 @@ -110,7 +110,8 @@ {% elif request.user %}

Awaiting payment

-

You accepted {{ buyer_name }}’s offer at ${{ "%.2f"|format(current_amount) }}. They need to sign in and pay from this same page — send them the link:

+

You accepted {{ buyer_name }}’s offer at ${{ "%.2f"|format(current_amount) }}. We emailed them a one-time checkout link — this offer can be redeemed only once.

+

If they need it again, share this same page: