Add codification of tax rates (#4372)

* draft

* .

* Rebase migration

* Update src/pretix/base/models/tax.py

Co-authored-by: Mira <weller@rami.io>

* Test, isort, flake, migration rebase

* carry data & API

* Fix failing tests

* docs fixes

* Improve validation

* Tests

* More fixes

---------

Co-authored-by: Mira <weller@rami.io>
This commit is contained in:
Raphael Michel
2024-12-13 12:04:38 +01:00
committed by GitHub
parent a4385c8b6e
commit 53f129d5d3
36 changed files with 818 additions and 124 deletions

View File

@@ -1513,6 +1513,7 @@ def get_fees(event, request, total, invoice_address, payments, positions):
value=payment_fee,
tax_rate=payment_fee_tax.rate,
tax_value=payment_fee_tax.tax,
tax_code=payment_fee_tax.code,
tax_rule=payment_fee_tax_rule
))

View File

@@ -271,7 +271,9 @@ def build_invoice(invoice: Invoice) -> Invoice:
event_date_from=p.subevent.date_from if invoice.event.has_subevents else invoice.event.date_from,
event_date_to=p.subevent.date_to if invoice.event.has_subevents else invoice.event.date_to,
event_location=location if invoice.event.settings.invoice_event_location else None,
tax_rate=p.tax_rate, tax_name=p.tax_rule.name if p.tax_rule else ''
tax_rate=p.tax_rate,
tax_code=p.tax_code,
tax_name=p.tax_rule.name if p.tax_rule else ''
)
if p.tax_rule and p.tax_rule.is_reverse_charge(ia) and p.price and not p.tax_value:
@@ -305,6 +307,7 @@ def build_invoice(invoice: Invoice) -> Invoice:
),
tax_value=fee.tax_value,
tax_rate=fee.tax_rate,
tax_code=fee.tax_code,
tax_name=fee.tax_rule.name if fee.tax_rule else '',
fee_type=fee.fee_type,
fee_internal_type=fee.internal_type or None,
@@ -491,13 +494,13 @@ def build_preview_invoice_pdf(event):
InvoiceLine.objects.create(
invoice=invoice, description=_("Sample product {}").format(i + 1),
gross_value=tax.gross, tax_value=tax.tax,
tax_rate=tax.rate, tax_name=tax.name
tax_rate=tax.rate, tax_name=tax.name, tax_code=tax.code,
)
else:
for i in range(5):
InvoiceLine.objects.create(
invoice=invoice, description=_("Sample product A"),
gross_value=100, tax_value=0, tax_rate=0
gross_value=100, tax_value=0, tax_rate=0, tax_code=None,
)
return event.invoice_renderer.generate(invoice)

View File

@@ -1721,16 +1721,17 @@ class OrderChangeManager:
try:
new_rate = tax_rule.tax_rate_for(ia)
new_code = tax_rule.tax_code_for(ia)
except TaxRule.SaleNotAllowed:
raise OrderError(error_messages['tax_rule_country_blocked'])
# We use override_tax_rate to make sure .tax() doesn't get clever and re-adjusts the pricing itself
if new_rate != pos.tax_rate:
if new_rate != pos.tax_rate or new_code != pos.tax_code:
if keep == 'net':
new_tax = tax_rule.tax(pos.price - pos.tax_value, base_price_is='net', currency=self.event.currency,
override_tax_rate=new_rate)
override_tax_rate=new_rate, override_tax_code=new_code)
else:
new_tax = tax_rule.tax(pos.price, base_price_is='gross', currency=self.event.currency,
override_tax_rate=new_rate)
override_tax_rate=new_rate, override_tax_code=new_code)
self._totaldiff += new_tax.gross - pos.price
self._operations.append(self.PriceOperation(pos, new_tax, new_tax.gross - pos.price))
self._invoice_dirty = True
@@ -2304,6 +2305,7 @@ class OrderChangeManager:
op.position.price = op.price.gross
op.position.tax_rate = op.price.rate
op.position.tax_value = op.price.tax
op.position.tax_code = op.price.code
op.position.save()
elif isinstance(op, self.TaxRuleOperation):
if isinstance(op.position, OrderPosition):
@@ -2400,7 +2402,7 @@ class OrderChangeManager:
elif isinstance(op, self.AddOperation):
pos = OrderPosition.objects.create(
item=op.item, variation=op.variation, addon_to=op.addon_to,
price=op.price.gross, order=self.order, tax_rate=op.price.rate,
price=op.price.gross, order=self.order, tax_rate=op.price.rate, tax_code=op.price.code,
tax_value=op.price.tax, tax_rule=op.item.tax_rule,
positionid=nextposid, subevent=op.subevent, seat=op.seat,
used_membership=op.membership, valid_from=op.valid_from, valid_until=op.valid_until,

View File

@@ -91,9 +91,11 @@ def get_price(item: Item, variation: ItemVariation = None,
if custom_price_is_net:
price = tax_rule.tax(max(custom_price, price.net), base_price_is='net', override_tax_rate=price.rate,
override_tax_code=price.code,
invoice_address=invoice_address, subtract_from_gross=bundled_sum)
else:
price = tax_rule.tax(max(custom_price, price.gross), base_price_is='gross', override_tax_rate=price.rate,
override_tax_code=price.code,
invoice_address=invoice_address, subtract_from_gross=bundled_sum)
else:
price = tax_rule.tax(price, invoice_address=invoice_address, subtract_from_gross=bundled_sum)
@@ -146,10 +148,12 @@ def get_line_price(price_after_voucher: Decimal, custom_price_input: Decimal, cu
if custom_price_input_is_net:
price = tax_rule.tax(max(custom_price_input, price.net), base_price_is='net', override_tax_rate=price.rate,
invoice_address=invoice_address, subtract_from_gross=bundled_sum)
override_tax_code=price.code, invoice_address=invoice_address,
subtract_from_gross=bundled_sum)
else:
price = tax_rule.tax(max(custom_price_input, price.gross), base_price_is='gross', override_tax_rate=price.rate,
invoice_address=invoice_address, subtract_from_gross=bundled_sum)
override_tax_code=price.code, invoice_address=invoice_address,
subtract_from_gross=bundled_sum)
else:
price = tax_rule.tax(price_after_voucher, invoice_address=invoice_address, subtract_from_gross=bundled_sum,
base_price_is='gross' if is_bundled else 'auto')