forked from CGM_Public/pretix_original
Tax rounding: Allow to apply only for B2B (Z#23220106) (#5810)
* Tax rounding: Allow to apply only for B2B (Z#23220106) Most effective in combination with #5807 * Update src/pretix/base/settings.py Co-authored-by: Richard Schreiber <schreiber@pretix.eu> --------- Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
This commit is contained in:
@@ -1639,7 +1639,7 @@ def get_fees(event, request, _total_ignored_=None, invoice_address=None, payment
|
||||
if fee.tax_rule and not fee.tax_rule.pk:
|
||||
fee.tax_rule = None # TODO: deprecate
|
||||
|
||||
apply_rounding(event.settings.tax_rounding, event.currency, [*positions, *fees])
|
||||
apply_rounding(event.settings.tax_rounding, invoice_address, event.currency, [*positions, *fees])
|
||||
total = sum([c.price for c in positions]) + sum([f.value for f in fees])
|
||||
|
||||
if total != 0 and payments:
|
||||
@@ -1679,7 +1679,7 @@ def get_fees(event, request, _total_ignored_=None, invoice_address=None, payment
|
||||
fees.append(pf)
|
||||
|
||||
# Re-apply rounding as grand total has changed
|
||||
apply_rounding(event.settings.tax_rounding, event.currency, [*positions, *fees])
|
||||
apply_rounding(event.settings.tax_rounding, invoice_address, event.currency, [*positions, *fees])
|
||||
total = sum([c.price for c in positions]) + sum([f.value for f in fees])
|
||||
|
||||
# Re-calculate to_pay as grand total has changed
|
||||
|
||||
@@ -955,7 +955,7 @@ def _apply_rounding_and_fees(positions: List[CartPosition], payment_requests: Li
|
||||
fee.tax_rule = None # TODO: deprecate
|
||||
|
||||
# Apply rounding to get final total in case no payment fees will be added
|
||||
apply_rounding(event.settings.tax_rounding, event.currency, [*positions, *fees])
|
||||
apply_rounding(event.settings.tax_rounding, address, event.currency, [*positions, *fees])
|
||||
total = sum([c.price for c in positions]) + sum([f.value for f in fees])
|
||||
|
||||
payments_assigned = Decimal("0.00")
|
||||
@@ -982,7 +982,7 @@ def _apply_rounding_and_fees(positions: List[CartPosition], payment_requests: Li
|
||||
p['fee'] = pf
|
||||
|
||||
# Re-apply rounding as grand total has changed
|
||||
apply_rounding(event.settings.tax_rounding, event.currency, [*positions, *fees])
|
||||
apply_rounding(event.settings.tax_rounding, address, event.currency, [*positions, *fees])
|
||||
total = sum([c.price for c in positions]) + sum([f.value for f in fees])
|
||||
|
||||
# Re-calculate to_pay as grand total has changed
|
||||
@@ -1610,6 +1610,7 @@ class OrderChangeManager:
|
||||
ChangeValidUntilOperation = namedtuple('ChangeValidUntilOperation', ('position', 'valid_until'))
|
||||
AddBlockOperation = namedtuple('AddBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||
RemoveBlockOperation = namedtuple('RemoveBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||
ForceRecomputeOperation = namedtuple('ForceRecomputeOperation', tuple())
|
||||
|
||||
class AddPositionResult:
|
||||
_position: Optional[OrderPosition]
|
||||
@@ -1773,6 +1774,7 @@ class OrderChangeManager:
|
||||
positions = self.order.positions.select_related('item', 'item__tax_rule')
|
||||
ia = self._invoice_address
|
||||
tax_rules = self._current_tax_rules()
|
||||
self._operations.append(self.ForceRecomputeOperation())
|
||||
|
||||
for pos in positions:
|
||||
tax_rule = tax_rules.get(pos.pk, pos.tax_rule)
|
||||
@@ -2611,6 +2613,10 @@ class OrderChangeManager:
|
||||
except BlockedTicketSecret.DoesNotExist:
|
||||
pass
|
||||
# todo: revoke list handling
|
||||
elif isinstance(op, self.ForceRecomputeOperation):
|
||||
self.order.log_action('pretix.event.order.changed.recomputed', user=self.user, auth=self.auth, data={})
|
||||
else:
|
||||
raise TypeError(f"Unknown operation {type(op)}")
|
||||
|
||||
for p in secret_dirty:
|
||||
assign_ticket_secret(
|
||||
@@ -2665,7 +2671,10 @@ class OrderChangeManager:
|
||||
fees.append(new_fee)
|
||||
|
||||
changed_by_rounding = set(apply_rounding(
|
||||
self.order.tax_rounding_mode, self.event.currency, [p for p in split_positions if not p.canceled] + fees
|
||||
self.order.tax_rounding_mode,
|
||||
self._invoice_address,
|
||||
self.event.currency,
|
||||
[p for p in split_positions if not p.canceled] + fees
|
||||
))
|
||||
split_order.total = sum([p.price for p in split_positions if not p.canceled])
|
||||
|
||||
@@ -2687,7 +2696,10 @@ class OrderChangeManager:
|
||||
fee.delete()
|
||||
|
||||
changed_by_rounding |= set(apply_rounding(
|
||||
self.order.tax_rounding_mode, self.event.currency, [p for p in split_positions if not p.canceled] + fees
|
||||
self.order.tax_rounding_mode,
|
||||
self._invoice_address,
|
||||
self.event.currency,
|
||||
[p for p in split_positions if not p.canceled] + fees
|
||||
))
|
||||
split_order.total = sum([p.price for p in split_positions if not p.canceled]) + sum([f.value for f in fees])
|
||||
|
||||
@@ -2804,7 +2816,12 @@ class OrderChangeManager:
|
||||
if fee_changed:
|
||||
fees = list(self.order.fees.all())
|
||||
|
||||
changed = apply_rounding(self.order.tax_rounding_mode, self.order.event.currency, [*positions, *fees])
|
||||
changed = apply_rounding(
|
||||
self.order.tax_rounding_mode,
|
||||
self._invoice_address,
|
||||
self.order.event.currency,
|
||||
[*positions, *fees]
|
||||
)
|
||||
for l in changed:
|
||||
if isinstance(l, OrderPosition):
|
||||
l.save(update_fields=[
|
||||
@@ -3240,8 +3257,12 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay
|
||||
|
||||
positions = list(order.positions.all())
|
||||
fees = list(order.fees.all())
|
||||
try:
|
||||
ia = order.invoice_address
|
||||
except InvoiceAddress.DoesNotExist:
|
||||
ia = None
|
||||
rounding_changed = set(apply_rounding(
|
||||
order.tax_rounding_mode, order.event.currency, [*positions, *[f for f in fees if f.pk != fee.pk]]
|
||||
order.tax_rounding_mode, ia, 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)
|
||||
@@ -3266,7 +3287,7 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay
|
||||
fee = None
|
||||
|
||||
rounding_changed |= set(apply_rounding(
|
||||
order.tax_rounding_mode, order.event.currency, [*positions, *fees]
|
||||
order.tax_rounding_mode, ia, order.event.currency, [*positions, *fees]
|
||||
))
|
||||
for l in rounding_changed:
|
||||
if isinstance(l, OrderPosition):
|
||||
|
||||
@@ -211,7 +211,8 @@ def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
|
||||
return [new_prices.get(idx, (p[3], None)) for idx, p in enumerate(positions)]
|
||||
|
||||
|
||||
def apply_rounding(rounding_mode: Literal["line", "sum_by_net", "sum_by_net_keep_gross"], currency: str,
|
||||
def apply_rounding(rounding_mode: Literal["line", "sum_by_net", "sum_by_net_only_business", "sum_by_net_keep_gross"],
|
||||
invoice_address: Optional[InvoiceAddress], currency: str,
|
||||
lines: List[Union[OrderPosition, CartPosition, OrderFee]]) -> list:
|
||||
"""
|
||||
Given a list of order positions / cart positions / order fees (may be mixed), applies the given rounding mode
|
||||
@@ -226,11 +227,17 @@ def apply_rounding(rounding_mode: Literal["line", "sum_by_net", "sum_by_net_keep
|
||||
When rounding mode is set to ``"sum_by_net"``, the gross prices and tax values of the individual lines will be
|
||||
adjusted such that the per-taxrate/taxcode subtotal is rounded correctly. The net prices will stay constant.
|
||||
|
||||
:param rounding_mode: One of ``"line"``, ``"sum_by_net"``, or ``"sum_by_net_keep_gross"``.
|
||||
:param rounding_mode: One of ``"line"``, ``"sum_by_net"``, ``"sum_by_net_only_business"``, or ``"sum_by_net_keep_gross"``.
|
||||
:param invoice_address: The invoice address, or ``None``
|
||||
:param currency: Currency that will be used to determine rounding precision
|
||||
:param lines: List of order/cart contents
|
||||
:return: Collection of ``lines`` members that have been changed and may need to be persisted to the database.
|
||||
"""
|
||||
if rounding_mode == "sum_by_net_only_business":
|
||||
if invoice_address and invoice_address.is_business:
|
||||
rounding_mode = "sum_by_net"
|
||||
else:
|
||||
rounding_mode = "line"
|
||||
|
||||
def _key(line):
|
||||
return (line.tax_rate, line.tax_code or "")
|
||||
|
||||
Reference in New Issue
Block a user