From bea3f3225106b70d5379f5119e406052e60a0e4f Mon Sep 17 00:00:00 2001 From: Mira Weller Date: Mon, 10 Mar 2025 13:13:12 +0100 Subject: [PATCH] Add deprecated fields --- src/pretix/base/datasync/datasync.py | 4 +- src/pretix/base/datasync/sourcefields.py | 132 +++++++++++++----- src/pretix/control/forms/mapping.py | 17 ++- .../datasync/control_order_info.html | 13 +- 4 files changed, 113 insertions(+), 53 deletions(-) diff --git a/src/pretix/base/datasync/datasync.py b/src/pretix/base/datasync/datasync.py index 6bdaab857f..0fef2943b4 100644 --- a/src/pretix/base/datasync/datasync.py +++ b/src/pretix/base/datasync/datasync.py @@ -217,8 +217,8 @@ class OutboundSyncProvider: @cached_property def data_fields(self): return { - key: (from_model, label, ptype, enum_opts, getter) - for (from_model, key, label, ptype, enum_opts, getter) in get_data_fields(self.event) + f.key: (f.required_input, f.label, f.type, f.enum_opts, f.getter) + for f in get_data_fields(self.event) } def get_field_value(self, inputs, mapping_entry): diff --git a/src/pretix/base/datasync/sourcefields.py b/src/pretix/base/datasync/sourcefields.py index d01031daee..f698a1c4ae 100644 --- a/src/pretix/base/datasync/sourcefields.py +++ b/src/pretix/base/datasync/sourcefields.py @@ -1,4 +1,5 @@ import json +from collections import namedtuple from functools import partial from django.db.models import Max @@ -65,6 +66,10 @@ def first_checkin_on_list(list_pk, position): if checkin: return isoformat_or_none(checkin.datetime) +def split_name_on_last_space(name, part): + name_parts = name.rsplit(" ", 1) + return name_parts[part] if len(name_parts) > part else "" + ORDER_POSITION = 'position' ORDER = 'order' @@ -76,6 +81,13 @@ AVAILABLE_MODELS = { } +DataFieldInfo = namedtuple( + 'DataFieldInfo', + field_names=('required_input', 'key', 'label', 'type', 'enum_opts', 'getter', 'deprecated'), + defaults=[False] +) + + def get_data_fields(event, for_model=None): """ Returns tuple of (required_input, key, label, type, enum_opts, getter) @@ -91,7 +103,7 @@ def get_data_fields(event, for_model=None): src_fields = ( [ - ( + DataFieldInfo( ORDER_POSITION, "attendee_name", _("Attendee name"), @@ -102,7 +114,7 @@ def get_data_fields(event, for_model=None): ), ] + [ - ( + DataFieldInfo( ORDER_POSITION, "attendee_name_" + k, _("Attendee") + ": " + label, @@ -116,11 +128,12 @@ def get_data_fields(event, for_model=None): ).get(k, ""), k, ), + deprecated=len(name_scheme["fields"]) == 1, ) for k, label, w in name_scheme["fields"] ] + [ - ( + DataFieldInfo( ORDER_POSITION, "attendee_email", _("Attendee email"), @@ -129,7 +142,7 @@ def get_data_fields(event, for_model=None): lambda position: position.attendee_email or (position.addon_to.attendee_email if position.addon_to else None), ), - ( + DataFieldInfo( ORDER_POSITION, "attendee_or_order_email", _("Attendee or order email"), @@ -139,7 +152,7 @@ def get_data_fields(event, for_model=None): or (position.addon_to.attendee_email if position.addon_to else None) or position.order.email, ), - ( + DataFieldInfo( ORDER_POSITION, "attendee_company", _("Attendee company"), @@ -147,7 +160,7 @@ def get_data_fields(event, for_model=None): None, lambda position: position.company or (position.addon_to.company if position.addon_to else None), ), - ( + DataFieldInfo( ORDER_POSITION, "attendee_street", _("Attendee address street"), @@ -155,7 +168,7 @@ def get_data_fields(event, for_model=None): None, lambda position: position.street or (position.addon_to.street if position.addon_to else None), ), - ( + DataFieldInfo( ORDER_POSITION, "attendee_zipcode", _("Attendee address ZIP code"), @@ -163,7 +176,7 @@ def get_data_fields(event, for_model=None): None, lambda position: position.zipcode or (position.addon_to.zipcode if position.addon_to else None), ), - ( + DataFieldInfo( ORDER_POSITION, "attendee_city", _("Attendee address city"), @@ -171,7 +184,7 @@ def get_data_fields(event, for_model=None): None, lambda position: position.city or (position.addon_to.city if position.addon_to else None), ), - ( + DataFieldInfo( ORDER_POSITION, "attendee_country", _("Attendee address country"), @@ -181,7 +194,7 @@ def get_data_fields(event, for_model=None): position.country or (position.addon_to.attendee_name if position.addon_to else "") ), ), - ( + DataFieldInfo( ORDER, "invoice_address_company", _("Invoice address company"), @@ -189,7 +202,7 @@ def get_data_fields(event, for_model=None): None, lambda order: order.invoice_address.company, ), - ( + DataFieldInfo( ORDER, "invoice_address_name", _("Invoice address name"), @@ -199,7 +212,7 @@ def get_data_fields(event, for_model=None): ), ] + [ - ( + DataFieldInfo( ORDER, "invoice_address_name_" + k, _("Invoice address") + ": " + label, @@ -211,11 +224,12 @@ def get_data_fields(event, for_model=None): ), k, ), + deprecated=len(name_scheme["fields"]) == 1, ) for k, label, w in name_scheme["fields"] ] + [ - ( + DataFieldInfo( ORDER, "invoice_address_street", _("Invoice address street"), @@ -223,7 +237,7 @@ def get_data_fields(event, for_model=None): None, lambda order: order.invoice_address.street, ), - ( + DataFieldInfo( ORDER, "invoice_address_zipcode", _("Invoice address ZIP code"), @@ -231,7 +245,7 @@ def get_data_fields(event, for_model=None): None, lambda order: order.invoice_address.zipcode, ), - ( + DataFieldInfo( ORDER, "invoice_address_city", _("Invoice address city"), @@ -239,7 +253,7 @@ def get_data_fields(event, for_model=None): None, lambda order: order.invoice_address.city, ), - ( + DataFieldInfo( ORDER, "invoice_address_country", _("Invoice address country"), @@ -247,7 +261,7 @@ def get_data_fields(event, for_model=None): None, lambda order: str(order.invoice_address.country), ), - ( + DataFieldInfo( ORDER, "email", _("Order email"), @@ -255,7 +269,7 @@ def get_data_fields(event, for_model=None): None, lambda order: order.email, ), - ( + DataFieldInfo( ORDER, "order_code", _("Order code"), @@ -263,7 +277,7 @@ def get_data_fields(event, for_model=None): None, lambda order: order.code, ), - ( + DataFieldInfo( ORDER, "event_order_code", _("Event and order code"), @@ -271,7 +285,7 @@ def get_data_fields(event, for_model=None): None, lambda order: order.full_code, ), - ( + DataFieldInfo( ORDER, "order_total", _("Order total"), @@ -279,7 +293,7 @@ def get_data_fields(event, for_model=None): None, lambda order: str(order.total), ), - ( + DataFieldInfo( ORDER_POSITION, "product", _("Product and variation name"), @@ -290,7 +304,7 @@ def get_data_fields(event, for_model=None): + ((" – " + str(position.variation.value)) if position.variation else "") ), ), - ( + DataFieldInfo( ORDER_POSITION, "product_id", _("Product ID"), @@ -298,7 +312,7 @@ def get_data_fields(event, for_model=None): None, lambda position: position.item.pk, ), - ( + DataFieldInfo( EVENT, "event_slug", _("Event short form"), @@ -306,7 +320,7 @@ def get_data_fields(event, for_model=None): None, lambda event: str(event.slug), ), - ( + DataFieldInfo( EVENT, "event_name", _("Event name"), @@ -314,7 +328,7 @@ def get_data_fields(event, for_model=None): None, lambda event: str(event.name), ), - ( + DataFieldInfo( EVENT_OR_SUBEVENT, "event_date_from", _("Event start date"), @@ -322,7 +336,7 @@ def get_data_fields(event, for_model=None): None, lambda event_or_subevent: isoformat_or_none(event_or_subevent.date_from), ), - ( + DataFieldInfo( EVENT_OR_SUBEVENT, "event_date_to", _("Event end date"), @@ -330,7 +344,7 @@ def get_data_fields(event, for_model=None): None, lambda event_or_subevent: isoformat_or_none(event_or_subevent.date_to), ), - ( + DataFieldInfo( ORDER_POSITION, "voucher_code", _("Voucher code"), @@ -338,7 +352,7 @@ def get_data_fields(event, for_model=None): None, lambda position: position.voucher.code if position.voucher_id else "", ), - ( + DataFieldInfo( ORDER_POSITION, "ticket_id", _("Ticket ID"), @@ -346,7 +360,7 @@ def get_data_fields(event, for_model=None): None, lambda position: position.code, ), - ( + DataFieldInfo( ORDER_POSITION, "ticket_price", _("Ticket price"), @@ -354,7 +368,7 @@ def get_data_fields(event, for_model=None): None, lambda position: str(position.price), ), - ( + DataFieldInfo( ORDER, "order_status", _("Order status"), @@ -362,7 +376,7 @@ def get_data_fields(event, for_model=None): Order.STATUS_CHOICE, lambda order: [str(order.status)], ), - ( + DataFieldInfo( ORDER, "order_date", _("Order date and time"), @@ -370,7 +384,7 @@ def get_data_fields(event, for_model=None): None, lambda order: order.datetime.isoformat(), ), - ( + DataFieldInfo( ORDER, "payment_date", _("Payment date and time"), @@ -378,7 +392,7 @@ def get_data_fields(event, for_model=None): None, get_payment_date, ), - ( + DataFieldInfo( ORDER, "order_locale", _("Order locale country code"), @@ -388,7 +402,7 @@ def get_data_fields(event, for_model=None): ), ] + [ - ( + DataFieldInfo( ORDER_POSITION, "checkin_date_" + str(cl.pk), _("Check-in datetime on list {}").format(cl.name), @@ -399,7 +413,7 @@ def get_data_fields(event, for_model=None): for cl in event.checkin_lists.all() ] + [ - ( + DataFieldInfo( ORDER_POSITION, "question_" + q.identifier, _("Question: {name}").format(name=str(q.question)), @@ -410,12 +424,54 @@ def get_data_fields(event, for_model=None): for q in event.questions.all().prefetch_related("options") ] ) + if not any(field_name == "given_name" for field_name, label, weight in name_scheme["fields"]): + src_fields += [ + DataFieldInfo( + ORDER_POSITION, + "attendee_name_given_name", + _("Attendee") + ": " + _("Given name") + " (⚠️ auto-generated, not recommended)", + Question.TYPE_STRING, + None, + lambda position: split_name_on_last_space(position.attendee_name, part=0), + deprecated=True, + ), + DataFieldInfo( + ORDER, + "invoice_address_name_given_name", + _("Invoice address") + ": " + _("Given name") + " (⚠️ auto-generated, not recommended)", + Question.TYPE_STRING, + None, + lambda order: split_name_on_last_space(order.invoice_address.name, part=0), + deprecated=True, + ), + ] + + if not any(field_name == "family_name" for field_name, label, weight in name_scheme["fields"]): + src_fields += [ + DataFieldInfo( + ORDER_POSITION, + "attendee_name_family_name", + _("Attendee") + ": " + _("Family name") + " (⚠️ auto-generated, not recommended)", + Question.TYPE_STRING, + None, + lambda position: split_name_on_last_space(position.attendee_name.rsplit, part=1), + deprecated=True, + ), + DataFieldInfo( + ORDER, + "invoice_address_name_family_name", + _("Invoice address") + ": " + _("Family name") + " (⚠️ auto-generated, not recommended)", + Question.TYPE_STRING, + None, + lambda order: split_name_on_last_space(order.invoice_address.name, part=1), + deprecated=True, + ), + ] + if for_model: available_inputs = AVAILABLE_MODELS[for_model] return [ - (required_input, key, label, qtype, enum_opts, getter) - for required_input, key, label, qtype, enum_opts, getter in src_fields - if required_input in available_inputs + f for f in src_fields if f.required_input in available_inputs ] else: return src_fields diff --git a/src/pretix/control/forms/mapping.py b/src/pretix/control/forms/mapping.py index 7f8ee4419c..8f9a35b835 100644 --- a/src/pretix/control/forms/mapping.py +++ b/src/pretix/control/forms/mapping.py @@ -21,11 +21,11 @@ class PropertyMappingForm(forms.Form): ] ) - def __init__(self, pretix_fields, external_fields_id, *args, **kwargs): + def __init__(self, pretix_fields, external_fields_id, available_modes, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["pretix_field"] = forms.ChoiceField( label=_("pretix Field"), - choices=pretix_fields_choices(pretix_fields), + choices=pretix_fields_choices(pretix_fields, kwargs.get("initial", {}).get("pretix_field")), required=False, ) if external_fields_id: @@ -40,6 +40,9 @@ class PropertyMappingForm(forms.Form): self.fields["external_field"].choices = [ (self["external_field"].value(), self["external_field"].value()), ] + self.fields["overwrite"].choices = [ + (key, label) for (key, label) in self.fields["overwrite"].choices if key in available_modes + ] print(self.fields) @@ -51,11 +54,12 @@ class PropertyMappingFormSet(formset_factory( )): template_name = "pretixcontrol/datasync/property_mapping_formset.html" - def __init__(self, pretix_fields, external_fields, prefix, *args, **kwargs): + def __init__(self, pretix_fields, external_fields, available_modes, prefix, *args, **kwargs): super().__init__( form_kwargs={ "pretix_fields": pretix_fields, "external_fields_id": prefix + "external-fields" if external_fields else None, + "available_modes": available_modes, }, prefix=prefix, *args, **kwargs) @@ -68,8 +72,9 @@ class PropertyMappingFormSet(formset_factory( return ctx -def pretix_fields_choices(pretix_fields): +def pretix_fields_choices(pretix_fields, initial_choice): return [ - (key, label + " [" + QUESTION_TYPE_IDENTIFIERS[ptype] + "]") - for (required_input, key, label, ptype, enum_opts, getter) in pretix_fields + (f.key, f.label + " [" + QUESTION_TYPE_IDENTIFIERS[f.type] + "]") + for f in pretix_fields + if not f.deprecated or f.key == initial_choice ] diff --git a/src/pretix/control/templates/pretixcontrol/datasync/control_order_info.html b/src/pretix/control/templates/pretixcontrol/datasync/control_order_info.html index 3af94f401e..7c507878b1 100644 --- a/src/pretix/control/templates/pretixcontrol/datasync/control_order_info.html +++ b/src/pretix/control/templates/pretixcontrol/datasync/control_order_info.html @@ -9,7 +9,6 @@
- {{ test.hello }} {% for identifier, display_name, pending, objects in providers %} @@ -20,20 +19,20 @@ {% if pending.failed_attempts %} {% blocktrans trimmed with num=pending.failed_attempts max=pending.max_retry_attempts %} - Error, retry {{ num }} of {{ max }} + Error, retry {{ num }} of {{ max }}. {% endblocktrans %}{% if pending.not_before %}, - {% blocktrans trimmed with datetime=pending.not_before %} - waiting until {{ datetime }} + {% blocktrans trimmed with datetime=pending.not_before|date:"SHORT_DATETIME_FORMAT" %} + Waiting until {{ datetime }}. {% endblocktrans %} {% endif %} {% elif pending.not_before %} - {% blocktrans trimmed with datetime=pending.not_before %} - Waiting until {{ datetime }} + {% blocktrans trimmed with datetime=pending.not_before|date:"SHORT_DATETIME_FORMAT" %} + Waiting until {{ datetime }}. {% endblocktrans %} {% else %} {% trans "Pending" %} {% endif %} - (triggered by {{ pending.triggered_by }} at {{ pending.triggered }}) + (triggered by {{ pending.triggered_by }} at {{ pending.triggered|date:"SHORT_DATETIME_FORMAT" }}) {% else %} - {% endif %}