Merge branch 'Kerl/clubs_support' into 'supportBDS'

Kerl/clubs support

- Add the club-related models
- Register them into the admin site in order to be able to play with them

See #133 

See merge request !175
This commit is contained in:
Martin Pepin 2017-02-23 12:46:27 +01:00
commit 4d825b485d
7 changed files with 188 additions and 37 deletions

View file

@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django import forms
from django.contrib import admin from django.contrib import admin
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -13,7 +12,7 @@ from .petits_cours_models import PetitCoursDemande, \
PetitCoursAttributionCounter PetitCoursAttributionCounter
from .models import ( from .models import (
SurveyQuestionAnswer, SurveyQuestion, CofProfile, EventOption, SurveyQuestionAnswer, SurveyQuestion, CofProfile, EventOption,
EventOptionChoice, Event, Club, EventCommentField, EventRegistration, EventOptionChoice, Event, EventCommentField, EventRegistration,
Survey Survey
) )
@ -135,30 +134,11 @@ class PetitCoursDemandeAdmin(admin.ModelAdmin):
search_fields = ('name', 'email', 'phone', 'lieu', 'remarques') 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(Survey, SurveyAdmin)
admin.site.register(SurveyQuestion, SurveyQuestionAdmin) admin.site.register(SurveyQuestion, SurveyQuestionAdmin)
admin.site.register(Event, EventAdmin) admin.site.register(Event, EventAdmin)
admin.site.register(EventOption, EventOptionAdmin) admin.site.register(EventOption, EventOptionAdmin)
admin.site.register(CofProfile) admin.site.register(CofProfile)
admin.site.register(Club, ClubAdmin)
admin.site.register(PetitCoursSubject) admin.site.register(PetitCoursSubject)
admin.site.register(PetitCoursAbility, PetitCoursAbilityAdmin) admin.site.register(PetitCoursAbility, PetitCoursAbilityAdmin)
admin.site.register(PetitCoursAttribution, PetitCoursAttributionAdmin) admin.site.register(PetitCoursAttribution, PetitCoursAttributionAdmin)

View file

@ -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',
),
]

View file

@ -79,18 +79,6 @@ class CofProfile(models.Model):
return self.profile.user.username 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 @python_2_unicode_compatible
class Event(models.Model): class Event(models.Model):
title = models.CharField("Titre", max_length=200) title = models.CharField("Titre", max_length=200)

View file

@ -2,9 +2,13 @@ from django.contrib import admin
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .models import Profile from .models import Profile, Club
# ---
# The user related stuff
# ---
class ProfileInline(admin.StackedInline): class ProfileInline(admin.StackedInline):
model = Profile model = Profile
inline_classes = ["collapse open"] 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.unregister(User)
admin.site.register(User, UserProfileAdmin) admin.site.register(User, UserProfileAdmin)

View file

@ -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),
]

View file

@ -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.db import models
from django.dispatch import receiver from django.dispatch import receiver
from django.db.models.signals import post_save, post_delete from django.db.models.signals import post_save, post_delete
@ -53,3 +53,53 @@ def create_user_profile(sender, instance, created, **kwargs):
@receiver(post_delete, sender=Profile) @receiver(post_delete, sender=Profile)
def post_delete_user(sender, instance, *args, **kwargs): def post_delete_user(sender, instance, *args, **kwargs):
instance.user.delete() 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"))

View file

@ -1,7 +1,6 @@
from django.conf.urls import url, include from django.conf.urls import url
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.contrib.auth import views as django_views 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 django_cas_ng import views as django_cas_views
from . import views from . import views