# Generated by Django 5.2.3 on 2025-06-21 21:59 import django.db.models.deletion from django.conf import settings from django.db import migrations, models from django.db.migrations.state import StateApps from django.db.models import Case, When from django.utils import translation def migrate_roles(apps: StateApps, schema_editor): ClubRole = apps.get_model("club", "ClubRole") Membership = apps.get_model("club", "Membership") translation.activate("fr") updates = [] presidency = settings.SITH_CLUB_ROLES_ID["President"] for club_id, role in Membership.objects.values_list("club", "role").distinct(): new_role = ClubRole.objects.create( name=SITH_CLUB_ROLES[role], is_board=role > settings.SITH_MAXIMUM_FREE_ROLE, is_presidency=role == presidency, club_id=club_id, order=presidency - role, ) updates.append(When(role=role, then=new_role.id)) # all updates must happen at the same time # otherwise, the 10 first created ClubRole would be # re-modified after their initial creation, and it would # result in an incoherent state. # To avoid that, all updates are wrapped in a single giant Case(When) statement # cf. https://docs.djangoproject.com/fr/stable/ref/models/conditional-expressions/#conditional-update Membership.objects.update(role=Case(*updates)) class Migration(migrations.Migration): dependencies = [ ("club", "0014_alter_club_options_rename_unix_name_club_slug_name_and_more") ] operations = [ migrations.CreateModel( name="ClubRole", fields=[ ( "id", models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "order", models.PositiveIntegerField( db_index=True, editable=False, verbose_name="order" ), ), ( "club", models.ForeignKey( help_text="The club with which this role is associated", on_delete=django.db.models.deletion.CASCADE, related_name="roles", to="club.club", verbose_name="club", ), ), ("name", models.CharField(max_length=50, verbose_name="name")), ( "description", models.TextField( default="", blank=True, verbose_name="description" ), ), ( "is_board", models.BooleanField(default=False, verbose_name="Board role"), ), ( "is_presidency", models.BooleanField(default=False, verbose_name="Presidency role"), ), ( "is_active", models.BooleanField( default=True, help_text=( "If the role is inactive, people joining the club " "won't be able to get it." ), verbose_name="is active", ), ), ], options={ "ordering": ("order",), "verbose_name": "club role", "verbose_name_plural": "club roles", }, ), migrations.AddConstraint( model_name="clubrole", constraint=models.CheckConstraint( condition=models.Q( ("is_presidency", False), ("is_board", True), _connector="OR" ), name="clubrole_presidency_implies_board", ), ), migrations.RunPython(migrate_roles, migrations.RunPython.noop), # because Postgres migrations run in a single transaction, # we cannot change the actual values of Membership.role # and apply the FOREIGN KEY constraint in the same migration. # The constraint is created in the next migration ]