fix: PayPal + Adyen checkout — drop bad quantity arg to cart.remove_product

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.
This commit is contained in:
russell@unturf.com 2026-05-15 06:46:34 -04:00
parent 31e06ffb0a
commit ef9146956d
No known key found for this signature in database

View file

@ -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: