Rounding on payment method change

This commit is contained in:
Raphael Michel
2025-08-12 13:04:44 +02:00
parent 00734f8972
commit e37724ab8b
2 changed files with 30 additions and 5 deletions

View File

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

View File

@@ -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'],
)