From e37724ab8ba303ef738e57741f17e6ca810d8056 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Tue, 12 Aug 2025 13:04:44 +0200 Subject: [PATCH] Rounding on payment method change --- src/pretix/base/services/orders.py | 30 ++++++++++++++++++++++++++++-- src/pretix/presale/checkoutflow.py | 5 ++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index d1f89a99dd..b9a92bbfde 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -3146,6 +3146,7 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay raise Exception('change_payment_provider should only be called in atomic transaction!') oldtotal = order.total + already_paid = order.payment_refund_sum e = OrderPayment.objects.filter(fee=OuterRef('pk'), state__in=(OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED)) open_fees = list( @@ -3162,19 +3163,44 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay fee = OrderFee(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.00'), order=order) old_fee = fee.value + positions = list(order.positions.all()) + fees = list(order.fees.all()) + rounding_changed = set(apply_rounding( + order.tax_rounding_mode, order.event.currency, [*positions, *[f for f in fees if f.pk != fee.pk]] + )) + total_without_fee = sum(c.price for c in positions) + sum(f.value for f in fees if f.pk != fee.pk) + pending_sum_without_fee = max(Decimal("0.00"), total_without_fee - already_paid) + new_fee = payment_provider.calculate_fee( - order.pending_sum - old_fee if amount is None else amount + pending_sum_without_fee if amount is None else amount ) if new_fee: fee.value = new_fee fee.internal_type = payment_provider.identifier fee._calculate_tax() + if not fee.pk: + fees.append(fee) fee.save() else: if fee.pk: fee.delete() + if fee in fees: + fees.remove(fee) fee = None + rounding_changed |= set(apply_rounding( + order.tax_rounding_mode, order.event.currency, [*positions, *fees] + )) + for l in rounding_changed: + if isinstance(l, OrderPosition): + l.save(update_fields=[ + "price", "price_includes_rounding_correction", "tax_value", "tax_value_includes_rounding_correction" + ]) + elif isinstance(l, OrderFee): + l.save(update_fields=[ + "value", "value_includes_rounding_correction", "tax_value", "tax_value_includes_rounding_correction" + ]) + open_payment = None if new_payment: lp = order.payments.select_for_update(of=OF_SELF).exclude(pk=new_payment.pk).last() @@ -3201,7 +3227,7 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay }, ) - order.total = (order.positions.aggregate(sum=Sum('price'))['sum'] or 0) + (order.fees.aggregate(sum=Sum('value'))['sum'] or 0) + order.total = sum(c.price for c in positions) + sum(f.value for f in fees) order.save(update_fields=['total']) if not new_payment: diff --git a/src/pretix/presale/checkoutflow.py b/src/pretix/presale/checkoutflow.py index f51354af95..3898045603 100644 --- a/src/pretix/presale/checkoutflow.py +++ b/src/pretix/presale/checkoutflow.py @@ -1388,7 +1388,7 @@ class PaymentStep(CartMixin, TemplateFlowStep): ctx['cart'] = self.get_cart() ctx['current_payments'] = [ p for p in self.current_selected_payments( - ctx['cart']['positions'], ctx['cart']['fees'], ctx['cart']['invoice_address'], + ctx['cart']['raw'], ctx['cart']['fees'], ctx['cart']['invoice_address'], ) if p.get('multi_use_supported') ] @@ -1430,7 +1430,6 @@ class PaymentStep(CartMixin, TemplateFlowStep): total = sum([c.price for c in cart]) + sum([f.value for f in fees]) selected = self.current_selected_payments(cart, fees, self.invoice_address, warn=warn) - print(sum(p['payment_amount'] for p in selected), total) if sum(p['payment_amount'] for p in selected) != total: if warn: messages.error(request, _('Please select a payment method to proceed.')) @@ -1515,7 +1514,7 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep): ctx['cart'] = self.get_cart(answers=True) selected_payments = self.current_selected_payments( - ctx['cart']['positions'], + ctx['cart']['raw'], ctx['cart']['fees'], ctx['cart']['invoice_address'], )