Commit debba553 authored by Skia's avatar Skia
Browse files

Add MetaGroup system

parent 5bcc94f9
Pipeline #3 skipped
......@@ -16,20 +16,20 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Customer',
fields=[
('user', models.OneToOneField(primary_key=True, to=settings.AUTH_USER_MODEL, serialize=False)),
('account_id', models.CharField(max_length=10, unique=True, verbose_name='account id')),
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, serialize=False, primary_key=True)),
('account_id', models.CharField(max_length=10, verbose_name='account id', unique=True)),
],
options={
'verbose_name_plural': 'customers',
'verbose_name': 'customer',
'verbose_name_plural': 'customers',
},
),
migrations.CreateModel(
name='GeneralJournal',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('start_date', models.DateField(verbose_name='start date')),
('end_date', models.DateField(blank=True, default=None, null=True, verbose_name='end date')),
('end_date', models.DateField(default=None, blank=True, null=True, verbose_name='end date')),
('name', models.CharField(max_length=30, verbose_name='name')),
('closed', models.BooleanField(default=False, verbose_name='is closed')),
],
......@@ -37,36 +37,36 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='GenericInvoice',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('name', models.CharField(max_length=100, verbose_name='name')),
('journal', models.ForeignKey(related_name='invoices', to='accounting.GeneralJournal')),
('journal', models.ForeignKey(to='accounting.GeneralJournal', related_name='invoices')),
],
),
migrations.CreateModel(
name='Product',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('name', models.CharField(max_length=30, verbose_name='name')),
('description', models.TextField(blank=True, verbose_name='description')),
('code', models.CharField(max_length=10, verbose_name='code')),
('purchase_price', accounting.models.CurrencyField(decimal_places=2, max_digits=12, verbose_name='purchase price')),
('selling_price', accounting.models.CurrencyField(decimal_places=2, max_digits=12, verbose_name='selling price')),
('special_selling_price', accounting.models.CurrencyField(decimal_places=2, max_digits=12, verbose_name='special selling price')),
('icon', models.ImageField(blank=True, upload_to='products', null=True)),
('purchase_price', accounting.models.CurrencyField(max_digits=12, verbose_name='purchase price', decimal_places=2)),
('selling_price', accounting.models.CurrencyField(max_digits=12, verbose_name='selling price', decimal_places=2)),
('special_selling_price', accounting.models.CurrencyField(max_digits=12, verbose_name='special selling price', decimal_places=2)),
('icon', models.ImageField(upload_to='products', blank=True, null=True)),
],
),
migrations.CreateModel(
name='ProductType',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('name', models.CharField(max_length=30, verbose_name='name')),
('description', models.TextField(blank=True, null=True, verbose_name='description')),
('icon', models.ImageField(blank=True, upload_to='products', null=True)),
('icon', models.ImageField(upload_to='products', blank=True, null=True)),
],
),
migrations.AddField(
model_name='product',
name='product_type',
field=models.ForeignKey(related_name='products', blank=True, to='accounting.ProductType', null=True),
field=models.ForeignKey(blank=True, related_name='products', to='accounting.ProductType', null=True),
),
]
......@@ -2,37 +2,41 @@
from __future__ import unicode_literals
from django.db import migrations, models
import django.core.validators
from django.conf import settings
import django.core.validators
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('core', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Club',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('name', models.CharField(max_length=30, verbose_name='name')),
('unix_name', models.CharField(unique=True, error_messages={'unique': 'A club with that unix name already exists.'}, validators=[django.core.validators.RegexValidator('^[a-z0-9][a-z0-9._-]*[a-z0-9]$', 'Enter a valid unix name. This value may contain only letters, numbers ./-/_ characters.')], verbose_name='unix name', max_length=30)),
('unix_name', models.CharField(unique=True, max_length=30, verbose_name='unix name', error_messages={'unique': 'A club with that unix name already exists.'}, validators=[django.core.validators.RegexValidator('^[a-z0-9][a-z0-9._-]*[a-z0-9]$', 'Enter a valid unix name. This value may contain only letters, numbers ./-/_ characters.')])),
('address', models.CharField(max_length=254, verbose_name='address')),
('parent', models.ForeignKey(related_name='children', blank=True, to='club.Club', null=True)),
('edit_groups', models.ManyToManyField(to='core.Group', blank=True, related_name='editable_club')),
('owner_group', models.ForeignKey(default=1, related_name='owned_club', to='core.Group')),
('parent', models.ForeignKey(blank=True, related_name='children', to='club.Club', null=True)),
('view_groups', models.ManyToManyField(to='core.Group', blank=True, related_name='viewable_club')),
],
),
migrations.CreateModel(
name='Membership',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('start_date', models.DateField(auto_now=True, verbose_name='start date')),
('end_date', models.DateField(null=True, verbose_name='end date', blank=True)),
('role', models.IntegerField(verbose_name='role', choices=[(0, 'Membre'), (1, 'Membre actif'), (2, 'Membre du bureau'), (3, 'Responsable info'), (4, 'Secrétaire'), (5, 'Responsable com'), (7, 'Trésorier'), (8, 'Vice-Président'), (9, 'Vice-Président'), (10, 'Président')], default=0)),
('description', models.CharField(max_length=30, verbose_name='description', blank=True)),
('club', models.ForeignKey(related_name='members', to='club.Club')),
('user', models.ForeignKey(related_name='membership', to=settings.AUTH_USER_MODEL)),
('end_date', models.DateField(blank=True, null=True, verbose_name='end date')),
('role', models.IntegerField(choices=[(0, 'Curieux'), (1, 'Membre actif'), (2, 'Membre du bureau'), (3, 'Responsable info'), (4, 'Secrétaire'), (5, 'Responsable com'), (7, 'Trésorier'), (9, 'Vice-Président'), (10, 'Président')], verbose_name='role', default=0)),
('description', models.CharField(max_length=30, blank=True, verbose_name='description')),
('club', models.ForeignKey(to='club.Club', related_name='members')),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='membership')),
],
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
('club', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='club',
name='edit_groups',
field=models.ManyToManyField(to='core.Group', blank=True, related_name='editable_club'),
),
migrations.AddField(
model_name='club',
name='view_groups',
field=models.ManyToManyField(to='core.Group', blank=True, related_name='viewable_club'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
('club', '0002_auto_20160202_1345'),
]
operations = [
migrations.AddField(
model_name='club',
name='owner_group',
field=models.ForeignKey(default=1, to='core.Group', related_name='owned_club'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('club', '0003_club_owner_group'),
]
operations = [
migrations.AlterField(
model_name='membership',
name='role',
field=models.IntegerField(choices=[(0, 'Curieux'), (1, 'Membre actif'), (2, 'Membre du bureau'), (3, 'Responsable info'), (4, 'Secrétaire'), (5, 'Responsable com'), (7, 'Trésorier'), (9, 'Vice-Président'), (10, 'Président')], default=0, verbose_name='role'),
),
]
......@@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
from core.models import User, Group
from core.models import User, MetaGroup, Group
from subscription.models import Subscriber
# Create your models here.
......@@ -48,6 +48,11 @@ class Club(models.Model):
def clean(self):
self.check_loop()
def save(self):
super(Club, self).save()
MetaGroup(name=self.unix_name+"-board").save()
MetaGroup(name=self.unix_name+"-members").save()
def __str__(self):
return self.name
......
from django.contrib import admin
from core.models import User, Page, Group
from core.models import User, Page, RealGroup
from django.contrib.auth.models import Group as AuthGroup
admin.site.register(User)
admin.site.unregister(AuthGroup)
admin.site.register(Group)
admin.site.register(RealGroup)
admin.site.register(Page)
......@@ -23,11 +23,11 @@ class Command(BaseCommand):
is_superuser=True, is_staff=True)
root.set_password("plop")
root.save()
for g in settings.AE_GROUPS.values():
Group(id=g['id'], name=g['name']).save()
ae = Club(name=settings.AE_MAIN_CLUB['name'], unix_name=settings.AE_MAIN_CLUB['unix_name'],
address=settings.AE_MAIN_CLUB['address'])
ae.save()
for g in settings.AE_GROUPS.values():
Group(id=g['id'], name=g['name']).save()
p = Page(name='Index')
p.set_lock(root)
p.save()
......
......@@ -3,39 +3,40 @@ from __future__ import unicode_literals
from django.db import migrations, models
import django.core.validators
from django.conf import settings
import django.db.models.deletion
import core.models
import django.contrib.auth.models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
('auth', '__first__'),
('auth', '0006_require_contenttypes_0002'),
]
operations = [
migrations.CreateModel(
name='User',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')),
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, verbose_name='last login', null=True)),
('is_superuser', models.BooleanField(help_text='Designates that this user has all permissions without explicitly assigning them.', default=False, verbose_name='superuser status')),
('username', models.CharField(max_length=254, verbose_name='username', unique=True, help_text='Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only.', validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], error_messages={'unique': 'A user with that username already exists.'})),
('last_login', models.DateTimeField(verbose_name='last login', null=True, blank=True)),
('is_superuser', models.BooleanField(verbose_name='superuser status', default=False, help_text='Designates that this user has all permissions without explicitly assigning them.')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, verbose_name='username', help_text='Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], max_length=254)),
('first_name', models.CharField(max_length=30, verbose_name='first name')),
('last_name', models.CharField(max_length=30, verbose_name='last name')),
('email', models.EmailField(max_length=254, verbose_name='email address', unique=True)),
('date_of_birth', models.DateField(verbose_name='date of birth')),
('nick_name', models.CharField(max_length=30, blank=True)),
('is_staff', models.BooleanField(help_text='Designates whether the user can log into this admin site.', default=False, verbose_name='staff status')),
('is_active', models.BooleanField(help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', default=True, verbose_name='active')),
('date_joined', models.DateField(auto_now_add=True, verbose_name='date joined')),
('is_staff', models.BooleanField(verbose_name='staff status', default=False, help_text='Designates whether the user can log into this admin site.')),
('is_active', models.BooleanField(verbose_name='active', default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.')),
('date_joined', models.DateField(verbose_name='date joined', auto_now_add=True)),
],
options={
'verbose_name_plural': 'users',
'permissions': (('change_prop_user', "Can change the user's properties (groups, ...)"), ('view_user', "Can view user's profile")),
'verbose_name': 'user',
'permissions': (('change_prop_user', "Can change the user's properties (groups, ...)"), ('view_user', "Can view user's profile")),
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
......@@ -44,20 +45,21 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Group',
fields=[
('group_ptr', models.OneToOneField(serialize=False, primary_key=True, parent_link=True, to='auth.Group', auto_created=True)),
('group_ptr', models.OneToOneField(to='auth.Group', auto_created=True, parent_link=True, primary_key=True, serialize=False)),
('is_meta', models.BooleanField(verbose_name='meta group status', default=False, help_text='Whether a group is a meta group or not')),
],
bases=('auth.group',),
),
migrations.CreateModel(
name='Page',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')),
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
('name', models.CharField(max_length=30, verbose_name='page name')),
('_full_name', models.CharField(max_length=255, verbose_name='page name', blank=True)),
('edit_groups', models.ManyToManyField(to='core.Group', related_name='editable_page', blank=True)),
('owner_group', models.ForeignKey(to='core.Group', related_name='owned_page', default=1)),
('parent', models.ForeignKey(to='core.Page', on_delete=django.db.models.deletion.SET_NULL, null=True, related_name='children', blank=True)),
('view_groups', models.ManyToManyField(to='core.Group', related_name='viewable_page', blank=True)),
('_full_name', models.CharField(verbose_name='page name', max_length=255, blank=True)),
('edit_groups', models.ManyToManyField(to='core.Group', blank=True, related_name='editable_page')),
('owner_group', models.ForeignKey(to='core.Group', default=1, related_name='owned_page')),
('parent', models.ForeignKey(to='core.Page', on_delete=django.db.models.deletion.SET_NULL, related_name='children', null=True, blank=True)),
('view_groups', models.ManyToManyField(to='core.Group', blank=True, related_name='viewable_page')),
],
options={
'permissions': (('change_prop_page', "Can change the page's properties (groups, ...)"), ('view_page', 'Can view the page')),
......@@ -66,12 +68,12 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='PageRev',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, primary_key=True, verbose_name='ID')),
('title', models.CharField(max_length=255, verbose_name='page title', blank=True)),
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
('title', models.CharField(verbose_name='page title', max_length=255, blank=True)),
('content', models.TextField(verbose_name='page content', blank=True)),
('date', models.DateTimeField(auto_now=True, verbose_name='date')),
('author', models.ForeignKey(related_name='page_rev', to=settings.AUTH_USER_MODEL)),
('page', models.ForeignKey(related_name='revisions', to='core.Page')),
('date', models.DateTimeField(verbose_name='date', auto_now=True)),
('author', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='page_rev')),
('page', models.ForeignKey(to='core.Page', related_name='revisions')),
],
options={
'ordering': ['date'],
......@@ -80,27 +82,51 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='user',
name='edit_groups',
field=models.ManyToManyField(to='core.Group', related_name='editable_user', blank=True),
field=models.ManyToManyField(to='core.Group', blank=True, related_name='editable_user'),
),
migrations.AddField(
model_name='user',
name='groups',
field=models.ManyToManyField(to='auth.Group', related_query_name='user', verbose_name='groups', related_name='user_set', help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', blank=True),
field=models.ManyToManyField(to='auth.Group', verbose_name='groups', help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_query_name='user', blank=True, related_name='user_set'),
),
migrations.AddField(
model_name='user',
name='owner_group',
field=models.ForeignKey(to='core.Group', related_name='owned_user', default=1),
field=models.ForeignKey(to='core.Group', default=1, related_name='owned_user'),
),
migrations.AddField(
model_name='user',
name='user_permissions',
field=models.ManyToManyField(to='auth.Permission', related_query_name='user', verbose_name='user permissions', related_name='user_set', help_text='Specific permissions for this user.', blank=True),
field=models.ManyToManyField(to='auth.Permission', verbose_name='user permissions', help_text='Specific permissions for this user.', related_query_name='user', blank=True, related_name='user_set'),
),
migrations.AddField(
model_name='user',
name='view_groups',
field=models.ManyToManyField(to='core.Group', related_name='viewable_user', blank=True),
field=models.ManyToManyField(to='core.Group', blank=True, related_name='viewable_user'),
),
migrations.CreateModel(
name='MetaGroup',
fields=[
],
options={
'proxy': True,
},
bases=('core.group',),
managers=[
('objects', core.models.MetaGroupManager()),
],
),
migrations.CreateModel(
name='RealGroup',
fields=[
],
options={
'proxy': True,
},
bases=('core.group',),
managers=[
('objects', core.models.RealGroupManager()),
],
),
migrations.AlterUniqueTogether(
name='page',
......
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager, Group as AuthGroup, AnonymousUser as AuthAnonymousUser
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager, Group as AuthGroup, GroupManager as AuthGroupManager, AnonymousUser as AuthAnonymousUser
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.core import validators
......@@ -10,13 +10,40 @@ from datetime import datetime, timedelta
import unicodedata
class RealGroupManager(AuthGroupManager):
def get_queryset(self):
return super(RealGroupManager, self).get_queryset().filter(is_meta=False)
class MetaGroupManager(AuthGroupManager):
def get_queryset(self):
return super(MetaGroupManager, self).get_queryset().filter(is_meta=True)
class Group(AuthGroup):
is_meta = models.BooleanField(
_('meta group status'),
default=False,
help_text=_('Whether a group is a meta group or not'),
)
def get_absolute_url(self):
"""
This is needed for black magic powered UpdateView's children
"""
return reverse('core:group_edit', kwargs={'group_id': self.pk})
class MetaGroup(Group):
objects = MetaGroupManager()
class Meta:
proxy = True
def __init__(self, *args, **kwargs):
super(MetaGroup, self).__init__(*args, **kwargs)
self.is_meta = True
class RealGroup(Group):
objects = RealGroupManager()
class Meta:
proxy = True
class User(AbstractBaseUser, PermissionsMixin):
"""
Defines the base user class, useable in every app
......
......@@ -7,7 +7,7 @@ Group list
{% block content %}
<h3>Group list</h3>
<ul>
{% for g in group_list %}
{% for g in realgroup_list %}
<li><a href="{{ url('core:group_edit', group_id=g.id) }}">{{ g.name }}</a></li>
{% endfor %}
</ul>
......
......@@ -4,7 +4,7 @@ from django.contrib.auth import logout, login, authenticate
from django.forms import CheckboxSelectMultiple
import logging
from core.models import User, Page, Group
from core.models import User, Page, RealGroup
class RegisteringForm(UserCreationForm):
error_css_class = 'error'
......@@ -65,7 +65,7 @@ class GroupEditForm(forms.ModelForm):
error_css_class = 'error'
required_css_class = 'required'
class Meta:
model = Group
model = RealGroup
fields = ['name', 'permissions',]
widgets = {
'permissions': CheckboxSelectMultiple,
......
from django.views.generic.edit import UpdateView
from django.views.generic import ListView
from core.models import Group
from core.models import RealGroup
from core.views.forms import GroupEditForm
from core.views import CanEditMixin
......@@ -9,11 +9,11 @@ class GroupListView(CanEditMixin, ListView):
"""
Displays the group list
"""
model = Group
model = RealGroup
template_name = "core/group_list.jinja"
class GroupEditView(CanEditMixin, UpdateView):
model = Group
model = RealGroup
pk_url_kwarg = "group_id"
template_name = "core/group_edit.jinja"
form_class = GroupEditForm
......
......@@ -7,21 +7,22 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('club', '0004_auto_20160321_1648'),
('core', '0001_initial'),
('club', '0001_initial'),
('accounting', '0001_initial'),
('core', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Counter',
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('name', models.CharField(max_length=30, verbose_name='name')),
('type', models.CharField(max_length=255, verbose_name='subscription type', choices=[('BAR', 'Bar'), ('OFFICE', 'Office')])),
('club', models.ForeignKey(to='club.Club', related_name='counters')),
('edit_groups', models.ManyToManyField(related_name='editable_counters', to='core.Group', blank=True)),
('products', models.ManyToManyField(related_name='counters', to='accounting.Product', blank=True)),
('view_groups', models.ManyToManyField(related_name='viewable_counters', to='core.Group', blank=True)),
('edit_groups', models.ManyToManyField(to='core.Group', blank=True, related_name='editable_counters')),
('products', models.ManyToManyField(to='accounting.Product', blank=True, related_name='counters')),
('view_groups', models.ManyToManyField(to='core.Group', blank=True, related_name='viewable_counters')),
],
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('counter', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='counter',
name='type',
field=models.CharField(max_length=255, default='BAR', verbose_name='subscription type', choices=[('BAR', 'Bar'), ('OFFICE', 'Office')]),
preserve_default=False,
),
]
......@@ -15,11 +15,11 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Subscription',
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
('subscription_type', models.CharField(choices=[('cursus-branche', 'Cursus Branche'), ('cursus-tronc-commun', 'Cursus Tronc Commun'), ('deux-semestres', 'Deux semestres'), ('un-semestre', 'Un semestre')], max_length=255, verbose_name='subscription type')),
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('subscription_type', models.CharField(max_length=255, verbose_name='subscription type', choices=[('cursus-branche', 'Cursus Branche'), ('cursus-tronc-commun', 'Cursus Tronc Commun'), ('deux-semestres', 'Deux semestres'), ('un-semestre', 'Un semestre')])),
('subscription_start', models.DateField(verbose_name='subscription start')),
('subscription_end', models.DateField(verbose_name='subscription end')),
('payment_method', models.CharField(choices=[('cheque', 'Chèque'), ('cash', 'Espèce'), ('other', 'Autre')], max_length=255, verbose_name='payment method')),
('payment_method', models.CharField(max_length=255, verbose_name='payment method', choices=[('cheque', 'Chèque'), ('cash', 'Espèce'),