diff --git a/src/pretix/base/migrations/0299_fixup_eventmetaproperties.py b/src/pretix/base/migrations/0299_fixup_eventmetaproperties.py index d3b4440b48..20ceee6a21 100644 --- a/src/pretix/base/migrations/0299_fixup_eventmetaproperties.py +++ b/src/pretix/base/migrations/0299_fixup_eventmetaproperties.py @@ -1,7 +1,7 @@ # Generated by Django 5.2.12 on 2026-04-28 11:34 import logging -from django.db import migrations +from django.db import IntegrityError, migrations, transaction from django.db.models import Count, F logger = logging.getLogger(__name__) @@ -17,6 +17,10 @@ def fix_cross_organizer_eventmetavalues(apps, schema_editor): try: emv.property = emv.event.organizer.meta_properties.filter(name=emv.property.name).first() logger.info(f' found existing EventMetaProperty in {emv.event.organizer.slug}') + if EventMetaValue.objects.filter(event=emv.event, property=emv.property).exists(): + logger.info(f' EventMetaValue with property in correct organizer already exists, deleting the cross-organizer one') + emv.delete() + continue except EventMetaProperty.DoesNotExist: meta_prop = emv.property meta_prop.pk = None @@ -24,7 +28,6 @@ def fix_cross_organizer_eventmetavalues(apps, schema_editor): meta_prop.save(force_insert=True) logger.info(f' created new EventMetaProperty') emv.property = meta_prop - # TODO: how to handle new duplicates in EventMetaValue.property logger.info(f' after: {emv.property.name}({emv.property.id}@{emv.property.organizer.slug}) = {emv.value}') emv.save() @@ -42,17 +45,28 @@ def make_eventmetaproperties_unique(apps, schema_editor): target = props[0] invalid = props[1:] - # TODO: how to handle new duplicates in EventMetaValue.property - affected = EventMetaValue.objects.filter( - event__organizer=dup['organizer'], property__in=invalid - ).update( - property=target - ) - logger.info(f' Switching {affected} value(s) over to {target.name}({target.id}@{target.organizer.slug})') + try: + with transaction.atomic(): + affected = EventMetaValue.objects.filter( + event__organizer=dup['organizer'], property__in=invalid + ).update( + property=target + ) + logger.info(f' Switching {affected} value(s) over to {target.name}({target.id}@{target.organizer.slug})') - for prop in invalid: - logger.info(f' Deleting {prop.name}({prop.id}@{prop.organizer.slug})') - prop.delete() + except IntegrityError as e: + logger.info(f' Failed to switch all value(s) over to {target.name}({target.id}@{target.organizer.slug})') + logger.info(f' {e}') + for prop in invalid: + newname = f'{prop.name}_DUPLICATE_{prop.id}' + logger.info(f' Renaming {prop.name}({prop.id}@{prop.organizer.slug}) to {newname}({prop.id}@{prop.organizer.slug})') + prop.name = newname + prop.save() + + else: + for prop in invalid: + logger.info(f' Deleting {prop.name}({prop.id}@{prop.organizer.slug})') + prop.delete() class Migration(migrations.Migration):