mirror of
https://github.com/pretix/pretix.git
synced 2026-08-06 10:07:50 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e3370fa89 | ||
|
|
9232f9e9fe | ||
|
|
c3ac143388 | ||
|
|
7e61dbaefb | ||
|
|
aee76b094d | ||
|
|
ad78934ad2 | ||
|
|
b5ba8c7304 | ||
|
|
3aefd9f95e | ||
|
|
98a54c6d21 | ||
|
|
77d8a587fe |
@@ -60,6 +60,9 @@ The following values for ``action_types`` are valid with pretix core:
|
||||
* ``pretix.event.added``
|
||||
* ``pretix.event.changed``
|
||||
* ``pretix.event.deleted``
|
||||
* ``pretix.giftcards.created``
|
||||
* ``pretix.giftcards.modified``
|
||||
* ``pretix.giftcards.transaction.*``
|
||||
* ``pretix.voucher.added``
|
||||
* ``pretix.voucher.changed``
|
||||
* ``pretix.voucher.deleted``
|
||||
|
||||
+3
-3
@@ -65,7 +65,7 @@ dependencies = [
|
||||
"kombu==5.6.*",
|
||||
"libsass==0.23.*",
|
||||
"lxml",
|
||||
"markdown==3.10.1", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
|
||||
"markdown==3.10", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
|
||||
# We can upgrade markdown again once django-bootstrap3 upgrades or once we drop Python 3.6 and 3.7
|
||||
"mt-940==4.30.*",
|
||||
"oauthlib==3.3.*",
|
||||
@@ -80,7 +80,7 @@ dependencies = [
|
||||
"protobuf==6.33.*",
|
||||
"psycopg2-binary",
|
||||
"pycountry",
|
||||
"pycparser==3.0",
|
||||
"pycparser==2.23",
|
||||
"pycryptodome==3.23.*",
|
||||
"pypdf==6.5.*",
|
||||
"python-bidi==0.6.*", # Support for Arabic in reportlab
|
||||
@@ -92,7 +92,7 @@ dependencies = [
|
||||
"redis==7.1.*",
|
||||
"reportlab==4.4.*",
|
||||
"requests==2.32.*",
|
||||
"sentry-sdk==2.50.*",
|
||||
"sentry-sdk==2.49.*",
|
||||
"sepaxml==2.7.*",
|
||||
"stripe==7.9.*",
|
||||
"text-unidecode==1.*",
|
||||
|
||||
@@ -966,7 +966,6 @@ class CheckinRPCSearchView(ListAPIView):
|
||||
def get_serializer_context(self):
|
||||
ctx = super().get_serializer_context()
|
||||
ctx['expand'] = self.request.query_params.getlist('expand')
|
||||
ctx['organizer'] = self.request.organizer
|
||||
ctx['pdf_data'] = False
|
||||
return ctx
|
||||
|
||||
|
||||
@@ -249,12 +249,17 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
def perform_create(self, serializer):
|
||||
value = serializer.validated_data.pop('value')
|
||||
inst = serializer.save(issuer=self.request.organizer)
|
||||
inst.transactions.create(value=value, acceptor=self.request.organizer)
|
||||
inst.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
action='pretix.giftcards.created',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=merge_dicts(self.request.data, {'id': inst.pk})
|
||||
)
|
||||
inst.transactions.create(value=value, acceptor=self.request.organizer)
|
||||
inst.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=merge_dicts(self.request.data, {'id': inst.pk, 'acceptor_id': self.request.organizer.id})
|
||||
)
|
||||
|
||||
@transaction.atomic()
|
||||
@@ -269,7 +274,7 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
inst = serializer.save(secret=serializer.instance.secret, currency=serializer.instance.currency,
|
||||
testmode=serializer.instance.testmode)
|
||||
inst.log_action(
|
||||
'pretix.giftcards.modified',
|
||||
action='pretix.giftcards.modified',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=self.request.data,
|
||||
@@ -282,10 +287,10 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
diff = value - old_value
|
||||
inst.transactions.create(value=diff, acceptor=self.request.organizer)
|
||||
inst.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={'value': diff}
|
||||
data={'value': diff, 'acceptor_id': self.request.organizer.id}
|
||||
)
|
||||
|
||||
return inst
|
||||
@@ -309,10 +314,14 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
}, status=status.HTTP_409_CONFLICT)
|
||||
gc.transactions.create(value=value, text=text, info=info, acceptor=self.request.organizer)
|
||||
gc.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={'value': value, 'text': text}
|
||||
data={
|
||||
'value': value,
|
||||
'text': text,
|
||||
'acceptor_id': self.request.organizer.id
|
||||
}
|
||||
)
|
||||
return Response(GiftCardSerializer(gc, context=self.get_serializer_context()).data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
@@ -174,6 +174,35 @@ class ParametrizedEventWebhookEvent(ParametrizedWebhookEvent):
|
||||
}
|
||||
|
||||
|
||||
class ParametrizedGiftcardWebhookEvent(ParametrizedWebhookEvent):
|
||||
def build_payload(self, logentry: LogEntry):
|
||||
giftcard = logentry.content_object
|
||||
if not giftcard:
|
||||
return None
|
||||
|
||||
return {
|
||||
'notification_id': logentry.pk,
|
||||
'issuer_id': logentry.organizer_id,
|
||||
'giftcard': giftcard.pk,
|
||||
'action': logentry.action_type,
|
||||
}
|
||||
|
||||
|
||||
class ParametrizedGiftcardTransactionWebhookEvent(ParametrizedWebhookEvent):
|
||||
def build_payload(self, logentry: LogEntry):
|
||||
giftcard = logentry.content_object
|
||||
if not giftcard:
|
||||
return None
|
||||
|
||||
return {
|
||||
'notification_id': logentry.pk,
|
||||
'issuer_id': logentry.organizer_id,
|
||||
'acceptor_id': logentry.parsed_data.get('acceptor_id'),
|
||||
'giftcard': giftcard.pk,
|
||||
'action': logentry.action_type,
|
||||
}
|
||||
|
||||
|
||||
class ParametrizedVoucherWebhookEvent(ParametrizedWebhookEvent):
|
||||
|
||||
def build_payload(self, logentry: LogEntry):
|
||||
@@ -433,6 +462,18 @@ def register_default_webhook_events(sender, **kwargs):
|
||||
'pretix.customer.anonymized',
|
||||
_('Customer account anonymized'),
|
||||
),
|
||||
ParametrizedGiftcardWebhookEvent(
|
||||
'pretix.giftcards.created',
|
||||
_('Gift card added'),
|
||||
),
|
||||
ParametrizedGiftcardWebhookEvent(
|
||||
'pretix.giftcards.modified',
|
||||
_('Gift card modified'),
|
||||
),
|
||||
ParametrizedGiftcardTransactionWebhookEvent(
|
||||
'pretix.giftcards.transaction.*',
|
||||
_('Gift card used in transcation'),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -617,7 +617,6 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
_('Country'),
|
||||
pgettext('address', 'State'),
|
||||
_('Voucher'),
|
||||
_('Voucher budget usage'),
|
||||
_('Pseudonymization ID'),
|
||||
_('Ticket secret'),
|
||||
_('Seat ID'),
|
||||
@@ -735,7 +734,6 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
op.country if op.country else '',
|
||||
op.state_for_address or '',
|
||||
op.voucher.code if op.voucher else '',
|
||||
op.voucher_budget_use if op.voucher_budget_use else '',
|
||||
op.pseudonymization_id,
|
||||
op.secret,
|
||||
]
|
||||
|
||||
@@ -141,7 +141,7 @@ def get_babel_locale():
|
||||
|
||||
for locale in try_locales:
|
||||
if localedata.exists(locale):
|
||||
return localedata.normalize_locale(locale)
|
||||
return locale
|
||||
|
||||
return "en"
|
||||
|
||||
|
||||
@@ -130,6 +130,8 @@ class LoggingMixin:
|
||||
organizer_id = self.event.organizer_id
|
||||
elif hasattr(self, 'organizer_id'):
|
||||
organizer_id = self.organizer_id
|
||||
elif hasattr(self, 'issuer_id'):
|
||||
organizer_id = self.issuer_id
|
||||
|
||||
if user and not user.is_authenticated:
|
||||
user = None
|
||||
|
||||
@@ -1646,6 +1646,13 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
'transaction_id': trans.pk,
|
||||
}
|
||||
payment.confirm(send_mail=not is_early_special_case, generate_invoice=not is_early_special_case)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.payment',
|
||||
data={
|
||||
'value': trans.value,
|
||||
'acceptor_id': self.event.organizer.id
|
||||
}
|
||||
)
|
||||
except PaymentException as e:
|
||||
payment.fail(info={'error': str(e)})
|
||||
raise e
|
||||
@@ -1670,6 +1677,14 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
'transaction_id': trans.pk,
|
||||
}
|
||||
refund.done()
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.refund',
|
||||
data={
|
||||
'value': refund.amount,
|
||||
'acceptor_id': self.event.organizer.id,
|
||||
'text': refund.comment,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@receiver(register_payment_providers, dispatch_uid="payment_free")
|
||||
|
||||
@@ -248,6 +248,15 @@ def reactivate_order(order: Order, force: bool=False, user: User=None, auth=None
|
||||
for gc in position.issued_gift_cards.all():
|
||||
gc = GiftCard.objects.select_for_update(of=OF_SELF).get(pk=gc.pk)
|
||||
gc.transactions.create(value=position.price, order=order, acceptor=order.event.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=user,
|
||||
auth=auth,
|
||||
data={
|
||||
'value': position.price,
|
||||
'acceptor_id': order.event.organizer.id
|
||||
}
|
||||
)
|
||||
break
|
||||
|
||||
for m in position.granted_memberships.all():
|
||||
@@ -558,6 +567,14 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
|
||||
)
|
||||
else:
|
||||
gc.transactions.create(value=-position.price, order=order, acceptor=order.event.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=user,
|
||||
data={
|
||||
'value': -position.price,
|
||||
'acceptor_id': order.event.organizer.id,
|
||||
}
|
||||
)
|
||||
|
||||
for m in position.granted_memberships.all():
|
||||
m.canceled = True
|
||||
@@ -2461,6 +2478,15 @@ class OrderChangeManager:
|
||||
))
|
||||
else:
|
||||
gc.transactions.create(value=-position.price, order=self.order, acceptor=self.order.event.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.user,
|
||||
auth=self.auth,
|
||||
data={
|
||||
'value': -position.price,
|
||||
'acceptor_id': self.order.event.organizer.id
|
||||
}
|
||||
)
|
||||
|
||||
for m in position.granted_memberships.with_usages().all():
|
||||
m.canceled = True
|
||||
@@ -2478,6 +2504,15 @@ class OrderChangeManager:
|
||||
))
|
||||
else:
|
||||
gc.transactions.create(value=-opa.position.price, order=self.order, acceptor=self.order.event.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.user,
|
||||
auth=self.auth,
|
||||
data={
|
||||
'value': -opa.position.price,
|
||||
'acceptor_id': self.order.event.organizer.id
|
||||
}
|
||||
)
|
||||
|
||||
for m in opa.granted_memberships.with_usages().all():
|
||||
m.canceled = True
|
||||
@@ -3131,7 +3166,10 @@ def _try_auto_refund(order, auto_refund=True, manual_refund=False, allow_partial
|
||||
customer=order.customer,
|
||||
testmode=order.testmode
|
||||
)
|
||||
giftcard.log_action('pretix.giftcards.created', data={})
|
||||
giftcard.log_action(
|
||||
action='pretix.giftcards.created',
|
||||
data={}
|
||||
)
|
||||
r = order.refunds.create(
|
||||
order=order,
|
||||
payment=None,
|
||||
@@ -3414,7 +3452,17 @@ def signal_listener_issue_giftcards(sender: Event, order: Order, **kwargs):
|
||||
currency=sender.currency, issued_in=p, testmode=order.testmode,
|
||||
expires=sender.organizer.default_gift_card_expiry,
|
||||
)
|
||||
gc.transactions.create(value=p.price - issued, order=order, acceptor=sender.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.created',
|
||||
)
|
||||
trans = gc.transactions.create(value=p.price - issued, order=order, acceptor=sender.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
data={
|
||||
'value': trans.value,
|
||||
'acceptor_id': order.event.organizer.id,
|
||||
}
|
||||
)
|
||||
any_giftcards = True
|
||||
p.secret = gc.secret
|
||||
p.save(update_fields=['secret'])
|
||||
|
||||
@@ -112,8 +112,7 @@ def dictsum(*dicts) -> dict:
|
||||
|
||||
def order_overview(
|
||||
event: Event, subevent: SubEvent=None, date_filter='', date_from=None, date_until=None, fees=False,
|
||||
admission_only=False, base_qs=None, base_fees_qs=None, subevent_date_from=None, subevent_date_until=None,
|
||||
skip_empty_lines=False,
|
||||
admission_only=False, base_qs=None, base_fees_qs=None, subevent_date_from=None, subevent_date_until=None
|
||||
) -> Tuple[List[Tuple[ItemCategory, List[Item]]], Dict[str, Tuple[Decimal, Decimal]]]:
|
||||
items = event.items.all().select_related(
|
||||
'category', # for re-grouping
|
||||
@@ -206,21 +205,13 @@ def order_overview(
|
||||
for l in states.keys():
|
||||
var.num[l] = num[l].get((item.id, variid), (0, 0, 0))
|
||||
var.num['total'] = num['total'].get((item.id, variid), (0, 0, 0))
|
||||
var._skip = all(v[0] == 0 for v in var.num.values())
|
||||
for l in states.keys():
|
||||
item.num[l] = tuplesum(var.num[l] for var in item.all_variations)
|
||||
item.num['total'] = tuplesum(var.num['total'] for var in item.all_variations)
|
||||
if skip_empty_lines:
|
||||
item.all_variations = [v for v in item.all_variations if not v._skip]
|
||||
item._skip = not item.all_variations
|
||||
else:
|
||||
for l in states.keys():
|
||||
item.num[l] = num[l].get((item.id, None), (0, 0, 0))
|
||||
item.num['total'] = num['total'].get((item.id, None), (0, 0, 0))
|
||||
item._skip = all(v[0] == 0 for v in item.num.values())
|
||||
|
||||
if skip_empty_lines:
|
||||
items = [i for i in items if not i._skip]
|
||||
|
||||
nonecat = ItemCategory(name=_('Uncategorized'))
|
||||
# Regroup those by category
|
||||
|
||||
@@ -1315,10 +1315,10 @@ class QuestionAnswerFilterForm(forms.Form):
|
||||
|
||||
if date_range is not None:
|
||||
d_start, d_end = resolve_timeframe_to_datetime_start_inclusive_end_exclusive(now(), date_range, self.event.timezone)
|
||||
if d_start:
|
||||
opqs = opqs.filter(subevent__date_from__gte=d_start)
|
||||
if d_end:
|
||||
opqs = opqs.filter(subevent__date_from__lt=d_end)
|
||||
opqs = opqs.filter(
|
||||
subevent__date_from__gte=d_start,
|
||||
subevent__date_from__lt=d_end
|
||||
)
|
||||
|
||||
s = fdata.get("status", Order.STATUS_PENDING + Order.STATUS_PAID)
|
||||
if s != "":
|
||||
|
||||
@@ -793,6 +793,8 @@ class CoreUserImpersonatedLogEntryType(UserImpersonatedLogEntryType):
|
||||
'pretix.giftcards.created': _('The gift card has been created.'),
|
||||
'pretix.giftcards.modified': _('The gift card has been changed.'),
|
||||
'pretix.giftcards.transaction.manual': _('A manual transaction has been performed.'),
|
||||
'pretix.giftcards.transaction.payment': _('A payment has been performed.'),
|
||||
'pretix.giftcards.transaction.refund': _('A refund has been performed. '),
|
||||
'pretix.team.token.created': _('The token "{name}" has been created.'),
|
||||
'pretix.team.token.deleted': _('The token "{name}" has been revoked.'),
|
||||
'pretix.event.checkin.reset': _('The check-in and print log state has been reset.')
|
||||
|
||||
@@ -1230,7 +1230,11 @@ class OrderRefundView(OrderView):
|
||||
customer=order.customer,
|
||||
testmode=order.testmode
|
||||
)
|
||||
giftcard.log_action('pretix.giftcards.created', user=self.request.user, data={})
|
||||
giftcard.log_action(
|
||||
action='pretix.giftcards.created',
|
||||
user=self.request.user,
|
||||
data={}
|
||||
)
|
||||
refunds.append(OrderRefund(
|
||||
order=order,
|
||||
payment=None,
|
||||
@@ -2790,16 +2794,7 @@ class ExportView(EventPermissionRequiredMixin, ExportMixin, ListView):
|
||||
@transaction.atomic()
|
||||
def post(self, request, *args, **kwargs):
|
||||
if request.POST.get("schedule") == "save":
|
||||
if not self.has_permission():
|
||||
messages.error(
|
||||
self.request,
|
||||
_(
|
||||
"Your user account does not have sufficient permission to run this report, therefore "
|
||||
"you cannot schedule it."
|
||||
)
|
||||
)
|
||||
return super().get(request, *args, **kwargs)
|
||||
elif self.exporter.form.is_valid() and self.rrule_form.is_valid() and self.schedule_form.is_valid():
|
||||
if self.exporter.form.is_valid() and self.rrule_form.is_valid() and self.schedule_form.is_valid():
|
||||
self.schedule_form.instance.export_identifier = self.exporter.identifier
|
||||
self.schedule_form.instance.export_form_data = self.exporter.form.cleaned_data
|
||||
self.schedule_form.instance.schedule_rrule = str(self.rrule_form.to_rrule())
|
||||
@@ -2878,8 +2873,17 @@ class ExportView(EventPermissionRequiredMixin, ExportMixin, ListView):
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
if "schedule" in self.request.POST or self.scheduled:
|
||||
ctx['schedule_form'] = self.schedule_form
|
||||
ctx['rrule_form'] = self.rrule_form
|
||||
if "schedule" in self.request.POST and not self.has_permission():
|
||||
messages.error(
|
||||
self.request,
|
||||
_(
|
||||
"Your user account does not have sufficient permission to run this report, therefore "
|
||||
"you cannot schedule it."
|
||||
)
|
||||
)
|
||||
else:
|
||||
ctx['schedule_form'] = self.schedule_form
|
||||
ctx['rrule_form'] = self.rrule_form
|
||||
elif not self.exporter:
|
||||
for s in ctx['scheduled']:
|
||||
try:
|
||||
|
||||
@@ -1669,9 +1669,12 @@ class GiftCardAcceptanceInviteView(OrganizerDetailViewMixin, OrganizerPermission
|
||||
active=False,
|
||||
)
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.acceptor.invited',
|
||||
data={'acceptor': form.cleaned_data['acceptor'].slug,
|
||||
'reusable_media': form.cleaned_data['reusable_media']},
|
||||
action='pretix.giftcards.acceptance.acceptor.invited',
|
||||
data={
|
||||
'acceptor': form.cleaned_data['acceptor'].slug,
|
||||
'issuer': self.request.organizer.slug,
|
||||
'reusable_media': form.cleaned_data['reusable_media']
|
||||
},
|
||||
user=self.request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected organizer has been invited.'))
|
||||
@@ -1707,8 +1710,11 @@ class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRe
|
||||
).delete()
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.acceptor.removed',
|
||||
data={'acceptor': request.POST.get("delete_acceptor")},
|
||||
action='pretix.giftcards.acceptance.acceptor.removed',
|
||||
data={
|
||||
'acceptor': request.POST.get("delete_acceptor"),
|
||||
'issuer': self.request.organizer.slug
|
||||
},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been removed.'))
|
||||
@@ -1718,8 +1724,11 @@ class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRe
|
||||
).delete()
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.issuer.removed',
|
||||
data={'issuer': request.POST.get("delete_acceptor")},
|
||||
action='pretix.giftcards.acceptance.issuer.removed',
|
||||
data={
|
||||
'issuer': request.POST.get("delete_acceptor"),
|
||||
'acceptor': self.request.organizer.slug
|
||||
},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been removed.'))
|
||||
@@ -1729,8 +1738,11 @@ class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRe
|
||||
).update(active=True)
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.issuer.accepted',
|
||||
data={'issuer': request.POST.get("accept_issuer")},
|
||||
action='pretix.giftcards.acceptance.issuer.accepted',
|
||||
data={
|
||||
'issuer': request.POST.get("accept_issuer"),
|
||||
'acceptor': self.request.organizer.slug
|
||||
},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been accepted.'))
|
||||
@@ -1836,10 +1848,11 @@ class GiftCardDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
acceptor=request.organizer,
|
||||
)
|
||||
self.object.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
data={
|
||||
'value': value,
|
||||
'text': request.POST.get('text')
|
||||
'text': request.POST.get('text'),
|
||||
'acceptor_id': self.request.organizer.id
|
||||
},
|
||||
user=self.request.user,
|
||||
)
|
||||
@@ -1888,15 +1901,23 @@ class GiftCardCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
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(
|
||||
acceptor=self.request.organizer,
|
||||
value=form.cleaned_data['value']
|
||||
form.instance.log_action(
|
||||
action='pretix.giftcards.created',
|
||||
user=self.request.user,
|
||||
)
|
||||
form.instance.log_action('pretix.giftcards.created', user=self.request.user, data={})
|
||||
if form.cleaned_data['value']:
|
||||
form.instance.log_action('pretix.giftcards.transaction.manual', user=self.request.user, data={
|
||||
'value': form.cleaned_data['value']
|
||||
})
|
||||
form.instance.transactions.create(
|
||||
acceptor=self.request.organizer,
|
||||
value=form.cleaned_data['value']
|
||||
)
|
||||
form.instance.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
data={
|
||||
'value': form.cleaned_data['value'],
|
||||
'acceptor_id': self.request.organizer.id
|
||||
}
|
||||
)
|
||||
return redirect(reverse(
|
||||
'control:organizer.giftcard',
|
||||
kwargs={
|
||||
@@ -1924,7 +1945,11 @@ class GiftCardUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
def form_valid(self, form):
|
||||
messages.success(self.request, _('The gift card has been changed.'))
|
||||
super().form_valid(form)
|
||||
form.instance.log_action('pretix.giftcards.modified', user=self.request.user, data=dict(form.cleaned_data))
|
||||
form.instance.log_action(
|
||||
action='pretix.giftcards.modified',
|
||||
user=self.request.user,
|
||||
data=dict(form.cleaned_data)
|
||||
)
|
||||
return redirect(reverse(
|
||||
'control:organizer.giftcard',
|
||||
kwargs={
|
||||
@@ -2113,16 +2138,7 @@ class ExportView(OrganizerPermissionRequiredMixin, ExportMixin, ListView):
|
||||
@transaction.atomic()
|
||||
def post(self, request, *args, **kwargs):
|
||||
if request.POST.get("schedule") == "save":
|
||||
if not self.has_permission():
|
||||
messages.error(
|
||||
self.request,
|
||||
_(
|
||||
"Your user account does not have sufficient permission to run this report, therefore "
|
||||
"you cannot schedule it."
|
||||
)
|
||||
)
|
||||
return super().get(request, *args, **kwargs)
|
||||
elif self.exporter.form.is_valid() and self.rrule_form.is_valid() and self.schedule_form.is_valid():
|
||||
if self.exporter.form.is_valid() and self.rrule_form.is_valid() and self.schedule_form.is_valid():
|
||||
self.schedule_form.instance.export_identifier = self.exporter.identifier
|
||||
self.schedule_form.instance.export_form_data = self.exporter.form.cleaned_data
|
||||
self.schedule_form.instance.schedule_rrule = str(self.rrule_form.to_rrule())
|
||||
@@ -2209,8 +2225,17 @@ class ExportView(OrganizerPermissionRequiredMixin, ExportMixin, ListView):
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
if "schedule" in self.request.POST or self.scheduled:
|
||||
ctx['schedule_form'] = self.schedule_form
|
||||
ctx['rrule_form'] = self.rrule_form
|
||||
if "schedule" in self.request.POST and not self.has_permission():
|
||||
messages.error(
|
||||
self.request,
|
||||
_(
|
||||
"Your user account does not have sufficient permission to run this report, therefore "
|
||||
"you cannot schedule it."
|
||||
)
|
||||
)
|
||||
else:
|
||||
ctx['schedule_form'] = self.schedule_form
|
||||
ctx['rrule_form'] = self.rrule_form
|
||||
elif not self.exporter:
|
||||
for s in ctx['scheduled']:
|
||||
try:
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2026-01-21 21:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-11 22:00+0000\n"
|
||||
"Last-Translator: Jiří Pastrňák <jiri@pastrnak.email>\n"
|
||||
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix/cs/>"
|
||||
"\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -1623,7 +1623,7 @@ msgstr "Čas konce události"
|
||||
#: pretix/base/models/event.py:1536 pretix/control/forms/subevents.py:494
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk.html:274
|
||||
msgid "Admission time"
|
||||
msgstr "Vstup"
|
||||
msgstr "Vstupní čas"
|
||||
|
||||
#: pretix/base/exporters/events.py:65 pretix/base/models/event.py:634
|
||||
#: pretix/base/models/event.py:1545 pretix/control/forms/subevents.py:93
|
||||
@@ -14592,7 +14592,7 @@ msgstr "Zaplaceno do"
|
||||
#: pretix/plugins/reports/exporters.py:396
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_order_status.html:23
|
||||
msgid "Paid"
|
||||
msgstr "Zaplaceno"
|
||||
msgstr "Placené"
|
||||
|
||||
#: pretix/control/forms/filter.py:1304
|
||||
msgctxt "subevent"
|
||||
@@ -35218,8 +35218,10 @@ msgid "Save selection"
|
||||
msgstr "Uložit volbu"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/fragment_modals.html:145
|
||||
#, fuzzy
|
||||
#| msgid "You did not select any products."
|
||||
msgid "You didn't select any ticket."
|
||||
msgstr "Nevybrali jste žádné vstupenky."
|
||||
msgstr "Nevybrali jste žádné produkty."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/fragment_modals.html:146
|
||||
msgid ""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:13+0000\n"
|
||||
"PO-Revision-Date: 2026-01-22 19:00+0000\n"
|
||||
"Last-Translator: Ruud Hendrickx <ruud@leckxicon.eu>\n"
|
||||
"PO-Revision-Date: 2025-06-10 04:00+0000\n"
|
||||
"Last-Translator: Tim Maurizio Dullaart <Tim.maurizio@gmail.com>\n"
|
||||
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"nl/>\n"
|
||||
"Language: nl\n"
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -63,7 +63,7 @@ msgstr "iDEAL"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
|
||||
msgid "SEPA Direct Debit"
|
||||
msgstr "SEPA-incasso"
|
||||
msgstr "SEPA Automatische Incasso"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
|
||||
msgid "Bancontact"
|
||||
@@ -160,7 +160,7 @@ msgstr "Betaalde bestellingen"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
msgid "Total revenue"
|
||||
msgstr "Totale omzet"
|
||||
msgstr "Totaal omzet"
|
||||
|
||||
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:15
|
||||
msgid "Contacting Stripe …"
|
||||
@@ -180,7 +180,7 @@ msgstr "Kies een inchecklijst"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
||||
msgid "No active check-in lists found."
|
||||
msgstr "Geen actieve check-inlijsten gevonden."
|
||||
msgstr "Geen actieve inchecklijsten gevonden."
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
||||
msgid "Switch check-in list"
|
||||
@@ -245,7 +245,7 @@ msgstr "Goedkeuring in afwachting"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
||||
msgid "Redeemed"
|
||||
msgstr "Ingewisseld"
|
||||
msgstr "Gebruikt"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
||||
msgid "Cancel"
|
||||
@@ -564,11 +564,11 @@ msgstr "afwezig"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
||||
msgid "Error: Product not found!"
|
||||
msgstr "Fout: product niet gevonden!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
||||
msgid "Error: Variation not found!"
|
||||
msgstr "Fout: variant niet gevonden!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||
msgid "Check-in QR"
|
||||
@@ -1125,31 +1125,31 @@ msgstr "Zo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:85
|
||||
msgid "Monday"
|
||||
msgstr "maandag"
|
||||
msgstr "Maandag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:86
|
||||
msgid "Tuesday"
|
||||
msgstr "dinsdag"
|
||||
msgstr "Dinsdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:87
|
||||
msgid "Wednesday"
|
||||
msgstr "woensdag"
|
||||
msgstr "Woensdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:88
|
||||
msgid "Thursday"
|
||||
msgstr "donderdag"
|
||||
msgstr "Donderdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:89
|
||||
msgid "Friday"
|
||||
msgstr "vrijdag"
|
||||
msgstr "Vrijdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:90
|
||||
msgid "Saturday"
|
||||
msgstr "zaterdag"
|
||||
msgstr "Zaterdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:91
|
||||
msgid "Sunday"
|
||||
msgstr "zondag"
|
||||
msgstr "Zondag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:94
|
||||
msgid "January"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2026-01-16 22:00+0000\n"
|
||||
"Last-Translator: Linnea Thelander <linnea@coeo.events>\n"
|
||||
"PO-Revision-Date: 2026-01-16 09:22+0000\n"
|
||||
"Last-Translator: Richard Schreiber <schreiber@rami.io>\n"
|
||||
"Language-Team: Swedish <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"sv/>\n"
|
||||
"Language: sv\n"
|
||||
@@ -35839,11 +35839,9 @@ msgid "A payment of %(total)s is still pending for this order."
|
||||
msgstr "Tack för din bokning på %(total)s."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:97
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
msgid "Please complete your payment before %(date)s"
|
||||
msgstr ""
|
||||
"Om din betalning inte gick igenom, se till att uppdatera din "
|
||||
"betalningsinformation innan %(date)s via knappen nedan."
|
||||
msgstr "Tack för din bokning!"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:108
|
||||
msgid "Re-try payment or choose another payment method"
|
||||
|
||||
@@ -337,8 +337,7 @@ class OverviewReport(Report):
|
||||
date_until=d_end,
|
||||
subevent_date_from=sd_start,
|
||||
subevent_date_until=sd_end,
|
||||
fees=True,
|
||||
skip_empty_lines=form_data.get("skip_empty_lines")
|
||||
fees=True
|
||||
)
|
||||
|
||||
def _table_story(self, doc, form_data, net=False):
|
||||
@@ -479,10 +478,6 @@ class OverviewReport(Report):
|
||||
'Use the "Accounting report" in the export section instead.'
|
||||
))
|
||||
)
|
||||
f.fields['skip_empty_lines'] = forms.BooleanField(
|
||||
label=_("Skip empty lines"),
|
||||
required=False,
|
||||
)
|
||||
return f.fields
|
||||
|
||||
|
||||
|
||||
@@ -932,12 +932,6 @@ def test_search(token_client, organizer, event, clist, clist_all, item, other_it
|
||||
assert resp.status_code == 200
|
||||
assert [p1] == resp.data['results']
|
||||
|
||||
with django_assert_max_num_queries(25):
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/checkinrpc/search/?list={}&search=z3fsn8jyu&expand=item'.format(organizer.slug, clist_all.pk))
|
||||
assert resp.status_code == 200
|
||||
assert resp.data['results'][0]['item']['name']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_search_no_list(token_client, organizer, event, clist, clist_all, item, other_item, order):
|
||||
|
||||
@@ -59,7 +59,6 @@ def test_get_locale():
|
||||
("pt-pt", "PT", "pt-pt", "pt-pt", "pt_PT"),
|
||||
("es", "MX", "es-mx", "es", "es_MX"),
|
||||
("es-419", "MX", "es-419", "es-419", "es_MX"),
|
||||
("zh-hans", "US", "zh-hans", "zh-hans", "zh_Hans"),
|
||||
("zh-hans", "CN", "zh-hans", "zh-hans", "zh_Hans_CN"),
|
||||
("zh-hant", "TW", "zh-hant", "zh-hant", "zh_Hant_TW"),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user