From ef9146956dc83d6ab6e166f6e331eebc673ee00c Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Fri, 15 May 2026 06:46:34 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20PayPal=20+=20Adyen=20checkout=20?= =?UTF-8?q?=E2=80=94=20drop=20bad=20quantity=20arg=20to=20cart.remove=5Fpr?= =?UTF-8?q?oduct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the inner exception the tm.doom switch was meant to surface. The PayPal complete-checkout flash now reads: "Payment processing failed: Cart.remove_product() takes 2 positional arguments but 3 were given" Cart.remove_product(self, product) deletes the cart entry entirely; it doesn't take a quantity. Two callsites in cart.py were passing line_item.quantity as a second positional arg — both inside the post-payment "drain the cart" loop that runs AFTER PayPal capture succeeded: views/cart.py:1094 — paypal_complete_checkout views/cart.py:1345 — adyen_complete_checkout PayPal got the buyer's money, the capture API succeeded, then the cart-drain raised TypeError. Pre-tm.doom that bubbled into the except block, hit tm.abort, blew up pyramid_tm.tm_tween → uwsgi 500 → Caddy 502 — buyer charged, no invoice on our side. Drop the quantity arg. cart.remove_product deletes the cart entry unconditionally; the line item's full quantity is removed in one shot, which is what the post-checkout drain wants anyway. Stripe's user_cart_complete_checkout doesn't call remove_product at all (it relies on cart.update_inventory + a session-clear elsewhere) — that's why this only ever bit PayPal + Adyen. --- make_post_sell/views/cart.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/make_post_sell/views/cart.py b/make_post_sell/views/cart.py index 99115ca..8aea20a 100644 --- a/make_post_sell/views/cart.py +++ b/make_post_sell/views/cart.py @@ -1091,7 +1091,13 @@ def paypal_complete_checkout(request): for invoice in successful_invoices: for line_item in invoice.line_items: - cart.remove_product(line_item.product, line_item.quantity) + # remove_product takes (product,) — drops the cart + # entry entirely regardless of quantity. A previous + # pair passed quantity as a second arg and was + # raising TypeError "takes 2 positional arguments + # but 3 were given" — which silently 502'd via the + # pyramid_tm tm.abort path until tm.doom landed. + cart.remove_product(line_item.product) cart.update_inventory(request.shop_location) for invoice in successful_invoices: @@ -1342,7 +1348,13 @@ def adyen_complete_checkout(request): for invoice in successful_invoices: for line_item in invoice.line_items: - cart.remove_product(line_item.product, line_item.quantity) + # remove_product takes (product,) — drops the cart + # entry entirely regardless of quantity. A previous + # pair passed quantity as a second arg and was + # raising TypeError "takes 2 positional arguments + # but 3 were given" — which silently 502'd via the + # pyramid_tm tm.abort path until tm.doom landed. + cart.remove_product(line_item.product) cart.update_inventory(request.shop_location) for invoice in successful_invoices: