diff --git a/bds/migrations/0001_initial.py b/bds/migrations/0001_initial.py index 3d6f5218..aad43b30 100644 --- a/bds/migrations/0001_initial.py +++ b/bds/migrations/0001_initial.py @@ -8,7 +8,7 @@ import bds.models class Migration(migrations.Migration): dependencies = [ - ('gestion', '0001_initial'), + ('gestion', '0002_create_cof_bds'), ] operations = [ @@ -28,5 +28,13 @@ class Migration(migrations.Migration): on_delete=models.CASCADE, to='gestion.Profile')), ], + options={ + 'permissions': [ + ('member', 'Is a BDS member'), + ('buro', 'Is part of the BDS staff') + ], + 'verbose_name': 'Profil BDS', + 'verbose_name_plural': 'Profils BDS' + }, ), ] diff --git a/bds/migrations/0002_add_BDS_groups.py b/bds/migrations/0002_add_BDS_groups.py deleted file mode 100644 index 45510e59..00000000 --- a/bds/migrations/0002_add_BDS_groups.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations - - -def create_groups(apps, schema_editor): - """ - Creates the groups for BDS members and staff - """ - Group = apps.get_model("auth", "Group") - Group.objects.get_or_create(name="bds_members") - Group.objects.get_or_create(name="bds_buro") - - -class Migration(migrations.Migration): - - dependencies = [ - ('bds', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='bdsprofile', - options={ - 'permissions': [ - ('member', 'Is a BDS member'), - ('buro', 'Is part of the BDS staff') - ], - 'verbose_name': 'Profil BDS', - 'verbose_name_plural': 'Profils BDS' - }, - ), - migrations.RunPython(create_groups, migrations.RunPython.noop), - ] diff --git a/cof/migrations/0009_generic_profiles.py b/cof/migrations/0009_move_profile.py similarity index 52% rename from cof/migrations/0009_generic_profiles.py rename to cof/migrations/0009_move_profile.py index 7f19dc47..d863e538 100644 --- a/cof/migrations/0009_generic_profiles.py +++ b/cof/migrations/0009_move_profile.py @@ -1,60 +1,72 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.contrib.auth.models import Group from django.db import migrations, models +from django.db.models import F -def create_profile(apps, schema_editor): - CofProfile = apps.get_model("cof", "CofProfile") - Profile = apps.get_model("gestion", "Profile") - for p in CofProfile.objects.all(): - profile = Profile.objects.create( - id=p.id, - user=p.user, - login_clipper=p.login_clipper, - phone=p.phone, - occupation=p.occupation, - departement=p.departement, - comments=p.comments +def profiles_to_gestion(apps, schema_editor): + OldProfile = apps.get_model('cof', 'CofProfile') + NewProfile = apps.get_model('gestion', 'Profile') + + # New profiles are massively imported from the old profiles. + # IDs are kept identical to ease the migration of models which were + # referencing the CofProfile model. + + new_profiles = [] + + for old_p in OldProfile.objects.values().iterator(): + new_profiles.append( + NewProfile( + id=old_p['id'], + user_id=old_p['user_id'], + login_clipper=old_p['login_clipper'], + phone=old_p['phone'], + occupation=old_p['occupation'], + departement=old_p['departement'], + comments=old_p['comments'], + ) ) - p.profile = profile - p.save() + + NewProfile.objects.bulk_create(new_profiles) + + OldProfile.objects.all().update(profile_id=F('id')) -def preserve_perms(apps, schema_editor): - COFProfile = apps.get_model("cof", "CofProfile") +def cof_status_to_gestion(apps, schema_editor): + Association = apps.get_model('gestion', 'Association') + CofProfile = apps.get_model('cof', 'CofProfile') - # create the groups for COF members and staff - member = Group.objects.create(name='cof_members') - buro = Group.objects.create(name='cof_buro') + cof_assoc = Association.objects.get(name='COF') - cprofiles = COFProfile.objects.select_related("profile__user") - for cofp in cprofiles.filter(is_cof=True): - cofp.profile.user.groups.add(member) - for cofp in cprofiles.filter(is_buro=True): - cofp.profile.user.groups.add(buro) + cof_pks = ( + CofProfile.objects + .select_related('profile') + .values_list('profile__user_id', flat=True) + ) - -def remove_profile(apps, schema_editor): - raise NotImplementedError - -fuckup_perms = remove_profile + cof_assoc.members_group.user_set.add( + *cof_pks.filter(is_cof=True) + ) + cof_assoc.staff_group.user_set.add( + *cof_pks.filter(is_buro=True) + ) class Migration(migrations.Migration): + """ + BDS support changes how users data is organized. + Data is migrated to the new schema. + + """ dependencies = [ - ('gestion', '0001_initial'), ('cof', '0008_py3'), + ('gestion', '0002_create_cof_bds'), ] operations = [ - migrations.RenameField( - model_name='cofprofile', - old_name='mailing_cof', - new_name='mailing', - ), + # Temporarly authorize 'profile' as nullable to allow migrating data. migrations.AddField( model_name='cofprofile', name='profile', @@ -66,15 +78,8 @@ class Migration(migrations.Migration): ), preserve_default=False, ), - migrations.AlterModelOptions( - name='cofprofile', - options={ - 'permissions': (('member', 'Is a COF member'), - ('buro', 'Is part of COF staff')), - 'verbose_name': 'Profil COF', - 'verbose_name_plural': 'Profils COF'}, - ), - migrations.RunPython(create_profile, remove_profile), + migrations.RunPython(profiles_to_gestion), + # Data is migrated, unset nullable on 'profile'. migrations.AlterField( model_name='cofprofile', name='profile', @@ -84,6 +89,11 @@ class Migration(migrations.Migration): related_name='cof' ), ), + # Remove fields no longer used. + migrations.RemoveField( + model_name='cofprofile', + name='user', + ), migrations.RemoveField( model_name='cofprofile', name='comments', @@ -104,7 +114,10 @@ class Migration(migrations.Migration): model_name='cofprofile', name='phone', ), - migrations.RunPython(preserve_perms, fuckup_perms), + + # Keep cof member/staff status. + migrations.RunPython(cof_status_to_gestion), + # Remove the last no longer used fields. migrations.RemoveField( model_name='cofprofile', name='is_cof', @@ -113,8 +126,19 @@ class Migration(migrations.Migration): model_name='cofprofile', name='is_buro', ), - migrations.RemoveField( + + # Now we are safe, let's do basic operations. + migrations.AlterModelOptions( + name='cofprofile', + options={ + 'permissions': (('member', 'Is a COF member'), + ('buro', 'Is part of COF staff')), + 'verbose_name': 'Profil COF', + 'verbose_name_plural': 'Profils COF'}, + ), + migrations.RenameField( model_name='cofprofile', - name='user', + old_name='mailing_cof', + new_name='mailing', ), ] diff --git a/cof/migrations/0010_move_club.py b/cof/migrations/0010_move_club.py new file mode 100644 index 00000000..349642fb --- /dev/null +++ b/cof/migrations/0010_move_club.py @@ -0,0 +1,65 @@ +from __future__ import unicode_literals + +from django.db import migrations + + +def clubs_to_gestion(apps, schema_editor): + Association = apps.get_model('gestion', 'Association') + Membership = apps.get_model('gestion', 'ClubUser') + OldClub = apps.get_model('cof', 'Club') + NewClub = apps.get_model('gestion', 'Club') + + cof_assoc = Association.objects.get(name='COF') + + memberships = [] + + for oldclub in OldClub.objects.all(): + newclub = NewClub.objects.create( + name=oldclub.name, + description=oldclub.description, + association=cof_assoc, + ) + + members = oldclub.membres.values_list('id', flat=True) + respos = oldclub.respos.values_list('id', flat=True) + + for user in members: + memberships.append( + Membership( + club=newclub, + user_id=user, + has_paid=True, + is_respo=user in respos, + ) + ) + + Membership.objects.bulk_create(memberships) + + +class Migration(migrations.Migration): + """ + This migration focus on migrating clubs data to the 'gestion' app. + """ + + dependencies = [ + ('cof', '0009_move_profile'), + ('gestion', '0002_create_cof_bds'), + ] + + operations = [ + # Move clubs from cof to gestion. + migrations.RunPython(clubs_to_gestion), + + # Delete legacy Club model. + migrations.RemoveField( + model_name='club', + name='membres', + ), + migrations.RemoveField( + model_name='club', + name='respos', + ), + migrations.DeleteModel( + name='Club', + ), + ] diff --git a/cof/migrations/0011_move_event.py b/cof/migrations/0011_move_event.py new file mode 100644 index 00000000..71750bf6 --- /dev/null +++ b/cof/migrations/0011_move_event.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations + + +def event_to_gestion(apps, schema_editor): + # Fetching the models that have be moved from cof to gestion + OldEvent = apps.get_model('cof', 'Event') + NewEvent = apps.get_model('gestion', 'Event') + Location = apps.get_model('gestion', 'Location') + Association = apps.get_model('gestion', 'Association') + + # The old Event.location field becomes a table: we need to create an entry + # in this table for each value of the old `location` field. + locations = set() # A set to prevent duplicate entries + old_events = OldEvent.objects.values() + new_events = [] + for event in old_events: + locations.add(event["location"]) + new_events.append(event) + Location.objects.bulk_create([Location(name=name) for name in locations]) + map_loc = { + loc.name: loc + for loc in Location.objects.all() + } + for event in new_events: + event["location"] = map_loc[event["location"]] + NewEvent.objects.bulk_create([ + NewEvent(**event) + for event in new_events + ]) + + # Do not forget to link all the existing event to the COF association + cof_assoc = Association.objects.get(name="COF") + cof_assoc.events.add(*NewEvent.objects.all()) + + # Migrating the other models is straightforward. + # Keep care to the ordering. A change can lead to DB error because of + # failed checks on foreignkey constraints. The dependencies between these + # models give the following constraints: + # - EventRegistration must precede EventCommentField and EventOption, + # - EventCommentField must precede EventCommentValue, + # - EventOption must precede EventOptionChoice. + model_names = [ + 'EventRegistration', 'EventCommentField', 'EventCommentValue', + 'EventOption', 'EventOptionChoice', + ] + + cls_models = [ + (apps.get_model('cof', name), apps.get_model('gestion', name)) + for name in model_names + ] + + for FromModel, ToModel in cls_models: + ToModel.objects.bulk_create([ + ToModel(**values) + for values in FromModel.objects.values() + ]) + + +class Migration(migrations.Migration): + + dependencies = [ + ('cof', '0010_move_club'), + ('gestion', '0002_create_cof_bds'), + ] + + operations = [ + migrations.RunPython(event_to_gestion), + migrations.RemoveField( + model_name='eventcommentfield', + name='event', + ), + migrations.RemoveField( + model_name='eventcommentvalue', + name='commentfield', + ), + migrations.RemoveField( + model_name='eventcommentvalue', + name='registration', + ), + migrations.RemoveField( + model_name='eventoption', + name='event', + ), + migrations.RemoveField( + model_name='eventoptionchoice', + name='event_option', + ), + migrations.AlterUniqueTogether( + name='eventregistration', + unique_together=set([]), + ), + migrations.RemoveField( + model_name='eventregistration', + name='event', + ), + migrations.RemoveField( + model_name='eventregistration', + name='filledcomments', + ), + migrations.RemoveField( + model_name='eventregistration', + name='options', + ), + migrations.RemoveField( + model_name='eventregistration', + name='user', + ), + migrations.DeleteModel( + name='Event', + ), + migrations.DeleteModel( + name='EventCommentField', + ), + migrations.DeleteModel( + name='EventCommentValue', + ), + migrations.DeleteModel( + name='EventOption', + ), + migrations.DeleteModel( + name='EventOptionChoice', + ), + migrations.DeleteModel( + name='EventRegistration', + ), + ] diff --git a/cof/migrations/0011_delete_clipper_and_custommail.py b/cof/migrations/0012_remove_clipper_custommail.py similarity index 61% rename from cof/migrations/0011_delete_clipper_and_custommail.py rename to cof/migrations/0012_remove_clipper_custommail.py index 1cfae5f5..0c9e297c 100644 --- a/cof/migrations/0011_delete_clipper_and_custommail.py +++ b/cof/migrations/0012_remove_clipper_custommail.py @@ -1,13 +1,10 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models +from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('cof', '0009_generic_profiles'), + ('cof', '0011_move_event'), ] operations = [ diff --git a/cof/migrations/0012_remove_club.py b/cof/migrations/0012_remove_club.py deleted file mode 100644 index ebc48d37..00000000 --- a/cof/migrations/0012_remove_club.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('cof', '0011_delete_clipper_and_custommail'), - ('gestion', '0002_club_support') - ] - - operations = [ - migrations.RemoveField( - model_name='club', - name='membres', - ), - migrations.RemoveField( - model_name='club', - name='respos', - ), - migrations.DeleteModel( - name='Club', - ), - ] diff --git a/cof/migrations/0013_alter_petitcours.py b/cof/migrations/0013_alter_petitcours.py new file mode 100644 index 00000000..288bdc0b --- /dev/null +++ b/cof/migrations/0013_alter_petitcours.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('cof', '0012_remove_clipper_custommail'), + ] + + operations = [ + migrations.AlterField( + model_name='petitcoursattribution', + name='matiere', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cof.PetitCoursSubject', verbose_name='Matière'), + ), + migrations.AlterField( + model_name='petitcoursattributioncounter', + name='matiere', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cof.PetitCoursSubject', verbose_name='Matiere'), + ), + migrations.AlterField( + model_name='petitcoursattributioncounter', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='petitcoursdemande', + name='traitee_par', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/cof/migrations/0013_move_events_to_gestion.py b/cof/migrations/0013_move_events_to_gestion.py deleted file mode 100644 index ea960186..00000000 --- a/cof/migrations/0013_move_events_to_gestion.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.3 on 2017-07-26 18:29 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('cof', '0012_remove_club'), - ("gestion", "0003_association_and_events") - ] - - operations = [ - migrations.RemoveField( - model_name='eventcommentfield', - name='event', - ), - migrations.RemoveField( - model_name='eventcommentvalue', - name='commentfield', - ), - migrations.RemoveField( - model_name='eventcommentvalue', - name='registration', - ), - migrations.RemoveField( - model_name='eventoption', - name='event', - ), - migrations.RemoveField( - model_name='eventoptionchoice', - name='event_option', - ), - migrations.AlterUniqueTogether( - name='eventregistration', - unique_together=set([]), - ), - migrations.RemoveField( - model_name='eventregistration', - name='event', - ), - migrations.RemoveField( - model_name='eventregistration', - name='filledcomments', - ), - migrations.RemoveField( - model_name='eventregistration', - name='options', - ), - migrations.RemoveField( - model_name='eventregistration', - name='user', - ), - migrations.AlterField( - model_name='petitcoursattribution', - name='matiere', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cof.PetitCoursSubject', verbose_name='Matière'), - ), - migrations.AlterField( - model_name='petitcoursattributioncounter', - name='matiere', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cof.PetitCoursSubject', verbose_name='Matiere'), - ), - migrations.AlterField( - model_name='petitcoursattributioncounter', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='petitcoursdemande', - name='traitee_par', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), - ), - migrations.DeleteModel( - name='Event', - ), - migrations.DeleteModel( - name='EventCommentField', - ), - migrations.DeleteModel( - name='EventCommentValue', - ), - migrations.DeleteModel( - name='EventOption', - ), - migrations.DeleteModel( - name='EventOptionChoice', - ), - migrations.DeleteModel( - name='EventRegistration', - ), - ] diff --git a/gestion/migrations/0001_initial.py b/gestion/migrations/0001_initial.py index a301bb9a..f921990f 100644 --- a/gestion/migrations/0001_initial.py +++ b/gestion/migrations/0001_initial.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import django.db.models.deletion from django.db import migrations, models from django.conf import settings @@ -9,6 +10,7 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('auth', '0008_alter_user_username_max_length'), ] operations = [ @@ -16,19 +18,182 @@ class Migration(migrations.Migration): name='Profile', fields=[ ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)), - ('login_clipper', models.CharField(verbose_name='Login clipper', max_length=8, blank=True)), - ('phone', models.CharField(verbose_name='Téléphone', max_length=20, blank=True)), - ('occupation', models.CharField(choices=[('exterieur', 'Extérieur'), ('1A', '1A'), ('2A', '2A'), ('3A', '3A'), ('4A', '4A'), ('archicube', 'Archicube'), ('doctorant', 'Doctorant'), ('CST', 'CST')], verbose_name='Occupation', max_length=9, default='1A')), - ('departement', models.CharField(verbose_name='Département', max_length=50, blank=True)), - ('comments', models.TextField(verbose_name="Commentaires visibles par l'utilisateur", blank=True)), + ('login_clipper', models.CharField(verbose_name='login clipper', max_length=8, blank=True)), + ('phone', models.CharField(verbose_name='téléphone', max_length=20, blank=True)), + ('occupation', models.CharField(choices=[('exterieur', 'Extérieur'), ('1A', '1A'), ('2A', '2A'), ('3A', '3A'), ('4A', '4A'), ('archicube', 'Archicube'), ('doctorant', 'Doctorant'), ('CST', 'CST')], verbose_name='occupation', max_length=9, default='1A')), + ('departement', models.CharField(verbose_name='département', max_length=50, blank=True)), + ('comments', models.TextField(verbose_name="commentaires visibles par l'utilisateur", blank=True)), ('user', models.OneToOneField( on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL, - related_name='profile')), + related_name='profile', + verbose_name='utilisateur', + )), ], options={ - 'verbose_name': 'Profil', - 'verbose_name_plural': 'Profils', + 'verbose_name': 'profil', + 'verbose_name_plural': 'profils', }, ), + migrations.CreateModel( + name='Association', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30, unique=True, verbose_name="nom de l'association")), + ('members_group', models.ForeignKey(blank=True, null=True, on_delete=models.deletion.PROTECT, related_name='member_group_of', to='auth.Group', verbose_name='groupe des membres')), + ('staff_group', models.ForeignKey(blank=True, null=True, on_delete=models.deletion.PROTECT, related_name='staff_group_of', to='auth.Group', verbose_name='groupe des membres du bureau')), + ], + options={ + 'verbose_name': 'association', + 'verbose_name_plural': 'associations', + }, + ), + migrations.CreateModel( + name='Club', + fields=[ + ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), + ('name', models.CharField(unique=True, max_length=200, verbose_name='nom')), + ('description', models.TextField(verbose_name='description', blank=True)), + ('cotiz_price', models.DecimalField(verbose_name='cotisation (€)', decimal_places=2, default=0, blank=True, max_digits=5)), + ('cotiz_frequency', models.CharField(choices=[('ANN', 'Annuelle'), ('SEM', 'Semestrielle'), ('COU', 'Au cours')], max_length=3, verbose_name='fréquence de la cotisation', default='ANN', blank=True)), + ('association', models.ForeignKey(on_delete=models.deletion.PROTECT, related_name='clubs', to='gestion.Association', verbose_name='association')), + ], + options={ + 'verbose_name': 'club', + 'verbose_name_plural': 'clubs', + }, + ), + migrations.CreateModel( + name='ClubUser', + fields=[ + ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), + ('is_respo', models.BooleanField(verbose_name='est responsable du club')), + ('has_paid', models.BooleanField(verbose_name='a payé sa cotisation')), + ('club', models.ForeignKey( + to='gestion.Club', + on_delete=models.CASCADE)), + ('user', models.ForeignKey( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'inscription au club', + 'verbose_name_plural': 'inscriptions aux clubs', + }, + ), + migrations.AddField( + model_name='club', + name='members', + field=models.ManyToManyField(to=settings.AUTH_USER_MODEL, related_name='in_clubs', through='gestion.ClubUser', blank=True, verbose_name='membres'), + ), + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200, verbose_name='titre')), + ('start_date', models.DateTimeField(blank=True, null=True, verbose_name="début de l'événement")), + ('end_date', models.DateTimeField(blank=True, null=True, verbose_name="fin de l'événement")), + ('description', models.TextField(blank=True, verbose_name='description')), + ('image', models.ImageField(blank=True, null=True, upload_to='public/imgs/events/', verbose_name='image')), + ('registration_open', models.NullBooleanField(default=True, help_text="Indéfini signifie « l'inscription n'est pas requise\xa0»", verbose_name='les inscriptions sont ouvertes')), + ('old', models.BooleanField(default=False, verbose_name='archiver (événement fini)')), + ('associations', models.ManyToManyField(related_name='events', to='gestion.Association', verbose_name='associations')), + ], + options={ + 'verbose_name': 'événement', + 'verbose_name_plural': 'événements', + }, + ), + migrations.CreateModel( + name='EventCommentField', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='nom du champ')), + ('fieldtype', models.CharField(choices=[('text', 'Texte long'), ('char', 'Texte court')], default='text', max_length=10, verbose_name='type de champ')), + ('default', models.TextField(blank=True, verbose_name='valeur par défaut')), + ('ordering', models.IntegerField(default=False, help_text='plus petit en premier, ordre alphabétique sur le nom si ambiguïté', verbose_name='ordre des champs')), + ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='commentfields', to='gestion.Event', verbose_name='événement')), + ], + options={ + 'verbose_name': 'champ', + 'verbose_name_plural': 'champs', + }, + ), + migrations.CreateModel( + name='EventCommentValue', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField(blank=True, verbose_name='contenu')), + ('commentfield', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='values', to='gestion.EventCommentField')), + ], + ), + migrations.CreateModel( + name='EventOption', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='option')), + ('multi_choices', models.BooleanField(default=False, verbose_name='choix multiples')), + ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='options', to='gestion.Event', verbose_name='événement')), + ], + options={ + 'verbose_name': 'option des événements', + 'verbose_name_plural': 'options des événements', + }, + ), + migrations.CreateModel( + name='EventOptionChoice', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('value', models.CharField(max_length=200, verbose_name='Valeur')), + ('event_option', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='gestion.EventOption', verbose_name='événement')), + ], + options={ + 'verbose_name': 'choix', + 'verbose_name_plural': 'choix', + }, + ), + migrations.CreateModel( + name='EventRegistration', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('paid', models.BooleanField(default=False, verbose_name='a payé')), + ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion.Event', verbose_name='événement')), + ('filledcomments', models.ManyToManyField(through='gestion.EventCommentValue', to='gestion.EventCommentField', verbose_name='commentaires')), + ('options', models.ManyToManyField(to='gestion.EventOptionChoice', verbose_name='choix')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='utilisateur')), + ], + options={ + 'verbose_name': 'inscription', + 'verbose_name_plural': 'inscriptions', + }, + ), + migrations.CreateModel( + name='Location', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, verbose_name='nom du lieu')), + ], + options={ + 'verbose_name': 'lieu', + 'verbose_name_plural': 'lieux', + }, + ), + migrations.AddField( + model_name='eventcommentvalue', + name='registration', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='gestion.EventRegistration'), + ), + migrations.AddField( + model_name='event', + name='location', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='gestion.Location', verbose_name='lieux', blank=True, null=True), + ), + migrations.AlterUniqueTogether( + name='eventregistration', + unique_together=set([('user', 'event')]), + ), + migrations.AlterUniqueTogether( + name='eventcommentvalue', + unique_together=set([('commentfield', 'registration')]), + ), ] diff --git a/gestion/migrations/0002_club_support.py b/gestion/migrations/0002_club_support.py deleted file mode 100644 index dc16f400..00000000 --- a/gestion/migrations/0002_club_support.py +++ /dev/null @@ -1,98 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -from django.conf import settings - - -def keep_cof_clubs(apps, schema_editor): - Group = apps.get_model("auth", "Group") - CofClub = apps.get_model("cof", "Club") - NewClub = apps.get_model("gestion", "Club") - Registration = apps.get_model("gestion", "ClubUser") - - cof_group = Group.objects.get(name="cof_members") - - for oldclub in CofClub.objects.all(): - newclub = NewClub.objects.create( - name=oldclub.name, - description=oldclub.description, - ) - for user in oldclub.membres.all(): - Registration.objects.create( - club=newclub, - user=user, - has_paid=True - ) - for user in oldclub.respos.all(): - reg = Registration.objects.get_or_create( - user=user, - club=newclub - ) - reg.is_respo = True - reg.save() - newclub.associations.add(cof_group) - newclub.save() - - -def restore_cof_clubs(apps, schema_editor): - Group = apps.get_model("auth", "Group") - Club = apps.get_model("cof", "Club") - Registration = apps.get_model("gestion", "ClubUser") - - cof_group = Group.objects.get(name="cof_members") - - for newclub in cof_group.clubs.all(): - club = Club.objects.create( - name=newclub.name, - description=newclub.description - ) - for reg in Registration.objects.filter(club=newclub): - if reg.is_respo: - club.respos.add(reg.user) - else: - club.membres.add(reg.user) - - -class Migration(migrations.Migration): - - dependencies = [ - ('auth', '0006_require_contenttypes_0002'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('cof', '0011_delete_clipper_and_custommail'), - ('gestion', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Club', - fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), - ('name', models.CharField(unique=True, max_length=200, verbose_name='Nom')), - ('description', models.TextField(verbose_name='Description', blank=True)), - ('price', models.DecimalField(verbose_name='Cotisation (€)', decimal_places=2, default=0, blank=True, max_digits=5)), - ('cotisation_frequency', models.CharField(choices=[('ANN', 'Annuel'), ('SEM', 'Semestriel'), ('COU', 'Au cours')], max_length=3, verbose_name='Fréquence de la cotisation', default='ANN', blank=True)), - ('associations', models.ManyToManyField(to='auth.Group', related_name='clubs')), - ], - ), - migrations.CreateModel( - name='ClubUser', - fields=[ - ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)), - ('is_respo', models.BooleanField(verbose_name='Est responsable du club')), - ('has_paid', models.BooleanField(verbose_name='A payé sa cotisation')), - ('club', models.ForeignKey( - to='gestion.Club', - on_delete=models.CASCADE)), - ('user', models.ForeignKey( - on_delete=models.CASCADE, - to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.AddField( - model_name='club', - name='members', - field=models.ManyToManyField(to=settings.AUTH_USER_MODEL, related_name='in_clubs', through='gestion.ClubUser', blank=True), - ), - migrations.RunPython(keep_cof_clubs, restore_cof_clubs), - ] diff --git a/gestion/migrations/0002_create_cof_bds.py b/gestion/migrations/0002_create_cof_bds.py new file mode 100644 index 00000000..f9326295 --- /dev/null +++ b/gestion/migrations/0002_create_cof_bds.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from functools import partial + +from django.db import migrations + + +def create_assoc(apps, schema_editor, assoc_name): + Association = apps.get_model('gestion', 'Association') + Group = apps.get_model('auth', 'Group') + + label = assoc_name.lower() + + g_buro, _ = Group.objects.get_or_create(name='{}_buro'.format(label)) + g_members, _ = Group.objects.get_or_create(name='{}_members'.format(label)) + + assoc, _ = Association.objects.get_or_create( + name=assoc_name, + staff_group=g_buro, + members_group=g_members, + ) + + +create_cof = partial(create_assoc, assoc_name='COF') +create_bds = partial(create_assoc, assoc_name='BDS') + + +class Migration(migrations.Migration): + """ + This data migration creates the Association instances and theirs related + groups for COF and BDS. + """ + + dependencies = [ + ('gestion', '0001_initial'), + ('auth', '0008_alter_user_username_max_length'), + ] + + operations = [ + migrations.RunPython(create_cof), + migrations.RunPython(create_bds), + ] diff --git a/gestion/migrations/0003_association_and_events.py b/gestion/migrations/0003_association_and_events.py deleted file mode 100644 index 12f5732a..00000000 --- a/gestion/migrations/0003_association_and_events.py +++ /dev/null @@ -1,289 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.3 on 2017-07-26 18:29 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -def create_apps(apps, schema_editor): - Association = apps.get_model("gestion", "Association") - Group = apps.get_model("auth", "Group") - - cof_m = Group.objects.get(name="cof_members") - cof_b = Group.objects.get(name="cof_buro") - bds_m = Group.objects.get(name="bds_members") - bds_b = Group.objects.get(name="bds_buro") - - Association.objects.bulk_create([ - Association(id=1, name="COF", staff_group=cof_b, members_group=cof_m), - Association(id=2, name="BDS", staff_group=bds_b, members_group=bds_m), - ]) - - -def import_events(apps, schema_editor): - # Fetching the models that have be moved from cof to gestion - model_names = [ - "Event", "EventCommentField", "EventCommentValue", "EventOption", - "EventOptionChoice", "EventRegistration" - ] - models = [ - (apps.get_model("cof", name), apps.get_model("gestion", name)) - for name in model_names - ] - - # The old Event.location field becomes a table: we need to create an entry - # in this table for each value of the old `location` field. - OldEvent, NewEvent = models[0] - Location = apps.get_model("gestion", "Location") - locations = set() # A set to prevent duplicate entries - events = [] - for event in OldEvent.objects.values(): - locations.add(event["location"]) - events.append(event) - Location.objects.bulk_create([Location(name=name) for name in locations]) - map_loc = { - loc.name: loc - for loc in Location.objects.all() - } - for event in events: - event["location"] = map_loc[event["location"]] - NewEvent.objects.bulk_create([ - NewEvent(**event) - for event in events - ]) - - # Do not forget to link all the existing event to the COF group - cof = apps.get_model("gestion", "Association").objects.get(name="COF") - for event in NewEvent.objects.all(): - event.associations.add(cof) - - # Migrating the other models is straigtforward - for OldModel, NewModel in models[1:]: - NewModel.objects.bulk_create([ - NewModel(**values) - for values in OldModel.objects.values() - ]) - - -def restore_events(apps, schema_editor): - # TODO? - raise NotImplementedError - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('auth', '0008_alter_user_username_max_length'), - ('gestion', '0002_club_support'), - ("cof", "0009_generic_profiles"), - ] - - operations = [ - migrations.CreateModel( - name='Association', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=30, unique=True, verbose_name="nom de l'association")), - ('members_group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='member_group_of', to='auth.Group', verbose_name='groupe des membres')), - ('staff_group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='staff_group_of', to='auth.Group', verbose_name='groupe des membres du bureau')), - ], - options={ - 'verbose_name': 'association', - 'verbose_name_plural': 'associations', - }, - ), - migrations.CreateModel( - name='Event', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=200, verbose_name='titre')), - ('start_date', models.DateTimeField(blank=True, null=True, verbose_name="début de l'événement")), - ('end_date', models.DateTimeField(blank=True, null=True, verbose_name="fin de l'événement")), - ('description', models.TextField(blank=True, verbose_name='description')), - ('image', models.ImageField(blank=True, null=True, upload_to='public/imgs/events/', verbose_name='image')), - ('registration_open', models.NullBooleanField(default=True, help_text="Indéfini signifie « l'inscription n'est pas requise\xa0»", verbose_name='les inscriptions sont ouvertes')), - ('old', models.BooleanField(default=False, verbose_name='archiver (événement fini)')), - ('associations', models.ManyToManyField(related_name='events', to='gestion.Association', verbose_name='associations')), - ], - options={ - 'verbose_name': 'événement', - 'verbose_name_plural': 'événements', - }, - ), - migrations.CreateModel( - name='EventCommentField', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=200, verbose_name='nom du champ')), - ('fieldtype', models.CharField(choices=[('text', 'Texte long'), ('char', 'Texte court')], default='text', max_length=10, verbose_name='type de champ')), - ('default', models.TextField(blank=True, verbose_name='valeur par défaut')), - ('ordering', models.IntegerField(default=False, help_text='plus petit en premier, ordre alphabétique sur le nom si ambiguïté', verbose_name='ordre des champs')), - ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='commentfields', to='gestion.Event', verbose_name='événement')), - ], - options={ - 'verbose_name': 'champ', - 'verbose_name_plural': 'champs', - }, - ), - migrations.CreateModel( - name='EventCommentValue', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content', models.TextField(blank=True, verbose_name='contenu')), - ('commentfield', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='values', to='gestion.EventCommentField')), - ], - ), - migrations.CreateModel( - name='EventOption', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=200, verbose_name='option')), - ('multi_choices', models.BooleanField(default=False, verbose_name='choix multiples')), - ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='options', to='gestion.Event', verbose_name='événement')), - ], - options={ - 'verbose_name': 'option des événements', - 'verbose_name_plural': 'options des événements', - }, - ), - migrations.CreateModel( - name='EventOptionChoice', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.CharField(max_length=200, verbose_name='Valeur')), - ('event_option', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='gestion.EventOption', verbose_name='événement')), - ], - options={ - 'verbose_name': 'choix', - 'verbose_name_plural': 'choix', - }, - ), - migrations.CreateModel( - name='EventRegistration', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('paid', models.BooleanField(default=False, verbose_name='a payé')), - ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion.Event', verbose_name='événement')), - ('filledcomments', models.ManyToManyField(through='gestion.EventCommentValue', to='gestion.EventCommentField', verbose_name='commentaires')), - ('options', models.ManyToManyField(to='gestion.EventOptionChoice', verbose_name='choix')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='utilisateur')), - ], - options={ - 'verbose_name': 'inscription', - 'verbose_name_plural': 'inscriptions', - }, - ), - migrations.CreateModel( - name='Location', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=200, verbose_name='nom du lieu')), - ], - options={ - 'verbose_name': 'lieu', - 'verbose_name_plural': 'lieux', - }, - ), - migrations.AlterModelOptions( - name='profile', - options={'verbose_name': 'profil', 'verbose_name_plural': 'profils'}, - ), - migrations.RemoveField( - model_name='club', - name='associations', - ), - migrations.AlterField( - model_name='club', - name='cotisation_frequency', - field=models.CharField(blank=True, choices=[('ANN', 'Annuel'), ('SEM', 'Semestriel'), ('COU', 'Au cours')], default='ANN', max_length=3, verbose_name='fréquence de la cotisation'), - ), - migrations.AlterField( - model_name='club', - name='description', - field=models.TextField(blank=True, verbose_name='description'), - ), - migrations.AlterField( - model_name='club', - name='members', - field=models.ManyToManyField(blank=True, related_name='in_clubs', through='gestion.ClubUser', to=settings.AUTH_USER_MODEL, verbose_name='membres du club'), - ), - migrations.AlterField( - model_name='club', - name='name', - field=models.CharField(max_length=200, unique=True, verbose_name='nom'), - ), - migrations.AlterField( - model_name='club', - name='price', - field=models.DecimalField(blank=True, decimal_places=2, default=0, max_digits=5, verbose_name='cotisation (€)'), - ), - migrations.AlterField( - model_name='clubuser', - name='has_paid', - field=models.BooleanField(verbose_name='a payé sa cotisation'), - ), - migrations.AlterField( - model_name='clubuser', - name='is_respo', - field=models.BooleanField(verbose_name='est responsable du club'), - ), - migrations.AlterField( - model_name='profile', - name='comments', - field=models.TextField(blank=True, verbose_name="commentaires visibles par l'utilisateur"), - ), - migrations.AlterField( - model_name='profile', - name='departement', - field=models.CharField(blank=True, max_length=50, verbose_name='département'), - ), - migrations.AlterField( - model_name='profile', - name='login_clipper', - field=models.CharField(blank=True, max_length=8, verbose_name='login clipper'), - ), - migrations.AlterField( - model_name='profile', - name='occupation', - field=models.CharField(choices=[('exterieur', 'Extérieur'), ('1A', '1A'), ('2A', '2A'), ('3A', '3A'), ('4A', '4A'), ('archicube', 'Archicube'), ('doctorant', 'Doctorant'), ('CST', 'CST')], default='1A', max_length=9, verbose_name='occupation'), - ), - migrations.AlterField( - model_name='profile', - name='phone', - field=models.CharField(blank=True, max_length=20, verbose_name='téléphone'), - ), - migrations.AlterField( - model_name='profile', - name='user', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL, verbose_name='utilisateur'), - ), - migrations.AddField( - model_name='eventcommentvalue', - name='registration', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='gestion.EventRegistration'), - ), - migrations.AddField( - model_name='event', - name='location', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='gestion.Location', verbose_name='lieux'), - ), - migrations.AddField( - model_name='club', - name='association', - field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='clubs', to='gestion.Association', verbose_name='association'), - preserve_default=False, - ), - migrations.AlterUniqueTogether( - name='eventregistration', - unique_together=set([('user', 'event')]), - ), - migrations.AlterUniqueTogether( - name='eventcommentvalue', - unique_together=set([('commentfield', 'registration')]), - ), - migrations.RunPython(create_apps, migrations.RunPython.noop), - migrations.RunPython(import_events, restore_events), - ] diff --git a/gestion/migrations/0004_event_location_not_mandatory.py b/gestion/migrations/0004_event_location_not_mandatory.py deleted file mode 100644 index 31835f2f..00000000 --- a/gestion/migrations/0004_event_location_not_mandatory.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11b1 on 2017-08-07 19:49 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('gestion', '0003_association_and_events'), - ] - - operations = [ - migrations.AlterField( - model_name='event', - name='location', - field=models.ForeignKey( - blank=True, null=True, - on_delete=django.db.models.deletion.PROTECT, - to='gestion.Location', - verbose_name='lieux' - ), - ), - ]