From 04769eb628b4bf74da2b3422bc68d5312cf6deb5 Mon Sep 17 00:00:00 2001 From: Kara Engelhardt Date: Mon, 5 Oct 2026 15:03:37 +0200 Subject: [PATCH] add wallet layout chooser to item settings --- src/pretix/plugins/wallet/forms.py | 35 ++++++++++++++++++++++- src/pretix/plugins/wallet/models.py | 4 +-- src/pretix/plugins/wallet/receivers.py | 24 ++++++++++++++-- src/pretix/plugins/wallet/ticketoutput.py | 8 ++++-- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/pretix/plugins/wallet/forms.py b/src/pretix/plugins/wallet/forms.py index eb86538445..42cd51572c 100644 --- a/src/pretix/plugins/wallet/forms.py +++ b/src/pretix/plugins/wallet/forms.py @@ -9,6 +9,8 @@ from django.core.files.uploadedfile import SimpleUploadedFile, UploadedFile from django.utils.translation import gettext_lazy as _ from pretix.control.forms import ClearableBasenameFileInput from django.core.files import File +from .models import WalletLayout, WalletLayoutItem + logger = logging.getLogger(__name__) @@ -18,7 +20,11 @@ def validate_rsa_privkey(value: File): value = value.decode() if not value: return - if not re.match(r"^-----BEGIN( (RSA |ENCRYPTED )?PRIVATE KEY-----).*-----END\1$", value, re.DOTALL): + if not re.match( + r"^-----BEGIN( (RSA |ENCRYPTED )?PRIVATE KEY-----).*-----END\1$", + value, + re.DOTALL, + ): raise ValidationError( _( "This does not look like an RSA private key in PEM format (it misses the correct begin or end signifiers)" @@ -99,3 +105,30 @@ class PNGImageField(forms.FileField): ) return value + + +class WalletLayoutItemForm(forms.ModelForm): + is_layouts = True + layout = forms.ModelChoiceField( + queryset=WalletLayout.objects.none(), + label=_("Wallet Layout"), + empty_label=_("(Event default)"), + required=False + ) + + class Meta: + model = WalletLayoutItem + fields = ("layout",) + + def __init__(self, *args, **kwargs): + event = kwargs.pop("event") + super().__init__(*args, **kwargs) + self.fields["layout"].queryset = event.wallet_layouts.all() + + def save(self, commit=True): + if self.cleaned_data["layout"] is None: + if self.instance.pk: + self.instance.delete() + else: + self.instance.layout = self.cleaned_data["layout"] + return super().save(commit=commit) diff --git a/src/pretix/plugins/wallet/models.py b/src/pretix/plugins/wallet/models.py index 678c3c3939..3dc2a48d75 100644 --- a/src/pretix/plugins/wallet/models.py +++ b/src/pretix/plugins/wallet/models.py @@ -78,10 +78,10 @@ class WalletPlatformLayout(LoggedModel): class WalletLayoutItem(models.Model): item = models.OneToOneField('pretixbase.Item', null=True, blank=True, related_name='walletlayout', on_delete=models.CASCADE) - layout = models.ForeignKey(WalletLayout, on_delete=models.CASCADE, related_name='item_assignments') + layout = models.ForeignKey(WalletLayout, null=True, on_delete=models.CASCADE, related_name='item_assignments') def clean(self): - if self.item.event != self.layout.event: + if self.layout and self.item.event != self.layout.event: raise ValidationError("cannot bind layout to item of different event") class WalletLayoutFileSetting(models.Model): diff --git a/src/pretix/plugins/wallet/receivers.py b/src/pretix/plugins/wallet/receivers.py index 14101effe6..3557549fe4 100644 --- a/src/pretix/plugins/wallet/receivers.py +++ b/src/pretix/plugins/wallet/receivers.py @@ -20,8 +20,12 @@ # . # -from pretix.base.signals import register_ticket_outputs, register_global_settings, EventPluginSignal +from pretix.base.signals import register_ticket_outputs, register_global_settings +from pretix.control.signals import item_forms from .ticketoutput import OUTPUTS +from django.dispatch import receiver +from .forms import WalletLayoutItemForm +from .models import WalletLayoutItem def connect_signals(): for output in OUTPUTS: @@ -34,4 +38,20 @@ def connect_signals(): if hasattr(output, "get_global_settings"): register_global_settings.connect(output.get_global_settings, dispatch_uid=f"wallet_global_settings_{output.identifier}") -connect_signals() \ No newline at end of file +connect_signals() + + +@receiver(item_forms, dispatch_uid="pretix_wallet_item_forms") +def control_item_forms(sender, request, item, **kwargs): + forms = [] + try: + inst = WalletLayoutItem.objects.get(item=item) + except WalletLayoutItem.DoesNotExist: + inst = WalletLayoutItem(item=item) + forms.append(WalletLayoutItemForm( + instance=inst, + event=sender, + data=(request.POST if request.method == "POST" else None), + prefix="wallet" + )) + return forms diff --git a/src/pretix/plugins/wallet/ticketoutput.py b/src/pretix/plugins/wallet/ticketoutput.py index 0e15879ef4..e74482bf63 100644 --- a/src/pretix/plugins/wallet/ticketoutput.py +++ b/src/pretix/plugins/wallet/ticketoutput.py @@ -65,7 +65,7 @@ class WalletOutput(BaseTicketOutput): def generate(self, op): if hasattr(op.item, "walletlayout"): - wallet_layout = op.item.walletlayout + wallet_layout = op.item.walletlayout.layout else: wallet_layout = op.event.wallet_layouts.get(default=True) platform_layout = get_object_or_404( @@ -92,7 +92,8 @@ class GoogleWalletTicketOutput(WalletOutput): "\n" "Please be aware, that there is no way to delete the data, once it has been transmitted.\n") - def get_global_settings(sender, **kwargs): + @classmethod + def get_global_settings(cls, **kwargs): return OrderedDict( [ ( @@ -143,7 +144,8 @@ class AppleWalletTicketOutput(WalletOutput): download_button_text = "Add to Apple Wallet" platform = ApplePlatform - def get_global_settings(sender, **kwargs): + @classmethod + def get_global_settings(cls, **kwargs): return OrderedDict( [ (