mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
Add support for custom taxation rules
This commit is contained in:
387
src/tests/base/test_taxrules.py
Normal file
387
src/tests/base/test_taxrules.py
Normal file
@@ -0,0 +1,387 @@
|
||||
import json
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from django.utils.timezone import now
|
||||
from django_countries.fields import Country
|
||||
|
||||
from pretix.base.models import Event, InvoiceAddress, Organizer, TaxRule
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def event():
|
||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
event = Event.objects.create(
|
||||
organizer=o, name='Dummy', slug='dummy',
|
||||
date_from=now()
|
||||
)
|
||||
return event
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_from_gross_price(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=True
|
||||
)
|
||||
tp = tr.tax(Decimal('100.00'))
|
||||
assert tp.gross == Decimal('100')
|
||||
assert tp.net == Decimal('90.91')
|
||||
assert tp.tax == Decimal('100.00') - Decimal('90.91')
|
||||
assert tp.rate == Decimal('10.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_from_net_price(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
tp = tr.tax(Decimal('100.00'))
|
||||
assert tp.gross == Decimal('110.00')
|
||||
assert tp.net == Decimal('100.00')
|
||||
assert tp.tax == Decimal('10.00')
|
||||
assert tp.rate == Decimal('10.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_no_address(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True,
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
assert not tr.is_reverse_charge(None)
|
||||
assert tr.tax_applicable(None)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_no_country(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True,
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_individual_same_country(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=False,
|
||||
country=Country('DE')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_individual_eu(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=False,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_individual_3rdc(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=False,
|
||||
country=Country('US')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_business_same_country(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('DE')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_business_eu(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_business_3rdc(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('US')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_valid_vat_id_business_same_country(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('DE'),
|
||||
vat_id='DE123456',
|
||||
vat_id_validated=True
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_valid_vat_id_business_eu(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
vat_id='AT12346',
|
||||
vat_id_validated=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_valid_vat_id_business_3rdc(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('US'),
|
||||
vat_id='US12346',
|
||||
vat_id_validated=True
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_disabled(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=False, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
vat_id='AT12346',
|
||||
vat_id_validated=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_rules_override(event):
|
||||
tr = TaxRule(
|
||||
event=event, eu_reverse_charge=True, home_country=Country('DE'),
|
||||
rate=Decimal('10.00'), price_includes_tax=False,
|
||||
custom_rules=json.dumps([
|
||||
{'country': 'ZZ', 'address_type': '', 'action': 'vat'}
|
||||
])
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
vat_id='AT12346',
|
||||
vat_id_validated=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_rules_in_order(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=False,
|
||||
custom_rules=json.dumps([
|
||||
{'country': 'ZZ', 'address_type': '', 'action': 'vat'},
|
||||
{'country': 'ZZ', 'address_type': '', 'action': 'reverse'}
|
||||
])
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
vat_id='AT12346',
|
||||
vat_id_validated=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_rules_any_country(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=False,
|
||||
custom_rules=json.dumps([
|
||||
{'country': 'ZZ', 'address_type': '', 'action': 'no'},
|
||||
])
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_rules_eu_country(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=False,
|
||||
custom_rules=json.dumps([
|
||||
{'country': 'EU', 'address_type': '', 'action': 'no'},
|
||||
])
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('US')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_rules_specific_country(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=False,
|
||||
custom_rules=json.dumps([
|
||||
{'country': 'AT', 'address_type': '', 'action': 'no'},
|
||||
])
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('DE')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_rules_individual(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=False,
|
||||
custom_rules=json.dumps([
|
||||
{'country': 'ZZ', 'address_type': 'individual', 'action': 'no'},
|
||||
])
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=False,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('DE')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_rules_business(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=False,
|
||||
custom_rules=json.dumps([
|
||||
{'country': 'ZZ', 'address_type': 'business', 'action': 'no'},
|
||||
])
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
ia = InvoiceAddress(
|
||||
is_business=False,
|
||||
country=Country('DE')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_custom_rules_vat_id(event):
|
||||
tr = TaxRule(
|
||||
event=event,
|
||||
rate=Decimal('10.00'), price_includes_tax=False,
|
||||
custom_rules=json.dumps([
|
||||
{'country': 'EU', 'address_type': 'business_vat_id', 'action': 'reverse'},
|
||||
])
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
assert not tr.is_reverse_charge(ia)
|
||||
assert tr.tax_applicable(ia)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True,
|
||||
country=Country('DE'),
|
||||
vat_id='DE1234',
|
||||
vat_id_validated=True
|
||||
)
|
||||
assert tr.is_reverse_charge(ia)
|
||||
assert not tr.tax_applicable(ia)
|
||||
Reference in New Issue
Block a user