forked from CGM_Public/pretix_original
Backend management of gift cards
This commit is contained in:
@@ -21,7 +21,7 @@ class Migration(migrations.Migration):
|
||||
('issuance', models.DateTimeField(auto_now_add=True)),
|
||||
('secret', models.CharField(db_index=True, default=pretix.base.models.giftcards.gen_giftcard_secret, max_length=190, unique=True)),
|
||||
('currency', models.CharField(max_length=10)),
|
||||
('issued_in', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='issued_gift_cards', to='pretixbase.OrderPosition')),
|
||||
('issued_in', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='issued_gift_cards', to='pretixbase.OrderPosition', null=True, blank=True)),
|
||||
('issuer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='issued_gift_cards', to='pretixbase.Organizer')),
|
||||
],
|
||||
),
|
||||
|
||||
29
src/pretix/base/migrations/0136_auto_20190918_1537.py
Normal file
29
src/pretix/base/migrations/0136_auto_20190918_1537.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 2.2.1 on 2019-09-18 15:37
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
|
||||
def fwd(app, schema_editor):
|
||||
Team = app.get_model('pretixbase', 'Team')
|
||||
Team.objects.filter(can_change_organizer_settings=True).update(can_manage_gift_cards=True)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0135_auto_20190910_2020'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='team',
|
||||
name='can_manage_gift_cards',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.RunPython(
|
||||
fwd, migrations.RunPython.noop
|
||||
),
|
||||
]
|
||||
@@ -730,7 +730,7 @@ class Event(EventMixin, LoggedModel):
|
||||
def has_payment_provider(self):
|
||||
result = False
|
||||
for provider in self.get_payment_providers().values():
|
||||
if provider.is_enabled and provider.identifier not in ('free', 'boxoffice', 'offsetting'):
|
||||
if provider.is_enabled and provider.identifier not in ('free', 'boxoffice', 'offsetting', 'giftcard'):
|
||||
result = True
|
||||
break
|
||||
return result
|
||||
|
||||
@@ -4,6 +4,9 @@ from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db.models import Sum
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from pretix.base.models import LoggedModel
|
||||
|
||||
|
||||
def gen_giftcard_secret():
|
||||
@@ -27,7 +30,7 @@ class GiftCardAcceptance(models.Model):
|
||||
)
|
||||
|
||||
|
||||
class GiftCard(models.Model):
|
||||
class GiftCard(LoggedModel):
|
||||
issuer = models.ForeignKey(
|
||||
'Organizer',
|
||||
related_name='issued_gift_cards',
|
||||
@@ -37,6 +40,7 @@ class GiftCard(models.Model):
|
||||
'OrderPosition',
|
||||
related_name='issued_gift_cards',
|
||||
on_delete=models.PROTECT,
|
||||
null=True, blank=True
|
||||
)
|
||||
issuance = models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
@@ -46,8 +50,13 @@ class GiftCard(models.Model):
|
||||
default=gen_giftcard_secret,
|
||||
unique=True,
|
||||
db_index=True,
|
||||
verbose_name=_('Gift card code'),
|
||||
)
|
||||
currency = models.CharField(max_length=10)
|
||||
CURRENCY_CHOICES = [(c.alpha_3, c.alpha_3 + " - " + c.name) for c in settings.CURRENCIES]
|
||||
currency = models.CharField(max_length=10, choices=CURRENCY_CHOICES)
|
||||
|
||||
def __str__(self):
|
||||
return self.secret
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
@@ -88,3 +97,6 @@ class GiftCardTransaction(models.Model):
|
||||
blank=True,
|
||||
on_delete=models.PROTECT
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ("datetime",)
|
||||
|
||||
@@ -156,6 +156,10 @@ class Team(LoggedModel):
|
||||
help_text=_('Someone with this setting can get access to most data of all of your events, i.e. via privacy '
|
||||
'reports, so be careful who you add to this team!')
|
||||
)
|
||||
can_manage_gift_cards = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name=_("Can manage gift cards")
|
||||
)
|
||||
|
||||
can_change_event_settings = models.BooleanField(
|
||||
default=False,
|
||||
|
||||
@@ -502,6 +502,29 @@ class OrganizerFilterForm(FilterForm):
|
||||
return qs
|
||||
|
||||
|
||||
class GiftCardFilterForm(FilterForm):
|
||||
query = forms.CharField(
|
||||
label=_('Search query'),
|
||||
widget=forms.TextInput(attrs={
|
||||
'placeholder': _('Search query'),
|
||||
'autofocus': 'autofocus'
|
||||
}),
|
||||
required=False
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.pop('request')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def filter_qs(self, qs):
|
||||
fdata = self.cleaned_data
|
||||
|
||||
if fdata.get('query'):
|
||||
query = fdata.get('query')
|
||||
qs = qs.filter(secret__icontains=query)
|
||||
return qs
|
||||
|
||||
|
||||
class EventFilterForm(FilterForm):
|
||||
orders = {
|
||||
'slug': 'slug',
|
||||
|
||||
@@ -4,6 +4,7 @@ from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db.models import Q
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
|
||||
from django_scopes.forms import SafeModelMultipleChoiceField
|
||||
@@ -12,7 +13,7 @@ from i18nfield.forms import I18nFormField, I18nTextarea
|
||||
from pretix.api.models import WebHook
|
||||
from pretix.api.webhooks import get_all_webhook_events
|
||||
from pretix.base.forms import I18nModelForm, SettingsForm
|
||||
from pretix.base.models import Device, Organizer, Team
|
||||
from pretix.base.models import Device, GiftCard, Organizer, Team
|
||||
from pretix.control.forms import (
|
||||
ExtFileField, FontSelect, MultipleLanguagesWidget,
|
||||
)
|
||||
@@ -145,6 +146,7 @@ class TeamForm(forms.ModelForm):
|
||||
model = Team
|
||||
fields = ['name', 'all_events', 'limit_events', 'can_create_events',
|
||||
'can_change_teams', 'can_change_organizer_settings',
|
||||
'can_manage_gift_cards',
|
||||
'can_change_event_settings', 'can_change_items',
|
||||
'can_view_orders', 'can_change_orders',
|
||||
'can_view_vouchers', 'can_change_vouchers']
|
||||
@@ -328,3 +330,29 @@ class WebHookForm(forms.ModelForm):
|
||||
field_classes = {
|
||||
'limit_events': SafeModelMultipleChoiceField
|
||||
}
|
||||
|
||||
|
||||
class GiftCardCreateForm(forms.ModelForm):
|
||||
value = forms.DecimalField(
|
||||
label=_('Gift card value')
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.organizer = kwargs.pop('organizer')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clean_secret(self):
|
||||
s = self.cleaned_data['secret']
|
||||
if GiftCard.objects.filter(
|
||||
secret=s
|
||||
).filter(
|
||||
Q(issuer=self.organizer) | Q(issuer__gift_card_collector_acceptance__collector=self.organizer)
|
||||
).exists():
|
||||
raise ValidationError(
|
||||
_('A gift card with the same secret already exists in your or an affiliated organizer account.')
|
||||
)
|
||||
return s
|
||||
|
||||
class Meta:
|
||||
model = GiftCard
|
||||
fields = ['secret', 'currency']
|
||||
|
||||
@@ -437,6 +437,16 @@ def get_organizer_navigation(request):
|
||||
'active': 'organizer.device' in url.url_name,
|
||||
'icon': 'tablet',
|
||||
})
|
||||
if 'can_manage_gift_cards' in request.orgapermset:
|
||||
nav.append({
|
||||
'label': _('Gift cards'),
|
||||
'url': reverse('control:organizer.giftcards', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': 'organizer.giftcard' in url.url_name,
|
||||
'icon': 'credit-card',
|
||||
})
|
||||
if 'can_change_organizer_settings' in request.orgapermset:
|
||||
nav.append({
|
||||
'label': _('Webhooks'),
|
||||
'url': reverse('control:organizer.webhooks', kwargs={
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load money %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% blocktrans trimmed with card=card.secret %}
|
||||
Gift card: {{ card }}
|
||||
{% endblocktrans %}
|
||||
</h1>
|
||||
<div class="panel panel-primary items">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{% trans "Details" %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Gift card code" %}</dt>
|
||||
<dd>{{ card.secret }}</dd>
|
||||
<dt>{% trans "Creation date" %}</dt>
|
||||
<dd>{{ card.issuance|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||
<dt>{% trans "Current value" %}</dt>
|
||||
<dd>{{ card.value|money:card.currency }}</dd>
|
||||
<dt>{% trans "Currency" %}</dt>
|
||||
<dd>{{ card.currency }}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default items">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{% trans "Transactions" %}
|
||||
</h3>
|
||||
</div>
|
||||
<table class="panel-body table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Date" %}</th>
|
||||
<th>{% trans "Order" %}</th>
|
||||
<th class="text-right">{% trans "Value" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for t in card.transactions.all %}
|
||||
<tr>
|
||||
<td>{{ t.datetime|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td>
|
||||
{% if t.order %}
|
||||
<a href="{% url "control:event.order" event=t.order.event.slug organizer=t.order.event.organizer.slug code=t.order.code %}">
|
||||
{{ t.order.full_code }}
|
||||
{% else %}
|
||||
<em>{% trans "Manual transaction" %}</em>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ t.value|money:card.currency }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="text-right">
|
||||
<form class="helper-display-inline form-inline" method="post" action="">
|
||||
{% csrf_token %}
|
||||
<input type="text" class="form-control input-sm" placeholder="{% trans "Value" %}" name="value">
|
||||
<button class="btn btn-primary">
|
||||
<span class="fa fa-plus"></span>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,18 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<h1>{% trans "Create a new gift card" %}</h1>
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
{% bootstrap_field form.secret layout="control" %}
|
||||
{% bootstrap_field form.value layout="control" %}
|
||||
{% bootstrap_field form.currency layout="control" %}
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,74 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load money %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% trans "Issued gift cards" %}
|
||||
</h1>
|
||||
{% if giftcards|length == 0 and not filter_form.filtered %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You haven't issued any gift cards yet. You can either set up a product in an event shop to sell gift cards,
|
||||
or you can manually issue gift cards.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<a href="{% url "control:organizer.giftcard.add" organizer=request.organizer.slug %}"
|
||||
class="btn btn-default btn-lg"><i class="fa fa-plus"></i> {% trans "Manually issue a gift card" %}</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<form class="row filter-form" action="" method="get">
|
||||
<div class="col-md-10 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.query layout='inline' %}
|
||||
</div>
|
||||
<div class="col-md-2 col-sm-6 col-xs-12">
|
||||
<button class="btn btn-primary btn-block" type="submit">
|
||||
<span class="fa fa-filter"></span>
|
||||
<span class="hidden-md">
|
||||
{% trans "Filter" %}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<p>
|
||||
<a href="{% url "control:organizer.giftcard.add" organizer=request.organizer.slug %}"
|
||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Manually issue a gift card" %}</a>
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Gift card code" %}</th>
|
||||
<th>{% trans "Creation date" %}</th>
|
||||
<th class="text-right">{% trans "Current value" %}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for g in giftcards %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=g.id %}">
|
||||
<strong>{{ g.secret }}</strong>
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ g.issuance|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td class="text-right">
|
||||
{{ g.cached_value|money:g.currency }}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=g.id %}"
|
||||
class="btn btn-default btn-sm" data-toggle="tooltip" title="{% trans "Details" %}">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% include "pretixcontrol/pagination.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -22,6 +22,7 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "Organizer permissions" %}</legend>
|
||||
{% bootstrap_field form.can_create_events layout="control" %}
|
||||
{% bootstrap_field form.can_manage_gift_cards layout="control" %}
|
||||
{% bootstrap_field form.can_change_teams layout="control" %}
|
||||
{% bootstrap_field form.can_change_organizer_settings layout="control" %}
|
||||
</fieldset>
|
||||
|
||||
@@ -75,6 +75,9 @@ urlpatterns = [
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/delete$', organizer.OrganizerDelete.as_view(), name='organizer.delete'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/settings/display$', organizer.OrganizerDisplaySettings.as_view(),
|
||||
name='organizer.display'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/giftcards$', organizer.GiftCardListView.as_view(), name='organizer.giftcards'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/giftcard/add$', organizer.GiftCardCreateView.as_view(), name='organizer.giftcard.add'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/$', organizer.GiftCardDetailView.as_view(), name='organizer.giftcard'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/webhooks$', organizer.WebHookListView.as_view(), name='organizer.webhooks'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/webhook/add$', organizer.WebHookCreateView.as_view(),
|
||||
name='organizer.webhook.add'),
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import json
|
||||
from decimal import Decimal
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.exceptions import PermissionDenied, ValidationError
|
||||
from django.core.files import File
|
||||
from django.db import transaction
|
||||
from django.db.models import Count, Max, Min, ProtectedError
|
||||
from django.db.models import Count, DecimalField, Max, Min, ProtectedError, Sum
|
||||
from django.db.models.functions import Coalesce, Greatest
|
||||
from django.forms import inlineformset_factory
|
||||
from django.http import JsonResponse
|
||||
@@ -21,14 +22,17 @@ from django.views.generic import (
|
||||
|
||||
from pretix.api.models import WebHook
|
||||
from pretix.base.auth import get_auth_backends
|
||||
from pretix.base.models import Device, Organizer, Team, TeamInvite, User
|
||||
from pretix.base.models import (
|
||||
Device, GiftCard, Organizer, Team, TeamInvite, User,
|
||||
)
|
||||
from pretix.base.models.event import Event, EventMetaProperty
|
||||
from pretix.base.models.organizer import TeamAPIToken
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.control.forms.filter import OrganizerFilterForm
|
||||
from pretix.control.forms.filter import GiftCardFilterForm, OrganizerFilterForm
|
||||
from pretix.control.forms.organizer import (
|
||||
DeviceForm, EventMetaPropertyForm, OrganizerDeleteForm, OrganizerForm,
|
||||
OrganizerSettingsForm, OrganizerUpdateForm, TeamForm, WebHookForm,
|
||||
DeviceForm, EventMetaPropertyForm, GiftCardCreateForm, OrganizerDeleteForm,
|
||||
OrganizerForm, OrganizerSettingsForm, OrganizerUpdateForm, TeamForm,
|
||||
WebHookForm,
|
||||
)
|
||||
from pretix.control.permissions import (
|
||||
AdministratorPermissionRequiredMixin, OrganizerPermissionRequiredMixin,
|
||||
@@ -337,7 +341,7 @@ class OrganizerCreate(CreateView):
|
||||
ret = super().form_valid(form)
|
||||
t = Team.objects.create(
|
||||
organizer=form.instance, name=_('Administrators'),
|
||||
all_events=True, can_create_events=True, can_change_teams=True,
|
||||
all_events=True, can_create_events=True, can_change_teams=True, can_manage_gift_cards=True,
|
||||
can_change_organizer_settings=True, can_change_event_settings=True, can_change_items=True,
|
||||
can_view_orders=True, can_change_orders=True, can_view_vouchers=True, can_change_vouchers=True
|
||||
)
|
||||
@@ -898,3 +902,109 @@ class WebHookLogsView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin
|
||||
|
||||
def get_queryset(self):
|
||||
return self.webhook.calls.order_by('-datetime')
|
||||
|
||||
|
||||
class GiftCardListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
||||
model = GiftCard
|
||||
template_name = 'pretixcontrol/organizers/giftcards.html'
|
||||
permission = 'can_manage_gift_cards'
|
||||
context_object_name = 'giftcards'
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.organizer.issued_gift_cards.annotate(
|
||||
cached_value=Sum('transactions__value')
|
||||
)
|
||||
if self.filter_form.is_valid():
|
||||
qs = self.filter_form.filter_qs(qs)
|
||||
return qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['filter_form'] = self.filter_form
|
||||
return ctx
|
||||
|
||||
@cached_property
|
||||
def filter_form(self):
|
||||
return GiftCardFilterForm(data=self.request.GET, request=self.request)
|
||||
|
||||
|
||||
class GiftCardDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView):
|
||||
template_name = 'pretixcontrol/organizers/giftcard.html'
|
||||
permission = 'can_manage_gift_cards'
|
||||
context_object_name = 'card'
|
||||
|
||||
def get_object(self, queryset=None) -> Organizer:
|
||||
return get_object_or_404(
|
||||
self.request.organizer.issued_gift_cards,
|
||||
pk=self.kwargs.get('giftcard')
|
||||
)
|
||||
|
||||
@transaction.atomic()
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
if 'value' in request.POST:
|
||||
try:
|
||||
value = DecimalField().to_python(request.POST.get('value'))
|
||||
except ValidationError:
|
||||
messages.error(request, _('Your input was invalid, please try again.'))
|
||||
else:
|
||||
if self.object.value + value < Decimal('0.00'):
|
||||
messages.error(request, _('Gift cards are not allowed to have negative values.'))
|
||||
else:
|
||||
self.object.transactions.create(
|
||||
value=value
|
||||
)
|
||||
self.object.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
data={
|
||||
'value': value
|
||||
},
|
||||
user=self.request.user,
|
||||
)
|
||||
messages.success(request, _('The manual transaction has been saved.'))
|
||||
return redirect(reverse(
|
||||
'control:organizer.giftcard',
|
||||
kwargs={
|
||||
'organizer': request.organizer.slug,
|
||||
'giftcard': self.object.pk
|
||||
}
|
||||
))
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class GiftCardCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView):
|
||||
template_name = 'pretixcontrol/organizers/giftcard_create.html'
|
||||
permission = 'can_manage_gift_cards'
|
||||
form_class = GiftCardCreateForm
|
||||
success_url = 'invalid'
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
any_event = self.request.organizer.events.first()
|
||||
kwargs['initial'] = {
|
||||
'currency': any_event.currency if any_event else settings.DEFAULT_CURRENCY
|
||||
}
|
||||
kwargs['organizer'] = self.request.organizer
|
||||
return kwargs
|
||||
|
||||
@transaction.atomic()
|
||||
def post(self, request, *args, **kwargs):
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
messages.success(self.request, _('The gift card has been created and can now be used.'))
|
||||
form.instance.issuer = self.request.organizer
|
||||
super().form_valid(form)
|
||||
form.instance.transactions.create(
|
||||
value=form.cleaned_data['value']
|
||||
)
|
||||
form.instance.log_action('pretix.giftcards.transaction.manual', user=self.request.user, data={
|
||||
'value': form.cleaned_data['value']
|
||||
})
|
||||
return redirect(reverse(
|
||||
'control:organizer.giftcard',
|
||||
kwargs={
|
||||
'organizer': self.request.organizer.slug,
|
||||
'giftcard': self.object.pk
|
||||
}
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user