diff --git a/src/pretix/control/templatetags/hierarkey_form.py b/src/pretix/control/templatetags/hierarkey_form.py index f1c91b59b1..faede40d1e 100644 --- a/src/pretix/control/templatetags/hierarkey_form.py +++ b/src/pretix/control/templatetags/hierarkey_form.py @@ -2,6 +2,8 @@ from django import template from django.template import Node from django.utils.translation import ugettext as _ +from pretix.base.models import Event + register = template.Library() @@ -39,15 +41,19 @@ class PropagatedNode(Node): """.format( body=body, - text_inh=_("Organizer-level settings"), + text_inh=_("Organizer-level settings") if isinstance(event, Event) else _('Site-level settings'), fnames=','.join(self.field_names), text_expl=_( 'These settings are currently set on organizer level. This way, you can easily change them for ' 'all of your events at the same time. You can either go to the organizer settings to change them ' 'or decouple them from the organizer account to change them for this event individually.' + ) if isinstance(event, Event) else _( + 'These settings are currently set on global level. This way, you can easily change them for ' + 'all organizers at the same time. You can either go to the global settings to change them ' + 'or decouple them from the global settings to change them for this event individually.' ), - text_unlink=_('Change only for this event'), - text_orga=_('Change for all events'), + text_unlink=_('Change only for this event') if isinstance(event, Event) else _('Change only for this organizer'), + text_orga=_('Change for all events') if isinstance(event, Event) else _('Change for all organizers'), url=url ) diff --git a/src/pretix/plugins/stripe/forms.py b/src/pretix/plugins/stripe/forms.py index 92d45d2958..82bb386cfc 100644 --- a/src/pretix/plugins/stripe/forms.py +++ b/src/pretix/plugins/stripe/forms.py @@ -1,6 +1,8 @@ from django import forms from django.utils.translation import ugettext_lazy as _ +from pretix.base.forms import SettingsForm + class StripeKeyValidator: def __init__(self, prefix): @@ -21,3 +23,18 @@ class StripeKeyValidator: 'prefix': self._prefixes[0], }, ) + + +class OrganizerStripeSettingsForm(SettingsForm): + payment_stripe_connect_app_fee_percent = forms.DecimalField( + label=_('Stripe Connect: App fee (percent)'), + required=False, + ) + payment_stripe_connect_app_fee_max = forms.DecimalField( + label=_('Stripe Connect: App fee (max)'), + required=False, + ) + payment_stripe_connect_app_fee_min = forms.DecimalField( + label=_('Stripe Connect: App fee (min)'), + required=False, + ) diff --git a/src/pretix/plugins/stripe/payment.py b/src/pretix/plugins/stripe/payment.py index 291e22f1eb..f7e4ee5bb7 100644 --- a/src/pretix/plugins/stripe/payment.py +++ b/src/pretix/plugins/stripe/payment.py @@ -3,6 +3,7 @@ import json import logging import urllib.parse from collections import OrderedDict +from decimal import Decimal import stripe from django import forms @@ -256,6 +257,20 @@ class StripeMethod(BasePaymentProvider): def _get_amount(self, payment): return self._decimal_to_int(payment.amount) + def _connect_kwargs(self, payment): + d = {} + if self.settings.connect_client_id and self.settings.connect_user_id: + fee = Decimal('0.00') + if self.settings.get('connect_app_fee_percent', as_type=Decimal): + fee = round_decimal(self.settings.get('connect_app_fee_percent', as_type=Decimal) * payment.amount / Decimal('100.00'), self.event.currency) + if self.settings.connect_app_fee_max: + fee = min(fee, self.settings.get('connect_app_fee_max', as_type=Decimal)) + if self.settings.get('connect_app_fee_min', as_type=Decimal): + fee = max(fee, self.settings.get('connect_app_fee_min', as_type=Decimal)) + if fee: + d['application_fee_amount'] = self._decimal_to_int(fee) + return d + @property def api_kwargs(self): if self.settings.connect_client_id and self.settings.connect_user_id: @@ -301,6 +316,7 @@ class StripeMethod(BasePaymentProvider): code=payment.order.code )[:22] params.update(self.api_kwargs) + params.update(self._connect_kwargs(payment)) charge = stripe.Charge.create( amount=self._get_amount(payment), currency=self.event.currency.lower(), @@ -612,6 +628,9 @@ class StripeCC(StripeMethod): try: if self.payment_is_valid_session(request): + params = {} + params.update(self._connect_kwargs(payment)) + params.update(self.api_kwargs) intent = stripe.PaymentIntent.create( amount=self._get_amount(payment), currency=self.event.currency.lower(), @@ -638,7 +657,7 @@ class StripeCC(StripeMethod): 'payment': payment.pk, 'hash': hashlib.sha1(payment.order.secret.lower().encode()).hexdigest(), }), - **self.api_kwargs + **params ) else: payment_info = json.loads(payment.info) diff --git a/src/pretix/plugins/stripe/signals.py b/src/pretix/plugins/stripe/signals.py index e1c05b29b8..200de8a525 100644 --- a/src/pretix/plugins/stripe/signals.py +++ b/src/pretix/plugins/stripe/signals.py @@ -4,7 +4,7 @@ from collections import OrderedDict from django import forms from django.dispatch import receiver from django.template.loader import get_template -from django.urls import resolve +from django.urls import resolve, reverse from django.utils.translation import ugettext_lazy as _ from pretix.base.settings import settings_hierarkey @@ -12,6 +12,7 @@ from pretix.base.signals import ( logentry_display, register_global_settings, register_payment_providers, requiredaction_display, ) +from pretix.control.signals import nav_organizer from pretix.plugins.stripe.forms import StripeKeyValidator from pretix.presale.signals import html_head @@ -121,6 +122,18 @@ def register_global_settings(sender, **kwargs): StripeKeyValidator('pk_test_'), ), )), + ('payment_stripe_connect_app_fee_percent', forms.DecimalField( + label=_('Stripe Connect: App fee (percent)'), + required=False, + )), + ('payment_stripe_connect_app_fee_max', forms.DecimalField( + label=_('Stripe Connect: App fee (max)'), + required=False, + )), + ('payment_stripe_connect_app_fee_min', forms.DecimalField( + label=_('Stripe Connect: App fee (min)'), + required=False, + )), ]) @@ -141,3 +154,20 @@ def pretixcontrol_action_display(sender, action, request, **kwargs): ctx = {'data': data, 'event': sender, 'action': action} return template.render(ctx, request) + + +@receiver(nav_organizer, dispatch_uid="stripe_nav_organizer") +def nav_o(sender, request, organizer, **kwargs): + if request.user.has_active_staff_session(request.session.session_key): + url = resolve(request.path_info) + return [{ + 'label': _('Stripe Connect'), + 'url': reverse('plugins:stripe:settings.connect', kwargs={ + 'organizer': request.organizer.slug + }), + 'parent': reverse('control:organizer.edit', kwargs={ + 'organizer': request.organizer.slug + }), + 'active': 'settings.connect' in url.url_name, + }] + return [] diff --git a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/organizer_stripe.html b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/organizer_stripe.html new file mode 100644 index 0000000000..e42a60fe24 --- /dev/null +++ b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/organizer_stripe.html @@ -0,0 +1,24 @@ +{% extends "pretixcontrol/base.html" %} +{% load i18n %} +{% load bootstrap3 %} +{% load hierarkey_form %} +{% load formset_tags %} +{% block title %}{% trans "Stripe Connect" %}{% endblock %} +{% block content %} +