mirror of
https://github.com/pretix/pretix.git
synced 2026-05-04 15:04:03 +00:00
@@ -53,3 +53,8 @@ def subevent(event):
|
||||
event.save()
|
||||
return event.subevents.create(name="Foobar",
|
||||
date_from=datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def taxrule(event):
|
||||
return event.tax_rules.create(name="VAT", rate=19)
|
||||
|
||||
@@ -63,6 +63,7 @@ TEST_ITEM_RES = {
|
||||
"description": None,
|
||||
"free_price": False,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": None,
|
||||
"admission": False,
|
||||
"position": 0,
|
||||
"picture": None,
|
||||
|
||||
@@ -54,6 +54,7 @@ TEST_ORDERPOSITION_RES = {
|
||||
"voucher": None,
|
||||
"tax_rate": "0.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_rule": None,
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": None,
|
||||
"checkins": [],
|
||||
@@ -74,17 +75,20 @@ TEST_ORDER_RES = {
|
||||
"payment_fee": "0.00",
|
||||
"payment_fee_tax_rate": "0.00",
|
||||
"payment_fee_tax_value": "0.00",
|
||||
"payment_fee_tax_rule": None,
|
||||
"total": "23.00",
|
||||
"comment": "",
|
||||
"invoice_address": {
|
||||
"last_modified": "2017-12-01T10:00:00Z",
|
||||
"is_business": False,
|
||||
"company": "Sample company",
|
||||
"name": "",
|
||||
"street": "",
|
||||
"zipcode": "",
|
||||
"city": "",
|
||||
"country": "NZ",
|
||||
"vat_id": ""
|
||||
"vat_id": "",
|
||||
"vat_id_validated": False
|
||||
},
|
||||
"positions": [TEST_ORDERPOSITION_RES],
|
||||
"downloads": []
|
||||
@@ -268,11 +272,15 @@ TEST_INVOICE_RES = {
|
||||
"additional_text": "",
|
||||
"payment_provider_text": "",
|
||||
"footer_text": "",
|
||||
"foreign_currency_display": None,
|
||||
"foreign_currency_rate": None,
|
||||
"foreign_currency_rate_date": None,
|
||||
"lines": [
|
||||
{
|
||||
"description": "Budget Ticket",
|
||||
"gross_value": "23.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_name": "",
|
||||
"tax_rate": "0.00"
|
||||
}
|
||||
]
|
||||
|
||||
28
src/tests/api/test_taxrules.py
Normal file
28
src/tests/api/test_taxrules.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import pytest
|
||||
|
||||
TEST_TAXRULE_RES = {
|
||||
'name': {'en': 'VAT'},
|
||||
'rate': '19.00',
|
||||
'price_includes_tax': True,
|
||||
'eu_reverse_charge': False,
|
||||
'home_country': ''
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_rule_list(token_client, organizer, event, taxrule):
|
||||
res = dict(TEST_TAXRULE_RES)
|
||||
res["id"] = taxrule.pk
|
||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/taxrules/'.format(organizer.slug, event.slug))
|
||||
assert resp.status_code == 200
|
||||
assert [res] == resp.data['results']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_rule_detail(token_client, organizer, event, taxrule):
|
||||
res = dict(TEST_TAXRULE_RES)
|
||||
res["id"] = taxrule.pk
|
||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/taxrules/{}/'.format(organizer.slug, event.slug,
|
||||
taxrule.pk))
|
||||
assert resp.status_code == 200
|
||||
assert res == resp.data
|
||||
@@ -1,8 +1,10 @@
|
||||
from datetime import timedelta
|
||||
import json
|
||||
from datetime import date, timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from django.db import DatabaseError
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.db import DatabaseError, transaction
|
||||
from django.utils.timezone import now
|
||||
from django_countries.fields import Country
|
||||
|
||||
@@ -14,6 +16,8 @@ from pretix.base.services.invoices import (
|
||||
build_preview_invoice_pdf, generate_cancellation, generate_invoice,
|
||||
invoice_pdf_task, regenerate_invoice,
|
||||
)
|
||||
from pretix.base.services.orders import OrderChangeManager
|
||||
from pretix.base.settings import GlobalSettingsObject
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -23,19 +27,20 @@ def env():
|
||||
organizer=o, name='Dummy', slug='dummy',
|
||||
date_from=now(), plugins='pretix.plugins.banktransfer'
|
||||
)
|
||||
tr = event.tax_rules.create(rate=Decimal('19.00'))
|
||||
o = Order.objects.create(
|
||||
code='FOO', event=event, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PENDING,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=0, payment_provider='banktransfer',
|
||||
payment_fee=Decimal('0.25'), payment_fee_tax_rate=0,
|
||||
payment_fee_tax_value=0, locale='en'
|
||||
payment_fee=Decimal('0.25'), payment_fee_tax_rate=Decimal('19.00'),
|
||||
payment_fee_tax_value=Decimal('0.04'), locale='en', payment_fee_tax_rule=tr
|
||||
)
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket',
|
||||
category=None, default_price=23,
|
||||
category=None, default_price=23, tax_rule=tr,
|
||||
admission=True)
|
||||
t_shirt = Item.objects.create(event=event, name='T-Shirt',
|
||||
category=None, default_price=42,
|
||||
category=None, default_price=42, tax_rule=tr,
|
||||
admission=True)
|
||||
variation = ItemVariation.objects.create(value='M', item=t_shirt)
|
||||
OrderPosition.objects.create(
|
||||
@@ -52,6 +57,22 @@ def env():
|
||||
price=Decimal("42.00"),
|
||||
positionid=2,
|
||||
)
|
||||
gs = GlobalSettingsObject()
|
||||
gs.settings.ecb_rates_date = date.today()
|
||||
gs.settings.ecb_rates_dict = json.dumps({
|
||||
"USD": "1.1648",
|
||||
"RON": "4.5638",
|
||||
"CZK": "26.024",
|
||||
"BGN": "1.9558",
|
||||
"HRK": "7.4098",
|
||||
"EUR": "1.0000",
|
||||
"NOK": "9.3525",
|
||||
"HUF": "305.15",
|
||||
"DKK": "7.4361",
|
||||
"PLN": "4.2408",
|
||||
"GBP": "0.89350",
|
||||
"SEK": "9.5883"
|
||||
}, cls=DjangoJSONEncoder)
|
||||
return event, o
|
||||
|
||||
|
||||
@@ -116,6 +137,59 @@ def test_positions_skip_free(env):
|
||||
assert inv.lines.count() == 2
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_note(env):
|
||||
event, order = env
|
||||
|
||||
tr = event.tax_rules.first()
|
||||
tr.eu_reverse_charge = True
|
||||
tr.home_country = Country('DE')
|
||||
tr.save()
|
||||
|
||||
event.settings.set('invoice_language', 'en')
|
||||
InvoiceAddress.objects.create(company='Acme Company', street='221B Baker Street', zipcode='12345', city='Warsaw',
|
||||
country=Country('PL'), vat_id='PL123456780', vat_id_validated=True, order=order,
|
||||
is_business=True)
|
||||
|
||||
ocm = OrderChangeManager(order, None)
|
||||
ocm.recalculate_taxes()
|
||||
ocm.commit()
|
||||
assert not order.positions.filter(tax_value__gt=0).exists()
|
||||
|
||||
inv = generate_invoice(order)
|
||||
assert "reverse charge" in inv.additional_text.lower()
|
||||
assert inv.foreign_currency_display == "PLN"
|
||||
assert inv.foreign_currency_rate == Decimal("4.2408")
|
||||
assert inv.foreign_currency_rate_date == date.today()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_reverse_charge_foreign_currency_data_too_old(env):
|
||||
event, order = env
|
||||
gs = GlobalSettingsObject()
|
||||
gs.settings.ecb_rates_date = date.today() - timedelta(days=14)
|
||||
|
||||
tr = event.tax_rules.first()
|
||||
tr.eu_reverse_charge = True
|
||||
tr.home_country = Country('DE')
|
||||
tr.save()
|
||||
|
||||
event.settings.set('invoice_language', 'en')
|
||||
InvoiceAddress.objects.create(company='Acme Company', street='221B Baker Street', zipcode='12345', city='Warsaw',
|
||||
country=Country('PL'), vat_id='PL123456780', vat_id_validated=True, order=order,
|
||||
is_business=True)
|
||||
|
||||
ocm = OrderChangeManager(order, None)
|
||||
ocm.recalculate_taxes()
|
||||
ocm.commit()
|
||||
assert not order.positions.filter(tax_value__gt=0).exists()
|
||||
|
||||
inv = generate_invoice(order)
|
||||
assert "reverse charge" in inv.additional_text.lower()
|
||||
assert inv.foreign_currency_rate is None
|
||||
assert inv.foreign_currency_rate_date is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_positions(env):
|
||||
event, order = env
|
||||
@@ -279,11 +353,12 @@ def test_invoice_number_prefixes(env):
|
||||
|
||||
# Test database uniqueness check
|
||||
with pytest.raises(DatabaseError):
|
||||
Invoice.objects.create(
|
||||
order=order,
|
||||
event=order.event,
|
||||
organizer=order.event.organizer,
|
||||
date=now().date(),
|
||||
locale='en',
|
||||
invoice_no='00001',
|
||||
)
|
||||
with transaction.atomic():
|
||||
Invoice.objects.create(
|
||||
order=order,
|
||||
event=order.event,
|
||||
organizer=order.event.organizer,
|
||||
date=now().date(),
|
||||
locale='en',
|
||||
invoice_no='00001',
|
||||
)
|
||||
|
||||
@@ -935,6 +935,56 @@ class EventTest(TestCase):
|
||||
|
||||
self.assertIn('slug', str(context.exception))
|
||||
|
||||
def test_copy(self):
|
||||
event1 = Event.objects.create(
|
||||
organizer=self.organizer, name='Download', slug='ab1234',
|
||||
date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc),
|
||||
is_public=True,
|
||||
)
|
||||
tr7 = event1.tax_rules.create(rate=Decimal('7.00'))
|
||||
c1 = event1.categories.create(name='Tickets')
|
||||
c2 = event1.categories.create(name='Workshops')
|
||||
i1 = event1.items.create(name='Foo', default_price=Decimal('13.00'), tax_rule=tr7,
|
||||
category=c1)
|
||||
v1 = i1.variations.create(value='Bar')
|
||||
i1.addons.create(addon_category=c2)
|
||||
q1 = event1.quotas.create(name='Quota 1', size=50)
|
||||
q1.items.add(i1)
|
||||
q1.variations.add(v1)
|
||||
que1 = event1.questions.create(question="Age", type="N")
|
||||
que1.items.add(i1)
|
||||
event1.settings.foo_setting = 23
|
||||
event1.settings.tax_rate_default = tr7
|
||||
|
||||
event2 = Event.objects.create(
|
||||
organizer=self.organizer, name='Download', slug='ab1234',
|
||||
date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc)
|
||||
)
|
||||
event2.copy_data_from(event1)
|
||||
|
||||
for a in (tr7, c1, c2, i1, q1, que1):
|
||||
a.refresh_from_db()
|
||||
assert a.event == event1
|
||||
|
||||
trnew = event2.tax_rules.first()
|
||||
assert trnew.rate == tr7.rate
|
||||
c1new = event2.categories.get(name='Tickets')
|
||||
c2new = event2.categories.get(name='Workshops')
|
||||
i1new = event2.items.first()
|
||||
assert i1new.name == i1.name
|
||||
assert i1new.category == c1new
|
||||
assert i1new.tax_rule == trnew
|
||||
assert i1new.variations.count() == 1
|
||||
assert i1new.addons.get(addon_category=c2new)
|
||||
q1new = event2.quotas.first()
|
||||
assert q1new.size == q1.size
|
||||
assert q1new.items.get(pk=i1new.pk)
|
||||
que1new = event2.questions.first()
|
||||
assert que1new.type == que1.type
|
||||
assert que1new.items.get(pk=i1new.pk)
|
||||
assert event2.settings.foo_setting == '23'
|
||||
assert event2.settings.tax_rate_default == trnew
|
||||
|
||||
|
||||
class SubEventTest(TestCase):
|
||||
@classmethod
|
||||
|
||||
@@ -6,10 +6,11 @@ import pytz
|
||||
from django.core import mail as djmail
|
||||
from django.test import TestCase
|
||||
from django.utils.timezone import make_aware, now
|
||||
from django_countries.fields import Country
|
||||
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models import (
|
||||
CartPosition, Event, Item, Order, OrderPosition, Organizer,
|
||||
CartPosition, Event, InvoiceAddress, Item, Order, OrderPosition, Organizer,
|
||||
)
|
||||
from pretix.base.models.items import SubEventItem
|
||||
from pretix.base.payment import FreeOrderProvider
|
||||
@@ -102,7 +103,8 @@ def test_expiry_last_relative_subevents(event):
|
||||
event.date_from = now() + timedelta(days=5)
|
||||
event.has_subevents = True
|
||||
event.save()
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket', tax_rate=Decimal('7.00'),
|
||||
tr7 = event.tax_rules.create(rate=Decimal('17.00'))
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket', tax_rule=tr7,
|
||||
default_price=Decimal('23.00'), admission=True)
|
||||
|
||||
se1 = event.subevents.create(name="SE1", date_from=now() + timedelta(days=10))
|
||||
@@ -196,7 +198,7 @@ class DownloadReminderTests(TestCase):
|
||||
expires=now() + timedelta(days=10),
|
||||
total=Decimal('46.00'), payment_provider='banktransfer'
|
||||
)
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket', tax_rate=Decimal('7.00'),
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
|
||||
default_price=Decimal('23.00'), admission=True)
|
||||
self.op1 = OrderPosition.objects.create(
|
||||
order=self.order, item=self.ticket, variation=None,
|
||||
@@ -233,18 +235,21 @@ class OrderChangeManagerTests(TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
self.event = Event.objects.create(organizer=o, name='Dummy', slug='dummy', date_from=now(), plugins='pretix.plugins.banktransfer')
|
||||
self.event = Event.objects.create(organizer=o, name='Dummy', slug='dummy', date_from=now(),
|
||||
plugins='pretix.plugins.banktransfer')
|
||||
self.order = Order.objects.create(
|
||||
code='FOO', event=self.event, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PENDING, locale='en',
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=Decimal('46.00'), payment_provider='banktransfer'
|
||||
)
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket', tax_rate=Decimal('7.00'),
|
||||
self.tr7 = self.event.tax_rules.create(rate=Decimal('7.00'))
|
||||
self.tr19 = self.event.tax_rules.create(rate=Decimal('19.00'))
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket', tax_rule=self.tr7,
|
||||
default_price=Decimal('23.00'), admission=True)
|
||||
self.ticket2 = Item.objects.create(event=self.event, name='Other ticket', tax_rate=Decimal('7.00'),
|
||||
self.ticket2 = Item.objects.create(event=self.event, name='Other ticket', tax_rule=self.tr7,
|
||||
default_price=Decimal('23.00'), admission=True)
|
||||
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', tax_rate=Decimal('19.00'),
|
||||
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', tax_rule=self.tr19,
|
||||
default_price=Decimal('12.00'))
|
||||
self.op1 = OrderPosition.objects.create(
|
||||
order=self.order, item=self.ticket, variation=None,
|
||||
@@ -260,6 +265,18 @@ class OrderChangeManagerTests(TestCase):
|
||||
self.quota.items.add(self.ticket2)
|
||||
self.quota.items.add(self.shirt)
|
||||
|
||||
def _enable_reverse_charge(self):
|
||||
self.tr7.eu_reverse_charge = True
|
||||
self.tr7.home_country = Country('DE')
|
||||
self.tr7.save()
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('DE')
|
||||
self.tr19.save()
|
||||
return InvoiceAddress.objects.create(
|
||||
order=self.order, is_business=True, vat_id='ATU1234567', vat_id_validated=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
|
||||
def test_change_subevent_quota_required(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
@@ -291,6 +308,48 @@ class OrderChangeManagerTests(TestCase):
|
||||
assert self.op1.price == 12
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_change_subevent_reverse_charge(self):
|
||||
self._enable_reverse_charge()
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
se1 = self.event.subevents.create(name="Foo", date_from=now())
|
||||
se2 = self.event.subevents.create(name="Bar", date_from=now())
|
||||
SubEventItem.objects.create(subevent=se2, item=self.ticket, price=10.7)
|
||||
self.op1.subevent = se1
|
||||
self.op1.save()
|
||||
self.quota.subevent = se2
|
||||
self.quota.save()
|
||||
|
||||
self.ocm.change_subevent(self.op1, se2)
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
self.order.refresh_from_db()
|
||||
assert self.op1.subevent == se2
|
||||
assert self.op1.price == Decimal('10.00')
|
||||
assert self.op1.tax_value == Decimal('0.00')
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_change_subevent_net_price(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
se1 = self.event.subevents.create(name="Foo", date_from=now())
|
||||
se2 = self.event.subevents.create(name="Bar", date_from=now())
|
||||
self.tr7.price_includes_tax = False
|
||||
self.tr7.save()
|
||||
SubEventItem.objects.create(subevent=se2, item=self.ticket, price=10)
|
||||
self.op1.subevent = se1
|
||||
self.op1.save()
|
||||
self.quota.subevent = se2
|
||||
self.quota.save()
|
||||
|
||||
self.ocm.change_subevent(self.op1, se2)
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
self.order.refresh_from_db()
|
||||
assert self.op1.subevent == se2
|
||||
assert self.op1.price == Decimal('10.70')
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_change_subevent_sold_out(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
@@ -320,10 +379,35 @@ class OrderChangeManagerTests(TestCase):
|
||||
self.order.refresh_from_db()
|
||||
assert self.op1.item == self.shirt
|
||||
assert self.op1.price == self.shirt.default_price
|
||||
assert self.op1.tax_rate == self.shirt.tax_rate
|
||||
assert self.op1.tax_rate == self.shirt.tax_rule.rate
|
||||
assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_change_item_net_price_success(self):
|
||||
self.tr19.price_includes_tax = False
|
||||
self.tr19.save()
|
||||
self.ocm.change_item(self.op1, self.shirt, None)
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
self.order.refresh_from_db()
|
||||
assert self.op1.item == self.shirt
|
||||
assert self.op1.price == Decimal('14.28')
|
||||
assert self.op1.tax_rate == self.shirt.tax_rule.rate
|
||||
assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_change_item_reverse_charge(self):
|
||||
self._enable_reverse_charge()
|
||||
self.ocm.change_item(self.op1, self.shirt, None)
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
self.order.refresh_from_db()
|
||||
assert self.op1.item == self.shirt
|
||||
assert self.op1.price == Decimal('10.08')
|
||||
assert self.op1.tax_rate == Decimal('0.00')
|
||||
assert self.op1.tax_value == Decimal('0.00')
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_change_price_success(self):
|
||||
self.ocm.change_price(self.op1, Decimal('24.00'))
|
||||
self.ocm.commit()
|
||||
@@ -334,6 +418,18 @@ class OrderChangeManagerTests(TestCase):
|
||||
assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_change_price_net_success(self):
|
||||
self.tr7.price_includes_tax = False
|
||||
self.tr7.save()
|
||||
self.ocm.change_price(self.op1, Decimal('10.00'))
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
self.order.refresh_from_db()
|
||||
assert self.op1.item == self.ticket
|
||||
assert self.op1.price == Decimal('10.70')
|
||||
assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_cancel_success(self):
|
||||
self.ocm.cancel(self.op1)
|
||||
self.ocm.commit()
|
||||
@@ -436,7 +532,7 @@ class OrderChangeManagerTests(TestCase):
|
||||
assert self.op2.item == self.ticket
|
||||
|
||||
def test_payment_fee_calculation(self):
|
||||
self.event.settings.set('tax_rate_default', Decimal('19.00'))
|
||||
self.event.settings.set('tax_rate_default', self.tr19.pk)
|
||||
prov = self.ocm._get_payment_provider()
|
||||
prov.settings.set('_fee_abs', Decimal('0.30'))
|
||||
self.ocm.change_price(self.op1, Decimal('24.00'))
|
||||
@@ -445,7 +541,8 @@ class OrderChangeManagerTests(TestCase):
|
||||
assert self.order.total == Decimal('47.30')
|
||||
assert self.order.payment_fee == prov.calculate_fee(self.order.total)
|
||||
assert self.order.payment_fee_tax_rate == Decimal('19.00')
|
||||
assert round_decimal(self.order.payment_fee * (1 - 100 / (100 + self.order.payment_fee_tax_rate))) == self.order.payment_fee_tax_value
|
||||
assert round_decimal(self.order.payment_fee * (
|
||||
1 - 100 / (100 + self.order.payment_fee_tax_rate))) == self.order.payment_fee_tax_value
|
||||
|
||||
def test_require_pending(self):
|
||||
self.order.status = Order.STATUS_PAID
|
||||
@@ -497,8 +594,37 @@ class OrderChangeManagerTests(TestCase):
|
||||
nop = self.order.positions.last()
|
||||
assert nop.item == self.shirt
|
||||
assert nop.price == self.shirt.default_price
|
||||
assert nop.tax_rate == self.shirt.tax_rate
|
||||
assert round_decimal(nop.price * (1 - 100 / (100 + self.shirt.tax_rate))) == nop.tax_value
|
||||
assert nop.tax_rate == self.shirt.tax_rule.rate
|
||||
assert round_decimal(nop.price * (1 - 100 / (100 + self.shirt.tax_rule.rate))) == nop.tax_value
|
||||
assert self.order.total == self.op1.price + self.op2.price + nop.price
|
||||
assert nop.positionid == 3
|
||||
|
||||
def test_add_item_net_price_success(self):
|
||||
self.tr19.price_includes_tax = False
|
||||
self.tr19.save()
|
||||
self.ocm.add_position(self.shirt, None, None, None)
|
||||
self.ocm.commit()
|
||||
self.order.refresh_from_db()
|
||||
assert self.order.positions.count() == 3
|
||||
nop = self.order.positions.last()
|
||||
assert nop.item == self.shirt
|
||||
assert nop.price == Decimal('14.28')
|
||||
assert nop.tax_rate == self.shirt.tax_rule.rate
|
||||
assert round_decimal(nop.price * (1 - 100 / (100 + self.shirt.tax_rule.rate))) == nop.tax_value
|
||||
assert self.order.total == self.op1.price + self.op2.price + nop.price
|
||||
assert nop.positionid == 3
|
||||
|
||||
def test_add_item_reverse_charge(self):
|
||||
self._enable_reverse_charge()
|
||||
self.ocm.add_position(self.shirt, None, None, None)
|
||||
self.ocm.commit()
|
||||
self.order.refresh_from_db()
|
||||
assert self.order.positions.count() == 3
|
||||
nop = self.order.positions.last()
|
||||
assert nop.item == self.shirt
|
||||
assert nop.price == Decimal('10.08')
|
||||
assert nop.tax_rate == Decimal('0.00')
|
||||
assert nop.tax_value == Decimal('0.00')
|
||||
assert self.order.total == self.op1.price + self.op2.price + nop.price
|
||||
assert nop.positionid == 3
|
||||
|
||||
@@ -510,8 +636,22 @@ class OrderChangeManagerTests(TestCase):
|
||||
nop = self.order.positions.last()
|
||||
assert nop.item == self.shirt
|
||||
assert nop.price == Decimal('13.00')
|
||||
assert nop.tax_rate == self.shirt.tax_rate
|
||||
assert round_decimal(nop.price * (1 - 100 / (100 + self.shirt.tax_rate))) == nop.tax_value
|
||||
assert nop.tax_rate == self.shirt.tax_rule.rate
|
||||
assert round_decimal(nop.price * (1 - 100 / (100 + self.shirt.tax_rule.rate))) == nop.tax_value
|
||||
assert self.order.total == self.op1.price + self.op2.price + nop.price
|
||||
|
||||
def test_add_item_custom_price_tax_always_included(self):
|
||||
self.tr19.price_includes_tax = False
|
||||
self.tr19.save()
|
||||
self.ocm.add_position(self.shirt, None, Decimal('11.90'), None)
|
||||
self.ocm.commit()
|
||||
self.order.refresh_from_db()
|
||||
assert self.order.positions.count() == 3
|
||||
nop = self.order.positions.last()
|
||||
assert nop.item == self.shirt
|
||||
assert nop.price == Decimal('11.90')
|
||||
assert nop.tax_rate == self.shirt.tax_rule.rate
|
||||
assert round_decimal(nop.price * (1 - 100 / (100 + self.shirt.tax_rule.rate))) == nop.tax_value
|
||||
assert self.order.total == self.op1.price + self.op2.price + nop.price
|
||||
|
||||
def test_add_item_quota_full(self):
|
||||
@@ -577,3 +717,44 @@ class OrderChangeManagerTests(TestCase):
|
||||
self.ocm.add_position(self.ticket, None, Decimal('0.00'))
|
||||
self.ocm.commit()
|
||||
assert self.order.invoices.count() == 1
|
||||
|
||||
def test_recalculate_reverse_charge(self):
|
||||
self.event.settings.set('tax_rate_default', self.tr19.pk)
|
||||
prov = self.ocm._get_payment_provider()
|
||||
prov.settings.set('_fee_abs', Decimal('0.30'))
|
||||
self.ocm._recalculate_total_and_payment_fee()
|
||||
|
||||
assert self.order.total == Decimal('46.30')
|
||||
assert self.order.payment_fee == prov.calculate_fee(self.order.total)
|
||||
assert self.order.payment_fee_tax_rate == Decimal('19.00')
|
||||
assert self.order.payment_fee_tax_value == Decimal('0.05')
|
||||
|
||||
ia = self._enable_reverse_charge()
|
||||
self.ocm.recalculate_taxes()
|
||||
self.ocm.commit()
|
||||
ops = list(self.order.positions.all())
|
||||
for op in ops:
|
||||
assert op.price == Decimal('21.50')
|
||||
assert op.tax_value == Decimal('0.00')
|
||||
assert op.tax_rate == Decimal('0.00')
|
||||
|
||||
assert self.order.total == Decimal('43.30')
|
||||
assert self.order.payment_fee == prov.calculate_fee(self.order.total)
|
||||
assert self.order.payment_fee_tax_rate == Decimal('0.00')
|
||||
assert self.order.payment_fee_tax_value == Decimal('0.00')
|
||||
|
||||
ia.vat_id_validated = False
|
||||
ia.save()
|
||||
|
||||
self.ocm.recalculate_taxes()
|
||||
self.ocm.commit()
|
||||
ops = list(self.order.positions.all())
|
||||
for op in ops:
|
||||
assert op.price == Decimal('23.01') # sic. we can't really avoid it.
|
||||
assert op.tax_value == Decimal('1.51')
|
||||
assert op.tax_rate == Decimal('7.00')
|
||||
|
||||
assert self.order.total == Decimal('46.32')
|
||||
assert self.order.payment_fee == prov.calculate_fee(self.order.total)
|
||||
assert self.order.payment_fee_tax_rate == Decimal('19.00')
|
||||
assert self.order.payment_fee_tax_value == Decimal('0.05')
|
||||
|
||||
@@ -108,7 +108,8 @@ def test_availability_date_cart_relative_subevents(event):
|
||||
event.date_from = now() + datetime.timedelta(days=5)
|
||||
event.has_subevents = True
|
||||
event.save()
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket', tax_rate=Decimal('7.00'),
|
||||
tr7 = event.tax_rules.create(rate=Decimal('7.00'))
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket', tax_rule=tr7,
|
||||
default_price=Decimal('23.00'), admission=True)
|
||||
|
||||
se1 = event.subevents.create(name="SE1", date_from=now() + datetime.timedelta(days=10))
|
||||
@@ -138,7 +139,8 @@ def test_availability_date_order_relative_subevents(event):
|
||||
event.date_from = now() + datetime.timedelta(days=5)
|
||||
event.has_subevents = True
|
||||
event.save()
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket', tax_rate=Decimal('7.00'),
|
||||
tr7 = event.tax_rules.create(rate=Decimal('7.00'))
|
||||
ticket = Item.objects.create(event=event, name='Early-bird ticket', tax_rule=tr7,
|
||||
default_price=Decimal('23.00'), admission=True)
|
||||
|
||||
se1 = event.subevents.create(name="SE1", date_from=now() + datetime.timedelta(days=10))
|
||||
|
||||
@@ -2,8 +2,9 @@ from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from django.utils.timezone import now
|
||||
from django_countries.fields import Country
|
||||
|
||||
from pretix.base.models import Event, Organizer
|
||||
from pretix.base.models import Event, InvoiceAddress, Organizer
|
||||
from pretix.base.models.items import SubEventItem, SubEventItemVariation
|
||||
from pretix.base.services.pricing import get_price
|
||||
|
||||
@@ -42,143 +43,143 @@ def subevent(event):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_base_item_default(item):
|
||||
assert get_price(item) == Decimal('23.00')
|
||||
assert get_price(item).gross == Decimal('23.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_base_item_subevent_no_entry(item, subevent):
|
||||
assert get_price(item, subevent=subevent) == Decimal('23.00')
|
||||
assert get_price(item, subevent=subevent).gross == Decimal('23.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_base_item_subevent_no_override(item, subevent):
|
||||
SubEventItem.objects.create(item=item, subevent=subevent, price=None)
|
||||
assert get_price(item, subevent=subevent) == Decimal('23.00')
|
||||
assert get_price(item, subevent=subevent).gross == Decimal('23.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_base_item_subevent_override(item, subevent):
|
||||
SubEventItem.objects.create(item=item, subevent=subevent, price=Decimal('24.00'))
|
||||
assert get_price(item, subevent=subevent) == Decimal('24.00')
|
||||
assert get_price(item, subevent=subevent).gross == Decimal('24.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_variation_with_default_item_price(item, variation):
|
||||
assert get_price(item, variation=variation) == Decimal('23.00')
|
||||
assert get_price(item, variation=variation).gross == Decimal('23.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_variation_with_specific_price(item, variation):
|
||||
variation.default_price = Decimal('24.00')
|
||||
assert get_price(item, variation=variation) == Decimal('24.00')
|
||||
assert get_price(item, variation=variation).gross == Decimal('24.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_variation_with_default_subevent_and_default_price(item, subevent, variation):
|
||||
SubEventItemVariation.objects.create(variation=variation, subevent=subevent, price=None)
|
||||
assert get_price(item, variation=variation, subevent=subevent) == Decimal('23.00')
|
||||
assert get_price(item, variation=variation, subevent=subevent).gross == Decimal('23.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_variation_with_subevent_and_default_price(item, subevent, variation):
|
||||
SubEventItemVariation.objects.create(variation=variation, subevent=subevent, price=Decimal('24.00'))
|
||||
assert get_price(item, variation=variation, subevent=subevent) == Decimal('24.00')
|
||||
assert get_price(item, variation=variation, subevent=subevent).gross == Decimal('24.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_variation_with_no_subevent_and_specific_price(item, subevent, variation):
|
||||
variation.default_price = Decimal('24.00')
|
||||
assert get_price(item, variation=variation, subevent=subevent) == Decimal('24.00')
|
||||
assert get_price(item, variation=variation, subevent=subevent).gross == Decimal('24.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_variation_with_default_subevent_and_specific_price(item, subevent, variation):
|
||||
variation.default_price = Decimal('24.00')
|
||||
SubEventItemVariation.objects.create(variation=variation, subevent=subevent, price=None)
|
||||
assert get_price(item, variation=variation, subevent=subevent) == Decimal('24.00')
|
||||
assert get_price(item, variation=variation, subevent=subevent).gross == Decimal('24.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_variation_with_subevent_and_specific_price(item, subevent, variation):
|
||||
variation.default_price = Decimal('24.00')
|
||||
SubEventItemVariation.objects.create(variation=variation, subevent=subevent, price=Decimal('26.00'))
|
||||
assert get_price(item, variation=variation, subevent=subevent) == Decimal('26.00')
|
||||
assert get_price(item, variation=variation, subevent=subevent).gross == Decimal('26.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_voucher_no_override(item, subevent, voucher):
|
||||
assert get_price(item, subevent=subevent, voucher=voucher) == Decimal('23.00')
|
||||
assert get_price(item, subevent=subevent, voucher=voucher).gross == Decimal('23.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_voucher_set_price(item, subevent, voucher):
|
||||
voucher.price_mode = 'set'
|
||||
voucher.value = Decimal('12.00')
|
||||
assert get_price(item, subevent=subevent, voucher=voucher) == Decimal('12.00')
|
||||
assert get_price(item, subevent=subevent, voucher=voucher).gross == Decimal('12.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_voucher_subtract(item, subevent, voucher):
|
||||
voucher.price_mode = 'subtract'
|
||||
voucher.value = Decimal('12.00')
|
||||
assert get_price(item, subevent=subevent, voucher=voucher) == Decimal('11.00')
|
||||
assert get_price(item, subevent=subevent, voucher=voucher).gross == Decimal('11.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_voucher_percent(item, subevent, voucher):
|
||||
voucher.price_mode = 'percent'
|
||||
voucher.value = Decimal('10.00')
|
||||
assert get_price(item, subevent=subevent, voucher=voucher) == Decimal('20.70')
|
||||
assert get_price(item, subevent=subevent, voucher=voucher).gross == Decimal('20.70')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_ignored_if_disabled(item):
|
||||
assert get_price(item, custom_price=Decimal('42.00')) == Decimal('23.00')
|
||||
assert get_price(item, custom_price=Decimal('42.00')).gross == Decimal('23.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_ignored_if_lower(item):
|
||||
item.free_price = True
|
||||
assert get_price(item, custom_price=Decimal('12.00')) == Decimal('23.00')
|
||||
assert get_price(item, custom_price=Decimal('12.00')).gross == Decimal('23.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_ignored_if_lower_than_voucher(item, voucher):
|
||||
voucher.price_mode = 'set'
|
||||
voucher.value = Decimal('50.00')
|
||||
assert get_price(item, voucher=voucher, custom_price=Decimal('40.00')) == Decimal('50.00')
|
||||
assert get_price(item, voucher=voucher, custom_price=Decimal('40.00')).gross == Decimal('50.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_ignored_if_lower_than_subevent(item, subevent):
|
||||
item.free_price = True
|
||||
SubEventItem.objects.create(item=item, subevent=subevent, price=Decimal('50.00'))
|
||||
assert get_price(item, subevent=subevent, custom_price=Decimal('40.00')) == Decimal('50.00')
|
||||
assert get_price(item, subevent=subevent, custom_price=Decimal('40.00')).gross == Decimal('50.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_ignored_if_lower_than_variation(item, variation):
|
||||
variation.default_price = Decimal('50.00')
|
||||
item.free_price = True
|
||||
assert get_price(item, variation=variation, custom_price=Decimal('40.00')) == Decimal('50.00')
|
||||
assert get_price(item, variation=variation, custom_price=Decimal('40.00')).gross == Decimal('50.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_accepted(item):
|
||||
item.free_price = True
|
||||
assert get_price(item, custom_price=Decimal('42.00')) == Decimal('42.00')
|
||||
assert get_price(item, custom_price=Decimal('42.00')).gross == Decimal('42.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_string(item):
|
||||
item.free_price = True
|
||||
assert get_price(item, custom_price='42,00') == Decimal('42.00')
|
||||
assert get_price(item, custom_price='42,00').gross == Decimal('42.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_float(item):
|
||||
item.free_price = True
|
||||
assert get_price(item, custom_price=42.00) == Decimal('42.00')
|
||||
assert get_price(item, custom_price=42.00).gross == Decimal('42.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -191,5 +192,136 @@ def test_free_price_limit(item):
|
||||
@pytest.mark.django_db
|
||||
def test_free_price_net(item):
|
||||
item.free_price = True
|
||||
item.tax_rate = 19
|
||||
assert get_price(item, custom_price=Decimal('100.00'), custom_price_is_net=True) == Decimal('119.00')
|
||||
item.tax_rule = item.event.tax_rules.create(rate=Decimal('19.00'))
|
||||
assert get_price(item, custom_price=Decimal('100.00'), custom_price_is_net=True).gross == Decimal('119.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_included(item):
|
||||
item.default_price = Decimal('119.00')
|
||||
item.tax_rule = item.event.tax_rules.create(rate=Decimal('19.00'), price_includes_tax=True)
|
||||
assert get_price(item).gross == Decimal('119.00')
|
||||
assert get_price(item).net == Decimal('100.00')
|
||||
assert get_price(item).tax == Decimal('19.00')
|
||||
assert get_price(item).rate == Decimal('19.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_none(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
assert get_price(item).gross == Decimal('100.00')
|
||||
assert get_price(item).net == Decimal('100.00')
|
||||
assert get_price(item).tax == Decimal('0.00')
|
||||
assert get_price(item).rate == Decimal('0.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_added(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
item.tax_rule = item.event.tax_rules.create(rate=Decimal('19.00'), price_includes_tax=False)
|
||||
assert get_price(item).gross == Decimal('119.00')
|
||||
assert get_price(item).net == Decimal('100.00')
|
||||
assert get_price(item).tax == Decimal('19.00')
|
||||
assert get_price(item).rate == Decimal('19.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_reverse_charge_valid(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
item.tax_rule = item.event.tax_rules.create(
|
||||
rate=Decimal('19.00'), price_includes_tax=False,
|
||||
eu_reverse_charge=True, home_country=Country('DE')
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True, vat_id="EU1234", vat_id_validated=True,
|
||||
country=Country('BE')
|
||||
)
|
||||
assert item.tax_rule.is_reverse_charge(ia)
|
||||
assert get_price(item, invoice_address=ia).gross == Decimal('100.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_reverse_charge_disabled(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
item.tax_rule = item.event.tax_rules.create(
|
||||
rate=Decimal('19.00'), price_includes_tax=False,
|
||||
eu_reverse_charge=False, home_country=Country('DE')
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True, vat_id="EU1234", vat_id_validated=True,
|
||||
country=Country('BE')
|
||||
)
|
||||
assert not item.tax_rule.is_reverse_charge(ia)
|
||||
assert get_price(item, invoice_address=ia).gross == Decimal('119.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_reverse_charge_no_country(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
item.tax_rule = item.event.tax_rules.create(
|
||||
rate=Decimal('19.00'), price_includes_tax=False,
|
||||
eu_reverse_charge=True, home_country=Country('DE')
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True, vat_id="EU1234", vat_id_validated=True,
|
||||
)
|
||||
assert not item.tax_rule.is_reverse_charge(ia)
|
||||
assert get_price(item, invoice_address=ia).gross == Decimal('119.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_reverse_charge_non_eu_country(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
item.tax_rule = item.event.tax_rules.create(
|
||||
rate=Decimal('19.00'), price_includes_tax=False,
|
||||
eu_reverse_charge=True, home_country=Country('DE')
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
country=Country('US')
|
||||
)
|
||||
assert not item.tax_rule.is_reverse_charge(ia)
|
||||
assert get_price(item, invoice_address=ia).gross == Decimal('100.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_reverse_charge_same_country(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
item.tax_rule = item.event.tax_rules.create(
|
||||
rate=Decimal('19.00'), price_includes_tax=False,
|
||||
eu_reverse_charge=True, home_country=Country('DE')
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True, vat_id="EU1234", vat_id_validated=True,
|
||||
country=Country('DE')
|
||||
)
|
||||
assert not item.tax_rule.is_reverse_charge(ia)
|
||||
assert get_price(item, invoice_address=ia).gross == Decimal('119.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_reverse_charge_consumer(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
item.tax_rule = item.event.tax_rules.create(
|
||||
rate=Decimal('19.00'), price_includes_tax=False,
|
||||
eu_reverse_charge=True, home_country=Country('DE')
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=False, country=Country('BE')
|
||||
)
|
||||
assert not item.tax_rule.is_reverse_charge(ia)
|
||||
assert get_price(item, invoice_address=ia).gross == Decimal('119.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_tax_reverse_charge_invalid_vat_id(item):
|
||||
item.default_price = Decimal('100.00')
|
||||
item.tax_rule = item.event.tax_rules.create(
|
||||
rate=Decimal('19.00'), price_includes_tax=False,
|
||||
eu_reverse_charge=True, home_country=Country('DE')
|
||||
)
|
||||
ia = InvoiceAddress(
|
||||
is_business=True, vat_id="EU1234", vat_id_validated=False,
|
||||
country=Country('BE')
|
||||
)
|
||||
assert not item.tax_rule.is_reverse_charge(ia)
|
||||
assert get_price(item, invoice_address=ia).gross == Decimal('119.00')
|
||||
|
||||
@@ -132,35 +132,39 @@ class EventsTest(SoupTest):
|
||||
assert len(doc.select(".btn-primary")) == 0
|
||||
|
||||
def test_payment_settings(self):
|
||||
tr19 = self.event1.tax_rules.create(rate=Decimal('19.00'))
|
||||
self.get_doc('/control/event/%s/%s/settings/payment' % (self.orga1.slug, self.event1.slug))
|
||||
self.post_doc('/control/event/%s/%s/settings/payment' % (self.orga1.slug, self.event1.slug), {
|
||||
'payment_banktransfer__enabled': 'true',
|
||||
'payment_banktransfer__fee_abs': '12.23',
|
||||
'payment_banktransfer_bank_details_0': 'Test',
|
||||
'settings-payment_term_days': '2',
|
||||
'settings-tax_rate_default': '19.00',
|
||||
'settings-tax_rate_default': tr19.pk,
|
||||
})
|
||||
self.event1.settings.flush()
|
||||
assert self.event1.settings.get('payment_banktransfer__enabled', as_type=bool)
|
||||
assert self.event1.settings.get('payment_banktransfer__fee_abs', as_type=Decimal) == Decimal('12.23')
|
||||
|
||||
def test_payment_settings_dont_require_fields_of_inactive_providers(self):
|
||||
tr19 = self.event1.tax_rules.create(rate=Decimal('19.00'))
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/payment' % (self.orga1.slug, self.event1.slug), {
|
||||
'settings-tax_rate_default': '19.00',
|
||||
'settings-tax_rate_default': tr19.pk,
|
||||
'settings-payment_term_days': '2'
|
||||
}, follow=True)
|
||||
assert doc.select('.alert-success')
|
||||
|
||||
def test_payment_settings_require_fields_of_active_providers(self):
|
||||
tr19 = self.event1.tax_rules.create(rate=Decimal('19.00'))
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/payment' % (self.orga1.slug, self.event1.slug), {
|
||||
'payment_banktransfer__enabled': 'true',
|
||||
'payment_banktransfer__fee_abs': '12.23',
|
||||
'settings-payment_term_days': '2',
|
||||
'settings-tax_rate_default': '19.00',
|
||||
'settings-tax_rate_default': tr19.pk,
|
||||
})
|
||||
assert doc.select('.alert-danger')
|
||||
|
||||
def test_payment_settings_last_date_payment_after_presale_end(self):
|
||||
tr19 = self.event1.tax_rules.create(rate=Decimal('19.00'))
|
||||
self.event1.presale_end = datetime.datetime.now()
|
||||
self.event1.save(update_fields=['presale_end'])
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/payment' % (self.orga1.slug, self.event1.slug), {
|
||||
@@ -172,13 +176,14 @@ class EventsTest(SoupTest):
|
||||
'settings-payment_term_last_1': (self.event1.presale_end - datetime.timedelta(1)).strftime('%Y-%m-%d'),
|
||||
'settings-payment_term_last_2': '0',
|
||||
'settings-payment_term_last_3': 'date_from',
|
||||
'settings-tax_rate_default': '19.00',
|
||||
'settings-tax_rate_default': tr19.pk,
|
||||
})
|
||||
assert doc.select('.alert-danger')
|
||||
self.event1.presale_end = None
|
||||
self.event1.save(update_fields=['presale_end'])
|
||||
|
||||
def test_payment_settings_relative_date_payment_after_presale_end(self):
|
||||
tr19 = self.event1.tax_rules.create(rate=Decimal('19.00'))
|
||||
self.event1.presale_end = self.event1.date_from - datetime.timedelta(days=5)
|
||||
self.event1.save(update_fields=['presale_end'])
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/payment' % (self.orga1.slug, self.event1.slug), {
|
||||
@@ -190,7 +195,7 @@ class EventsTest(SoupTest):
|
||||
'settings-payment_term_last_1': '',
|
||||
'settings-payment_term_last_2': '10',
|
||||
'settings-payment_term_last_3': 'date_from',
|
||||
'settings-tax_rate_default': '19.00',
|
||||
'settings-tax_rate_default': tr19.pk,
|
||||
})
|
||||
assert doc.select('.alert-danger')
|
||||
self.event1.presale_end = None
|
||||
@@ -268,6 +273,7 @@ class EventsTest(SoupTest):
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-location_1': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-tax_rate': '',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
@@ -292,6 +298,7 @@ class EventsTest(SoupTest):
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-location_1': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-tax_rate': '',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
@@ -323,6 +330,7 @@ class EventsTest(SoupTest):
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-location_1': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-tax_rate': '19.00',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
@@ -352,6 +360,8 @@ class EventsTest(SoupTest):
|
||||
assert ev.presale_start == berlin_tz.localize(datetime.datetime(2016, 11, 1, 10, 0, 0)).astimezone(pytz.utc)
|
||||
assert ev.presale_end == berlin_tz.localize(datetime.datetime(2016, 11, 30, 18, 0, 0)).astimezone(pytz.utc)
|
||||
|
||||
assert ev.tax_rules.filter(rate=Decimal('19.00')).exists()
|
||||
|
||||
def test_create_event_with_subevents_success(self):
|
||||
doc = self.get_doc('/control/events/add')
|
||||
tabletext = doc.select("form")[0].text
|
||||
@@ -374,6 +384,7 @@ class EventsTest(SoupTest):
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-location_1': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-tax_rate': '',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
@@ -402,6 +413,7 @@ class EventsTest(SoupTest):
|
||||
'basics-date_to': '',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-tax_rate': '',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'UTC',
|
||||
'basics-presale_start': '',
|
||||
@@ -441,6 +453,7 @@ class EventsTest(SoupTest):
|
||||
'basics-date_to': '2016-12-30 19:00:00',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-tax_rate': '',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-20 11:00:00',
|
||||
@@ -463,6 +476,7 @@ class EventsTest(SoupTest):
|
||||
'basics-date_to': '2016-12-30 19:00:00',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-currency': '$',
|
||||
'basics-tax_rate': '',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
@@ -485,6 +499,7 @@ class EventsTest(SoupTest):
|
||||
'basics-date_to': '2016-12-30 19:00:00',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-currency': 'ASD',
|
||||
'basics-tax_rate': '',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from django.core import mail
|
||||
from django.utils.timezone import now
|
||||
from django_countries.fields import Country
|
||||
from tests.base import SoupTest
|
||||
|
||||
from pretix.base.models import (
|
||||
@@ -558,9 +560,11 @@ class OrderChangeTests(SoupTest):
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=Decimal('46.00'), payment_provider='banktransfer'
|
||||
)
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket', tax_rate=Decimal('7.00'),
|
||||
self.tr7 = self.event.tax_rules.create(rate=Decimal('7.00'))
|
||||
self.tr19 = self.event.tax_rules.create(rate=Decimal('19.00'))
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket', tax_rule=self.tr7,
|
||||
default_price=Decimal('23.00'), admission=True)
|
||||
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', tax_rate=Decimal('19.00'),
|
||||
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', tax_rule=self.tr19,
|
||||
default_price=Decimal('12.00'))
|
||||
self.op1 = OrderPosition.objects.create(
|
||||
order=self.order, item=self.ticket, variation=None,
|
||||
@@ -593,7 +597,7 @@ class OrderChangeTests(SoupTest):
|
||||
self.order.refresh_from_db()
|
||||
assert self.op1.item == self.shirt
|
||||
assert self.op1.price == self.shirt.default_price
|
||||
assert self.op1.tax_rate == self.shirt.tax_rate
|
||||
assert self.op1.tax_rate == self.shirt.tax_rule.rate
|
||||
assert self.order.total == self.op1.price + self.op2.price
|
||||
|
||||
def test_change_subevent_success(self):
|
||||
@@ -678,3 +682,135 @@ class OrderChangeTests(SoupTest):
|
||||
assert self.order.positions.count() == 3
|
||||
assert self.order.positions.last().item == self.shirt
|
||||
assert self.order.positions.last().price == 14
|
||||
|
||||
def test_recalculate_reverse_charge(self):
|
||||
self.tr7.eu_reverse_charge = True
|
||||
self.tr7.home_country = Country('DE')
|
||||
self.tr7.save()
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('DE')
|
||||
self.tr19.save()
|
||||
InvoiceAddress.objects.create(
|
||||
order=self.order, is_business=True, vat_id='ATU1234567', vat_id_validated=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
|
||||
self.client.post('/control/event/{}/{}/orders/{}/change'.format(
|
||||
self.event.organizer.slug, self.event.slug, self.order.code
|
||||
), {
|
||||
'other-recalculate_taxes': 'on',
|
||||
'add-itemvar'.format(self.op2.pk): str(self.ticket.pk),
|
||||
'op-{}-operation'.format(self.op1.pk): '',
|
||||
'op-{}-operation'.format(self.op2.pk): '',
|
||||
'op-{}-itemvar'.format(self.op2.pk): str(self.ticket.pk),
|
||||
'op-{}-price'.format(self.op2.pk): str(self.op2.price),
|
||||
'op-{}-itemvar'.format(self.op1.pk): str(self.ticket.pk),
|
||||
'op-{}-price'.format(self.op1.pk): str(self.op1.price),
|
||||
})
|
||||
|
||||
ops = list(self.order.positions.all())
|
||||
for op in ops:
|
||||
assert op.price == Decimal('21.50')
|
||||
assert op.tax_value == Decimal('0.00')
|
||||
assert op.tax_rate == Decimal('0.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_vatid(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
ia = InvoiceAddress.objects.create(order=env[2], is_business=True, vat_id='ATU1234567', country=Country('AT'))
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
response = client.post('/control/event/dummy/dummy/orders/FOO/checkvatid', {}, follow=True)
|
||||
assert 'alert-success' in response.rendered_content
|
||||
ia.refresh_from_db()
|
||||
assert ia.vat_id_validated
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_vatid_no_entered(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
ia = InvoiceAddress.objects.create(order=env[2], is_business=True, country=Country('AT'))
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
response = client.post('/control/event/dummy/dummy/orders/FOO/checkvatid', {}, follow=True)
|
||||
assert 'alert-danger' in response.rendered_content
|
||||
ia.refresh_from_db()
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_vatid_invalid_country(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
ia = InvoiceAddress.objects.create(order=env[2], is_business=True, vat_id='ATU1234567', country=Country('FR'))
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
response = client.post('/control/event/dummy/dummy/orders/FOO/checkvatid', {}, follow=True)
|
||||
assert 'alert-danger' in response.rendered_content
|
||||
ia.refresh_from_db()
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_vatid_noneu_country(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
ia = InvoiceAddress.objects.create(order=env[2], is_business=True, vat_id='CHU1234567', country=Country('CH'))
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
response = client.post('/control/event/dummy/dummy/orders/FOO/checkvatid', {}, follow=True)
|
||||
assert 'alert-danger' in response.rendered_content
|
||||
ia.refresh_from_db()
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_vatid_no_country(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
ia = InvoiceAddress.objects.create(order=env[2], is_business=True, vat_id='ATU1234567')
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
response = client.post('/control/event/dummy/dummy/orders/FOO/checkvatid', {}, follow=True)
|
||||
assert 'alert-danger' in response.rendered_content
|
||||
ia.refresh_from_db()
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_vatid_no_invoiceaddress(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
response = client.post('/control/event/dummy/dummy/orders/FOO/checkvatid', {}, follow=True)
|
||||
assert 'alert-danger' in response.rendered_content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_vatid_invalid(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
ia = InvoiceAddress.objects.create(order=env[2], is_business=True, vat_id='ATU1234567', country=Country('AT'))
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
def raiser(*args, **kwargs):
|
||||
import vat_moss.errors
|
||||
raise vat_moss.errors.InvalidError('Fail')
|
||||
|
||||
mock_validate.side_effect = raiser
|
||||
response = client.post('/control/event/dummy/dummy/orders/FOO/checkvatid', {}, follow=True)
|
||||
assert 'alert-danger' in response.rendered_content
|
||||
ia.refresh_from_db()
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_vatid_unavailable(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
ia = InvoiceAddress.objects.create(order=env[2], is_business=True, vat_id='ATU1234567', country=Country('AT'))
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
def raiser(*args, **kwargs):
|
||||
import vat_moss.errors
|
||||
raise vat_moss.errors.WebServiceUnavailableError('Fail')
|
||||
|
||||
mock_validate.side_effect = raiser
|
||||
response = client.post('/control/event/dummy/dummy/orders/FOO/checkvatid', {}, follow=True)
|
||||
assert 'alert-danger' in response.rendered_content
|
||||
ia.refresh_from_db()
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
@@ -41,6 +41,10 @@ event_urls = [
|
||||
"settings/invoice",
|
||||
"settings/invoice/preview",
|
||||
"settings/display",
|
||||
"settings/tax/",
|
||||
"settings/tax/add",
|
||||
"settings/tax/1/",
|
||||
"settings/tax/1/delete",
|
||||
"items/",
|
||||
"items/add",
|
||||
"items/1/",
|
||||
@@ -81,6 +85,7 @@ event_urls = [
|
||||
"orders/ABC/contact",
|
||||
"orders/ABC/comment",
|
||||
"orders/ABC/locale",
|
||||
"orders/ABC/checkvatid",
|
||||
"orders/ABC/",
|
||||
"orders/",
|
||||
"waitinglist/",
|
||||
@@ -162,6 +167,10 @@ event_permission_urls = [
|
||||
("can_change_event_settings", "settings/display", 200),
|
||||
("can_change_event_settings", "settings/invoice", 200),
|
||||
("can_change_event_settings", "settings/invoice/preview", 200),
|
||||
("can_change_event_settings", "settings/tax/", 200),
|
||||
("can_change_event_settings", "settings/tax/1/", 404),
|
||||
("can_change_event_settings", "settings/tax/add", 200),
|
||||
("can_change_event_settings", "settings/tax/1/delete", 404),
|
||||
("can_change_event_settings", "comment/", 405),
|
||||
# Lists are currently not access-controlled
|
||||
# ("can_change_items", "items/", 200),
|
||||
@@ -197,6 +206,7 @@ event_permission_urls = [
|
||||
("can_change_orders", "orders/FOO/extend", 200),
|
||||
("can_change_orders", "orders/FOO/contact", 200),
|
||||
("can_change_orders", "orders/FOO/transition", 405),
|
||||
("can_change_orders", "orders/FOO/checkvatid", 405),
|
||||
("can_change_orders", "orders/FOO/resend", 405),
|
||||
("can_change_orders", "orders/FOO/invoice", 405),
|
||||
("can_change_orders", "orders/FOO/change", 200),
|
||||
|
||||
115
src/tests/control/test_taxrates.py
Normal file
115
src/tests/control/test_taxrates.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from django.utils.timezone import now
|
||||
from tests.base import SoupTest, extract_form_fields
|
||||
|
||||
from pretix.base.models import Event, Order, Organizer, Team, User
|
||||
|
||||
|
||||
class TaxRateFormTest(SoupTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
|
||||
self.orga1 = Organizer.objects.create(name='CCC', slug='ccc')
|
||||
self.orga2 = Organizer.objects.create(name='MRM', slug='mrm')
|
||||
self.event1 = Event.objects.create(
|
||||
organizer=self.orga1, name='30C3', slug='30c3',
|
||||
date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc),
|
||||
)
|
||||
t = Team.objects.create(organizer=self.orga1, can_change_event_settings=True, can_change_items=True)
|
||||
t.members.add(self.user)
|
||||
t.limit_events.add(self.event1)
|
||||
self.client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
|
||||
def test_create(self):
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/tax/add' % (self.orga1.slug, self.event1.slug))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
form_data['name_0'] = 'VAT'
|
||||
form_data['rate'] = '19.00'
|
||||
form_data['price_includes_tax'] = 'on'
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/tax/add' % (self.orga1.slug, self.event1.slug), form_data)
|
||||
assert doc.select(".alert-success")
|
||||
self.assertIn("VAT", doc.select("#page-wrapper table")[0].text)
|
||||
assert self.event1.tax_rules.get(
|
||||
rate=19, price_includes_tax=True, eu_reverse_charge=False
|
||||
)
|
||||
|
||||
def test_update(self):
|
||||
tr = self.event1.tax_rules.create(rate=19, name="VAT")
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/tax/%s/' % (self.orga1.slug, self.event1.slug, tr.id))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
form_data['rate'] = '20.00'
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/tax/%s/' % (self.orga1.slug, self.event1.slug, tr.id),
|
||||
form_data)
|
||||
assert doc.select(".alert-success")
|
||||
tr.refresh_from_db()
|
||||
assert tr.rate == Decimal('20.00')
|
||||
|
||||
def test_delete(self):
|
||||
tr = self.event1.tax_rules.create(rate=19, name="VAT")
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id),
|
||||
form_data)
|
||||
assert doc.select(".alert-success")
|
||||
self.assertNotIn("VAT", doc.select("#page-wrapper")[0].text)
|
||||
assert not self.event1.tax_rules.exists()
|
||||
|
||||
def test_delete_item_existing(self):
|
||||
tr = self.event1.tax_rules.create(rate=19, name="VAT")
|
||||
self.event1.items.create(name="foo", default_price=12, tax_rule=tr)
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id),
|
||||
form_data)
|
||||
self.assertIn("VAT", doc.select("#page-wrapper")[0].text)
|
||||
assert self.event1.tax_rules.exists()
|
||||
|
||||
def test_delete_default_rule(self):
|
||||
tr = self.event1.tax_rules.create(rate=19, name="VAT")
|
||||
self.event1.settings.tax_rate_default = tr
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id),
|
||||
form_data)
|
||||
self.assertIn("VAT", doc.select("#page-wrapper")[0].text)
|
||||
assert self.event1.tax_rules.exists()
|
||||
|
||||
def test_delete_order_existing(self):
|
||||
tr = self.event1.tax_rules.create(rate=19, name="VAT")
|
||||
self.event1.orders.create(
|
||||
code='FOO', event=self.event1, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PENDING,
|
||||
datetime=now(), expires=now() + datetime.timedelta(days=10),
|
||||
total=14, payment_provider='banktransfer', locale='en',
|
||||
payment_fee=0.3,
|
||||
payment_fee_tax_rate=19,
|
||||
payment_fee_tax_value=0.05,
|
||||
payment_fee_tax_rule=tr
|
||||
)
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id),
|
||||
form_data)
|
||||
self.assertIn("VAT", doc.select("#page-wrapper")[0].text)
|
||||
assert self.event1.tax_rules.exists()
|
||||
|
||||
def test_delete_orderpos_existing(self):
|
||||
tr = self.event1.tax_rules.create(rate=19, name="VAT")
|
||||
i = self.event1.items.create(name="foo", default_price=12)
|
||||
o = self.event1.orders.create(
|
||||
code='FOO', event=self.event1, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PENDING,
|
||||
datetime=now(), expires=now() + datetime.timedelta(days=10),
|
||||
total=12, payment_provider='banktransfer', locale='en'
|
||||
)
|
||||
o.positions.create(
|
||||
item=i, price=12, tax_rule=tr, tax_rate=19, tax_value=12 - 12 / 1.19
|
||||
)
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id))
|
||||
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/tax/%s/delete' % (self.orga1.slug, self.event1.slug, tr.id),
|
||||
form_data)
|
||||
self.assertIn("VAT", doc.select("#page-wrapper")[0].text)
|
||||
assert self.event1.tax_rules.exists()
|
||||
@@ -6,10 +6,12 @@ from bs4 import BeautifulSoup
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.utils.timezone import now
|
||||
from django_countries.fields import Country
|
||||
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models import (
|
||||
CartPosition, Event, Item, ItemCategory, ItemVariation, Organizer,
|
||||
Question, QuestionAnswer, Quota, Voucher,
|
||||
CartPosition, Event, InvoiceAddress, Item, ItemCategory, ItemVariation,
|
||||
Organizer, Question, QuestionAnswer, Quota, Voucher,
|
||||
)
|
||||
from pretix.base.models.items import (
|
||||
ItemAddOn, SubEventItem, SubEventItemVariation,
|
||||
@@ -26,9 +28,11 @@ class CartTestMixin:
|
||||
date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc),
|
||||
live=True
|
||||
)
|
||||
self.tr19 = self.event.tax_rules.create(rate=19)
|
||||
self.category = ItemCategory.objects.create(event=self.event, name="Everything", position=0)
|
||||
self.quota_shirts = Quota.objects.create(event=self.event, name='Shirts', size=2)
|
||||
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', category=self.category, default_price=12)
|
||||
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', category=self.category, default_price=12,
|
||||
tax_rule=self.tr19)
|
||||
self.quota_shirts.items.add(self.shirt)
|
||||
self.shirt_red = ItemVariation.objects.create(item=self.shirt, default_price=14, value='Red')
|
||||
self.shirt_blue = ItemVariation.objects.create(item=self.shirt, value='Blue')
|
||||
@@ -36,7 +40,8 @@ class CartTestMixin:
|
||||
self.quota_shirts.variations.add(self.shirt_blue)
|
||||
self.quota_tickets = Quota.objects.create(event=self.event, name='Tickets', size=5)
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
|
||||
category=self.category, default_price=23)
|
||||
category=self.category, default_price=23,
|
||||
tax_rule=self.tr19)
|
||||
self.quota_tickets.items.add(self.ticket)
|
||||
|
||||
self.quota_all = Quota.objects.create(event=self.event, name='All', size=None)
|
||||
@@ -90,6 +95,35 @@ class CartTest(CartTestMixin, TestCase):
|
||||
self.assertIsNone(objs[0].variation)
|
||||
self.assertEqual(objs[0].price, 23)
|
||||
|
||||
def _set_session(self, key, value):
|
||||
session = self.client.session
|
||||
session[key] = value
|
||||
session.save()
|
||||
|
||||
def _enable_reverse_charge(self):
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('DE')
|
||||
self.tr19.save()
|
||||
ia = InvoiceAddress.objects.create(
|
||||
is_business=True, vat_id='ATU1234567', vat_id_validated=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
self._set_session('invoice_address_{}'.format(self.event.pk), ia.pk)
|
||||
return ia
|
||||
|
||||
def test_reverse_charge(self):
|
||||
self._enable_reverse_charge()
|
||||
response = self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
|
||||
'item_%d' % self.ticket.id: '1'
|
||||
}, follow=True)
|
||||
self.assertRedirects(response, '/%s/%s/' % (self.orga.slug, self.event.slug),
|
||||
target_status_code=200)
|
||||
doc = BeautifulSoup(response.rendered_content, "lxml")
|
||||
self.assertIn('Early-bird', doc.select('.cart .cart-row')[0].select('strong')[0].text)
|
||||
objs = list(CartPosition.objects.filter(cart_id=self.session_key, event=self.event))
|
||||
self.assertEqual(len(objs), 1)
|
||||
self.assertEqual(objs[0].price, round_decimal(Decimal('23.00') / Decimal('1.19')))
|
||||
|
||||
def test_subevent_missing(self):
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
|
||||
@@ -2,16 +2,19 @@ import datetime
|
||||
import os
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
from unittest import mock
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from django.conf import settings
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import TestCase
|
||||
from django.utils.timezone import now
|
||||
from django_countries.fields import Country
|
||||
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models import (
|
||||
CartPosition, Event, Item, ItemCategory, Order, OrderPosition, Organizer,
|
||||
Question, Quota, Voucher,
|
||||
CartPosition, Event, InvoiceAddress, Item, ItemCategory, Order,
|
||||
OrderPosition, Organizer, Question, Quota, Voucher,
|
||||
)
|
||||
from pretix.base.models.items import ItemAddOn, ItemVariation, SubEventItem
|
||||
|
||||
@@ -26,10 +29,12 @@ class CheckoutTestCase(TestCase):
|
||||
plugins='pretix.plugins.stripe,pretix.plugins.banktransfer',
|
||||
live=True
|
||||
)
|
||||
self.tr19 = self.event.tax_rules.create(rate=19)
|
||||
self.category = ItemCategory.objects.create(event=self.event, name="Everything", position=0)
|
||||
self.quota_tickets = Quota.objects.create(event=self.event, name='Tickets', size=5)
|
||||
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
|
||||
category=self.category, default_price=23, admission=True)
|
||||
category=self.category, default_price=23, admission=True,
|
||||
tax_rule=self.tr19)
|
||||
self.quota_tickets.items.add(self.ticket)
|
||||
self.event.settings.set('attendee_names_asked', False)
|
||||
self.event.settings.set('payment_banktransfer__enabled', True)
|
||||
@@ -51,6 +56,17 @@ class CheckoutTestCase(TestCase):
|
||||
self.workshopquota.variations.add(self.workshop2a)
|
||||
self.workshopquota.variations.add(self.workshop2b)
|
||||
|
||||
def _enable_reverse_charge(self):
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('DE')
|
||||
self.tr19.save()
|
||||
ia = InvoiceAddress.objects.create(
|
||||
is_business=True, vat_id='ATU1234567', vat_id_validated=True,
|
||||
country=Country('AT')
|
||||
)
|
||||
self._set_session('invoice_address_{}'.format(self.event.pk), ia.pk)
|
||||
return ia
|
||||
|
||||
def test_empty_cart(self):
|
||||
response = self.client.get('/%s/%s/checkout/start' % (self.orga.slug, self.event.slug), follow=True)
|
||||
self.assertRedirects(response, '/%s/%s/' % (self.orga.slug, self.event.slug),
|
||||
@@ -112,6 +128,218 @@ class CheckoutTestCase(TestCase):
|
||||
self.assertEqual(cr1.answers.filter(question=q2).count(), 1)
|
||||
self.assertFalse(cr2.answers.filter(question=q2).exists())
|
||||
|
||||
def test_reverse_charge(self):
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('DE')
|
||||
self.tr19.save()
|
||||
self.event.settings.invoice_address_vatid = True
|
||||
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10)
|
||||
)
|
||||
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
self.client.post('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), {
|
||||
'is_business': 'business',
|
||||
'company': 'Foo',
|
||||
'name': 'Bar',
|
||||
'street': 'Baz',
|
||||
'zipcode': '12345',
|
||||
'city': 'Here',
|
||||
'country': 'AT',
|
||||
'vat_id': 'AT123456',
|
||||
'email': 'admin@localhost'
|
||||
}, follow=True)
|
||||
|
||||
cr1.refresh_from_db()
|
||||
assert cr1.price == round_decimal(Decimal('23.00') / Decimal('1.19'))
|
||||
|
||||
ia = InvoiceAddress.objects.get(pk=self.client.session.get('invoice_address_{}'.format(self.event.pk)))
|
||||
assert ia.vat_id_validated
|
||||
|
||||
def test_reverse_charge_enable_then_disable(self):
|
||||
self.test_reverse_charge()
|
||||
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
self.client.post('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), {
|
||||
'is_business': 'individual',
|
||||
'name': 'Bar',
|
||||
'street': 'Baz',
|
||||
'zipcode': '12345',
|
||||
'city': 'Here',
|
||||
'country': 'AT',
|
||||
'vat_id': '',
|
||||
'email': 'admin@localhost'
|
||||
}, follow=True)
|
||||
|
||||
cr = CartPosition.objects.get(cart_id=self.session_key)
|
||||
assert cr.price == Decimal('23.00')
|
||||
|
||||
ia = InvoiceAddress.objects.get(pk=self.client.session.get('invoice_address_{}'.format(self.event.pk)))
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
def test_reverse_charge_invalid_vatid(self):
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('DE')
|
||||
self.tr19.save()
|
||||
self.event.settings.invoice_address_vatid = True
|
||||
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10)
|
||||
)
|
||||
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
def raiser(*args, **kwargs):
|
||||
import vat_moss.errors
|
||||
raise vat_moss.errors.InvalidError()
|
||||
|
||||
mock_validate.side_effect = raiser
|
||||
resp = self.client.post('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), {
|
||||
'is_business': 'business',
|
||||
'company': 'Foo',
|
||||
'name': 'Bar',
|
||||
'street': 'Baz',
|
||||
'zipcode': '12345',
|
||||
'city': 'Here',
|
||||
'country': 'AT',
|
||||
'vat_id': 'AT123456',
|
||||
'email': 'admin@localhost'
|
||||
}, follow=True)
|
||||
assert 'alert-danger' in resp.rendered_content
|
||||
|
||||
cr1.refresh_from_db()
|
||||
assert cr1.price == Decimal('23.00')
|
||||
|
||||
def test_reverse_charge_vatid_non_eu(self):
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('NO')
|
||||
self.tr19.save()
|
||||
self.event.settings.invoice_address_vatid = True
|
||||
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10)
|
||||
)
|
||||
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AU', 'AU123456', 'Foo')
|
||||
self.client.post('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), {
|
||||
'is_business': 'business',
|
||||
'company': 'Foo',
|
||||
'name': 'Bar',
|
||||
'street': 'Baz',
|
||||
'zipcode': '12345',
|
||||
'city': 'Here',
|
||||
'country': 'AU',
|
||||
'vat_id': 'AU123456',
|
||||
'email': 'admin@localhost'
|
||||
}, follow=True)
|
||||
|
||||
cr1.refresh_from_db()
|
||||
assert cr1.price == round_decimal(Decimal('23.00') / Decimal('1.19'))
|
||||
|
||||
ia = InvoiceAddress.objects.get(pk=self.client.session.get('invoice_address_{}'.format(self.event.pk)))
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
def test_reverse_charge_vatid_same_country(self):
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('AT')
|
||||
self.tr19.save()
|
||||
self.event.settings.invoice_address_vatid = True
|
||||
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10)
|
||||
)
|
||||
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
self.client.post('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), {
|
||||
'is_business': 'business',
|
||||
'company': 'Foo',
|
||||
'name': 'Bar',
|
||||
'street': 'Baz',
|
||||
'zipcode': '12345',
|
||||
'city': 'Here',
|
||||
'country': 'AT',
|
||||
'vat_id': 'AT123456',
|
||||
'email': 'admin@localhost'
|
||||
}, follow=True)
|
||||
|
||||
cr1.refresh_from_db()
|
||||
assert cr1.price == Decimal('23.00')
|
||||
|
||||
ia = InvoiceAddress.objects.get(pk=self.client.session.get('invoice_address_{}'.format(self.event.pk)))
|
||||
assert ia.vat_id_validated
|
||||
|
||||
def test_reverse_charge_vatid_check_invalid_country(self):
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('DE')
|
||||
self.tr19.save()
|
||||
self.event.settings.invoice_address_vatid = True
|
||||
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10)
|
||||
)
|
||||
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
mock_validate.return_value = ('AT', 'AT123456', 'Foo')
|
||||
resp = self.client.post('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), {
|
||||
'is_business': 'business',
|
||||
'company': 'Foo',
|
||||
'name': 'Bar',
|
||||
'street': 'Baz',
|
||||
'zipcode': '12345',
|
||||
'city': 'Here',
|
||||
'country': 'FR',
|
||||
'vat_id': 'AT123456',
|
||||
'email': 'admin@localhost'
|
||||
}, follow=True)
|
||||
assert 'alert-danger' in resp.rendered_content
|
||||
|
||||
cr1.refresh_from_db()
|
||||
assert cr1.price == Decimal('23.00')
|
||||
|
||||
def test_reverse_charge_vatid_check_unavailable(self):
|
||||
self.tr19.eu_reverse_charge = True
|
||||
self.tr19.home_country = Country('DE')
|
||||
self.tr19.save()
|
||||
self.event.settings.invoice_address_vatid = True
|
||||
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() + timedelta(minutes=10)
|
||||
)
|
||||
|
||||
with mock.patch('vat_moss.id.validate') as mock_validate:
|
||||
def raiser(*args, **kwargs):
|
||||
import vat_moss.errors
|
||||
raise vat_moss.errors.WebServiceUnavailableError('Fail')
|
||||
|
||||
mock_validate.side_effect = raiser
|
||||
self.client.post('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), {
|
||||
'is_business': 'business',
|
||||
'company': 'Foo',
|
||||
'name': 'Bar',
|
||||
'street': 'Baz',
|
||||
'zipcode': '12345',
|
||||
'city': 'Here',
|
||||
'country': 'AT',
|
||||
'vat_id': 'AT123456',
|
||||
'email': 'admin@localhost'
|
||||
}, follow=True)
|
||||
|
||||
cr1.refresh_from_db()
|
||||
assert cr1.price == Decimal('23.00')
|
||||
|
||||
ia = InvoiceAddress.objects.get(pk=self.client.session.get('invoice_address_{}'.format(self.event.pk)))
|
||||
assert not ia.vat_id_validated
|
||||
|
||||
def test_question_file_upload(self):
|
||||
q1 = Question.objects.create(
|
||||
event=self.event, question='Student ID', type=Question.TYPE_FILE,
|
||||
@@ -426,6 +654,22 @@ class CheckoutTestCase(TestCase):
|
||||
self.assertEqual(len(doc.select(".thank-you")), 1)
|
||||
self.assertEqual(OrderPosition.objects.filter(item=self.workshop1).last().price, 0)
|
||||
|
||||
def test_confirm_price_changed_reverse_charge(self):
|
||||
self._enable_reverse_charge()
|
||||
self.ticket.default_price = 24
|
||||
self.ticket.save()
|
||||
cr1 = CartPosition.objects.create(
|
||||
event=self.event, cart_id=self.session_key, item=self.ticket,
|
||||
price=23, expires=now() - timedelta(minutes=10)
|
||||
)
|
||||
self._set_session('payment', 'banktransfer')
|
||||
|
||||
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
doc = BeautifulSoup(response.rendered_content, "lxml")
|
||||
self.assertEqual(len(doc.select(".alert-danger")), 1)
|
||||
cr1 = CartPosition.objects.get(id=cr1.id)
|
||||
self.assertEqual(cr1.price, round_decimal(Decimal('24.00') / Decimal('1.19')))
|
||||
|
||||
def test_confirm_price_changed(self):
|
||||
self.ticket.default_price = 24
|
||||
self.ticket.save()
|
||||
@@ -1018,9 +1262,9 @@ class CheckoutTestCase(TestCase):
|
||||
self.workshopquota.size = 1
|
||||
self.workshopquota.subevent = se
|
||||
self.workshopquota.save()
|
||||
self.workshop1.tax_rate = 19
|
||||
self.workshop1.tax_rule = self.event.tax_rules.get_or_create(rate=Decimal('19.00'), name="VAT")[0]
|
||||
self.workshop1.save()
|
||||
self.workshop2.tax_rate = 19
|
||||
self.workshop2.tax_rule = self.event.tax_rules.get_or_create(rate=Decimal('19.00'), name="VAT")[0]
|
||||
self.workshop2.save()
|
||||
SubEventItem.objects.create(subevent=se, item=self.workshop1, price=42)
|
||||
|
||||
@@ -1033,8 +1277,8 @@ class CheckoutTestCase(TestCase):
|
||||
response = self.client.get('/%s/%s/checkout/questions/' % (self.orga.slug, self.event.slug), follow=True)
|
||||
self.assertRedirects(response, '/%s/%s/checkout/addons/' % (self.orga.slug, self.event.slug),
|
||||
target_status_code=200)
|
||||
assert 'Workshop 1 (+ EUR 35.29 plus 19.00% taxes)' in response.rendered_content
|
||||
assert 'A (+ EUR 10.08 plus 19.00% taxes)' in response.rendered_content
|
||||
assert 'Workshop 1 (+ EUR 35.29 plus 19.00% VAT)' in response.rendered_content
|
||||
assert 'A (+ EUR 10.08 plus 19.00% VAT)' in response.rendered_content
|
||||
|
||||
def test_confirm_subevent_presale_not_yet(self):
|
||||
self.event.has_subevents = True
|
||||
|
||||
@@ -215,8 +215,9 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
self.event.settings.display_net_prices = True
|
||||
se1 = self.event.subevents.create(name='Foo', date_from=now(), active=True)
|
||||
se2 = self.event.subevents.create(name='Foo', date_from=now(), active=True)
|
||||
tr = self.event.tax_rules.get_or_create(rate=Decimal('19.00'))[0]
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=15,
|
||||
tax_rate=19)
|
||||
tax_rule=tr)
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2, subevent=se1)
|
||||
q.items.add(item)
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2, subevent=se2)
|
||||
@@ -463,7 +464,7 @@ class VoucherRedeemItemDisplayTest(EventTestMixin, SoupTest):
|
||||
self.event.settings.display_net_prices = True
|
||||
self.event.has_subevents = True
|
||||
self.event.save()
|
||||
self.item.tax_rate = 19
|
||||
self.item.tax_rule = self.event.tax_rules.get_or_create(rate=Decimal('19.00'))[0]
|
||||
self.item.save()
|
||||
se1 = self.event.subevents.create(name='SE1', date_from=now(), active=True)
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2, subevent=se1)
|
||||
|
||||
Reference in New Issue
Block a user