diff --git a/bda/migrations/0001_initial.py b/bda/migrations/0001_initial.py index aa2cb252..da447b9d 100644 --- a/bda/migrations/0001_initial.py +++ b/bda/migrations/0001_initial.py @@ -59,7 +59,9 @@ class Migration(migrations.Migration): ('price', models.FloatField(verbose_name=b"Prix d'une place", blank=True)), ('slots', models.IntegerField(verbose_name=b'Places')), ('priority', models.IntegerField(default=1000, verbose_name=b'Priorit\xc3\xa9')), - ('location', models.ForeignKey(to='bda.Salle')), + ('location', models.ForeignKey( + on_delete=models.CASCADE, + to='bda.Salle')), ], options={ 'ordering': ('priority', 'date', 'title'), @@ -79,27 +81,39 @@ class Migration(migrations.Migration): migrations.AddField( model_name='participant', name='user', - field=models.OneToOneField(to=settings.AUTH_USER_MODEL), + field=models.OneToOneField( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL), ), migrations.AddField( model_name='choixspectacle', name='participant', - field=models.ForeignKey(to='bda.Participant'), + field=models.ForeignKey( + on_delete=models.CASCADE, + to='bda.Participant'), ), migrations.AddField( model_name='choixspectacle', name='spectacle', - field=models.ForeignKey(related_name='participants', to='bda.Spectacle'), + field=models.ForeignKey( + on_delete=models.CASCADE, + related_name='participants', + to='bda.Spectacle'), ), migrations.AddField( model_name='attribution', name='participant', - field=models.ForeignKey(to='bda.Participant'), + field=models.ForeignKey( + on_delete=models.CASCADE, + to='bda.Participant'), ), migrations.AddField( model_name='attribution', name='spectacle', - field=models.ForeignKey(related_name='attribues', to='bda.Spectacle'), + field=models.ForeignKey( + related_name='attribues', + on_delete=models.CASCADE, + to='bda.Spectacle'), ), migrations.AlterUniqueTogether( name='choixspectacle', diff --git a/bda/migrations/0002_add_tirage.py b/bda/migrations/0002_add_tirage.py index 1956a4a4..3b5c5a0b 100644 --- a/bda/migrations/0002_add_tirage.py +++ b/bda/migrations/0002_add_tirage.py @@ -39,18 +39,26 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='participant', name='user', - field=models.ForeignKey(to=settings.AUTH_USER_MODEL), + field=models.ForeignKey( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL), ), migrations.AddField( model_name='participant', name='tirage', - field=models.ForeignKey(default=1, to='bda.Tirage'), + field=models.ForeignKey( + on_delete=models.CASCADE, + default=1, + to='bda.Tirage'), preserve_default=False, ), migrations.AddField( model_name='spectacle', name='tirage', - field=models.ForeignKey(default=1, to='bda.Tirage'), + field=models.ForeignKey( + on_delete=models.CASCADE, + default=1, + to='bda.Tirage'), preserve_default=False, ), ] diff --git a/bda/migrations/0007_extends_spectacle.py b/bda/migrations/0007_extends_spectacle.py index b95c18de..f6e1834f 100644 --- a/bda/migrations/0007_extends_spectacle.py +++ b/bda/migrations/0007_extends_spectacle.py @@ -72,8 +72,11 @@ class Migration(migrations.Migration): migrations.AddField( model_name='spectacle', name='category', - field=models.ForeignKey(blank=True, to='bda.CategorieSpectacle', - null=True), + field=models.ForeignKey( + on_delete=models.CASCADE, + blank=True, + to='bda.CategorieSpectacle', + null=True), ), migrations.AddField( model_name='spectacle', @@ -84,6 +87,8 @@ class Migration(migrations.Migration): migrations.AddField( model_name='quote', name='spectacle', - field=models.ForeignKey(to='bda.Spectacle'), + field=models.ForeignKey( + on_delete=models.CASCADE, + to='bda.Spectacle'), ), ] diff --git a/bda/migrations/0009_revente.py b/bda/migrations/0009_revente.py index 1cca4e86..223a2ed7 100644 --- a/bda/migrations/0009_revente.py +++ b/bda/migrations/0009_revente.py @@ -46,21 +46,28 @@ class Migration(migrations.Migration): migrations.AddField( model_name='spectaclerevente', name='attribution', - field=models.OneToOneField(to='bda.Attribution', - related_name='revente'), + field=models.OneToOneField( + to='bda.Attribution', + on_delete=models.CASCADE, + related_name='revente'), ), migrations.AddField( model_name='spectaclerevente', name='seller', - field=models.ForeignKey(to='bda.Participant', - verbose_name='Vendeur', - related_name='original_shows'), + field=models.ForeignKey( + on_delete=models.CASCADE, + to='bda.Participant', + verbose_name='Vendeur', + related_name='original_shows'), ), migrations.AddField( model_name='spectaclerevente', name='soldTo', - field=models.ForeignKey(to='bda.Participant', - verbose_name='Vendue à', null=True, - blank=True), + field=models.ForeignKey( + on_delete=models.CASCADE, + to='bda.Participant', + verbose_name='Vendue à', + null=True, + blank=True), ), ] diff --git a/bda/models.py b/bda/models.py index a405a665..008f55f5 100644 --- a/bda/models.py +++ b/bda/models.py @@ -46,9 +46,14 @@ class CategorieSpectacle(models.Model): class Spectacle(models.Model): title = models.CharField("Titre", max_length=300) - category = models.ForeignKey(CategorieSpectacle, blank=True, null=True) + category = models.ForeignKey( + CategorieSpectacle, + on_delete=models.CASCADE, + blank=True, + null=True + ) date = models.DateTimeField("Date & heure") - location = models.ForeignKey(Salle) + location = models.ForeignKey(Salle, on_delete=models.CASCADE) vips = models.TextField('Personnalités', blank=True) description = models.TextField("Description", blank=True) slots_description = models.TextField("Description des places", blank=True) @@ -58,7 +63,7 @@ class Spectacle(models.Model): max_length=500) price = models.FloatField("Prix d'une place") slots = models.IntegerField("Places") - tirage = models.ForeignKey(Tirage) + tirage = models.ForeignKey(Tirage, on_delete=models.CASCADE) listing = models.BooleanField("Les places sont sur listing") rappel_sent = models.DateTimeField("Mail de rappel envoyé", blank=True, null=True) @@ -116,7 +121,7 @@ class Spectacle(models.Model): class Quote(models.Model): - spectacle = models.ForeignKey(Spectacle) + spectacle = models.ForeignKey(Spectacle, on_delete=models.CASCADE) text = models.TextField('Citation') author = models.CharField('Auteur', max_length=200) @@ -130,7 +135,7 @@ PAYMENT_TYPES = ( class Participant(models.Model): - user = models.ForeignKey(User) + user = models.ForeignKey(User, on_delete=models.CASCADE) choices = models.ManyToManyField(Spectacle, through="ChoixSpectacle", related_name="chosen_by") @@ -141,7 +146,7 @@ class Participant(models.Model): paymenttype = models.CharField("Moyen de paiement", max_length=6, choices=PAYMENT_TYPES, blank=True) - tirage = models.ForeignKey(Tirage) + tirage = models.ForeignKey(Tirage, on_delete=models.CASCADE) choicesrevente = models.ManyToManyField(Spectacle, related_name="subscribed", blank=True) @@ -157,8 +162,15 @@ DOUBLE_CHOICES = ( class ChoixSpectacle(models.Model): - participant = models.ForeignKey(Participant) - spectacle = models.ForeignKey(Spectacle, related_name="participants") + participant = models.ForeignKey( + Participant, + on_delete=models.CASCADE + ) + spectacle = models.ForeignKey( + Spectacle, + on_delete=models.CASCADE, + related_name="participants" + ) priority = models.PositiveIntegerField("Priorité") double_choice = models.CharField("Nombre de places", default="1", choices=DOUBLE_CHOICES, @@ -185,8 +197,15 @@ class ChoixSpectacle(models.Model): class Attribution(models.Model): - participant = models.ForeignKey(Participant) - spectacle = models.ForeignKey(Spectacle, related_name="attribues") + participant = models.ForeignKey( + Participant, + on_delete=models.CASCADE + ) + spectacle = models.ForeignKey( + Spectacle, + on_delete=models.CASCADE, + related_name="attribues" + ) given = models.BooleanField("Donnée", default=False) def __str__(self): @@ -195,19 +214,29 @@ class Attribution(models.Model): class SpectacleRevente(models.Model): - attribution = models.OneToOneField(Attribution, - related_name="revente") + attribution = models.OneToOneField( + Attribution, + on_delete=models.CASCADE, + related_name="revente" + ) date = models.DateTimeField("Date de mise en vente", default=timezone.now) answered_mail = models.ManyToManyField(Participant, related_name="wanted", blank=True) - seller = models.ForeignKey(Participant, - related_name="original_shows", - verbose_name="Vendeur") - soldTo = models.ForeignKey(Participant, blank=True, null=True, - verbose_name="Vendue à") - + seller = models.ForeignKey( + Participant, + on_delete=models.CASCADE, + related_name="original_shows", + verbose_name="Vendeur" + ) + soldTo = models.ForeignKey( + Participant, + on_delete=models.CASCADE, + blank=True, + null=True, + verbose_name="Vendue à" + ) notif_sent = models.BooleanField("Notification envoyée", default=False) tirage_done = models.BooleanField("Tirage effectué", diff --git a/bda/templates/bda/resume_places.html b/bda/templates/bda/resume_places.html index 226e697a..7cbd06ea 100644 --- a/bda/templates/bda/resume_places.html +++ b/bda/templates/bda/resume_places.html @@ -16,7 +16,7 @@

Total à payer : {{ total|floatformat }}€


Ne manque pas un spectacle avec le - calendrier + calendrier automatique !

{% else %}

Vous n'avez aucune place :(

diff --git a/bds/migrations/0001_initial.py b/bds/migrations/0001_initial.py index e0d3ddd9..3d6f5218 100644 --- a/bds/migrations/0001_initial.py +++ b/bds/migrations/0001_initial.py @@ -23,7 +23,10 @@ class Migration(migrations.Migration): ('cotisation_period', models.CharField(choices=[('ANN', 'Année'), ('SE1', 'Premier semestre'), ('SE2', 'Deuxième semestre')], verbose_name='Inscription', max_length=3, default='ANN')), ('registration_date', models.DateField(verbose_name="Date d'inscription", auto_now_add=True)), ('payment_method', models.CharField(choices=[('CASH', 'Liquide'), ('BANK', 'Transfer bancaire'), ('CHEQUE', 'Cheque'), ('OTHER', 'Autre')], verbose_name='Methode de paiement', max_length=6, default='CASH')), - ('profile', models.OneToOneField(related_name='bds', to='gestion.Profile')), + ('profile', models.OneToOneField( + related_name='bds', + on_delete=models.CASCADE, + to='gestion.Profile')), ], ), ] diff --git a/bds/migrations/0002_add_BDS_groups.py b/bds/migrations/0002_add_BDS_groups.py new file mode 100644 index 00000000..45510e59 --- /dev/null +++ b/bds/migrations/0002_add_BDS_groups.py @@ -0,0 +1,35 @@ +# -*- 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/bds/models.py b/bds/models.py index ecfbb3db..da80dd77 100644 --- a/bds/models.py +++ b/bds/models.py @@ -55,3 +55,11 @@ class BdsProfile(models.Model): default='CASH', choices=PAYMENT_METHOD_CHOICES, max_length=6) + + class Meta: + verbose_name = "Profil BDS" + verbose_name_plural = "Profils BDS" + permissions = [ + ("member", "Is a BDS member"), + ("buro", "Is part of the BDS staff") + ] diff --git a/cof/admin.py b/cof/admin.py index ce998cd4..fc6fe515 100644 --- a/cof/admin.py +++ b/cof/admin.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -from django import forms from django.contrib import admin from django.core.urlresolvers import reverse from django.utils.safestring import mark_safe @@ -11,7 +10,7 @@ from .petits_cours_models import PetitCoursDemande, \ PetitCoursAttributionCounter from .models import ( SurveyQuestionAnswer, SurveyQuestion, CofProfile, EventOption, - EventOptionChoice, Event, Club, EventCommentField, EventRegistration, + EventOptionChoice, Event, EventCommentField, EventRegistration, Survey ) @@ -132,30 +131,11 @@ class PetitCoursDemandeAdmin(admin.ModelAdmin): search_fields = ('name', 'email', 'phone', 'lieu', 'remarques') -class ClubAdminForm(forms.ModelForm): - def clean(self): - cleaned_data = super(ClubAdminForm, self).clean() - respos = cleaned_data.get('respos') - members = cleaned_data.get('membres') - for respo in respos.all(): - if respo not in members: - raise forms.ValidationError( - "Erreur : le respo %s n'est pas membre du club." - % respo.get_full_name()) - return cleaned_data - - -class ClubAdmin(admin.ModelAdmin): - list_display = ['name'] - form = ClubAdminForm - - admin.site.register(Survey, SurveyAdmin) admin.site.register(SurveyQuestion, SurveyQuestionAdmin) admin.site.register(Event, EventAdmin) admin.site.register(EventOption, EventOptionAdmin) admin.site.register(CofProfile) -admin.site.register(Club, ClubAdmin) admin.site.register(PetitCoursSubject) admin.site.register(PetitCoursAbility, PetitCoursAbilityAdmin) admin.site.register(PetitCoursAttribution, PetitCoursAttributionAdmin) diff --git a/cof/forms.py b/cof/forms.py index eac9f2ed..e707194e 100644 --- a/cof/forms.py +++ b/cof/forms.py @@ -12,8 +12,7 @@ from django.forms.formsets import BaseFormSet, formset_factory from django.db.models import Max from django.core.validators import MinLengthValidator -from .models import CofProfile, EventCommentValue, \ - CalendarSubscription, Club +from .models import CofProfile, EventCommentValue, CalendarSubscription from .widgets import TriStateCheckbox from gestion.models import Profile @@ -368,14 +367,3 @@ class CalendarForm(forms.ModelForm): model = CalendarSubscription fields = ['subscribe_to_events', 'subscribe_to_my_shows', 'other_shows'] - - -class ClubsForm(forms.Form): - """ - Formulaire d'inscription d'un membre à plusieurs clubs du COF. - """ - clubs = forms.ModelMultipleChoiceField( - label="Inscriptions aux clubs du COF", - queryset=Club.objects.all(), - widget=forms.CheckboxSelectMultiple, - required=False) diff --git a/cof/migrations/0001_initial.py b/cof/migrations/0001_initial.py index 0540e689..1ba71322 100644 --- a/cof/migrations/0001_initial.py +++ b/cof/migrations/0001_initial.py @@ -48,7 +48,10 @@ class Migration(migrations.Migration): ('is_buro', models.BooleanField(default=False, verbose_name=b'Membre du Bur\xc3\xb4')), ('petits_cours_accept', models.BooleanField(default=False, verbose_name=b'Recevoir des petits cours')), ('petits_cours_remarques', models.TextField(default=b'', verbose_name='Remarques et pr\xe9cisions pour les petits cours', blank=True)), - ('user', models.OneToOneField(related_name='profile', to=settings.AUTH_USER_MODEL)), + ('user', models.OneToOneField( + related_name='profile', + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': 'Profil COF', @@ -91,7 +94,10 @@ class Migration(migrations.Migration): ('name', models.CharField(max_length=200, verbose_name=b'Champ')), ('fieldtype', models.CharField(default=b'text', max_length=10, verbose_name=b'Type', choices=[(b'text', 'Texte long'), (b'char', 'Texte court')])), ('default', models.TextField(verbose_name=b'Valeur par d\xc3\xa9faut', blank=True)), - ('event', models.ForeignKey(related_name='commentfields', to='cof.Event')), + ('event', models.ForeignKey( + related_name='commentfields', + on_delete=models.CASCADE, + to='cof.Event')), ], options={ 'verbose_name': 'Champ', @@ -102,7 +108,10 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('content', models.TextField(null=True, verbose_name=b'Contenu', blank=True)), - ('commentfield', models.ForeignKey(related_name='values', to='cof.EventCommentField')), + ('commentfield', models.ForeignKey( + related_name='values', + on_delete=models.CASCADE, + to='cof.EventCommentField')), ], ), migrations.CreateModel( @@ -111,7 +120,10 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('name', models.CharField(max_length=200, verbose_name=b'Option')), ('multi_choices', models.BooleanField(default=False, verbose_name=b'Choix multiples')), - ('event', models.ForeignKey(related_name='options', to='cof.Event')), + ('event', models.ForeignKey( + related_name='options', + on_delete=models.CASCADE, + to='cof.Event')), ], options={ 'verbose_name': 'Option', @@ -122,7 +134,10 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('value', models.CharField(max_length=200, verbose_name=b'Valeur')), - ('event_option', models.ForeignKey(related_name='choices', to='cof.EventOption')), + ('event_option', models.ForeignKey( + related_name='choices', + on_delete=models.CASCADE, + to='cof.EventOption')), ], options={ 'verbose_name': 'Choix', @@ -133,10 +148,14 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('paid', models.BooleanField(default=False, verbose_name=b'A pay\xc3\xa9')), - ('event', models.ForeignKey(to='cof.Event')), + ('event', models.ForeignKey( + on_delete=models.CASCADE, + to='cof.Event')), ('filledcomments', models.ManyToManyField(to='cof.EventCommentField', through='cof.EventCommentValue')), ('options', models.ManyToManyField(to='cof.EventOptionChoice')), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': 'Inscription', @@ -240,7 +259,10 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('question', models.CharField(max_length=200, verbose_name=b'Question')), ('multi_answers', models.BooleanField(default=False, verbose_name=b'Choix multiples')), - ('survey', models.ForeignKey(related_name='questions', to='cof.Survey')), + ('survey', models.ForeignKey( + on_delete=models.CASCADE, + related_name='questions', + to='cof.Survey')), ], options={ 'verbose_name': 'Question', @@ -251,7 +273,10 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('answer', models.CharField(max_length=200, verbose_name=b'R\xc3\xa9ponse')), - ('survey_question', models.ForeignKey(related_name='answers', to='cof.SurveyQuestion')), + ('survey_question', models.ForeignKey( + related_name='answers', + on_delete=models.CASCADE, + to='cof.SurveyQuestion')), ], options={ 'verbose_name': 'R\xe9ponse', @@ -265,12 +290,16 @@ class Migration(migrations.Migration): migrations.AddField( model_name='surveyanswer', name='survey', - field=models.ForeignKey(to='cof.Survey'), + field=models.ForeignKey( + on_delete=models.CASCADE, + to='cof.Survey'), ), migrations.AddField( model_name='surveyanswer', name='user', - field=models.ForeignKey(to=settings.AUTH_USER_MODEL), + field=models.ForeignKey( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL), ), migrations.AddField( model_name='petitcoursdemande', @@ -280,47 +309,72 @@ class Migration(migrations.Migration): migrations.AddField( model_name='petitcoursdemande', name='traitee_par', - field=models.ForeignKey(blank=True, to=settings.AUTH_USER_MODEL, null=True), + field=models.ForeignKey( + on_delete=models.PROTECT, + blank=True, + to=settings.AUTH_USER_MODEL, + null=True), ), migrations.AddField( model_name='petitcoursattributioncounter', name='matiere', - field=models.ForeignKey(verbose_name='Matiere', to='cof.PetitCoursSubject'), + field=models.ForeignKey( + on_delete=models.PROTECT, + verbose_name='Matiere', + to='cof.PetitCoursSubject'), ), migrations.AddField( model_name='petitcoursattributioncounter', name='user', - field=models.ForeignKey(to=settings.AUTH_USER_MODEL), + field=models.ForeignKey( + on_delete=models.PROTECT, + to=settings.AUTH_USER_MODEL), ), migrations.AddField( model_name='petitcoursattribution', name='demande', - field=models.ForeignKey(verbose_name='Demande', to='cof.PetitCoursDemande'), + field=models.ForeignKey( + on_delete=models.CASCADE, + verbose_name='Demande', + to='cof.PetitCoursDemande'), ), migrations.AddField( model_name='petitcoursattribution', name='matiere', - field=models.ForeignKey(verbose_name='Mati\xe8re', to='cof.PetitCoursSubject'), + field=models.ForeignKey( + on_delete=models.PROTECT, + verbose_name='Mati\xe8re', + to='cof.PetitCoursSubject'), ), migrations.AddField( model_name='petitcoursattribution', name='user', - field=models.ForeignKey(to=settings.AUTH_USER_MODEL), + field=models.ForeignKey( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL), ), migrations.AddField( model_name='petitcoursability', name='matiere', - field=models.ForeignKey(verbose_name='Mati\xe8re', to='cof.PetitCoursSubject'), + field=models.ForeignKey( + on_delete=models.CASCADE, + verbose_name='Mati\xe8re', + to='cof.PetitCoursSubject'), ), migrations.AddField( model_name='petitcoursability', name='user', - field=models.ForeignKey(to=settings.AUTH_USER_MODEL), + field=models.ForeignKey( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL), ), migrations.AddField( model_name='eventcommentvalue', name='registration', - field=models.ForeignKey(related_name='comments', to='cof.EventRegistration'), + field=models.ForeignKey( + on_delete=models.CASCADE, + related_name='comments', + to='cof.EventRegistration'), ), migrations.AlterUniqueTogether( name='surveyanswer', diff --git a/cof/migrations/0006_add_calendar.py b/cof/migrations/0006_add_calendar.py index 3009ac4d..f40ad39f 100644 --- a/cof/migrations/0006_add_calendar.py +++ b/cof/migrations/0006_add_calendar.py @@ -23,7 +23,9 @@ class Migration(migrations.Migration): ('subscribe_to_events', models.BooleanField(default=True)), ('subscribe_to_my_shows', models.BooleanField(default=True)), ('other_shows', models.ManyToManyField(to='bda.Spectacle')), - ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)), + ('user', models.OneToOneField( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL)), ], ), migrations.AlterModelOptions( diff --git a/cof/migrations/0009_generic_profiles.py b/cof/migrations/0009_generic_profiles.py index 673202b8..e24ebd2f 100644 --- a/cof/migrations/0009_generic_profiles.py +++ b/cof/migrations/0009_generic_profiles.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.contrib.auth.models import Group, Permission +from django.contrib.auth.models import Group from django.db import migrations, models @@ -23,23 +23,23 @@ def create_profile(apps, schema_editor): def preserve_perms(apps, schema_editor): - from django.contrib.auth.management import create_permissions + # from django.contrib.auth.management import create_permissions - apps.models_module = True - create_permissions(apps, verbosity=0) - apps.models_module = None + # apps.models_module = True + # create_permissions(apps, verbosity=0) + # apps.models_module = None CofProfile = apps.get_model("cof", "CofProfile") - memberp = Permission.objects.get(codename='member') - burop = Permission.objects.get(codename='buro') + # memberp = Permission.objects.get(codename='member') + # burop = Permission.objects.get(codename='buro') # creates the groups for COF members and member = Group.objects.create(name='cof_members') buro = Group.objects.create(name='cof_buro') # associate permissions to the respective groups. - buro.permissions = [burop, memberp] - member.permissions = [memberp] + # buro.permissions = [burop, memberp] + # member.permissions = [memberp] for cofp in CofProfile.objects.filter(is_cof=True): cofp.profile.user.groups.add(member) @@ -70,6 +70,7 @@ class Migration(migrations.Migration): model_name='cofprofile', name='profile', field=models.OneToOneField( + on_delete=models.CASCADE, to='gestion.Profile', null=True, related_name='cof' @@ -89,6 +90,7 @@ class Migration(migrations.Migration): model_name='cofprofile', name='profile', field=models.OneToOneField( + on_delete=models.CASCADE, to='gestion.Profile', related_name='cof' ), diff --git a/cof/migrations/0012_remove_club.py b/cof/migrations/0012_remove_club.py new file mode 100644 index 00000000..ebc48d37 --- /dev/null +++ b/cof/migrations/0012_remove_club.py @@ -0,0 +1,23 @@ +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/models.py b/cof/models.py index dafe9996..472937fd 100644 --- a/cof/models.py +++ b/cof/models.py @@ -79,18 +79,6 @@ class CofProfile(models.Model): return self.profile.user.username -@python_2_unicode_compatible -class Club(models.Model): - name = models.CharField("Nom", max_length=200, unique=True) - description = models.TextField("Description", blank=True) - respos = models.ManyToManyField(User, related_name="clubs_geres", - blank=True) - membres = models.ManyToManyField(User, related_name="clubs", blank=True) - - def __str__(self): - return self.name - - @python_2_unicode_compatible class Event(models.Model): title = models.CharField("Titre", max_length=200) @@ -113,7 +101,11 @@ class Event(models.Model): @python_2_unicode_compatible class EventCommentField(models.Model): - event = models.ForeignKey(Event, related_name="commentfields") + event = models.ForeignKey( + Event, + on_delete=models.CASCADE, + related_name="commentfields" + ) name = models.CharField("Champ", max_length=200) fieldtype = models.CharField("Type", max_length=10, choices=TYPE_COMMENT_FIELD, default="text") @@ -128,9 +120,16 @@ class EventCommentField(models.Model): @python_2_unicode_compatible class EventCommentValue(models.Model): - commentfield = models.ForeignKey(EventCommentField, related_name="values") - registration = models.ForeignKey("EventRegistration", - related_name="comments") + commentfield = models.ForeignKey( + EventCommentField, + on_delete=models.CASCADE, + related_name="values" + ) + registration = models.ForeignKey( + "EventRegistration", + on_delete=models.CASCADE, + related_name="comments" + ) content = models.TextField("Contenu", blank=True, null=True) def __str__(self): @@ -139,7 +138,11 @@ class EventCommentValue(models.Model): @python_2_unicode_compatible class EventOption(models.Model): - event = models.ForeignKey(Event, related_name="options") + event = models.ForeignKey( + Event, + on_delete=models.CASCADE, + related_name="options" + ) name = models.CharField("Option", max_length=200) multi_choices = models.BooleanField("Choix multiples", default=False) @@ -152,7 +155,11 @@ class EventOption(models.Model): @python_2_unicode_compatible class EventOptionChoice(models.Model): - event_option = models.ForeignKey(EventOption, related_name="choices") + event_option = models.ForeignKey( + EventOption, + on_delete=models.CASCADE, + related_name="choices" + ) value = models.CharField("Valeur", max_length=200) class Meta: @@ -165,8 +172,14 @@ class EventOptionChoice(models.Model): @python_2_unicode_compatible class EventRegistration(models.Model): - user = models.ForeignKey(User) - event = models.ForeignKey(Event) + user = models.ForeignKey( + User, + on_delete=models.CASCADE + ) + event = models.ForeignKey( + Event, + on_delete=models.CASCADE + ) options = models.ManyToManyField(EventOptionChoice) filledcomments = models.ManyToManyField(EventCommentField, through=EventCommentValue) @@ -197,7 +210,11 @@ class Survey(models.Model): @python_2_unicode_compatible class SurveyQuestion(models.Model): - survey = models.ForeignKey(Survey, related_name="questions") + survey = models.ForeignKey( + Survey, + on_delete=models.CASCADE, + related_name="questions" + ) question = models.CharField("Question", max_length=200) multi_answers = models.BooleanField("Choix multiples", default=False) @@ -210,7 +227,11 @@ class SurveyQuestion(models.Model): @python_2_unicode_compatible class SurveyQuestionAnswer(models.Model): - survey_question = models.ForeignKey(SurveyQuestion, related_name="answers") + survey_question = models.ForeignKey( + SurveyQuestion, + on_delete=models.CASCADE, + related_name="answers" + ) answer = models.CharField("Réponse", max_length=200) class Meta: @@ -222,8 +243,14 @@ class SurveyQuestionAnswer(models.Model): @python_2_unicode_compatible class SurveyAnswer(models.Model): - user = models.ForeignKey(User) - survey = models.ForeignKey(Survey) + user = models.ForeignKey( + User, + on_delete=models.CASCADE + ) + survey = models.ForeignKey( + Survey, + on_delete=models.CASCADE + ) answers = models.ManyToManyField(SurveyQuestionAnswer, related_name="selected_by") @@ -240,7 +267,10 @@ class SurveyAnswer(models.Model): @python_2_unicode_compatible class CalendarSubscription(models.Model): token = models.UUIDField() - user = models.OneToOneField(User) + user = models.OneToOneField( + User, + on_delete=models.CASCADE + ) other_shows = models.ManyToManyField(Spectacle) subscribe_to_events = models.BooleanField(default=True) subscribe_to_my_shows = models.BooleanField(default=True) diff --git a/cof/petits_cours_models.py b/cof/petits_cours_models.py index 753e8674..e67a20bf 100644 --- a/cof/petits_cours_models.py +++ b/cof/petits_cours_models.py @@ -35,8 +35,15 @@ class PetitCoursSubject(models.Model): class PetitCoursAbility(models.Model): - user = models.ForeignKey(User) - matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matière")) + user = models.ForeignKey( + User, + on_delete=models.CASCADE + ) + matiere = models.ForeignKey( + PetitCoursSubject, + on_delete=models.CASCADE, + verbose_name=_("Matière") + ) niveau = models.CharField(_("Niveau"), choices=LEVELS_CHOICES, max_length=choices_length(LEVELS_CHOICES)) @@ -84,7 +91,11 @@ class PetitCoursDemande(models.Model): remarques = models.TextField(_("Remarques et précisions"), blank=True) traitee = models.BooleanField(_("Traitée"), default=False) - traitee_par = models.ForeignKey(User, blank=True, null=True) + traitee_par = models.ForeignKey( + User, + on_delete=models.CASCADE, + blank=True, null=True + ) processed = models.DateTimeField(_("Date de traitement"), blank=True, null=True) created = models.DateTimeField(_("Date de création"), auto_now_add=True) @@ -126,9 +137,20 @@ class PetitCoursDemande(models.Model): class PetitCoursAttribution(models.Model): - user = models.ForeignKey(User) - demande = models.ForeignKey(PetitCoursDemande, verbose_name=_("Demande")) - matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matière")) + user = models.ForeignKey( + User, + on_delete=models.CASCADE + ) + demande = models.ForeignKey( + PetitCoursDemande, + on_delete=models.CASCADE, + verbose_name=_("Demande") + ) + matiere = models.ForeignKey( + PetitCoursSubject, + on_delete=models.CASCADE, + verbose_name=_("Matière") + ) date = models.DateTimeField(_("Date d'attribution"), auto_now_add=True) rank = models.IntegerField("Rang dans l'email") selected = models.BooleanField(_("Sélectionné par le demandeur"), @@ -145,8 +167,15 @@ class PetitCoursAttribution(models.Model): class PetitCoursAttributionCounter(models.Model): - user = models.ForeignKey(User) - matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matiere")) + user = models.ForeignKey( + User, + on_delete=models.CASCADE + ) + matiere = models.ForeignKey( + PetitCoursSubject, + on_delete=models.CASCADE, + verbose_name=_("Matiere") + ) count = models.IntegerField("Nombre d'envois", default=0) @classmethod diff --git a/cof/templates/cof/base_header.html b/cof/templates/cof/base_header.html index 4713a286..dd9c1967 100644 --- a/cof/templates/cof/base_header.html +++ b/cof/templates/cof/base_header.html @@ -3,7 +3,7 @@ {% block content %}
@@ -105,8 +104,8 @@

Liens utiles

diff --git a/cof/templates/liste_clubs.html b/cof/templates/liste_clubs.html deleted file mode 100644 index c248a7a6..00000000 --- a/cof/templates/liste_clubs.html +++ /dev/null @@ -1,25 +0,0 @@ -{% extends "base_title.html" %} - -{% block page_size %}col-sm-8{% endblock %} - -{% block realcontent %} -

Clubs enregistrés sur GestioCOF

- -{% endblock %} diff --git a/cof/templates/membres_clubs.html b/cof/templates/membres_clubs.html deleted file mode 100644 index 8c932ed5..00000000 --- a/cof/templates/membres_clubs.html +++ /dev/null @@ -1,41 +0,0 @@ -{% extends "base_title.html" %} - - -{% block realcontent %} -

{{ club }}

- - -{% if club.respos.exists %} -

Respo{{ club.respos.all|pluralize }}

- -{% for member in club.respos.all %} - - - - - -{% endfor %} -
{{ member }}{{ member.email }}
-{% else %} -

Pas de respo

-{% endif %} - - -{% if club.membres.exists %} -

Liste des membres

- -{% for member in members_no_respo %} - - - - - -{% endfor %} -
{{ member }}{{ member.email }}
-{% else %} -Ce club ne comporte actuellement aucun membre. -{% endif %} - -{% endblock %} diff --git a/cof/templates/registration.html b/cof/templates/registration.html index 559226b7..e81d7b2b 100644 --- a/cof/templates/registration.html +++ b/cof/templates/registration.html @@ -16,7 +16,7 @@ // On attend que la page soit prête pour executer le code $(document).ready(function() { $('input#search_autocomplete').yourlabsAutocomplete({ - url: '{% url 'cof.autocomplete.autocomplete' %}', + url: '{% url 'autocomplete' %}', minimumCharacters: 3, id: 'search_autocomplete', choiceSelector: 'li:has(a)', diff --git a/cof/templates/registration/password_change_done.html b/cof/templates/registration/password_change_done.html index 2f2e4eea..9f2c4a60 100644 --- a/cof/templates/registration/password_change_done.html +++ b/cof/templates/registration/password_change_done.html @@ -5,5 +5,5 @@ {% block realcontent %}

Mot de passe modifié avec succès !

-

Retour au menu principal

+

Retour au menu principal

{% endblock %} diff --git a/cof/templates/registration/password_change_form.html b/cof/templates/registration/password_change_form.html index f579fb31..d9a3f66a 100644 --- a/cof/templates/registration/password_change_form.html +++ b/cof/templates/registration/password_change_form.html @@ -5,7 +5,7 @@ {% block realcontent %}

Changement de mot de passe

- + {% csrf_token %} {{ form | bootstrap }} diff --git a/cof/templates/registration_form.html b/cof/templates/registration_form.html index 97bc375c..06df8220 100644 --- a/cof/templates/registration_form.html +++ b/cof/templates/registration_form.html @@ -7,7 +7,7 @@ {% else %}

Inscription d'un nouveau compte (extérieur ?)

{% endif %} - + {% csrf_token %} {{ user_form | bootstrap }} @@ -16,7 +16,6 @@
{{ cofprofile_form | bootstrap }} - {{ clubs_form | bootstrap }}
{{ event_formset.management_form }} {% for event_form in event_formset %} diff --git a/cof/templates/survey_status.html b/cof/templates/survey_status.html index 2e8b28fd..820aeb38 100644 --- a/cof/templates/survey_status.html +++ b/cof/templates/survey_status.html @@ -11,7 +11,7 @@ {% endif %}

Filtres

{% include "tristate_js.html" %} - + {% csrf_token %} {{ form.as_p }} diff --git a/cof/templates/utile_bda.html b/cof/templates/utile_bda.html index 83b96fb8..854009c1 100644 --- a/cof/templates/utile_bda.html +++ b/cof/templates/utile_bda.html @@ -7,7 +7,7 @@

Liens utiles du BdA

Listes mail

{% endblock %} diff --git a/cof/urls.py b/cof/urls.py index 52826f29..91a73665 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -7,12 +7,20 @@ from . import views, petits_cours_views export_patterns = [ - url(r'^members$', views.export_members), + url(r'^members$', + views.export_members, + name="export.members"), url(r'^mega/avecremarques$', views.export_mega_remarksonly), - url(r'^mega/participants$', views.export_mega_participants), - url(r'^mega/orgas$', views.export_mega_orgas), + url(r'^mega/participants$', + views.export_mega_participants, + name="export.mega.participants"), + url(r'^mega/orgas$', + views.export_mega_orgas, + name="export.mega.orgas"), url(r'^mega/(?P.+)$', views.export_mega_bytype), - url(r'^mega$', views.export_mega), + url(r'^mega$', + views.export_mega, + name="export.mega"), ] petitcours_patterns = [ @@ -37,23 +45,28 @@ petitcours_patterns = [ ] surveys_patterns = [ - url(r'^(?P\d+)/status$', views.survey_status), - url(r'^(?P\d+)$', views.survey), + url(r'^(?P\d+)/status$', + views.survey_status, + name="survey.status"), + url(r'^(?P\d+)$', + views.survey, + name="survey"), ] events_patterns = [ - url(r'^(?P\d+)$', views.event), - url(r'^(?P\d+)/status$', views.event_status), + url(r'^(?P\d+)$', + views.event, + name="event"), + url(r'^(?P\d+)/status$', + views.event_status, + name="event.status"), ] calendar_patterns = [ - url(r'^subscription$', views.calendar), - url(r'^(?P[a-z0-9-]+)/calendar.ics$', views.calendar_ics) -] - -clubs_patterns = [ - url(r'^membres/(?P\w+)', views.membres_club, name='membres-club'), - url(r'^liste', views.liste_clubs, name='liste-clubs'), - url(r'^change_respo/(?P\w+)/(?P\d+)', - views.change_respo, name='change-respo'), + url(r'^subscription$', + views.calendar, + name="calendar"), + url(r'^(?P[a-z0-9-]+)/calendar.ics$', + views.calendar_ics, + name="calendar.ics") ] diff --git a/cof/views.py b/cof/views.py index e1c0e394..cbb09af4 100644 --- a/cof/views.py +++ b/cof/views.py @@ -6,8 +6,8 @@ from datetime import timedelta from icalendar import Calendar, Event as Vevent from custommail.shortcuts import send_custom_mail -from django.shortcuts import redirect, get_object_or_404, render -from django.http import Http404, HttpResponse, HttpResponseForbidden +from django.shortcuts import get_object_or_404, render +from django.http import Http404, HttpResponse from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.contrib.sites.models import Site @@ -21,12 +21,12 @@ from .models import Event, EventRegistration, EventOption, \ EventOptionChoice from .models import EventCommentField, EventCommentValue, \ CalendarSubscription -from .models import CofProfile, Club +from .models import CofProfile from .decorators import buro_required, cof_required from .forms import ( EventStatusFilterForm, SurveyForm, SurveyStatusFilterForm, RegistrationUserForm, RegistrationProfileForm, RegistrationCofProfileForm, - EventForm, CalendarForm, EventFormset, RegistrationPassUserForm, ClubsForm + EventForm, CalendarForm, EventFormset, RegistrationPassUserForm ) from bda.models import Tirage, Spectacle @@ -305,9 +305,8 @@ def registration_form2(request, login_clipper=None, username=None, # COF - profile cofprofile_form = RegistrationCofProfileForm() registration_set_ro_fields(user_form, profile_form) - # events & clubs + # events event_formset = EventFormset(events=events, prefix='events') - clubs_form = ClubsForm() if username: member = get_object_or_404(User, username=username) (profile, _) = Profile.objects.get_or_create(user=member) @@ -328,8 +327,6 @@ def registration_form2(request, login_clipper=None, username=None, event_formset = EventFormset( events=events, prefix='events', current_registrations=current_registrations) - # Clubs - clubs_form = ClubsForm(initial={'clubs': member.clubs.all()}) elif not login_clipper: # new user user_form = RegistrationPassUserForm() @@ -337,14 +334,12 @@ def registration_form2(request, login_clipper=None, username=None, profile_form = RegistrationProfileForm() cofprofile_form = RegistrationCofProfileForm() event_formset = EventFormset(events=events, prefix='events') - clubs_form = ClubsForm() return render(request, "cof/registration_form.html", {"member": member, "login_clipper": login_clipper, "user_form": user_form, "profile_form": profile_form, "cofprofile_form": cofprofile_form, - "event_formset": event_formset, - "clubs_form": clubs_form}) + "event_formset": event_formset}) @buro_required @@ -368,7 +363,6 @@ def registration(request): user_form = RegistrationUserForm(request_dict) profile_form = RegistrationProfileForm(request_dict) cofprofile_form = RegistrationCofProfileForm(request_dict) - clubs_form = ClubsForm(request_dict) events = Event.objects.filter(old=False).all() event_formset = EventFormset(events=events, data=request_dict, prefix='events') @@ -409,7 +403,6 @@ def registration(request): profile_form.is_valid(), cofprofile_form.is_valid(), event_formset.is_valid(), - clubs_form.is_valid() )) if forms_are_valid: # Enregistrement du profil @@ -455,11 +448,6 @@ def registration(request): # l'inscription aux événements et/ou donner la # possibilité d'associer un mail aux événements # send_custom_mail(...) - # Enregistrement des inscriptions aux clubs - member.clubs.clear() - for club in clubs_form.cleaned_data['clubs']: - club.membres.add(member) - club.save() success = True # Messages if success: @@ -476,56 +464,11 @@ def registration(request): "cofprofile_form": cofprofile_form, "member": member, "login_clipper": login_clipper, - "event_formset": event_formset, - "clubs_form": clubs_form}) + "event_formset": event_formset}) else: return render(request, "registration.html") -# ----- -# Clubs -# ----- - - -@login_required -def membres_club(request, name): - # Vérification des permissions : l'utilisateur doit être membre du burô - # ou respo du club. - user = request.user - club = get_object_or_404(Club, name=name) - if not request.user.profile.is_buro \ - and club not in user.clubs_geres.all(): - return HttpResponseForbidden('

Permission denied

') - members_no_respo = club.membres.exclude(clubs_geres=club).all() - return render(request, 'membres_clubs.html', - {'club': club, - 'members_no_respo': members_no_respo}) - - -@buro_required -def change_respo(request, club_name, user_id): - club = get_object_or_404(Club, name=club_name) - user = get_object_or_404(User, id=user_id) - if user in club.respos.all(): - club.respos.remove(user) - elif user in club.membres.all(): - club.respos.add(user) - else: - raise Http404 - return redirect('membres-club', name=club_name) - - -@cof_required -def liste_clubs(request): - clubs = Club.objects - if request.user.profile.is_buro: - data = {'owned_clubs': clubs.all()} - else: - data = {'owned_clubs': request.user.clubs_geres, - 'other_clubs': clubs.exclude(respos=request.user)} - return render(request, 'liste_clubs.html', data) - - @buro_required def export_members(request): response = HttpResponse(content_type='text/csv') diff --git a/gestioCOF/urls.py b/gestioCOF/urls.py index 1df71648..e3e6fe04 100644 --- a/gestioCOF/urls.py +++ b/gestioCOF/urls.py @@ -4,6 +4,10 @@ Fichier principal de configuration des urls du projet GestioCOF """ +import gestion.urls +import kfet.urls +import bda.urls + from django.conf import settings from django.conf.urls import include, url from django.conf.urls.static import static @@ -12,8 +16,7 @@ from django.contrib.auth import views as django_views from cof import views as cof_views from cof.urls import export_patterns, petitcours_patterns, \ - surveys_patterns, events_patterns, calendar_patterns, \ - clubs_patterns + surveys_patterns, events_patterns, calendar_patterns from cof.autocomplete import autocomplete from gestion import views as gestion_views @@ -24,13 +27,13 @@ urlpatterns = [ # Page d'accueil url(r'^$', cof_views.home, name='home'), # The common views - url(r"^", include("gestion.urls", namespace='gestion')), + url(r"^", include(gestion.urls, namespace="gestion")), # Admin urls url(r'^admin/logout/', gestion_views.logout), url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - url(r'^admin/', include(admin.site.urls)), + url(r'^admin/', admin.site.urls), # Le BdA - url(r'^bda/', include('bda.urls')), + url(r'^bda/', include(bda.urls)), # Les exports url(r'^export/', include(export_patterns)), # Les petits cours @@ -41,15 +44,17 @@ urlpatterns = [ url(r'^event/', include(events_patterns)), # Calendrier url(r'^calendar/', include(calendar_patterns)), - # Clubs - url(r'^clubs/', include(clubs_patterns)), # Infos persos - url(r'^outsider/password-change$', django_views.password_change), + url(r'^outsider/password-change$', + django_views.password_change, + name="password_change"), url(r'^outsider/password-change-done$', django_views.password_change_done, name='password_change_done'), # Inscription d'un nouveau membre - url(r'^registration$', cof_views.registration), + url(r'^registration$', + cof_views.registration, + name="registration"), url(r'^registration/clipper/(?P[\w-]+)$', cof_views.registration_form2, name="clipper-registration"), url(r'^registration/user/(?P.+)$', @@ -57,21 +62,33 @@ urlpatterns = [ url(r'^registration/empty$', cof_views.registration_form2, name="empty-registration"), # Autocompletion - url(r'^autocomplete/registration$', autocomplete), + url(r'^autocomplete/registration$', + autocomplete, + name="autocomplete"), url(r'^autocomplete/', include('autocomplete_light.urls')), # Liens utiles du COF et du BdA - url(r'^utile_cof$', cof_views.utile_cof), - url(r'^utile_bda$', cof_views.utile_bda), - url(r'^utile_bda/bda_diff$', cof_views.liste_bdadiff), - url(r'^utile_cof/diff_cof$', cof_views.liste_diffcof), - url(r'^utile_bda/bda_revente$', cof_views.liste_bdarevente), - url(r'^k-fet/', include('kfet.urls')), + url(r'^utile_cof$', + cof_views.utile_cof, + name="utile_cof"), + url(r'^utile_bda$', + cof_views.utile_bda, + name="utile_bda"), + url(r'^utile_bda/bda_diff$', + cof_views.liste_bdadiff, + name="liste_bdadiff"), + url(r'^utile_cof/diff_cof$', + cof_views.liste_diffcof, + name="liste_diffcof"), + url(r'^utile_bda/bda_revente$', + cof_views.liste_bdarevente, + name="liste_bdarevente"), + url(r'^k-fet/', include(kfet.urls)), ] if 'debug_toolbar' in settings.INSTALLED_APPS: import debug_toolbar urlpatterns += [ - url(r'^__debug__/', include(debug_toolbar.urls)), + url(r'^__debug__/', debug_toolbar.urls), ] # Si on est en production, MEDIA_ROOT est servi par Apache. diff --git a/gestion/admin.py b/gestion/admin.py index 52e3cb55..a25c618d 100644 --- a/gestion/admin.py +++ b/gestion/admin.py @@ -2,9 +2,13 @@ from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User -from .models import Profile +from .models import Profile, Club +# --- +# The user related stuff +# --- + class ProfileInline(admin.StackedInline): model = Profile inline_classes = ["collapse open"] @@ -16,5 +20,14 @@ class UserProfileAdmin(UserAdmin): ] +# --- +# Clubs +# --- + +@admin.register(Club) +class ClubAdmin(admin.ModelAdmin): + pass + + admin.site.unregister(User) admin.site.register(User, UserProfileAdmin) diff --git a/gestion/migrations/0001_initial.py b/gestion/migrations/0001_initial.py index daeaa39b..a301bb9a 100644 --- a/gestion/migrations/0001_initial.py +++ b/gestion/migrations/0001_initial.py @@ -21,7 +21,10 @@ class Migration(migrations.Migration): ('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(to=settings.AUTH_USER_MODEL, related_name='profile')), + ('user', models.OneToOneField( + on_delete=models.CASCADE, + to=settings.AUTH_USER_MODEL, + related_name='profile')), ], options={ 'verbose_name': 'Profil', diff --git a/gestion/migrations/0002_club_support.py b/gestion/migrations/0002_club_support.py new file mode 100644 index 00000000..dc16f400 --- /dev/null +++ b/gestion/migrations/0002_club_support.py @@ -0,0 +1,98 @@ +# -*- 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/models.py b/gestion/models.py index 81335ddc..bba33dd9 100644 --- a/gestion/models.py +++ b/gestion/models.py @@ -1,4 +1,4 @@ -from django.contrib.auth.models import User +from django.contrib.auth.models import User, Group from django.db import models from django.dispatch import receiver from django.db.models.signals import post_save, post_delete @@ -17,9 +17,13 @@ OCCUPATION_CHOICES = ( ('CST', _("CST")), ) -class Profile(models.Model): - user = models.OneToOneField(User, related_name="profile") +class Profile(models.Model): + user = models.OneToOneField( + User, + on_delete=models.CASCADE, + related_name="profile" + ) login_clipper = models.CharField("Login clipper", max_length=8, blank=True) phone = models.CharField("Téléphone", max_length=20, blank=True) occupation = models.CharField(_("Occupation"), @@ -39,6 +43,7 @@ class Profile(models.Model): def __str__(self): return self.user.username + @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: @@ -48,3 +53,53 @@ def create_user_profile(sender, instance, created, **kwargs): @receiver(post_delete, sender=Profile) def post_delete_user(sender, instance, *args, **kwargs): instance.user.delete() + + +class Club(models.Model): + ANNUAL = "ANN" + SEMESTER = "SEM" + COURSE = "COU" + + COTISATION_FREQUENCY_CHOICES = [ + (ANNUAL, _("Annuel")), + (SEMESTER, _("Semestriel")), + (COURSE, _("Au cours")) + ] + + associations = models.ManyToManyField(Group, related_name="clubs") + name = models.CharField(_("Nom"), max_length=200, unique=True) + description = models.TextField("Description", blank=True) + members = models.ManyToManyField( + User, + through="ClubUser", + related_name="in_clubs", + blank=True + ) + price = models.DecimalField( + _("Cotisation (€)"), + decimal_places=2, + max_digits=5, + blank=True, + default=0 + ) + cotisation_frequency = models.CharField( + _("Fréquence de la cotisation"), + default=ANNUAL, + choices=COTISATION_FREQUENCY_CHOICES, + max_length=3, + blank=True + ) + + def __str__(self): + template = ( + self.price and "{name} ({price}€ / {cotisation_frequency})" + or "{name}" + ) + return template.format(**vars(self)) + + +class ClubUser(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + club = models.ForeignKey(Club, on_delete=models.CASCADE) + is_respo = models.BooleanField(_("Est responsable du club")) + has_paid = models.BooleanField(_("A payé sa cotisation")) diff --git a/gestion/urls.py b/gestion/urls.py index 55e5658a..c1cb3db6 100644 --- a/gestion/urls.py +++ b/gestion/urls.py @@ -1,12 +1,11 @@ -from django.conf.urls import url, include +from django.conf.urls import url from django.views.generic.base import TemplateView from django.contrib.auth import views as django_views -from django.contrib import admin from django_cas_ng import views as django_cas_views from . import views - +app_name = "gestion" urlpatterns = [ # Profile edition url(r"^profile/?$", views.profile, name="profile"), diff --git a/gestion/views.py b/gestion/views.py index 7b3a4997..0a210918 100644 --- a/gestion/views.py +++ b/gestion/views.py @@ -16,7 +16,7 @@ from .forms import ProfileForm, UserForm def login(request): if request.user.is_authenticated(): - return redirect("cof.views.home") + return redirect("home") context = {} # Fetch the next page from the request data if request.method == "GET" and 'next' in request.GET: diff --git a/kfet/backends.py b/kfet/backends.py index d0dcc5f6..56d85b81 100644 --- a/kfet/backends.py +++ b/kfet/backends.py @@ -1,15 +1,11 @@ # -*- coding: utf-8 -*- -from __future__ import (absolute_import, division, - print_function, unicode_literals) -from builtins import * - import hashlib from django.contrib.auth.models import User, Permission -from cof.models import CofProfile from kfet.models import Account, GenericTeamToken + class KFetBackend(object): def authenticate(self, request): password = request.POST.get('KFETPASSWORD', '') @@ -17,8 +13,8 @@ class KFetBackend(object): if not password: return None + password_sha256 = hashlib.sha256(password.encode('utf-8')).hexdigest() try: - password_sha256 = hashlib.sha256(password.encode('utf-8')).hexdigest() account = Account.objects.get(password=password_sha256) user = account.profile.user except Account.DoesNotExist: @@ -26,16 +22,20 @@ class KFetBackend(object): return user + class GenericTeamBackend(object): + """ + Authenticate using the generic_team user. + """ def authenticate(self, username=None, token=None): valid_token = GenericTeamToken.objects.get(token=token) if username == 'kfet_genericteam' and valid_token: # Création du user s'il n'existe pas déjà user, _ = User.objects.get_or_create(username='kfet_genericteam') - profile, _ = CofProfile.objects.get_or_create(user=user) account, _ = Account.objects.get_or_create( - profile=profile, - trigramme='GNR') + profile=user.profile, + trigramme='GNR' + ) # Ajoute la permission kfet.is_team à ce user perm_is_team = Permission.objects.get(codename='is_team') diff --git a/kfet/migrations/0048_generic_profiles.py b/kfet/migrations/0048_generic_profiles.py index e3fda98b..ef5eae4e 100644 --- a/kfet/migrations/0048_generic_profiles.py +++ b/kfet/migrations/0048_generic_profiles.py @@ -15,6 +15,9 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='account', name='cofprofile', - field=models.OneToOneField(to='gestion.Profile', related_name='account_kfet'), + field=models.OneToOneField( + to='gestion.Profile', + on_delete=models.CASCADE, + related_name='account_kfet'), ), ]