diff --git a/src/pretix/base/migrations/0311_questionnaire_questionnairechild.py b/src/pretix/base/migrations/0311_questionnaire_questionnairechild.py index d0652dc92d..e855a0ad57 100644 --- a/src/pretix/base/migrations/0311_questionnaire_questionnairechild.py +++ b/src/pretix/base/migrations/0311_questionnaire_questionnairechild.py @@ -1,6 +1,7 @@ # Generated by Django 4.2.29 on 2026-03-19 14:24 import json from collections import namedtuple + from itertools import chain, groupby from django.db import migrations, models @@ -10,7 +11,7 @@ from i18nfield.strings import LazyI18nString import pretix.base.models.base import pretix.base.models.fields - +from pretix.base.i18n import language FakeQuestion = namedtuple( 'FakeQuestion', 'id question position required' @@ -43,6 +44,8 @@ def get_fake_questions(settings): def migrate_questions_forward(apps, schema_editor): + from django.utils.translation import gettext as _, get_supported_language_variant + Event = apps.get_model("pretixbase", "Event") Item = apps.get_model("pretixbase", "Item") Question = apps.get_model("pretixbase", "Question") @@ -50,7 +53,7 @@ def migrate_questions_forward(apps, schema_editor): QuestionnaireChild = apps.get_model("pretixbase", "QuestionnaireChild") EventSettingsStore = apps.get_model('pretixbase', 'Event_SettingsStore') - def create_grouped_item_questionnaires(event, children, label_prefix, questionnaire_type): + def create_grouped_item_questionnaires(event, children, label_prefix, questionnaire_type, personalized_items=None): # group by item, creating a unique questionnaire per item item_questionnaires = (([t[3] for t in children], item_id) for item_id, children in groupby(children, key=lambda t: t[0])) @@ -61,10 +64,16 @@ def migrate_questions_forward(apps, schema_editor): for children, iterator in merged_questionnaires: items = [item for _c, item in iterator] + internal_name = label_prefix + ', '.join(str(iname or name) for (id, iname, name) in items) + if all(i.personalized for i in items) and len(items) == len(personalized_items) and questionnaire_type == 'PS': + # if we have a questionnaire for exactly all personalized items, we just call it "Attendee data" + # (same as the default questionnaire for new events) + internal_name = _('Attendee data') + # create questionnaires and children questionnaire = Questionnaire.objects.create( event=event, type=questionnaire_type, position=0, all_sales_channels=True, - internal_name=label_prefix + ', '.join(str(iname or name) for (id, iname, name) in items) + internal_name=internal_name ) questionnaire.items.set([id for (id, iname, name) in items]) deps = {} @@ -94,52 +103,65 @@ def migrate_questions_forward(apps, schema_editor): settings = { setting.key: setting.value for setting in EventSettingsStore.objects.filter(object_id=event.id, key__in=( 'system_question_order', 'attendee_names_asked', 'attendee_names_required', 'attendee_emails_asked', 'attendee_emails_required', - 'attendee_company_asked', 'attendee_company_required', 'attendee_addresses_asked', 'attendee_addresses_required', + 'attendee_company_asked', 'attendee_company_required', 'attendee_addresses_asked', 'attendee_addresses_required', 'locale', )) } + with language(get_supported_language_variant(settings.get('locale', 'en'))): + # [P] get all ticket-level questions (user-defined and system provided), along with the products for which they're asked + questions = event.questions.filter(container_type='P') - # get all ticket-level questions (user-defined and system provided), along with the products for which they're asked - questions = event.questions.filter(container_type='P') - children = sorted(chain(( - (item, q.position, 0, q) - for q in get_fake_questions(settings) - for item in event.items.filter(personalized=True).values_list('id', 'internal_name', 'name') - ), ( - (item, q.position, q.id, q) - for q in questions.filter(hidden=False) - for item in q.items.values_list('id', 'internal_name', 'name') - )), key=lambda t: (t[0], t[1])) + # [PS] presale + personalized_items = event.items.filter(personalized=True).values_list('id', 'internal_name', 'name') + children = sorted(chain(( + (item, q.position, 0, q) + for q in get_fake_questions(settings) + for item in personalized_items + ), ( + (item, q.position, q.id, q) + for q in questions.filter(hidden=False, ask_during_checkin=False) + for item in q.items.values_list('id', 'internal_name', 'name') + )), key=lambda t: (t[0], t[1])) - create_grouped_item_questionnaires(event, children, '', 'PS') + create_grouped_item_questionnaires(event, children, '', 'PS', personalized_items) - children = sorted(chain(( - (item, q.position, q.id, q) - for q in questions.filter(hidden=True) - for item in q.items.values_list('id', 'internal_name', 'name') - )), key=lambda t: (t[0], t[1])) + # [PC] checkin + children = sorted(chain(( + (item, q.position, q.id, q) + for q in questions.filter(ask_during_checkin=True) + for item in q.items.values_list('id', 'internal_name', 'name') + )), key=lambda t: (t[0], t[1])) - create_grouped_item_questionnaires(event, children, 'Hidden questions for ', 'PH') + create_grouped_item_questionnaires(event, children, _('Check-in questions for '), 'PC') - # get all order-level questions - questions = list(event.questions.filter(container_type='O', hidden=False).order_by('position')) - if questions: - # create questionnaires and children - questionnaire = Questionnaire.objects.create( - event=event, type='OS', position=0, all_sales_channels=True, - internal_name='Per-order questions', - ) - deps = {} - for position, child in enumerate(questions): - deps[child.id] = QuestionnaireChild.objects.create( - questionnaire=questionnaire, - position=position + 1, - user_datafield=child, - required=child.required, - label=child.question, - help_text=child.help_text, - dependency_question=deps[child.dependency_question.id] if child.dependency_question else None, - dependency_values=child.dependency_values, + # [PH] hidden + children = sorted(chain(( + (item, q.position, q.id, q) + for q in questions.filter(hidden=True, ask_during_checkin=False) + for item in q.items.values_list('id', 'internal_name', 'name') + )), key=lambda t: (t[0], t[1])) + + create_grouped_item_questionnaires(event, children, _('Hidden questions for '), 'PH') + + # [O] get all order-level questions + questions = list(event.questions.filter(container_type='O', hidden=False).order_by('position')) + if questions: + # create questionnaires and children + questionnaire = Questionnaire.objects.create( + event=event, type='OS', position=0, all_sales_channels=True, + internal_name=_('Per-order questions'), ) + deps = {} + for position, child in enumerate(questions): + deps[child.id] = QuestionnaireChild.objects.create( + questionnaire=questionnaire, + position=position + 1, + user_datafield=child, + required=child.required, + label=child.question, + help_text=child.help_text, + dependency_question=deps[child.dependency_question.id] if child.dependency_question else None, + dependency_values=child.dependency_values, + ) def migrate_questions_backward(apps, schema_editor):