mirror of
https://github.com/pretix/pretix-servicefees.git
synced 2024-12-24 20:13:08 +01:00
Add tax splitting
This commit is contained in:
commit
8343230a96
3 changed files with 64 additions and 17 deletions
|
@ -1,17 +1,19 @@
|
|||
from collections import defaultdict
|
||||
from decimal import Decimal
|
||||
|
||||
from django.urls import resolve, reverse
|
||||
from django.dispatch import receiver
|
||||
from django.http import HttpRequest
|
||||
from django.utils.translation import gettext_lazy as _, gettext, get_language
|
||||
from django.urls import resolve, reverse
|
||||
from django.utils.translation import get_language, gettext, gettext_lazy as _
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models import Event, Order, TaxRule
|
||||
from pretix.base.models import CartPosition, Event, Order, TaxRule
|
||||
from pretix.base.models.orders import OrderFee
|
||||
from pretix.base.settings import settings_hierarkey
|
||||
from pretix.base.signals import order_fee_calculation
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.control.signals import nav_event_settings
|
||||
from pretix.presale.signals import fee_calculation_for_cart, front_page_top, order_meta_from_request
|
||||
from pretix.presale.signals import (
|
||||
fee_calculation_for_cart, front_page_top, order_meta_from_request,
|
||||
)
|
||||
from pretix.presale.views import get_cart
|
||||
from pretix.presale.views.cart import cart_session
|
||||
|
||||
|
@ -76,17 +78,52 @@ def get_fees(event, total, invoice_address, mod='', request=None, positions=[],
|
|||
summed += fval
|
||||
|
||||
if (fee_per_ticket or fee_abs or fee_percent) and total != Decimal('0.00'):
|
||||
tax_rule_zero = TaxRule.zero()
|
||||
fee = round_decimal(fee_abs + total * (fee_percent / 100) + len(positions) * fee_per_ticket, event.currency)
|
||||
tax_rule = event.settings.tax_rate_default or TaxRule.zero()
|
||||
tax = tax_rule.tax(fee, invoice_address=invoice_address, base_price_is='gross')
|
||||
return [OrderFee(
|
||||
fee_type=OrderFee.FEE_TYPE_SERVICE,
|
||||
internal_type='',
|
||||
value=fee,
|
||||
tax_rate=tax.rate,
|
||||
tax_value=tax.tax,
|
||||
tax_rule=tax_rule
|
||||
)]
|
||||
split_taxes = event.settings.get('service_fee_split_taxes', as_type=bool)
|
||||
if split_taxes:
|
||||
# split taxes based on products ordered
|
||||
d = defaultdict(lambda: Decimal('0.00'))
|
||||
for p in positions:
|
||||
if isinstance(p, CartPosition):
|
||||
tr = p.item.tax_rule
|
||||
else:
|
||||
tr = p.tax_rule
|
||||
d[tr] += p.price - p.tax_value
|
||||
|
||||
base_values = sorted([tuple(t) for t in d.items()], key=lambda t: t[0].rate)
|
||||
sum_base = sum(t[1] for t in base_values)
|
||||
if sum_base:
|
||||
fee_values = [(t[0], round_decimal(fee * t[1] / sum_base, event.currency))
|
||||
for t in base_values]
|
||||
sum_fee = sum(t[1] for t in fee_values)
|
||||
|
||||
# If there are rounding differences, we fix them up, but always leaning to the benefit of the tax
|
||||
# authorities
|
||||
if sum_fee > fee:
|
||||
fee_values[0] = (fee_values[0][0], fee_values[0][1] + (fee - sum_fee))
|
||||
elif sum_fee < fee:
|
||||
fee_values[-1] = (fee_values[-1][0], fee_values[-1][1] + (fee - sum_fee))
|
||||
else:
|
||||
fee_values = [(event.settings.tax_rate_default or tax_rule_zero, fee)]
|
||||
|
||||
else:
|
||||
fee_values = [(event.settings.tax_rate_default or tax_rule_zero, fee)]
|
||||
|
||||
fees = []
|
||||
for tax_rule, price in fee_values:
|
||||
tax_rule = tax_rule or tax_rule_zero
|
||||
tax = tax_rule.tax(price, invoice_address=invoice_address, base_price_is='gross')
|
||||
fees.append(OrderFee(
|
||||
fee_type=OrderFee.FEE_TYPE_SERVICE,
|
||||
internal_type='',
|
||||
value=price,
|
||||
tax_rate=tax.rate,
|
||||
tax_value=tax.tax,
|
||||
tax_rule=tax_rule
|
||||
))
|
||||
return fees
|
||||
|
||||
return []
|
||||
|
||||
|
||||
|
@ -94,7 +131,9 @@ def get_fees(event, total, invoice_address, mod='', request=None, positions=[],
|
|||
def cart_fee(sender: Event, request: HttpRequest, invoice_address, total, **kwargs):
|
||||
mod = ''
|
||||
try:
|
||||
from pretix_resellers.utils import ResellerException, get_reseller_and_user
|
||||
from pretix_resellers.utils import (
|
||||
ResellerException, get_reseller_and_user,
|
||||
)
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
|
@ -153,7 +192,9 @@ def front_page_top_recv(sender: Event, **kwargs):
|
|||
def order_meta_signal(sender: Event, request: HttpRequest, **kwargs):
|
||||
meta = {}
|
||||
try:
|
||||
from pretix_resellers.utils import ResellerException, get_reseller_and_user
|
||||
from pretix_resellers.utils import (
|
||||
ResellerException, get_reseller_and_user,
|
||||
)
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
{% bootstrap_field form.service_fee_skip_free layout="control" %}
|
||||
{% bootstrap_field form.service_fee_abs addon_after=request.event.currency layout="control" %}
|
||||
{% bootstrap_field form.service_fee_percent addon_after="%" layout="control" %}
|
||||
{% bootstrap_field form.service_fee_split_taxes layout="control" %}
|
||||
{% bootstrap_field form.service_fee_skip_if_gift_card layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
|
|
|
@ -46,6 +46,11 @@ class ServiceFeeSettingsForm(SettingsForm):
|
|||
help_text=_('Note that regardless of this setting, a per-ticket fee will not be charged if the entire order is free.'),
|
||||
required=False
|
||||
)
|
||||
service_fee_split_taxes = forms.BooleanField(
|
||||
label=_('Split taxes proportionate to the tax rates and net values of the ordered products.'),
|
||||
help_text=_('If not split based on ordered products, the tax rate falls back to the event’s base tax rate or no tax, if none is given.'),
|
||||
required=False
|
||||
)
|
||||
|
||||
service_fee_abs_resellers = forms.DecimalField(
|
||||
label=_('Fixed fee per order'),
|
||||
|
|
Loading…
Reference in a new issue