From a3358bae6bd5ad2fac7bffbfef8b70fab0249cc7 Mon Sep 17 00:00:00 2001 From: Mira Weller Date: Mon, 17 Jun 2024 17:57:45 +0200 Subject: [PATCH] migrate from logentry_display signal to LogEntryTypes --- src/pretix/base/models/log.py | 68 +- src/pretix/control/logdisplay.py | 726 ++++++++++-------- src/pretix/plugins/badges/signals.py | 45 +- src/pretix/plugins/banktransfer/signals.py | 14 +- src/pretix/plugins/paypal/signals.py | 9 +- src/pretix/plugins/paypal2/signals.py | 50 +- src/pretix/plugins/sendmail/signals.py | 56 +- src/pretix/plugins/ticketoutputpdf/signals.py | 43 +- 8 files changed, 503 insertions(+), 508 deletions(-) diff --git a/src/pretix/base/models/log.py b/src/pretix/base/models/log.py index 752913462..2c399bb04 100644 --- a/src/pretix/base/models/log.py +++ b/src/pretix/base/models/log.py @@ -33,6 +33,7 @@ # License for the specific language governing permissions and limitations under the License. import json +from collections import defaultdict from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType @@ -130,8 +131,8 @@ class LogEntry(models.Model): @cached_property def display_object(self): from . import ( - Discount, Event, Item, ItemCategory, Order, Question, Quota, - SubEvent, TaxRule, Voucher, + Discount, Event, Item, Order, Question, Quota, + SubEvent, Voucher, ) try: @@ -204,16 +205,6 @@ class LogEntry(models.Model): }), 'val': escape(co.internal_name), } - elif isinstance(co, ItemCategory): - a_text = _('Category {val}') - a_map = { - 'href': reverse('control:event.items.categories.edit', kwargs={ - 'event': self.event.slug, - 'organizer': self.event.organizer.slug, - 'category': co.id - }), - 'val': escape(co.name), - } elif isinstance(co, Question): a_text = _('Question {val}') a_map = { @@ -224,16 +215,6 @@ class LogEntry(models.Model): }), 'val': escape(co.question), } - elif isinstance(co, TaxRule): - a_text = _('Tax rule {val}') - a_map = { - 'href': reverse('control:event.settings.tax.edit', kwargs={ - 'event': self.event.slug, - 'organizer': self.event.organizer.slug, - 'rule': co.id - }), - 'val': escape(co.name), - } if a_text and a_map: a_map['val'] = '{val}'.format_map(a_map) @@ -298,7 +279,12 @@ log_entry_types = Registry({'action_type': lambda o: getattr(o, 'action_type')}) class LogEntryType: def display(self, logentry): if hasattr(self, 'plain'): - return self.plain + plain = str(self.plain) + if '{' in plain: + data = defaultdict(lambda: '?', logentry.parsed_data) + return plain.format_map(data) + else: + return plain def get_object_link_info(self, logentry) -> dict: pass @@ -312,7 +298,7 @@ class LogEntryType: object_link_wrapper = '{val}' def shred_pii(self, logentry): - raise NotImplemented + raise NotImplementedError @classmethod def derive_plains(cls, plains): @@ -363,24 +349,6 @@ class VoucherLogEntryType(EventLogEntryType): return order.code[:6] -@log_entry_types.register_instance() -class VoucherRedeemedLogEntryType(VoucherLogEntryType): - action_type = 'pretix.voucher.redeemed' - plain = _('The voucher has been redeemed in order {order_code}.') - - def display(self, logentry): - data = json.loads(logentry.data) - data = defaultdict(lambda: '?', data) - url = reverse('control:event.order', kwargs={ - 'event': logentry.event.slug, - 'organizer': logentry.event.organizer.slug, - 'code': data['order_code'] - }) - return mark_safe(self.plain.format( - order_code='{}'.format(url, data['order_code']), - )) - - class ItemLogEntryType(EventLogEntryType): object_link_wrapper = _('Product {val}') object_link_viewname = 'control:event.item' @@ -411,14 +379,6 @@ class ItemCategoryLogEntryType(EventLogEntryType): object_link_argname = 'category' -log_entry_types.register(*ItemCategoryLogEntryType.derive_plains({ - 'pretix.event.category.added': _('The category has been added.'), - 'pretix.event.category.deleted': _('The category has been deleted.'), - 'pretix.event.category.changed': _('The category has been changed.'), - 'pretix.event.category.reordered': _('The category has been reordered.'), -})) - - class QuestionLogEntryType(EventLogEntryType): object_link_wrapper = _('Question {val}') object_link_viewname = 'control:event.items.questions.show' @@ -429,11 +389,3 @@ class TaxRuleLogEntryType(EventLogEntryType): object_link_wrapper = _('Tax rule {val}') object_link_viewname = 'control:event.settings.tax.edit' object_link_argname = 'rule' - - -log_entry_types.register(*TaxRuleLogEntryType.derive_plains({ - 'pretix.event.taxrule.added': _('The tax rule has been added.'), - 'pretix.event.taxrule.deleted': _('The tax rule has been deleted.'), - 'pretix.event.taxrule.changed': _('The tax rule has been changed.'), -})) - diff --git a/src/pretix/control/logdisplay.py b/src/pretix/control/logdisplay.py index c69583bdb..1813f9ebf 100644 --- a/src/pretix/control/logdisplay.py +++ b/src/pretix/control/logdisplay.py @@ -51,6 +51,12 @@ from pretix.base.models import ( Checkin, CheckinList, Event, ItemVariation, LogEntry, OrderPosition, TaxRule, ) +from pretix.base.models.log import ( + DiscountLogEntryType, EventLogEntryType, ItemCategoryLogEntryType, + ItemLogEntryType, LogEntryType, OrderLogEntryType, QuestionLogEntryType, + QuotaLogEntryType, TaxRuleLogEntryType, VoucherLogEntryType, + log_entry_types, +) from pretix.base.signals import logentry_display, orderposition_blocked_display from pretix.base.templatetags.money import money_filter @@ -328,277 +334,6 @@ def _display_checkin(event, logentry): @receiver(signal=logentry_display, dispatch_uid="pretixcontrol_logentry_display") def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs): - plains = { - 'pretix.object.cloned': _('This object has been created by cloning.'), - 'pretix.organizer.changed': _('The organizer has been changed.'), - 'pretix.organizer.settings': _('The organizer settings have been changed.'), - 'pretix.organizer.footerlinks.changed': _('The footer links have been changed.'), - 'pretix.organizer.export.schedule.added': _('A scheduled export has been added.'), - 'pretix.organizer.export.schedule.changed': _('A scheduled export has been changed.'), - 'pretix.organizer.export.schedule.deleted': _('A scheduled export has been deleted.'), - 'pretix.organizer.export.schedule.executed': _('A scheduled export has been executed.'), - 'pretix.organizer.export.schedule.failed': _('A scheduled export has failed: {reason}.'), - 'pretix.giftcards.acceptance.added': _('Gift card acceptance for another organizer has been added.'), - 'pretix.giftcards.acceptance.removed': _('Gift card acceptance for another organizer has been removed.'), - 'pretix.giftcards.acceptance.acceptor.invited': _('A new gift card acceptor has been invited.'), - 'pretix.giftcards.acceptance.acceptor.removed': _('A gift card acceptor has been removed.'), - 'pretix.giftcards.acceptance.issuer.removed': _('A gift card issuer has been removed or declined.'), - 'pretix.giftcards.acceptance.issuer.accepted': _('A new gift card issuer has been accepted.'), - 'pretix.webhook.created': _('The webhook has been created.'), - 'pretix.webhook.changed': _('The webhook has been changed.'), - 'pretix.webhook.retries.expedited': _('The webhook call retry jobs have been manually expedited.'), - 'pretix.webhook.retries.dropped': _('The webhook call retry jobs have been dropped.'), - 'pretix.ssoprovider.created': _('The SSO provider has been created.'), - 'pretix.ssoprovider.changed': _('The SSO provider has been changed.'), - 'pretix.ssoprovider.deleted': _('The SSO provider has been deleted.'), - 'pretix.ssoclient.created': _('The SSO client has been created.'), - 'pretix.ssoclient.changed': _('The SSO client has been changed.'), - 'pretix.ssoclient.deleted': _('The SSO client has been deleted.'), - 'pretix.membershiptype.created': _('The membership type has been created.'), - 'pretix.membershiptype.changed': _('The membership type has been changed.'), - 'pretix.membershiptype.deleted': _('The membership type has been deleted.'), - 'pretix.saleschannel.created': _('The sales channel has been created.'), - 'pretix.saleschannel.changed': _('The sales channel has been changed.'), - 'pretix.saleschannel.deleted': _('The sales channel has been deleted.'), - 'pretix.customer.created': _('The account has been created.'), - 'pretix.customer.changed': _('The account has been changed.'), - 'pretix.customer.membership.created': _('A membership for this account has been added.'), - 'pretix.customer.membership.changed': _('A membership of this account has been changed.'), - 'pretix.customer.membership.deleted': _('A membership of this account has been deleted.'), - 'pretix.customer.anonymized': _('The account has been disabled and anonymized.'), - 'pretix.customer.password.resetrequested': _('A new password has been requested.'), - 'pretix.customer.password.set': _('A new password has been set.'), - 'pretix.reusable_medium.created': _('The reusable medium has been created.'), - 'pretix.reusable_medium.created.auto': _('The reusable medium has been created automatically.'), - 'pretix.reusable_medium.changed': _('The reusable medium has been changed.'), - 'pretix.reusable_medium.linked_orderposition.changed': _('The medium has been connected to a new ticket.'), - 'pretix.reusable_medium.linked_giftcard.changed': _('The medium has been connected to a new gift card.'), - 'pretix.email.error': _('Sending of an email has failed.'), - 'pretix.event.comment': _('The event\'s internal comment has been updated.'), - 'pretix.event.canceled': _('The event has been canceled.'), - 'pretix.event.deleted': _('An event has been deleted.'), - 'pretix.event.shredder.started': _('A removal process for personal data has been started.'), - 'pretix.event.shredder.completed': _('A removal process for personal data has been completed.'), - 'pretix.event.order.modified': _('The order details have been changed.'), - 'pretix.event.order.unpaid': _('The order has been marked as unpaid.'), - 'pretix.event.order.secret.changed': _('The order\'s secret has been changed.'), - 'pretix.event.order.expirychanged': _('The order\'s expiry date has been changed.'), - 'pretix.event.order.valid_if_pending.set': _('The order has been set to be usable before it is paid.'), - 'pretix.event.order.valid_if_pending.unset': _('The order has been set to require payment before use.'), - 'pretix.event.order.expired': _('The order has been marked as expired.'), - 'pretix.event.order.paid': _('The order has been marked as paid.'), - 'pretix.event.order.cancellationrequest.deleted': _('The cancellation request has been deleted.'), - 'pretix.event.order.refunded': _('The order has been refunded.'), - 'pretix.event.order.reactivated': _('The order has been reactivated.'), - 'pretix.event.order.deleted': _('The test mode order {code} has been deleted.'), - 'pretix.event.order.placed': _('The order has been created.'), - 'pretix.event.order.placed.require_approval': _('The order requires approval before it can continue to be processed.'), - 'pretix.event.order.approved': _('The order has been approved.'), - 'pretix.event.order.denied': _('The order has been denied (comment: "{comment}").'), - 'pretix.event.order.contact.changed': _('The email address has been changed from "{old_email}" ' - 'to "{new_email}".'), - 'pretix.event.order.contact.confirmed': _('The email address has been confirmed to be working (the user clicked on a link ' - 'in the email for the first time).'), - 'pretix.event.order.phone.changed': _('The phone number has been changed from "{old_phone}" ' - 'to "{new_phone}".'), - 'pretix.event.order.customer.changed': _('The customer account has been changed.'), - 'pretix.event.order.locale.changed': _('The order locale has been changed.'), - 'pretix.event.order.invoice.generated': _('The invoice has been generated.'), - 'pretix.event.order.invoice.regenerated': _('The invoice has been regenerated.'), - 'pretix.event.order.invoice.reissued': _('The invoice has been reissued.'), - 'pretix.event.order.comment': _('The order\'s internal comment has been updated.'), - 'pretix.event.order.custom_followup_at': _('The order\'s follow-up date has been updated.'), - 'pretix.event.order.checkin_attention': _('The order\'s flag to require attention at check-in has been ' - 'toggled.'), - 'pretix.event.order.checkin_text': _('The order\'s check-in text has been changed.'), - 'pretix.event.order.pretix.event.order.valid_if_pending': _('The order\'s flag to be considered valid even if ' - 'unpaid has been toggled.'), - 'pretix.event.order.payment.changed': _('A new payment {local_id} has been started instead of the previous one.'), - 'pretix.event.order.email.sent': _('An unidentified type email has been sent.'), - 'pretix.event.order.email.error': _('Sending of an email has failed.'), - 'pretix.event.order.email.attachments.skipped': _('The email has been sent without attached tickets since they ' - 'would have been too large to be likely to arrive.'), - 'pretix.event.order.email.custom_sent': _('A custom email has been sent.'), - 'pretix.event.order.position.email.custom_sent': _('A custom email has been sent to an attendee.'), - 'pretix.event.order.email.download_reminder_sent': _('An email has been sent with a reminder that the ticket ' - 'is available for download.'), - 'pretix.event.order.email.expire_warning_sent': _('An email has been sent with a warning that the order is about ' - 'to expire.'), - 'pretix.event.order.email.order_canceled': _('An email has been sent to notify the user that the order has been canceled.'), - 'pretix.event.order.email.event_canceled': _('An email has been sent to notify the user that the event has ' - 'been canceled.'), - 'pretix.event.order.email.order_changed': _('An email has been sent to notify the user that the order has been changed.'), - 'pretix.event.order.email.order_free': _('An email has been sent to notify the user that the order has been received.'), - 'pretix.event.order.email.order_paid': _('An email has been sent to notify the user that payment has been received.'), - 'pretix.event.order.email.order_denied': _('An email has been sent to notify the user that the order has been denied.'), - 'pretix.event.order.email.order_approved': _('An email has been sent to notify the user that the order has ' - 'been approved.'), - 'pretix.event.order.email.order_placed': _('An email has been sent to notify the user that the order has been received and requires payment.'), - 'pretix.event.order.email.order_placed_require_approval': _('An email has been sent to notify the user that ' - 'the order has been received and requires ' - 'approval.'), - 'pretix.event.order.email.resend': _('An email with a link to the order detail page has been resent to the user.'), - 'pretix.event.order.email.payment_failed': _('An email has been sent to notify the user that the payment failed.'), - 'pretix.event.order.payment.confirmed': _('Payment {local_id} has been confirmed.'), - 'pretix.event.order.payment.canceled': _('Payment {local_id} has been canceled.'), - 'pretix.event.order.payment.canceled.failed': _('Canceling payment {local_id} has failed.'), - 'pretix.event.order.payment.started': _('Payment {local_id} has been started.'), - 'pretix.event.order.payment.failed': _('Payment {local_id} has failed.'), - 'pretix.event.order.quotaexceeded': _('The order could not be marked as paid: {message}'), - 'pretix.event.order.overpaid': _('The order has been overpaid.'), - 'pretix.event.order.refund.created': _('Refund {local_id} has been created.'), - 'pretix.event.order.refund.created.externally': _('Refund {local_id} has been created by an external entity.'), - 'pretix.event.order.refund.requested': _('The customer requested you to issue a refund.'), - 'pretix.event.order.refund.done': _('Refund {local_id} has been completed.'), - 'pretix.event.order.refund.canceled': _('Refund {local_id} has been canceled.'), - 'pretix.event.order.refund.failed': _('Refund {local_id} has failed.'), - 'pretix.event.export.schedule.added': _('A scheduled export has been added.'), - 'pretix.event.export.schedule.changed': _('A scheduled export has been changed.'), - 'pretix.event.export.schedule.deleted': _('A scheduled export has been deleted.'), - 'pretix.event.export.schedule.executed': _('A scheduled export has been executed.'), - 'pretix.event.export.schedule.failed': _('A scheduled export has failed: {reason}.'), - 'pretix.control.auth.user.created': _('The user has been created.'), - 'pretix.control.auth.user.new_source': _('A first login using {agent_type} on {os_type} from {country} has ' - 'been detected.'), - 'pretix.user.settings.2fa.enabled': _('Two-factor authentication has been enabled.'), - 'pretix.user.settings.2fa.disabled': _('Two-factor authentication has been disabled.'), - 'pretix.user.settings.2fa.regenemergency': _('Your two-factor emergency codes have been regenerated.'), - 'pretix.user.settings.2fa.emergency': _('A two-factor emergency code has been generated.'), - 'pretix.user.settings.2fa.device.added': _('A new two-factor authentication device "{name}" has been added to ' - 'your account.'), - 'pretix.user.settings.2fa.device.deleted': _('The two-factor authentication device "{name}" has been removed ' - 'from your account.'), - 'pretix.user.settings.notifications.enabled': _('Notifications have been enabled.'), - 'pretix.user.settings.notifications.disabled': _('Notifications have been disabled.'), - 'pretix.user.settings.notifications.changed': _('Your notification settings have been changed.'), - 'pretix.user.anonymized': _('This user has been anonymized.'), - 'pretix.user.oauth.authorized': _('The application "{application_name}" has been authorized to access your ' - 'account.'), - 'pretix.control.auth.user.forgot_password.mail_sent': _('Password reset mail sent.'), - 'pretix.control.auth.user.forgot_password.recovered': _('The password has been reset.'), - 'pretix.control.auth.user.forgot_password.denied.repeated': _('A repeated password reset has been denied, as ' - 'the last request was less than 24 hours ago.'), - 'pretix.organizer.deleted': _('The organizer "{name}" has been deleted.'), - 'pretix.voucher.added': _('The voucher has been created.'), - 'pretix.voucher.sent': _('The voucher has been sent to {recipient}.'), - 'pretix.voucher.added.waitinglist': _('The voucher has been created and sent to a person on the waiting list.'), - 'pretix.voucher.expired.waitinglist': _('The voucher has been set to expire because the recipient removed themselves from the waiting list.'), - 'pretix.voucher.changed': _('The voucher has been changed.'), - 'pretix.voucher.deleted': _('The voucher has been deleted.'), - 'pretix.voucher.redeemed': _('The voucher has been redeemed in order {order_code}.'), - 'pretix.event.item.added': _('The product has been created.'), - 'pretix.event.item.changed': _('The product has been changed.'), - 'pretix.event.item.reordered': _('The product has been reordered.'), - 'pretix.event.item.deleted': _('The product has been deleted.'), - 'pretix.event.item.variation.added': _('The variation "{value}" has been created.'), - 'pretix.event.item.variation.deleted': _('The variation "{value}" has been deleted.'), - 'pretix.event.item.variation.changed': _('The variation "{value}" has been changed.'), - 'pretix.event.item.addons.added': _('An add-on has been added to this product.'), - 'pretix.event.item.addons.removed': _('An add-on has been removed from this product.'), - 'pretix.event.item.addons.changed': _('An add-on has been changed on this product.'), - 'pretix.event.item.bundles.added': _('A bundled item has been added to this product.'), - 'pretix.event.item.bundles.removed': _('A bundled item has been removed from this product.'), - 'pretix.event.item.bundles.changed': _('A bundled item has been changed on this product.'), - 'pretix.event.item_meta_property.added': _('A meta property has been added to this event.'), - 'pretix.event.item_meta_property.deleted': _('A meta property has been removed from this event.'), - 'pretix.event.item_meta_property.changed': _('A meta property has been changed on this event.'), - 'pretix.event.quota.added': _('The quota has been added.'), - 'pretix.event.quota.deleted': _('The quota has been deleted.'), - 'pretix.event.quota.changed': _('The quota has been changed.'), - 'pretix.event.quota.closed': _('The quota has closed.'), - 'pretix.event.quota.opened': _('The quota has been re-opened.'), - 'pretix.event.category.added': _('The category has been added.'), - 'pretix.event.category.deleted': _('The category has been deleted.'), - 'pretix.event.category.changed': _('The category has been changed.'), - 'pretix.event.category.reordered': _('The category has been reordered.'), - 'pretix.event.question.added': _('The question has been added.'), - 'pretix.event.question.deleted': _('The question has been deleted.'), - 'pretix.event.question.changed': _('The question has been changed.'), - 'pretix.event.question.reordered': _('The question has been reordered.'), - 'pretix.event.discount.added': _('The discount has been added.'), - 'pretix.event.discount.deleted': _('The discount has been deleted.'), - 'pretix.event.discount.changed': _('The discount has been changed.'), - 'pretix.event.taxrule.added': _('The tax rule has been added.'), - 'pretix.event.taxrule.deleted': _('The tax rule has been deleted.'), - 'pretix.event.taxrule.changed': _('The tax rule has been changed.'), - 'pretix.event.checkinlist.added': _('The check-in list has been added.'), - 'pretix.event.checkinlist.deleted': _('The check-in list has been deleted.'), - 'pretix.event.checkinlists.deleted': _('The check-in list has been deleted.'), # backwards compatibility - 'pretix.event.checkinlist.changed': _('The check-in list has been changed.'), - 'pretix.event.settings': _('The event settings have been changed.'), - 'pretix.event.tickets.settings': _('The ticket download settings have been changed.'), - 'pretix.event.plugins.enabled': _('A plugin has been enabled.'), - 'pretix.event.plugins.disabled': _('A plugin has been disabled.'), - 'pretix.event.live.activated': _('The shop has been taken live.'), - 'pretix.event.live.deactivated': _('The shop has been taken offline.'), - 'pretix.event.testmode.activated': _('The shop has been taken into test mode.'), - 'pretix.event.testmode.deactivated': _('The test mode has been disabled.'), - 'pretix.event.added': _('The event has been created.'), - 'pretix.event.changed': _('The event details have been changed.'), - 'pretix.event.footerlinks.changed': _('The footer links have been changed.'), - 'pretix.event.question.option.added': _('An answer option has been added to the question.'), - 'pretix.event.question.option.deleted': _('An answer option has been removed from the question.'), - 'pretix.event.question.option.changed': _('An answer option has been changed.'), - 'pretix.event.permissions.added': _('A user has been added to the event team.'), - 'pretix.event.permissions.invited': _('A user has been invited to the event team.'), - 'pretix.event.permissions.changed': _('A user\'s permissions have been changed.'), - 'pretix.event.permissions.deleted': _('A user has been removed from the event team.'), - 'pretix.waitinglist.voucher': _('A voucher has been sent to a person on the waiting list.'), # legacy - 'pretix.event.orders.waitinglist.voucher_assigned': _('A voucher has been sent to a person on the waiting list.'), - 'pretix.event.orders.waitinglist.deleted': _('An entry has been removed from the waiting list.'), - 'pretix.event.order.waitinglist.transferred': _('An entry has been transferred to another waiting list.'), # legacy - 'pretix.event.orders.waitinglist.changed': _('An entry has been changed on the waiting list.'), - 'pretix.event.orders.waitinglist.added': _('An entry has been added to the waiting list.'), - 'pretix.team.created': _('The team has been created.'), - 'pretix.team.changed': _('The team settings have been changed.'), - 'pretix.team.deleted': _('The team has been deleted.'), - 'pretix.gate.created': _('The gate has been created.'), - 'pretix.gate.changed': _('The gate has been changed.'), - 'pretix.gate.deleted': _('The gate has been deleted.'), - 'pretix.subevent.deleted': pgettext_lazy('subevent', 'The event date has been deleted.'), - 'pretix.subevent.canceled': pgettext_lazy('subevent', 'The event date has been canceled.'), - 'pretix.subevent.changed': pgettext_lazy('subevent', 'The event date has been changed.'), - 'pretix.subevent.added': pgettext_lazy('subevent', 'The event date has been created.'), - 'pretix.subevent.quota.added': pgettext_lazy('subevent', 'A quota has been added to the event date.'), - 'pretix.subevent.quota.changed': pgettext_lazy('subevent', 'A quota has been changed on the event date.'), - 'pretix.subevent.quota.deleted': pgettext_lazy('subevent', 'A quota has been removed from the event date.'), - 'pretix.device.created': _('The device has been created.'), - 'pretix.device.changed': _('The device has been changed.'), - 'pretix.device.revoked': _('Access of the device has been revoked.'), - 'pretix.device.initialized': _('The device has been initialized.'), - 'pretix.device.keyroll': _('The access token of the device has been regenerated.'), - 'pretix.device.updated': _('The device has notified the server of an hardware or software update.'), - '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.'), - } - - if logentry.action_type.startswith('pretix.event.item.variation'): - data = logentry.parsed_data - if 'value' not in data: - # Backwards compatibility - var = ItemVariation.objects.filter(id=data['id']).first() - if var: - data['value'] = str(var.value) - else: - data['value'] = '?' - else: - data['value'] = LazyI18nString(data['value']) - - if logentry.action_type == "pretix.voucher.redeemed": - data = defaultdict(lambda: '?', logentry.parsed_data) - url = reverse('control:event.order', kwargs={ - 'event': logentry.event.slug, - 'organizer': logentry.event.organizer.slug, - 'code': data['order_code'] - }) - return mark_safe(plains[logentry.action_type].format( - order_code='{}'.format(url, data['order_code']), - )) - - if logentry.action_type in plains: - data = defaultdict(lambda: '?', logentry.parsed_data) - return plains[logentry.action_type].format_map(data) if logentry.action_type.startswith('pretix.event.order.changed'): return _display_order_changed(sender, logentry) @@ -638,14 +373,405 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs): if sender and logentry.action_type.startswith('pretix.event.checkin'): return _display_checkin(sender, logentry) - if logentry.action_type == 'pretix.control.views.checkin': + +@receiver(signal=orderposition_blocked_display, dispatch_uid="pretixcontrol_orderposition_blocked_display") +def pretixcontrol_orderposition_blocked_display(sender: Event, orderposition, block_name, **kwargs): + if block_name == 'admin': + return _('Blocked manually') + elif block_name.startswith('api:'): + return _('Blocked because of an API integration') + + +log_entry_types.register(*OrderLogEntryType.derive_plains({ + 'pretix.event.order.modified': _('The order details have been changed.'), + 'pretix.event.order.unpaid': _('The order has been marked as unpaid.'), + 'pretix.event.order.secret.changed': _('The order\'s secret has been changed.'), + 'pretix.event.order.expirychanged': _('The order\'s expiry date has been changed.'), + 'pretix.event.order.valid_if_pending.set': _('The order has been set to be usable before it is paid.'), + 'pretix.event.order.valid_if_pending.unset': _('The order has been set to require payment before use.'), + 'pretix.event.order.expired': _('The order has been marked as expired.'), + 'pretix.event.order.paid': _('The order has been marked as paid.'), + 'pretix.event.order.cancellationrequest.deleted': _('The cancellation request has been deleted.'), + 'pretix.event.order.refunded': _('The order has been refunded.'), + 'pretix.event.order.reactivated': _('The order has been reactivated.'), + 'pretix.event.order.deleted': _('The test mode order {code} has been deleted.'), + 'pretix.event.order.placed': _('The order has been created.'), + 'pretix.event.order.placed.require_approval': _( + 'The order requires approval before it can continue to be processed.'), + 'pretix.event.order.approved': _('The order has been approved.'), + 'pretix.event.order.denied': _('The order has been denied (comment: "{comment}").'), + 'pretix.event.order.contact.changed': _('The email address has been changed from "{old_email}" ' + 'to "{new_email}".'), + 'pretix.event.order.contact.confirmed': _( + 'The email address has been confirmed to be working (the user clicked on a link ' + 'in the email for the first time).'), + 'pretix.event.order.phone.changed': _('The phone number has been changed from "{old_phone}" ' + 'to "{new_phone}".'), + 'pretix.event.order.customer.changed': _('The customer account has been changed.'), + 'pretix.event.order.locale.changed': _('The order locale has been changed.'), + 'pretix.event.order.invoice.generated': _('The invoice has been generated.'), + 'pretix.event.order.invoice.regenerated': _('The invoice has been regenerated.'), + 'pretix.event.order.invoice.reissued': _('The invoice has been reissued.'), + 'pretix.event.order.comment': _('The order\'s internal comment has been updated.'), + 'pretix.event.order.custom_followup_at': _('The order\'s follow-up date has been updated.'), + 'pretix.event.order.checkin_attention': _('The order\'s flag to require attention at check-in has been ' + 'toggled.'), + 'pretix.event.order.checkin_text': _('The order\'s check-in text has been changed.'), + 'pretix.event.order.pretix.event.order.valid_if_pending': _('The order\'s flag to be considered valid even if ' + 'unpaid has been toggled.'), + 'pretix.event.order.payment.changed': _('A new payment {local_id} has been started instead of the previous one.'), + 'pretix.event.order.email.sent': _('An unidentified type email has been sent.'), + 'pretix.event.order.email.error': _('Sending of an email has failed.'), + 'pretix.event.order.email.attachments.skipped': _('The email has been sent without attached tickets since they ' + 'would have been too large to be likely to arrive.'), + 'pretix.event.order.email.custom_sent': _('A custom email has been sent.'), + 'pretix.event.order.position.email.custom_sent': _('A custom email has been sent to an attendee.'), + 'pretix.event.order.email.download_reminder_sent': _('An email has been sent with a reminder that the ticket ' + 'is available for download.'), + 'pretix.event.order.email.expire_warning_sent': _('An email has been sent with a warning that the order is about ' + 'to expire.'), + 'pretix.event.order.email.order_canceled': _( + 'An email has been sent to notify the user that the order has been canceled.'), + 'pretix.event.order.email.event_canceled': _('An email has been sent to notify the user that the event has ' + 'been canceled.'), + 'pretix.event.order.email.order_changed': _( + 'An email has been sent to notify the user that the order has been changed.'), + 'pretix.event.order.email.order_free': _( + 'An email has been sent to notify the user that the order has been received.'), + 'pretix.event.order.email.order_paid': _( + 'An email has been sent to notify the user that payment has been received.'), + 'pretix.event.order.email.order_denied': _( + 'An email has been sent to notify the user that the order has been denied.'), + 'pretix.event.order.email.order_approved': _('An email has been sent to notify the user that the order has ' + 'been approved.'), + 'pretix.event.order.email.order_placed': _( + 'An email has been sent to notify the user that the order has been received and requires payment.'), + 'pretix.event.order.email.order_placed_require_approval': _('An email has been sent to notify the user that ' + 'the order has been received and requires ' + 'approval.'), + 'pretix.event.order.email.resend': _('An email with a link to the order detail page has been resent to the user.'), + 'pretix.event.order.email.payment_failed': _('An email has been sent to notify the user that the payment failed.'), +})) + + +log_entry_types.register(*VoucherLogEntryType.derive_plains({ + 'pretix.voucher.added': _('The voucher has been created.'), + 'pretix.voucher.sent': _('The voucher has been sent to {recipient}.'), + 'pretix.voucher.added.waitinglist': _('The voucher has been created and sent to a person on the waiting list.'), + 'pretix.voucher.expired.waitinglist': _( + 'The voucher has been set to expire because the recipient removed themselves from the waiting list.'), + 'pretix.voucher.changed': _('The voucher has been changed.'), + 'pretix.voucher.deleted': _('The voucher has been deleted.'), +})) + + +@log_entry_types.register_instance() +class VoucherRedeemedLogEntryType(VoucherLogEntryType): + action_type = 'pretix.voucher.redeemed' + plain = _('The voucher has been redeemed in order {order_code}.') + + def display(self, logentry): + data = json.loads(logentry.data) + data = defaultdict(lambda: '?', data) + url = reverse('control:event.order', kwargs={ + 'event': logentry.event.slug, + 'organizer': logentry.event.organizer.slug, + 'code': data['order_code'] + }) + return mark_safe(self.plain.format( + order_code='{}'.format(url, data['order_code']), + )) + + +log_entry_types.register(*ItemCategoryLogEntryType.derive_plains({ + 'pretix.event.category.added': _('The category has been added.'), + 'pretix.event.category.deleted': _('The category has been deleted.'), + 'pretix.event.category.changed': _('The category has been changed.'), + 'pretix.event.category.reordered': _('The category has been reordered.'), +})) + + +log_entry_types.register(*TaxRuleLogEntryType.derive_plains({ + 'pretix.event.taxrule.added': _('The tax rule has been added.'), + 'pretix.event.taxrule.deleted': _('The tax rule has been deleted.'), + 'pretix.event.taxrule.changed': _('The tax rule has been changed.'), +})) + + +class TeamMembershipLogEntryType(LogEntryType): + def display(self, logentry): + return self.plain.format(user=logentry.parsed_data.get('email')) + + +log_entry_types.register(*TeamMembershipLogEntryType.derive_plains({ + 'pretix.team.member.added': _('{user} has been added to the team.'), + 'pretix.team.member.removed': _('{user} has been removed from the team.'), + 'pretix.team.invite.created': _('{user} has been invited to the team.'), + 'pretix.team.invite.resent': _('Invite for {user} has been resent.'), +})) + + +@log_entry_types.register_instance() +class TeamMemberJoinedLogEntryType(LogEntryType): + action_type = 'pretix.team.member.joined' + + def display(self, logentry): + return _('{user} has joined the team using the invite sent to {email}.').format( + user=logentry.parsed_data.get('email'), email=logentry.parsed_data.get('invite_email') + ) + + +@log_entry_types.register_instance() +class UserSettingsChangedLogEntryType(LogEntryType): + action_type = 'pretix.user.settings.changed' + + def display(self, logentry): + text = str(_('Your account settings have been changed.')) + if 'email' in logentry.parsed_data: + text = text + ' ' + str( + _('Your email address has been changed to {email}.').format(email=logentry.parsed_data['email'])) + if 'new_pw' in logentry.parsed_data: + text = text + ' ' + str(_('Your password has been changed.')) + if logentry.parsed_data.get('is_active') is True: + text = text + ' ' + str(_('Your account has been enabled.')) + elif logentry.parsed_data.get('is_active') is False: + text = text + ' ' + str(_('Your account has been disabled.')) + return text + + +class UserImpersonatedLogEntryType(LogEntryType): + def display(self, logentry): + return self.plain.format(logentry.parsed_data['other_email']) + + +log_entry_types.register(*UserImpersonatedLogEntryType.derive_plains({ + 'pretix.control.auth.user.impersonated': _('You impersonated {}.'), + 'pretix.control.auth.user.impersonate_stopped': _('You stopped impersonating {}.'), +})) + + +log_entry_types.register(*LogEntryType.derive_plains({ + 'pretix.object.cloned': _('This object has been created by cloning.'), + 'pretix.organizer.changed': _('The organizer has been changed.'), + 'pretix.organizer.settings': _('The organizer settings have been changed.'), + 'pretix.organizer.footerlinks.changed': _('The footer links have been changed.'), + 'pretix.organizer.export.schedule.added': _('A scheduled export has been added.'), + 'pretix.organizer.export.schedule.changed': _('A scheduled export has been changed.'), + 'pretix.organizer.export.schedule.deleted': _('A scheduled export has been deleted.'), + 'pretix.organizer.export.schedule.executed': _('A scheduled export has been executed.'), + 'pretix.organizer.export.schedule.failed': _('A scheduled export has failed: {reason}.'), + 'pretix.giftcards.acceptance.added': _('Gift card acceptance for another organizer has been added.'), + 'pretix.giftcards.acceptance.removed': _('Gift card acceptance for another organizer has been removed.'), + 'pretix.giftcards.acceptance.acceptor.invited': _('A new gift card acceptor has been invited.'), + 'pretix.giftcards.acceptance.acceptor.removed': _('A gift card acceptor has been removed.'), + 'pretix.giftcards.acceptance.issuer.removed': _('A gift card issuer has been removed or declined.'), + 'pretix.giftcards.acceptance.issuer.accepted': _('A new gift card issuer has been accepted.'), + 'pretix.webhook.created': _('The webhook has been created.'), + 'pretix.webhook.changed': _('The webhook has been changed.'), + 'pretix.webhook.retries.expedited': _('The webhook call retry jobs have been manually expedited.'), + 'pretix.webhook.retries.dropped': _('The webhook call retry jobs have been dropped.'), + 'pretix.ssoprovider.created': _('The SSO provider has been created.'), + 'pretix.ssoprovider.changed': _('The SSO provider has been changed.'), + 'pretix.ssoprovider.deleted': _('The SSO provider has been deleted.'), + 'pretix.ssoclient.created': _('The SSO client has been created.'), + 'pretix.ssoclient.changed': _('The SSO client has been changed.'), + 'pretix.ssoclient.deleted': _('The SSO client has been deleted.'), + 'pretix.membershiptype.created': _('The membership type has been created.'), + 'pretix.membershiptype.changed': _('The membership type has been changed.'), + 'pretix.membershiptype.deleted': _('The membership type has been deleted.'), + 'pretix.saleschannel.created': _('The sales channel has been created.'), + 'pretix.saleschannel.changed': _('The sales channel has been changed.'), + 'pretix.saleschannel.deleted': _('The sales channel has been deleted.'), + 'pretix.customer.created': _('The account has been created.'), + 'pretix.customer.changed': _('The account has been changed.'), + 'pretix.customer.membership.created': _('A membership for this account has been added.'), + 'pretix.customer.membership.changed': _('A membership of this account has been changed.'), + 'pretix.customer.membership.deleted': _('A membership of this account has been deleted.'), + 'pretix.customer.anonymized': _('The account has been disabled and anonymized.'), + 'pretix.customer.password.resetrequested': _('A new password has been requested.'), + 'pretix.customer.password.set': _('A new password has been set.'), + 'pretix.reusable_medium.created': _('The reusable medium has been created.'), + 'pretix.reusable_medium.created.auto': _('The reusable medium has been created automatically.'), + 'pretix.reusable_medium.changed': _('The reusable medium has been changed.'), + 'pretix.reusable_medium.linked_orderposition.changed': _('The medium has been connected to a new ticket.'), + 'pretix.reusable_medium.linked_giftcard.changed': _('The medium has been connected to a new gift card.'), + 'pretix.email.error': _('Sending of an email has failed.'), + 'pretix.event.comment': _('The event\'s internal comment has been updated.'), + 'pretix.event.canceled': _('The event has been canceled.'), + 'pretix.event.deleted': _('An event has been deleted.'), + 'pretix.event.shredder.started': _('A removal process for personal data has been started.'), + 'pretix.event.shredder.completed': _('A removal process for personal data has been completed.'), + 'pretix.event.export.schedule.added': _('A scheduled export has been added.'), + 'pretix.event.export.schedule.changed': _('A scheduled export has been changed.'), + 'pretix.event.export.schedule.deleted': _('A scheduled export has been deleted.'), + 'pretix.event.export.schedule.executed': _('A scheduled export has been executed.'), + 'pretix.event.export.schedule.failed': _('A scheduled export has failed: {reason}.'), + 'pretix.control.auth.user.created': _('The user has been created.'), + 'pretix.control.auth.user.new_source': _('A first login using {agent_type} on {os_type} from {country} has ' + 'been detected.'), + 'pretix.user.settings.2fa.enabled': _('Two-factor authentication has been enabled.'), + 'pretix.user.settings.2fa.disabled': _('Two-factor authentication has been disabled.'), + 'pretix.user.settings.2fa.regenemergency': _('Your two-factor emergency codes have been regenerated.'), + 'pretix.user.settings.2fa.emergency': _('A two-factor emergency code has been generated.'), + 'pretix.user.settings.2fa.device.added': _('A new two-factor authentication device "{name}" has been added to ' + 'your account.'), + 'pretix.user.settings.2fa.device.deleted': _('The two-factor authentication device "{name}" has been removed ' + 'from your account.'), + 'pretix.user.settings.notifications.enabled': _('Notifications have been enabled.'), + 'pretix.user.settings.notifications.disabled': _('Notifications have been disabled.'), + 'pretix.user.settings.notifications.changed': _('Your notification settings have been changed.'), + 'pretix.user.anonymized': _('This user has been anonymized.'), + 'pretix.user.oauth.authorized': _('The application "{application_name}" has been authorized to access your ' + 'account.'), + 'pretix.control.auth.user.forgot_password.mail_sent': _('Password reset mail sent.'), + 'pretix.control.auth.user.forgot_password.recovered': _('The password has been reset.'), + 'pretix.control.auth.user.forgot_password.denied.repeated': _('A repeated password reset has been denied, as ' + 'the last request was less than 24 hours ago.'), + 'pretix.organizer.deleted': _('The organizer "{name}" has been deleted.'), + 'pretix.waitinglist.voucher': _('A voucher has been sent to a person on the waiting list.'), # legacy + 'pretix.event.orders.waitinglist.voucher_assigned': _('A voucher has been sent to a person on the waiting list.'), + 'pretix.event.orders.waitinglist.deleted': _('An entry has been removed from the waiting list.'), + 'pretix.event.order.waitinglist.transferred': _('An entry has been transferred to another waiting list.'), # legacy + 'pretix.event.orders.waitinglist.changed': _('An entry has been changed on the waiting list.'), + 'pretix.event.orders.waitinglist.added': _('An entry has been added to the waiting list.'), + 'pretix.team.created': _('The team has been created.'), + 'pretix.team.changed': _('The team settings have been changed.'), + 'pretix.team.deleted': _('The team has been deleted.'), + 'pretix.gate.created': _('The gate has been created.'), + 'pretix.gate.changed': _('The gate has been changed.'), + 'pretix.gate.deleted': _('The gate has been deleted.'), + 'pretix.subevent.deleted': pgettext_lazy('subevent', 'The event date has been deleted.'), + 'pretix.subevent.canceled': pgettext_lazy('subevent', 'The event date has been canceled.'), + 'pretix.subevent.changed': pgettext_lazy('subevent', 'The event date has been changed.'), + 'pretix.subevent.added': pgettext_lazy('subevent', 'The event date has been created.'), + 'pretix.subevent.quota.added': pgettext_lazy('subevent', 'A quota has been added to the event date.'), + 'pretix.subevent.quota.changed': pgettext_lazy('subevent', 'A quota has been changed on the event date.'), + 'pretix.subevent.quota.deleted': pgettext_lazy('subevent', 'A quota has been removed from the event date.'), + 'pretix.device.created': _('The device has been created.'), + 'pretix.device.changed': _('The device has been changed.'), + 'pretix.device.revoked': _('Access of the device has been revoked.'), + 'pretix.device.initialized': _('The device has been initialized.'), + 'pretix.device.keyroll': _('The access token of the device has been regenerated.'), + 'pretix.device.updated': _('The device has notified the server of an hardware or software update.'), + '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.team.token.created': _('The token "{name}" has been created.'), + 'pretix.team.token.deleted': _('The token "{name}" has been revoked.'), +})) + +log_entry_types.register(*EventLogEntryType.derive_plains({ + 'pretix.event.item_meta_property.added': _('A meta property has been added to this event.'), + 'pretix.event.item_meta_property.deleted': _('A meta property has been removed from this event.'), + 'pretix.event.item_meta_property.changed': _('A meta property has been changed on this event.'), + 'pretix.event.checkinlist.added': _('The check-in list has been added.'), + 'pretix.event.checkinlist.deleted': _('The check-in list has been deleted.'), + 'pretix.event.checkinlists.deleted': _('The check-in list has been deleted.'), # backwards compatibility + 'pretix.event.checkinlist.changed': _('The check-in list has been changed.'), + 'pretix.event.settings': _('The event settings have been changed.'), + 'pretix.event.tickets.settings': _('The ticket download settings have been changed.'), + 'pretix.event.plugins.enabled': _('A plugin has been enabled.'), + 'pretix.event.plugins.disabled': _('A plugin has been disabled.'), + 'pretix.event.live.activated': _('The shop has been taken live.'), + 'pretix.event.live.deactivated': _('The shop has been taken offline.'), + 'pretix.event.testmode.activated': _('The shop has been taken into test mode.'), + 'pretix.event.testmode.deactivated': _('The test mode has been disabled.'), + 'pretix.event.added': _('The event has been created.'), + 'pretix.event.changed': _('The event details have been changed.'), + 'pretix.event.footerlinks.changed': _('The footer links have been changed.'), + 'pretix.event.question.option.added': _('An answer option has been added to the question.'), + 'pretix.event.question.option.deleted': _('An answer option has been removed from the question.'), + 'pretix.event.question.option.changed': _('An answer option has been changed.'), + 'pretix.event.permissions.added': _('A user has been added to the event team.'), + 'pretix.event.permissions.invited': _('A user has been invited to the event team.'), + 'pretix.event.permissions.changed': _('A user\'s permissions have been changed.'), + 'pretix.event.permissions.deleted': _('A user has been removed from the event team.'), +})) + +log_entry_types.register(*ItemLogEntryType.derive_plains({ + 'pretix.event.item.added': _('The product has been created.'), + 'pretix.event.item.changed': _('The product has been changed.'), + 'pretix.event.item.reordered': _('The product has been reordered.'), + 'pretix.event.item.deleted': _('The product has been deleted.'), + 'pretix.event.item.addons.added': _('An add-on has been added to this product.'), + 'pretix.event.item.addons.removed': _('An add-on has been removed from this product.'), + 'pretix.event.item.addons.changed': _('An add-on has been changed on this product.'), + 'pretix.event.item.bundles.added': _('A bundled item has been added to this product.'), + 'pretix.event.item.bundles.removed': _('A bundled item has been removed from this product.'), + 'pretix.event.item.bundles.changed': _('A bundled item has been changed on this product.'), +})) + + +class VariationLogEntryType(ItemLogEntryType): + def display(self, logentry): + if 'value' not in logentry.parsed_data: + # Backwards compatibility + var = ItemVariation.objects.filter(id=logentry.parsed_data['id']).first() + if var: + logentry.parsed_data['value'] = str(var.value) + else: + logentry.parsed_data['value'] = '?' + else: + logentry.parsed_data['value'] = LazyI18nString(logentry.parsed_data['value']) + return super().display(logentry_display) + + +log_entry_types.register(*VariationLogEntryType.derive_plains({ + 'pretix.event.item.variation.added': _('The variation "{value}" has been created.'), + 'pretix.event.item.variation.deleted': _('The variation "{value}" has been deleted.'), + 'pretix.event.item.variation.changed': _('The variation "{value}" has been changed.'), +})) + +log_entry_types.register(*OrderLogEntryType.derive_plains({ + 'pretix.event.order.payment.confirmed': _('Payment {local_id} has been confirmed.'), + 'pretix.event.order.payment.canceled': _('Payment {local_id} has been canceled.'), + 'pretix.event.order.payment.canceled.failed': _('Canceling payment {local_id} has failed.'), + 'pretix.event.order.payment.started': _('Payment {local_id} has been started.'), + 'pretix.event.order.payment.failed': _('Payment {local_id} has failed.'), + 'pretix.event.order.quotaexceeded': _('The order could not be marked as paid: {message}'), + 'pretix.event.order.overpaid': _('The order has been overpaid.'), + 'pretix.event.order.refund.created': _('Refund {local_id} has been created.'), + 'pretix.event.order.refund.created.externally': _('Refund {local_id} has been created by an external entity.'), + 'pretix.event.order.refund.requested': _('The customer requested you to issue a refund.'), + 'pretix.event.order.refund.done': _('Refund {local_id} has been completed.'), + 'pretix.event.order.refund.canceled': _('Refund {local_id} has been canceled.'), + 'pretix.event.order.refund.failed': _('Refund {local_id} has failed.'), +})) + +log_entry_types.register(*QuotaLogEntryType.derive_plains({ + 'pretix.event.quota.added': _('The quota has been added.'), + 'pretix.event.quota.deleted': _('The quota has been deleted.'), + 'pretix.event.quota.changed': _('The quota has been changed.'), + 'pretix.event.quota.closed': _('The quota has closed.'), + 'pretix.event.quota.opened': _('The quota has been re-opened.'), +})) + +log_entry_types.register(*QuestionLogEntryType.derive_plains({ + 'pretix.event.question.added': _('The question has been added.'), + 'pretix.event.question.deleted': _('The question has been deleted.'), + 'pretix.event.question.changed': _('The question has been changed.'), + 'pretix.event.question.reordered': _('The question has been reordered.'), +})) + +log_entry_types.register(*DiscountLogEntryType.derive_plains({ + 'pretix.event.discount.added': _('The discount has been added.'), + 'pretix.event.discount.deleted': _('The discount has been deleted.'), + 'pretix.event.discount.changed': _('The discount has been changed.'), +})) + + +@log_entry_types.register_instance() +class LegacyCheckinLogEntryType(OrderLogEntryType): + action_type = 'pretix.control.views.checkin' + + def display(self, logentry): # deprecated dt = dateutil.parser.parse(logentry.parsed_data.get('datetime')) - tz = sender.timezone + tz = logentry.event.timezone dt_formatted = date_format(dt.astimezone(tz), "SHORT_DATETIME_FORMAT") if 'list' in logentry.parsed_data: try: - checkin_list = sender.checkin_lists.get(pk=logentry.parsed_data.get('list')).name + checkin_list = logentry.event.checkin_lists.get(pk=logentry.parsed_data.get('list')).name except CheckinList.DoesNotExist: checkin_list = _("(unknown)") else: @@ -662,55 +788,3 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs): datetime=dt_formatted, list=checkin_list ) - - if logentry.action_type == 'pretix.team.member.added': - return _('{user} has been added to the team.').format(user=logentry.parsed_data.get('email')) - - if logentry.action_type == 'pretix.team.member.removed': - return _('{user} has been removed from the team.').format(user=logentry.parsed_data.get('email')) - - if logentry.action_type == 'pretix.team.member.joined': - return _('{user} has joined the team using the invite sent to {email}.').format( - user=logentry.parsed_data.get('email'), email=logentry.parsed_data.get('invite_email') - ) - - if logentry.action_type == 'pretix.team.invite.created': - return _('{user} has been invited to the team.').format(user=logentry.parsed_data.get('email')) - - if logentry.action_type == 'pretix.team.invite.resent': - return _('Invite for {user} has been resent.').format(user=logentry.parsed_data.get('email')) - - if logentry.action_type == 'pretix.team.invite.deleted': - return _('The invite for {user} has been revoked.').format(user=logentry.parsed_data.get('email')) - - if logentry.action_type == 'pretix.team.token.created': - return _('The token "{name}" has been created.').format(name=logentry.parsed_data.get('name')) - - if logentry.action_type == 'pretix.team.token.deleted': - return _('The token "{name}" has been revoked.').format(name=logentry.parsed_data.get('name')) - - if logentry.action_type == 'pretix.user.settings.changed': - text = str(_('Your account settings have been changed.')) - if 'email' in logentry.parsed_data: - text = text + ' ' + str(_('Your email address has been changed to {email}.').format(email=logentry.parsed_data['email'])) - if 'new_pw' in logentry.parsed_data: - text = text + ' ' + str(_('Your password has been changed.')) - if logentry.parsed_data.get('is_active') is True: - text = text + ' ' + str(_('Your account has been enabled.')) - elif logentry.parsed_data.get('is_active') is False: - text = text + ' ' + str(_('Your account has been disabled.')) - return text - - if logentry.action_type == 'pretix.control.auth.user.impersonated': - return str(_('You impersonated {}.')).format(logentry.parsed_data['other_email']) - - if logentry.action_type == 'pretix.control.auth.user.impersonate_stopped': - return str(_('You stopped impersonating {}.')).format(logentry.parsed_data['other_email']) - - -@receiver(signal=orderposition_blocked_display, dispatch_uid="pretixcontrol_orderposition_blocked_display") -def pretixcontrol_orderposition_blocked_display(sender: Event, orderposition, block_name, **kwargs): - if block_name == 'admin': - return _('Blocked manually') - elif block_name.startswith('api:'): - return _('Blocked because of an API integration') diff --git a/src/pretix/plugins/badges/signals.py b/src/pretix/plugins/badges/signals.py index dd315b1d1..c867ae0dc 100644 --- a/src/pretix/plugins/badges/signals.py +++ b/src/pretix/plugins/badges/signals.py @@ -26,13 +26,12 @@ from collections import defaultdict from django.dispatch import receiver from django.template.loader import get_template from django.urls import resolve, reverse -from django.utils.html import escape from django.utils.translation import gettext_lazy as _ from pretix.base.models import Event, Order +from pretix.base.models.log import EventLogEntryType, log_entry_types from pretix.base.signals import ( - event_copy_data, item_copy_data, logentry_display, logentry_object_link, - register_data_exporters, + event_copy_data, item_copy_data, register_data_exporters, ) from pretix.control.signals import ( item_forms, nav_event, order_info, order_position_buttons, @@ -173,35 +172,15 @@ def control_order_info(sender: Event, request, order: Order, **kwargs): return template.render(ctx, request=request) -@receiver(signal=logentry_display, dispatch_uid="badges_logentry_display") -def badges_logentry_display(sender, logentry, **kwargs): - if not logentry.action_type.startswith('pretix.plugins.badges'): - return - - plains = { - 'pretix.plugins.badges.layout.added': _('Badge layout created.'), - 'pretix.plugins.badges.layout.deleted': _('Badge layout deleted.'), - 'pretix.plugins.badges.layout.changed': _('Badge layout changed.'), - } - - if logentry.action_type in plains: - return plains[logentry.action_type] +class BadgeLogEntryType(EventLogEntryType): + object_type = BadgeLayout + object_link_wrapper = _('Badge layout {val}') + object_link_viewname = 'plugins:badges:edit' + object_link_argname = 'layout' -@receiver(signal=logentry_object_link, dispatch_uid="badges_logentry_object_link") -def badges_logentry_object_link(sender, logentry, **kwargs): - if not logentry.action_type.startswith('pretix.plugins.badges.layout') or not isinstance(logentry.content_object, - BadgeLayout): - return - - a_text = _('Badge layout {val}') - a_map = { - 'href': reverse('plugins:badges:edit', kwargs={ - 'event': sender.slug, - 'organizer': sender.organizer.slug, - 'layout': logentry.content_object.id - }), - 'val': escape(logentry.content_object.name), - } - a_map['val'] = '{val}'.format_map(a_map) - return a_text.format_map(a_map) +log_entry_types.register(*BadgeLogEntryType.derive_plains({ + 'pretix.plugins.badges.layout.added': _('Badge layout created.'), + 'pretix.plugins.badges.layout.deleted': _('Badge layout deleted.'), + 'pretix.plugins.badges.layout.changed': _('Badge layout changed.'), +})) diff --git a/src/pretix/plugins/banktransfer/signals.py b/src/pretix/plugins/banktransfer/signals.py index 0d8d0aa76..4a4924cd6 100644 --- a/src/pretix/plugins/banktransfer/signals.py +++ b/src/pretix/plugins/banktransfer/signals.py @@ -25,7 +25,8 @@ from django.urls import resolve, reverse from django.utils.translation import gettext_lazy as _, gettext_noop from i18nfield.strings import LazyI18nString -from pretix.base.signals import logentry_display, register_payment_providers +from pretix.base.models.log import OrderLogEntryType, log_entry_types +from pretix.base.signals import register_payment_providers from pretix.control.signals import html_head, nav_event, nav_organizer from ...base.settings import settings_hierarkey @@ -117,13 +118,10 @@ def html_head_presale(sender, request=None, **kwargs): return "" -@receiver(signal=logentry_display) -def pretixcontrol_logentry_display(sender, logentry, **kwargs): - plains = { - 'pretix.plugins.banktransfer.order.email.invoice': _('The invoice was sent to the designated email address.'), - } - if logentry.action_type in plains: - return plains[logentry.action_type] +@log_entry_types.register_instance() +class BanktransferOrderEmailInvoiceLogEntryType(OrderLogEntryType): + action_type = 'pretix.plugins.banktransfer.order.email.invoice' + plain = _('The invoice was sent to the designated email address.') settings_hierarkey.add_default( diff --git a/src/pretix/plugins/paypal/signals.py b/src/pretix/plugins/paypal/signals.py index 3c7d36f50..572a79c81 100644 --- a/src/pretix/plugins/paypal/signals.py +++ b/src/pretix/plugins/paypal/signals.py @@ -22,17 +22,10 @@ from django.dispatch import receiver -from pretix.base.signals import logentry_display, register_payment_providers +from pretix.base.signals import register_payment_providers @receiver(register_payment_providers, dispatch_uid="payment_paypal") def register_payment_provider(sender, **kwargs): from .payment import Paypal return Paypal - - -@receiver(signal=logentry_display, dispatch_uid="paypal_logentry_display") -def pretixcontrol_logentry_display(sender, logentry, **kwargs): - from pretix.plugins.paypal2.signals import pretixcontrol_logentry_display - - return pretixcontrol_logentry_display(sender, logentry, **kwargs) diff --git a/src/pretix/plugins/paypal2/signals.py b/src/pretix/plugins/paypal2/signals.py index 50ca242cf..bbb3e5b5d 100644 --- a/src/pretix/plugins/paypal2/signals.py +++ b/src/pretix/plugins/paypal2/signals.py @@ -19,7 +19,6 @@ # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # -import json from collections import OrderedDict from django import forms @@ -33,9 +32,10 @@ from django.utils.translation import gettext_lazy as _, pgettext_lazy from pretix.base.forms import SecretKeySettingsField from pretix.base.middleware import _merge_csp, _parse_csp, _render_csp +from pretix.base.models.log import EventLogEntryType from pretix.base.settings import settings_hierarkey from pretix.base.signals import ( - logentry_display, register_global_settings, register_payment_providers, + register_global_settings, register_payment_providers, ) from pretix.plugins.paypal2.payment import PaypalMethod from pretix.presale.signals import html_head, process_response @@ -47,33 +47,31 @@ def register_payment_provider(sender, **kwargs): return [PaypalSettingsHolder, PaypalWallet, PaypalAPM] -@receiver(signal=logentry_display, dispatch_uid="paypal2_logentry_display") -def pretixcontrol_logentry_display(sender, logentry, **kwargs): - if logentry.action_type != 'pretix.plugins.paypal.event': - return +class PaypalEventLogEntryType(EventLogEntryType): + action_type = 'pretix.plugins.paypal.event' - data = json.loads(logentry.data) - event_type = data.get('event_type') - text = None - plains = { - 'PAYMENT.SALE.COMPLETED': _('Payment completed.'), - 'PAYMENT.SALE.DENIED': _('Payment denied.'), - 'PAYMENT.SALE.REFUNDED': _('Payment refunded.'), - 'PAYMENT.SALE.REVERSED': _('Payment reversed.'), - 'PAYMENT.SALE.PENDING': _('Payment pending.'), - 'CHECKOUT.ORDER.APPROVED': pgettext_lazy('paypal', 'Order approved.'), - 'CHECKOUT.ORDER.COMPLETED': pgettext_lazy('paypal', 'Order completed.'), - 'PAYMENT.CAPTURE.COMPLETED': pgettext_lazy('paypal', 'Capture completed.'), - 'PAYMENT.CAPTURE.PENDING': pgettext_lazy('paypal', 'Capture pending.'), - } + def display(self, logentry): + event_type = logentry.parsed_data.get('event_type') + text = None + plains = { + 'PAYMENT.SALE.COMPLETED': _('Payment completed.'), + 'PAYMENT.SALE.DENIED': _('Payment denied.'), + 'PAYMENT.SALE.REFUNDED': _('Payment refunded.'), + 'PAYMENT.SALE.REVERSED': _('Payment reversed.'), + 'PAYMENT.SALE.PENDING': _('Payment pending.'), + 'CHECKOUT.ORDER.APPROVED': pgettext_lazy('paypal', 'Order approved.'), + 'CHECKOUT.ORDER.COMPLETED': pgettext_lazy('paypal', 'Order completed.'), + 'PAYMENT.CAPTURE.COMPLETED': pgettext_lazy('paypal', 'Capture completed.'), + 'PAYMENT.CAPTURE.PENDING': pgettext_lazy('paypal', 'Capture pending.'), + } - if event_type in plains: - text = plains[event_type] - else: - text = event_type + if event_type in plains: + text = plains[event_type] + else: + text = event_type - if text: - return _('PayPal reported an event: {}').format(text) + if text: + return _('PayPal reported an event: {}').format(text) @receiver(register_global_settings, dispatch_uid='paypal2_global_settings') diff --git a/src/pretix/plugins/sendmail/signals.py b/src/pretix/plugins/sendmail/signals.py index 418f2545c..fb71c3eea 100644 --- a/src/pretix/plugins/sendmail/signals.py +++ b/src/pretix/plugins/sendmail/signals.py @@ -47,12 +47,15 @@ from django.utils.translation import gettext_lazy as _ from django_scopes import scope, scopes_disabled from pretix.base.models import SubEvent +from pretix.base.models.log import ( + EventLogEntryType, OrderLogEntryType, log_entry_types, +) from pretix.base.signals import ( - EventPluginSignal, event_copy_data, logentry_display, periodic_task, + EventPluginSignal, event_copy_data, periodic_task, ) from pretix.control.signals import nav_event from pretix.helpers import OF_SELF -from pretix.plugins.sendmail.models import ScheduledMail +from pretix.plugins.sendmail.models import Rule, ScheduledMail from pretix.plugins.sendmail.views import OrderSendView, WaitinglistSendView logger = logging.getLogger(__name__) @@ -116,21 +119,40 @@ def control_nav_import(sender, request=None, **kwargs): ] -@receiver(signal=logentry_display) -def pretixcontrol_logentry_display(sender, logentry, **kwargs): - plains = { - 'pretix.plugins.sendmail.sent': _('Mass email was sent to customers or attendees.'), - 'pretix.plugins.sendmail.sent.waitinglist': _('Mass email was sent to waiting list entries.'), - 'pretix.plugins.sendmail.order.email.sent': _('The order received a mass email.'), - 'pretix.plugins.sendmail.order.email.sent.attendee': _('A ticket holder of this order received a mass email.'), - 'pretix.plugins.sendmail.rule.added': _('An email rule was created'), - 'pretix.plugins.sendmail.rule.changed': _('An email rule was updated'), - 'pretix.plugins.sendmail.rule.order.email.sent': _('A scheduled email was sent to the order'), - 'pretix.plugins.sendmail.rule.order.position.email.sent': _('A scheduled email was sent to a ticket holder'), - 'pretix.plugins.sendmail.rule.deleted': _('An email rule was deleted'), - } - if logentry.action_type in plains: - return plains[logentry.action_type] +class SendmailPluginLogEntryType(EventLogEntryType): + pass + + +log_entry_types.register(*SendmailPluginLogEntryType.derive_plains({ + 'pretix.plugins.sendmail.sent': _('Mass email was sent to customers or attendees.'), + 'pretix.plugins.sendmail.sent.waitinglist': _('Mass email was sent to waiting list entries.'), +})) + + +class SendmailPluginOrderLogEntryType(OrderLogEntryType): + pass + + +log_entry_types.register(*SendmailPluginOrderLogEntryType.derive_plains({ + 'pretix.plugins.sendmail.order.email.sent': _('The order received a mass email.'), + 'pretix.plugins.sendmail.order.email.sent.attendee': _('A ticket holder of this order received a mass email.'), +})) + + +class SendmailPluginRuleLogEntryType(EventLogEntryType): + object_type = Rule + object_link_wrapper = _('Mail rule {val}') + object_link_viewname = 'plugins:sendmail:rule.update' + object_link_argname = 'rule' + + +log_entry_types.register(*SendmailPluginRuleLogEntryType.derive_plains({ + 'pretix.plugins.sendmail.rule.added': _('An email rule was created'), + 'pretix.plugins.sendmail.rule.changed': _('An email rule was updated'), + 'pretix.plugins.sendmail.rule.order.email.sent': _('A scheduled email was sent to the order'), + 'pretix.plugins.sendmail.rule.order.position.email.sent': _('A scheduled email was sent to a ticket holder'), + 'pretix.plugins.sendmail.rule.deleted': _('An email rule was deleted'), +})) @receiver(periodic_task) diff --git a/src/pretix/plugins/ticketoutputpdf/signals.py b/src/pretix/plugins/ticketoutputpdf/signals.py index eb1d377a9..a6c54ea1e 100644 --- a/src/pretix/plugins/ticketoutputpdf/signals.py +++ b/src/pretix/plugins/ticketoutputpdf/signals.py @@ -24,11 +24,10 @@ import json from django.dispatch import receiver from django.template.loader import get_template -from django.urls import reverse -from django.utils.html import escape from django.utils.translation import gettext_lazy as _ from pretix.base.models import Event, SalesChannel +from pretix.base.models.log import EventLogEntryType, log_entry_types from pretix.base.signals import ( # NOQA: legacy import EventPluginSignal, event_copy_data, item_copy_data, layout_text_variables, logentry_display, logentry_object_link, register_data_exporters, @@ -134,38 +133,18 @@ def pdf_event_copy_data_receiver(sender, other, item_map, question_map, **kwargs return layout_map -@receiver(signal=logentry_display, dispatch_uid="pretix_ticketoutputpdf_logentry_display") -def pdf_logentry_display(sender, logentry, **kwargs): - if not logentry.action_type.startswith('pretix.plugins.ticketoutputpdf'): - return - - plains = { - 'pretix.plugins.ticketoutputpdf.layout.added': _('Ticket layout created.'), - 'pretix.plugins.ticketoutputpdf.layout.deleted': _('Ticket layout deleted.'), - 'pretix.plugins.ticketoutputpdf.layout.changed': _('Ticket layout changed.'), - } - - if logentry.action_type in plains: - return plains[logentry.action_type] +class PdfTicketLayoutLogEntryType(EventLogEntryType): + object_type = TicketLayout + object_link_wrapper = _('Ticket layout {val}') + object_link_viewname = 'plugins:ticketoutputpdf:edit' + object_link_argname = 'layout' -@receiver(signal=logentry_object_link, dispatch_uid="pretix_ticketoutputpdf_logentry_object_link") -def pdf_logentry_object_link(sender, logentry, **kwargs): - if not logentry.action_type.startswith('pretix.plugins.ticketoutputpdf.layout') or not isinstance( - logentry.content_object, TicketLayout): - return - - a_text = _('Ticket layout {val}') - a_map = { - 'href': reverse('plugins:ticketoutputpdf:edit', kwargs={ - 'event': sender.slug, - 'organizer': sender.organizer.slug, - 'layout': logentry.content_object.id - }), - 'val': escape(logentry.content_object.name), - } - a_map['val'] = '{val}'.format_map(a_map) - return a_text.format_map(a_map) +log_entry_types.register(*PdfTicketLayoutLogEntryType.derive_plains({ + 'pretix.plugins.ticketoutputpdf.layout.added': _('Ticket layout created.'), + 'pretix.plugins.ticketoutputpdf.layout.deleted': _('Ticket layout deleted.'), + 'pretix.plugins.ticketoutputpdf.layout.changed': _('Ticket layout changed.'), +})) def _ticket_layouts_for_item(request, item):