diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5080ef32..19bcc736 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,6 +7,7 @@ variables:
DJANGO_SETTINGS_MODULE: "cof.settings.prod"
DBHOST: "postgres"
REDIS_HOST: "redis"
+ REDIS_PASSWD: "dummy"
# Cached packages
PYTHONPATH: "$CI_PROJECT_DIR/vendor/python"
@@ -16,6 +17,8 @@ variables:
POSTGRES_USER: "cof_gestion"
POSTGRES_DB: "cof_gestion"
+ # psql password authentication
+ PGPASSWORD: $POSTGRES_PASSWORD
cache:
paths:
@@ -27,10 +30,10 @@ before_script:
- mkdir -p vendor/{python,pip,apt}
- apt-get update -q && apt-get -o dir::cache::archives="vendor/apt" install -yqq postgresql-client
- sed -E 's/^REDIS_HOST.*/REDIS_HOST = "redis"/' cof/settings/secret_example.py > cof/settings/secret.py
+ - sed -i.bak -E 's;^REDIS_PASSWD = .*$;REDIS_PASSWD = "";' cof/settings/secret.py
# Remove the old test database if it has not been done yet
- - psql --username=cof_gestion --password="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" --host="$DBHOST"
- -e "DROP DATABASE test_$DBNAME" || true
- - pip install --cache-dir vendor/pip -t vendor/python -r requirements.txt
+ - psql --username=$POSTGRES_USER --host=$DBHOST -c "DROP DATABASE IF EXISTS test_$POSTGRES_DB"
+ - pip install --upgrade --cache-dir vendor/pip -t vendor/python -r requirements.txt
test:
stage: test
diff --git a/bda/admin.py b/bda/admin.py
index 0cc66d43..6638ad45 100644
--- a/bda/admin.py
+++ b/bda/admin.py
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
-import autocomplete_light
from datetime import timedelta
from custommail.shortcuts import send_mass_custom_mail
@@ -9,6 +8,9 @@ from django.db.models import Sum, Count
from django.template.defaultfilters import pluralize
from django.utils import timezone
from django import forms
+
+from dal.autocomplete import ModelSelect2
+
from bda.models import Spectacle, Salle, Participant, ChoixSpectacle,\
Attribution, Tirage, Quote, CategorieSpectacle, SpectacleRevente
@@ -24,8 +26,17 @@ class ReadOnlyMixin(object):
return readonly_fields + self.readonly_fields_update
+class ChoixSpectacleAdminForm(forms.ModelForm):
+ class Meta:
+ widgets = {
+ 'participant': ModelSelect2(url='bda-participant-autocomplete'),
+ 'spectacle': ModelSelect2(url='bda-spectacle-autocomplete'),
+ }
+
+
class ChoixSpectacleInline(admin.TabularInline):
model = ChoixSpectacle
+ form = ChoixSpectacleAdminForm
sortable_field_name = "priority"
@@ -56,17 +67,17 @@ class AttributionInline(admin.TabularInline):
def get_queryset(self, request):
qs = super().get_queryset(request)
if self.listing is not None:
- qs.filter(spectacle__listing=self.listing)
+ qs = qs.filter(spectacle__listing=self.listing)
return qs
class WithListingAttributionInline(AttributionInline):
+ exclude = ('given', )
form = WithListingAttributionTabularAdminForm
listing = True
class WithoutListingAttributionInline(AttributionInline):
- exclude = ('given', )
form = WithoutListingAttributionTabularAdminForm
listing = False
@@ -180,7 +191,7 @@ class AttributionAdmin(ReadOnlyMixin, admin.ModelAdmin):
class ChoixSpectacleAdmin(admin.ModelAdmin):
- form = autocomplete_light.modelform_factory(ChoixSpectacle, exclude=[])
+ form = ChoixSpectacleAdminForm
def tirage(self, obj):
return obj.participant.tirage
diff --git a/bda/autocomplete_light_registry.py b/bda/autocomplete_light_registry.py
deleted file mode 100644
index 6c2f3ea6..00000000
--- a/bda/autocomplete_light_registry.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import division
-from __future__ import print_function
-from __future__ import unicode_literals
-
-import autocomplete_light
-
-from bda.models import Participant, Spectacle
-
-autocomplete_light.register(
- Participant, search_fields=('user__username', 'user__first_name',
- 'user__last_name'),
- autocomplete_js_attributes={'placeholder': 'participant...'})
-
-autocomplete_light.register(
- Spectacle, search_fields=('title', ),
- autocomplete_js_attributes={'placeholder': 'spectacle...'})
diff --git a/bda/migrations/0001_initial.py b/bda/migrations/0001_initial.py
index aa2cb252..c4494413 100644
--- a/bda/migrations/0001_initial.py
+++ b/bda/migrations/0001_initial.py
@@ -59,7 +59,7 @@ 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(to='bda.Salle', on_delete=models.CASCADE)),
],
options={
'ordering': ('priority', 'date', 'title'),
@@ -79,27 +79,27 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='participant',
name='user',
- field=models.OneToOneField(to=settings.AUTH_USER_MODEL),
+ field=models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='choixspectacle',
name='participant',
- field=models.ForeignKey(to='bda.Participant'),
+ field=models.ForeignKey(to='bda.Participant', on_delete=models.CASCADE),
),
migrations.AddField(
model_name='choixspectacle',
name='spectacle',
- field=models.ForeignKey(related_name='participants', to='bda.Spectacle'),
+ field=models.ForeignKey(related_name='participants', to='bda.Spectacle', on_delete=models.CASCADE),
),
migrations.AddField(
model_name='attribution',
name='participant',
- field=models.ForeignKey(to='bda.Participant'),
+ field=models.ForeignKey(to='bda.Participant', on_delete=models.CASCADE),
),
migrations.AddField(
model_name='attribution',
name='spectacle',
- field=models.ForeignKey(related_name='attribues', to='bda.Spectacle'),
+ field=models.ForeignKey(related_name='attribues', to='bda.Spectacle', on_delete=models.CASCADE),
),
migrations.AlterUniqueTogether(
name='choixspectacle',
diff --git a/bda/migrations/0002_add_tirage.py b/bda/migrations/0002_add_tirage.py
index 1956a4a4..79f79a57 100644
--- a/bda/migrations/0002_add_tirage.py
+++ b/bda/migrations/0002_add_tirage.py
@@ -5,17 +5,34 @@ from django.db import migrations, models
from django.conf import settings
from django.utils import timezone
-def forwards_func(apps, schema_editor):
+
+def fill_tirage_fields(apps, schema_editor):
+ """
+ Create a `Tirage` to fill new field `tirage` of `Participant`
+ and `Spectacle` already existing.
+ """
+ Participant = apps.get_model("bda", "Participant")
+ Spectacle = apps.get_model("bda", "Spectacle")
Tirage = apps.get_model("bda", "Tirage")
- db_alias = schema_editor.connection.alias
- Tirage.objects.using(db_alias).bulk_create([
- Tirage(
- id=1,
- title="Tirage de test (migration)",
- active=False,
- ouverture=timezone.now(),
- fermeture=timezone.now()),
- ])
+
+ # These querysets only contains instances not linked to any `Tirage`.
+ participants = Participant.objects.filter(tirage=None)
+ spectacles = Spectacle.objects.filter(tirage=None)
+
+ if not participants.count() and not spectacles.count():
+ # No need to create a "trash" tirage.
+ return
+
+ tirage = Tirage.objects.create(
+ title="Tirage de test (migration)",
+ active=False,
+ ouverture=timezone.now(),
+ fermeture=timezone.now(),
+ )
+
+ participants.update(tirage=tirage)
+ spectacles.update(tirage=tirage)
+
class Migration(migrations.Migration):
@@ -35,22 +52,33 @@ class Migration(migrations.Migration):
('active', models.BooleanField(default=True, verbose_name=b'Tirage actif')),
],
),
- migrations.RunPython(forwards_func, migrations.RunPython.noop),
migrations.AlterField(
model_name='participant',
name='user',
- field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
+ field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
),
+ # Create fields `spectacle` for `Participant` and `Spectacle` models.
+ # These fields are not nullable, but we first create them as nullable
+ # to give a default value for existing instances of these models.
migrations.AddField(
model_name='participant',
name='tirage',
- field=models.ForeignKey(default=1, to='bda.Tirage'),
- preserve_default=False,
+ field=models.ForeignKey(to='bda.Tirage', null=True, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='spectacle',
name='tirage',
- field=models.ForeignKey(default=1, to='bda.Tirage'),
- preserve_default=False,
+ field=models.ForeignKey(to='bda.Tirage', null=True, on_delete=models.CASCADE),
+ ),
+ migrations.RunPython(fill_tirage_fields, migrations.RunPython.noop),
+ migrations.AlterField(
+ model_name='participant',
+ name='tirage',
+ field=models.ForeignKey(to='bda.Tirage', on_delete=models.CASCADE),
+ ),
+ migrations.AlterField(
+ model_name='spectacle',
+ name='tirage',
+ field=models.ForeignKey(to='bda.Tirage', on_delete=models.CASCADE),
),
]
diff --git a/bda/migrations/0007_extends_spectacle.py b/bda/migrations/0007_extends_spectacle.py
index b95c18de..6ea11dc0 100644
--- a/bda/migrations/0007_extends_spectacle.py
+++ b/bda/migrations/0007_extends_spectacle.py
@@ -73,6 +73,7 @@ class Migration(migrations.Migration):
model_name='spectacle',
name='category',
field=models.ForeignKey(blank=True, to='bda.CategorieSpectacle',
+ on_delete=models.CASCADE,
null=True),
),
migrations.AddField(
@@ -84,6 +85,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='quote',
name='spectacle',
- field=models.ForeignKey(to='bda.Spectacle'),
+ field=models.ForeignKey(to='bda.Spectacle',
+ on_delete=models.CASCADE),
),
]
diff --git a/bda/migrations/0009_revente.py b/bda/migrations/0009_revente.py
index 1cca4e86..70d6f338 100644
--- a/bda/migrations/0009_revente.py
+++ b/bda/migrations/0009_revente.py
@@ -47,12 +47,14 @@ class Migration(migrations.Migration):
model_name='spectaclerevente',
name='attribution',
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',
+ on_delete=models.CASCADE,
verbose_name='Vendeur',
related_name='original_shows'),
),
@@ -60,6 +62,7 @@ class Migration(migrations.Migration):
model_name='spectaclerevente',
name='soldTo',
field=models.ForeignKey(to='bda.Participant',
+ on_delete=models.CASCADE,
verbose_name='Vendue à', null=True,
blank=True),
),
diff --git a/bda/models.py b/bda/models.py
index 41462d70..73356038 100644
--- a/bda/models.py
+++ b/bda/models.py
@@ -6,12 +6,15 @@ from datetime import timedelta
from custommail.shortcuts import send_mass_custom_mail
from django.contrib.sites.models import Site
+from django.core import mail
from django.db import models
from django.db.models import Count
from django.contrib.auth.models import User
from django.conf import settings
from django.utils import timezone, formats
+from custommail.models import CustomMail
+
def get_generic_user():
generic, _ = User.objects.get_or_create(
@@ -59,9 +62,12 @@ 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)
@@ -71,7 +77,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)
@@ -135,7 +141,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)
@@ -149,7 +155,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")
@@ -160,7 +166,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)
@@ -176,8 +182,11 @@ 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,
@@ -204,8 +213,11 @@ 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):
@@ -214,18 +226,25 @@ 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,
+ verbose_name="Vendeur",
+ related_name="original_shows",
+ )
+ soldTo = models.ForeignKey(
+ Participant, on_delete=models.CASCADE,
+ verbose_name="Vendue à",
+ blank=True, null=True,
+ )
notif_sent = models.BooleanField("Notification envoyée",
default=False)
@@ -312,37 +331,55 @@ class SpectacleRevente(models.Model):
# Envoie un mail au gagnant et au vendeur
winner = random.choice(inscrits)
self.soldTo = winner
- datatuple = []
+
+ mails = []
+
context = {
'acheteur': winner.user,
'vendeur': seller.user,
'show': spectacle,
}
- datatuple.append((
- 'bda-revente-winner',
- context,
- settings.MAIL_DATA['revente']['FROM'],
- [winner.user.email],
- ))
- datatuple.append((
+
+ c_mails_qs = CustomMail.objects.filter(shortname__in=[
+ 'bda-revente-winner', 'bda-revente-loser',
'bda-revente-seller',
- context,
- settings.MAIL_DATA['revente']['FROM'],
- [seller.user.email]
- ))
+ ])
+
+ c_mails = {cm.shortname: cm for cm in c_mails_qs}
+
+ mails.append(
+ c_mails['bda-revente-winner'].get_message(
+ context,
+ from_email=settings.MAIL_DATA['revente']['FROM'],
+ to=[winner.user.email],
+ )
+ )
+
+ mails.append(
+ c_mails['bda-revente-seller'].get_message(
+ context,
+ from_email=settings.MAIL_DATA['revente']['FROM'],
+ to=[seller.user.email],
+ reply_to=[winner.user.email],
+ )
+ )
# Envoie un mail aux perdants
for inscrit in inscrits:
if inscrit != winner:
new_context = dict(context)
new_context['acheteur'] = inscrit.user
- datatuple.append((
- 'bda-revente-loser',
- new_context,
- settings.MAIL_DATA['revente']['FROM'],
- [inscrit.user.email]
- ))
- send_mass_custom_mail(datatuple)
+
+ mails.append(
+ c_mails['bda-revente-loser'].get_message(
+ new_context,
+ from_email=settings.MAIL_DATA['revente']['FROM'],
+ to=[inscrit.user.email],
+ )
+ )
+
+ mail_conn = mail.get_connection()
+ mail_conn.send_messages(mails)
# Si personne ne veut de la place, elle part au shotgun
else:
self.shotgun = True
diff --git a/bda/templates/bda/participants.html b/bda/templates/bda/participants.html
index 85af4a2e..c3ff31d6 100644
--- a/bda/templates/bda/participants.html
+++ b/bda/templates/bda/participants.html
@@ -47,11 +47,11 @@
{% spaceless %}
-{% for participant in participants %}{{participant.name}} : {{participant.nb_places}} places
+{% for participant in participants %}{{ participant.name }} : {{ participant.nb_places }} place{{ participant.nb_places|pluralize }}
{% endfor %}
{% endspaceless %}
-
+
diff --git a/bda/tests/__init__.py b/bda/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/bda/tests/test_models.py b/bda/tests/test_models.py
new file mode 100644
index 00000000..d9242b3f
--- /dev/null
+++ b/bda/tests/test_models.py
@@ -0,0 +1,100 @@
+from datetime import timedelta
+from unittest import mock
+
+from django.contrib.auth import get_user_model
+from django.core import mail
+from django.test import TestCase
+from django.utils import timezone
+
+from bda.models import (
+ Attribution, Participant, Salle, Spectacle, SpectacleRevente, Tirage,
+)
+
+User = get_user_model()
+
+
+class SpectacleReventeTests(TestCase):
+ fixtures = ['gestioncof/management/data/custommail.json']
+
+ def setUp(self):
+ now = timezone.now()
+
+ self.t = Tirage.objects.create(
+ title='Tirage',
+ ouverture=now - timedelta(days=7),
+ fermeture=now - timedelta(days=3),
+ active=True,
+ )
+ self.s = Spectacle.objects.create(
+ title='Spectacle',
+ date=now + timedelta(days=20),
+ location=Salle.objects.create(name='Salle', address='Address'),
+ price=10.5,
+ slots=5,
+ tirage=self.t,
+ listing=False,
+ )
+
+ self.seller = Participant.objects.create(
+ user=User.objects.create(
+ username='seller', email='seller@mail.net'),
+ tirage=self.t,
+ )
+ self.p1 = Participant.objects.create(
+ user=User.objects.create(username='part1', email='part1@mail.net'),
+ tirage=self.t,
+ )
+ self.p2 = Participant.objects.create(
+ user=User.objects.create(username='part2', email='part2@mail.net'),
+ tirage=self.t,
+ )
+ self.p3 = Participant.objects.create(
+ user=User.objects.create(username='part3', email='part3@mail.net'),
+ tirage=self.t,
+ )
+
+ self.attr = Attribution.objects.create(
+ participant=self.seller,
+ spectacle=self.s,
+ )
+
+ self.rev = SpectacleRevente.objects.create(
+ attribution=self.attr,
+ seller=self.seller,
+ )
+
+ def test_tirage(self):
+ revente = self.rev
+
+ wanted_by = [self.p1, self.p2, self.p3]
+ revente.answered_mail = wanted_by
+
+ with mock.patch('bda.models.random.choice') as mc:
+ # Set winner to self.p1.
+ mc.return_value = self.p1
+
+ revente.tirage()
+
+ # Call to random.choice used participants in wanted_by.
+ mc_args, _ = mc.call_args
+
+ self.assertEqual(set(mc_args[0]), set(wanted_by))
+
+ self.assertEqual(revente.soldTo, self.p1)
+ self.assertTrue(revente.tirage_done)
+
+ mails = {m.to[0]: m for m in mail.outbox}
+
+ self.assertEqual(len(mails), 4)
+
+ m_seller = mails['seller@mail.net']
+ self.assertListEqual(m_seller.to, ['seller@mail.net'])
+ self.assertListEqual(m_seller.reply_to, ['part1@mail.net'])
+
+ m_winner = mails['part1@mail.net']
+ self.assertListEqual(m_winner.to, ['part1@mail.net'])
+
+ self.assertCountEqual(
+ [mails['part2@mail.net'].to, mails['part3@mail.net'].to],
+ [['part2@mail.net'], ['part3@mail.net']],
+ )
diff --git a/bda/tests.py b/bda/tests/test_views.py
similarity index 98%
rename from bda/tests.py
rename to bda/tests/test_views.py
index 97a220c9..88dfd980 100644
--- a/bda/tests.py
+++ b/bda/tests/test_views.py
@@ -4,7 +4,7 @@ from django.contrib.auth.models import User
from django.test import TestCase, Client
from django.utils import timezone
-from .models import Tirage, Spectacle, Salle, CategorieSpectacle
+from bda.models import Tirage, Spectacle, Salle, CategorieSpectacle
class TestBdAViews(TestCase):
diff --git a/bda/urls.py b/bda/urls.py
index 876c84ea..6acc1746 100644
--- a/bda/urls.py
+++ b/bda/urls.py
@@ -32,6 +32,12 @@ urlpatterns = [
url(r'^spectacles/unpaid/(?P\d+)$',
views.unpaid,
name="bda-unpaid"),
+ url(r'^spectacles/autocomplete$',
+ views.spectacle_autocomplete,
+ name="bda-spectacle-autocomplete"),
+ url(r'^participants/autocomplete$',
+ views.participant_autocomplete,
+ name="bda-participant-autocomplete"),
url(r'^liste-revente/(?P\d+)$',
views.list_revente,
name="bda-liste-revente"),
diff --git a/bda/views.py b/bda/views.py
index d6da2e9f..6c4edff8 100644
--- a/bda/views.py
+++ b/bda/views.py
@@ -33,6 +33,8 @@ from bda.forms import (
InscriptionInlineFormSet,
)
+from utils.views.autocomplete import Select2QuerySetView
+
@cof_required
def etat_places(request, tirage_id):
@@ -782,9 +784,9 @@ def catalogue(request, request_type):
.select_related('location')
.prefetch_related('quote_set')
)
- if categories_id:
+ if categories_id and 0 not in categories_id:
shows_qs = shows_qs.filter(category__id__in=categories_id)
- if locations_id:
+ if locations_id and 0 not in locations_id:
shows_qs = shows_qs.filter(location__id__in=locations_id)
# On convertit les descriptions à envoyer en une liste facilement
@@ -813,3 +815,26 @@ def catalogue(request, request_type):
return JsonResponse(data_return, safe=False)
# Si la requête n'est pas de la forme attendue, on quitte avec une erreur
return HttpResponseBadRequest()
+
+
+##
+# Autocomplete views
+#
+# https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#create-an-autocomplete-view
+##
+
+
+class ParticipantAutocomplete(Select2QuerySetView):
+ model = Participant
+ search_fields = ('user__username', 'user__first_name', 'user__last_name')
+
+
+participant_autocomplete = buro_required(ParticipantAutocomplete.as_view())
+
+
+class SpectacleAutocomplete(Select2QuerySetView):
+ model = Spectacle
+ search_fields = ('title',)
+
+
+spectacle_autocomplete = buro_required(SpectacleAutocomplete.as_view())
diff --git a/cof/settings/__init__.py b/cof/settings/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/cof/settings/common.py b/cof/settings/common.py
index d1641f03..8e1dcc6f 100644
--- a/cof/settings/common.py
+++ b/cof/settings/common.py
@@ -31,6 +31,7 @@ def import_secret(name):
SECRET_KEY = import_secret("SECRET_KEY")
ADMINS = import_secret("ADMINS")
SERVER_EMAIL = import_secret("SERVER_EMAIL")
+EMAIL_HOST = import_secret("EMAIL_HOST")
DBNAME = import_secret("DBNAME")
DBUSER = import_secret("DBUSER")
@@ -45,6 +46,7 @@ RECAPTCHA_PUBLIC_KEY = import_secret("RECAPTCHA_PUBLIC_KEY")
RECAPTCHA_PRIVATE_KEY = import_secret("RECAPTCHA_PRIVATE_KEY")
KFETOPEN_TOKEN = import_secret("KFETOPEN_TOKEN")
+LDAP_SERVER_URL = import_secret("LDAP_SERVER_URL")
BASE_DIR = os.path.dirname(
@@ -55,17 +57,22 @@ BASE_DIR = os.path.dirname(
# Application definition
INSTALLED_APPS = [
'gestioncof',
+
+ # Must be before 'django.contrib.admin'.
+ # https://django-autocomplete-light.readthedocs.io/en/master/install.html
+ 'dal',
+ 'dal_select2',
+
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
- 'grappelli',
'django.contrib.admin',
'django.contrib.admindocs',
+
'bda',
- 'autocomplete_light',
'captcha',
'django_cas_ng',
'bootstrapform',
@@ -91,16 +98,17 @@ INSTALLED_APPS = [
'wagtailmenus',
'modelcluster',
'taggit',
+ 'kfet.auth',
'kfet.cms',
]
-MIDDLEWARE_CLASSES = [
+MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
- 'kfet.middleware.KFetAuthenticationMiddleware',
+ 'kfet.auth.middleware.TemporaryAuthMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
@@ -122,13 +130,13 @@ TEMPLATES = [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
- 'django.core.context_processors.i18n',
- 'django.core.context_processors.media',
- 'django.core.context_processors.static',
+ 'django.template.context_processors.i18n',
+ 'django.template.context_processors.media',
+ 'django.template.context_processors.static',
'wagtailmenus.context_processors.wagtailmenus',
'djconfig.context_processors.config',
'gestioncof.shared.context_processor',
- 'kfet.context_processors.auth',
+ 'kfet.auth.context_processors.temporary_auth',
'kfet.context_processors.config',
],
},
@@ -191,7 +199,7 @@ CAS_EMAIL_FORMAT = "%s@clipper.ens.fr"
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'gestioncof.shared.COFCASBackend',
- 'kfet.backends.GenericTeamBackend',
+ 'kfet.auth.backends.GenericBackend',
)
RECAPTCHA_USE_SSL = True
diff --git a/cof/settings/dev.py b/cof/settings/dev.py
index 9c622063..6e1f6b11 100644
--- a/cof/settings/dev.py
+++ b/cof/settings/dev.py
@@ -4,7 +4,7 @@ The settings that are not listed here are imported from .common
"""
from .common import * # NOQA
-from .common import INSTALLED_APPS, MIDDLEWARE_CLASSES
+from .common import INSTALLED_APPS, MIDDLEWARE
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
@@ -37,10 +37,11 @@ def show_toolbar(request):
return DEBUG
INSTALLED_APPS += ["debug_toolbar", "debug_panel"]
-MIDDLEWARE_CLASSES = (
- ["debug_panel.middleware.DebugPanelMiddleware"]
- + MIDDLEWARE_CLASSES
-)
+
+MIDDLEWARE = [
+ "debug_panel.middleware.DebugPanelMiddleware"
+] + MIDDLEWARE
+
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': show_toolbar,
}
diff --git a/cof/settings/secret_example.py b/cof/settings/secret_example.py
index e9c0e63c..e966565a 100644
--- a/cof/settings/secret_example.py
+++ b/cof/settings/secret_example.py
@@ -1,6 +1,7 @@
SECRET_KEY = 'q()(zn4m63i%5cp4)f+ww4-28_w+ly3q9=6imw2ciu&_(5_4ah'
ADMINS = None
SERVER_EMAIL = "root@vagrant"
+EMAIL_HOST = "localhost"
DBUSER = "cof_gestion"
DBNAME = "cof_gestion"
diff --git a/cof/urls.py b/cof/urls.py
index 1b9950f1..ac669420 100644
--- a/cof/urls.py
+++ b/cof/urls.py
@@ -4,8 +4,6 @@
Fichier principal de configuration des urls du projet GestioCOF
"""
-import autocomplete_light
-
from django.conf import settings
from django.conf.urls import include, url
from django.conf.urls.static import static
@@ -26,7 +24,6 @@ from gestioncof.urls import export_patterns, petitcours_patterns, \
clubs_patterns
from gestioncof.autocomplete import autocomplete
-autocomplete_light.autodiscover()
admin.autodiscover()
urlpatterns = [
@@ -51,18 +48,22 @@ urlpatterns = [
name="cof-denied"),
url(r'^cas/login$', django_cas_views.login, name="cas_login_view"),
url(r'^cas/logout$', django_cas_views.logout),
- url(r'^outsider/login$', gestioncof_views.login_ext),
+ url(r'^outsider/login$', gestioncof_views.login_ext,
+ name="ext_login_view"),
url(r'^outsider/logout$', django_views.logout, {'next_page': 'home'}),
url(r'^login$', gestioncof_views.login, name="cof-login"),
url(r'^logout$', gestioncof_views.logout, name="cof-logout"),
# Infos persos
- url(r'^profile$', gestioncof_views.profile),
- url(r'^outsider/password-change$', django_views.password_change),
+ url(r'^profile$', gestioncof_views.profile,
+ name='profile'),
+ 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$', gestioncof_views.registration),
+ url(r'^registration$', gestioncof_views.registration,
+ name='registration'),
url(r'^registration/clipper/(?P[\w-]+)/'
r'(?P.*)$',
gestioncof_views.registration_form2, name="clipper-registration"),
@@ -72,7 +73,8 @@ urlpatterns = [
name="empty-registration"),
# Autocompletion
url(r'^autocomplete/registration$', autocomplete),
- url(r'^autocomplete/', include('autocomplete_light.urls')),
+ url(r'^user/autocomplete$', gestioncof_views.user_autocomplete,
+ name='cof-user-autocomplete'),
# Interface admin
url(r'^admin/logout/', gestioncof_views.logout),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
@@ -80,10 +82,11 @@ urlpatterns = [
csv_views.admin_list_export,
{'fields': ['username', ]}),
url(r'^admin/', include(admin.site.urls)),
- url(r'^grappelli/', include('grappelli.urls')),
# Liens utiles du COF et du BdA
- url(r'^utile_cof$', gestioncof_views.utile_cof),
- url(r'^utile_bda$', gestioncof_views.utile_bda),
+ url(r'^utile_cof$', gestioncof_views.utile_cof,
+ name='utile_cof'),
+ url(r'^utile_bda$', gestioncof_views.utile_bda,
+ name='utile_bda'),
url(r'^utile_bda/bda_diff$', gestioncof_views.liste_bdadiff),
url(r'^utile_cof/diff_cof$', gestioncof_views.liste_diffcof),
url(r'^utile_bda/bda_revente$', gestioncof_views.liste_bdarevente),
diff --git a/gestioncof/admin.py b/gestioncof/admin.py
index 0d7d7143..51969822 100644
--- a/gestioncof/admin.py
+++ b/gestioncof/admin.py
@@ -13,7 +13,7 @@ from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.db.models import Q
-import autocomplete_light
+from dal.autocomplete import ModelSelect2
def add_link_field(target_model='', field='', link_text=str,
@@ -217,8 +217,16 @@ def user_str(self):
User.__str__ = user_str
+class EventRegistrationAdminForm(forms.ModelForm):
+ class Meta:
+ widgets = {
+ 'user': ModelSelect2(url='cof-user-autocomplete'),
+ }
+
+
class EventRegistrationAdmin(admin.ModelAdmin):
- form = autocomplete_light.modelform_factory(EventRegistration, exclude=[])
+ form = EventRegistrationAdminForm
+
list_display = ('__str__', 'event', 'user', 'paid')
list_filter = ('paid',)
search_fields = ('user__username', 'user__first_name', 'user__last_name',
diff --git a/gestioncof/autocomplete.py b/gestioncof/autocomplete.py
index 3532525d..968398fd 100644
--- a/gestioncof/autocomplete.py
+++ b/gestioncof/autocomplete.py
@@ -58,7 +58,7 @@ def autocomplete(request):
)
# Fetching data from the SPI
- if hasattr(settings, 'LDAP_SERVER_URL'):
+ if getattr(settings, 'LDAP_SERVER_URL', None):
# Fetching
ldap_query = '(&{:s})'.format(''.join(
'(|(cn=*{bit:s}*)(uid=*{bit:s}*))'.format(bit=bit)
diff --git a/gestioncof/autocomplete_light_registry.py b/gestioncof/autocomplete_light_registry.py
deleted file mode 100644
index 4c62d995..00000000
--- a/gestioncof/autocomplete_light_registry.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import autocomplete_light
-
-from django.contrib.auth.models import User
-
-autocomplete_light.register(
- User, search_fields=('username', 'first_name', 'last_name'),
- attrs={'placeholder': 'membre...'}
-)
diff --git a/gestioncof/management/data/custommail.json b/gestioncof/management/data/custommail.json
index 9ee9b1ea..590ebf18 100644
--- a/gestioncof/management/data/custommail.json
+++ b/gestioncof/management/data/custommail.json
@@ -1,587 +1,600 @@
[
{
- "model": "custommail.variabletype",
- "pk": 1,
+ "model": "custommail.type",
"fields": {
+ "kind": "model",
"content_type": [
"auth",
"user"
],
"inner1": null,
- "kind": "model",
"inner2": null
- }
+ },
+ "pk": 1
},
{
- "model": "custommail.variabletype",
- "pk": 2,
+ "model": "custommail.type",
"fields": {
+ "kind": "int",
"content_type": null,
"inner1": null,
- "kind": "int",
"inner2": null
- }
+ },
+ "pk": 2
},
{
- "model": "custommail.variabletype",
- "pk": 3,
+ "model": "custommail.type",
"fields": {
+ "kind": "model",
"content_type": [
"bda",
"spectacle"
],
"inner1": null,
- "kind": "model",
"inner2": null
- }
+ },
+ "pk": 3
},
{
- "model": "custommail.variabletype",
- "pk": 4,
+ "model": "custommail.type",
"fields": {
+ "kind": "model",
"content_type": [
"bda",
"spectaclerevente"
],
"inner1": null,
- "kind": "model",
"inner2": null
- }
+ },
+ "pk": 4
},
{
- "model": "custommail.variabletype",
- "pk": 5,
+ "model": "custommail.type",
"fields": {
+ "kind": "model",
"content_type": [
"sites",
"site"
],
"inner1": null,
- "kind": "model",
"inner2": null
- }
+ },
+ "pk": 5
},
{
- "model": "custommail.variabletype",
- "pk": 6,
+ "model": "custommail.type",
"fields": {
+ "kind": "model",
"content_type": [
"gestioncof",
"petitcoursdemande"
],
"inner1": null,
- "kind": "model",
"inner2": null
- }
+ },
+ "pk": 6
},
{
- "model": "custommail.variabletype",
- "pk": 7,
+ "model": "custommail.type",
"fields": {
- "content_type": null,
- "inner1": null,
"kind": "list",
+ "content_type": null,
+ "inner1": 12,
"inner2": null
- }
+ },
+ "pk": 7
},
{
- "model": "custommail.variabletype",
- "pk": 8,
+ "model": "custommail.type",
"fields": {
+ "kind": "list",
"content_type": null,
"inner1": 1,
- "kind": "list",
"inner2": null
- }
+ },
+ "pk": 8
},
{
- "model": "custommail.variabletype",
- "pk": 9,
+ "model": "custommail.type",
"fields": {
- "content_type": null,
- "inner1": null,
"kind": "pair",
+ "content_type": null,
+ "inner1": 12,
"inner2": 8
- }
+ },
+ "pk": 9
},
{
- "model": "custommail.variabletype",
- "pk": 10,
+ "model": "custommail.type",
"fields": {
+ "kind": "list",
"content_type": null,
"inner1": 9,
- "kind": "list",
"inner2": null
- }
+ },
+ "pk": 10
},
{
- "model": "custommail.variabletype",
- "pk": 11,
+ "model": "custommail.type",
"fields": {
+ "kind": "list",
"content_type": null,
"inner1": 3,
- "kind": "list",
"inner2": null
- }
+ },
+ "pk": 11
+},
+{
+ "model": "custommail.type",
+ "fields": {
+ "kind": "model",
+ "content_type": [
+ "gestioncof",
+ "petitcourssubject"
+ ],
+ "inner1": null,
+ "inner2": null
+ },
+ "pk": 12
},
{
"model": "custommail.custommail",
- "pk": 1,
"fields": {
"shortname": "welcome",
"subject": "Bienvenue au COF",
- "description": "Mail de bienvenue au COF envoy\u00e9 automatiquement \u00e0 l'inscription d'un nouveau membre",
- "body": "Bonjour {{ member.first_name }} et bienvenue au COF !\r\n\r\nTu trouveras plein de trucs cool sur le site du COF : https://www.cof.ens.fr/ et notre page Facebook : https://www.facebook.com/cof.ulm\r\nEt n'oublie pas d'aller d\u00e9couvrir GestioCOF, la plateforme de gestion du COF !\r\nSi tu as des questions, tu peux nous envoyer un mail \u00e0 cof@ens.fr (on aime le spam), ou passer nous voir au Bur\u00f4 pr\u00e8s de la Cour\u00f4 du lundi au vendredi de 12h \u00e0 14h et de 18h \u00e0 20h.\r\n\r\nRetrouvez les \u00e9v\u00e8nements de rentr\u00e9e pour les conscrit.e.s et les vieux/vieilles organis\u00e9s par le COF et ses clubs ici : http://www.cof.ens.fr/depot/Rentree.pdf \r\n\r\nAmicalement,\r\n\r\nTon COF qui t'aime."
- }
+ "body": "Bonjour {{ member.first_name }} et bienvenue au COF !\r\n\r\nTu trouveras plein de trucs cool sur le site du COF : https://www.cof.ens.fr/ et notre page Facebook : https://www.facebook.com/cof.ulm\r\nEt n'oublie pas d'aller d\u00e9couvrir GestioCOF, la plateforme de gestion du COF !\r\nSi tu as des questions, tu peux nous envoyer un mail \u00e0 cof@ens.fr (on aime le spam), ou passer nous voir au Bur\u00f4 pr\u00e8s de la Cour\u00f4 du lundi au vendredi de 12h \u00e0 14h et de 18h \u00e0 20h.\r\n\r\nRetrouvez les \u00e9v\u00e8nements de rentr\u00e9e pour les conscrit.e.s et les vieux/vieilles organis\u00e9s par le COF et ses clubs ici : http://www.cof.ens.fr/depot/Rentree.pdf \r\n\r\nAmicalement,\r\n\r\nTon COF qui t'aime.",
+ "description": "Mail de bienvenue au COF envoy\u00e9 automatiquement \u00e0 l'inscription d'un nouveau membre"
+ },
+ "pk": 1
},
{
"model": "custommail.custommail",
- "pk": 2,
"fields": {
"shortname": "bda-rappel",
"subject": "{{ show }}",
- "description": "Mail de rappel pour les spectacles BdA",
- "body": "Bonjour {{ member.first_name }},\r\n\r\nNous te rappellons que tu as eu la chance d'obtenir {{ nb_attr|pluralize:\"une place,deux places\" }}\r\npour {{ show.title }}, le {{ show.date }} au {{ show.location }}. N'oublie pas de t'y rendre !\r\n{% if nb_attr == 2 %}\r\nTu as obtenu deux places pour ce spectacle. Nous te rappelons que\r\nces places sont strictement r\u00e9serv\u00e9es aux personnes de moins de 28 ans.\r\n{% endif %}\r\n{% if show.listing %}Pour ce spectacle, tu as re\u00e7u des places sur\r\nlisting. Il te faudra donc te rendre 15 minutes en avance sur les lieux de la repr\u00e9sentation\r\npour retirer {{ nb_attr|pluralize:\"ta place,tes places\" }}.\r\n{% else %}Pour assister \u00e0 ce spectacle, tu dois pr\u00e9senter les billets qui ont\r\n\u00e9t\u00e9 distribu\u00e9s au bur\u00f4.\r\n{% endif %}\r\n\r\nSi tu ne peux plus assister \u00e0 cette repr\u00e9sentation, tu peux\r\nrevendre ta place via BdA-revente, accessible directement sur\r\nGestioCOF (lien \"revendre une place du premier tirage\" sur la page\r\nd'accueil https://www.cof.ens.fr/gestion/).\r\n\r\nEn te souhaitant un excellent spectacle,\r\n\r\nLe Bureau des Arts"
- }
+ "body": "Bonjour {{ member.first_name }},\r\n\r\nNous te rappellons que tu as eu la chance d'obtenir {{ nb_attr|pluralize:\"une place,deux places\" }}\r\npour {{ show.title }}, le {{ show.date }} au {{ show.location }}. N'oublie pas de t'y rendre !\r\n{% if nb_attr == 2 %}\r\nTu as obtenu deux places pour ce spectacle. Nous te rappelons que\r\nces places sont strictement r\u00e9serv\u00e9es aux personnes de moins de 28 ans.\r\n{% endif %}\r\n{% if show.listing %}Pour ce spectacle, tu as re\u00e7u des places sur\r\nlisting. Il te faudra donc te rendre 15 minutes en avance sur les lieux de la repr\u00e9sentation\r\npour retirer {{ nb_attr|pluralize:\"ta place,tes places\" }}.\r\n{% else %}Pour assister \u00e0 ce spectacle, tu dois pr\u00e9senter les billets qui ont\r\n\u00e9t\u00e9 distribu\u00e9s au bur\u00f4.\r\n{% endif %}\r\n\r\nSi tu ne peux plus assister \u00e0 cette repr\u00e9sentation, tu peux\r\nrevendre ta place via BdA-revente, accessible directement sur\r\nGestioCOF (lien \"revendre une place du premier tirage\" sur la page\r\nd'accueil https://www.cof.ens.fr/gestion/).\r\n\r\nEn te souhaitant un excellent spectacle,\r\n\r\nLe Bureau des Arts",
+ "description": "Mail de rappel pour les spectacles BdA"
+ },
+ "pk": 2
},
{
"model": "custommail.custommail",
- "pk": 3,
"fields": {
"shortname": "bda-revente",
"subject": "{{ show }}",
- "description": "Notification envoy\u00e9e \u00e0 toutes les personnes int\u00e9ress\u00e9es par un spectacle pour le signaler qu'une place vient d'\u00eatre mise en vente.",
- "body": "Bonjour {{ member.first_name }}\r\n\r\nUne place pour le spectacle {{ show.title }} ({{ show.date }})\r\na \u00e9t\u00e9 post\u00e9e sur BdA-Revente.\r\n\r\nSi ce spectacle t'int\u00e9resse toujours, merci de nous le signaler en cliquant\r\nsur ce lien : http://{{ site }}{% url \"bda-revente-interested\" revente.id %}.\r\nDans le cas o\u00f9 plusieurs personnes seraient int\u00e9ress\u00e9es, nous proc\u00e8derons \u00e0\r\nun tirage au sort le {{ revente.date_tirage|date:\"DATE_FORMAT\" }}.\r\n\r\nChaleureusement,\r\nLe BdA"
- }
+ "body": "Bonjour {{ member.first_name }}\r\n\r\nUne place pour le spectacle {{ show.title }} ({{ show.date }})\r\na \u00e9t\u00e9 post\u00e9e sur BdA-Revente.\r\n\r\nSi ce spectacle t'int\u00e9resse toujours, merci de nous le signaler en cliquant\r\nsur ce lien : http://{{ site }}{% url \"bda-revente-interested\" revente.id %}.\r\nDans le cas o\u00f9 plusieurs personnes seraient int\u00e9ress\u00e9es, nous proc\u00e8derons \u00e0\r\nun tirage au sort le {{ revente.date_tirage|date:\"DATE_FORMAT\" }}.\r\n\r\nChaleureusement,\r\nLe BdA",
+ "description": "Notification envoy\u00e9e \u00e0 toutes les personnes int\u00e9ress\u00e9es par un spectacle pour le signaler qu'une place vient d'\u00eatre mise en vente."
+ },
+ "pk": 3
},
{
"model": "custommail.custommail",
- "pk": 4,
"fields": {
"shortname": "bda-shotgun",
"subject": "{{ show }}",
- "description": "Notification signalant qu'une place est au shotgun aux personnes int\u00e9ress\u00e9es.",
- "body": "Bonjour {{ member.first_name }}\r\n\r\nUne place pour le spectacle {{ show.title }} ({{ show.date }})\r\na \u00e9t\u00e9 post\u00e9e sur BdA-Revente.\r\n\r\nPuisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour\r\ncette place : elle est disponible imm\u00e9diatement \u00e0 l'adresse\r\nhttp://{{ site }}{% url \"bda-buy-revente\" show.id %}, \u00e0 la disposition de tous.\r\n\r\nChaleureusement,\r\nLe BdA"
- }
+ "body": "Bonjour {{ member.first_name }}\r\n\r\nUne place pour le spectacle {{ show.title }} ({{ show.date }})\r\na \u00e9t\u00e9 post\u00e9e sur BdA-Revente.\r\n\r\nPuisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour\r\ncette place : elle est disponible imm\u00e9diatement \u00e0 l'adresse\r\nhttp://{{ site }}{% url \"bda-buy-revente\" show.id %}, \u00e0 la disposition de tous.\r\n\r\nChaleureusement,\r\nLe BdA",
+ "description": "Notification signalant qu'une place est au shotgun aux personnes int\u00e9ress\u00e9es."
+ },
+ "pk": 4
},
{
"model": "custommail.custommail",
- "pk": 5,
"fields": {
"shortname": "bda-revente-winner",
"subject": "BdA-Revente : {{ show.title }}",
- "description": "Mail envoy\u00e9 au gagnant d'un tirage BdA-Revente",
- "body": "Bonjour {{ acheteur.first_name }},\r\n\r\nTu as \u00e9t\u00e9 tir\u00e9-e au sort pour racheter une place pour {{ show.title }} le {{ show.date }} ({{ show.location }}) \u00e0 {{ show.price|floatformat:2 }}\u20ac.\r\nTu peux contacter le/la vendeur-se \u00e0 l'adresse {{ vendeur.email }}.\r\n\r\nChaleureusement,\r\nLe BdA"
- }
+ "body": "Bonjour {{ acheteur.first_name }},\r\n\r\nTu as \u00e9t\u00e9 tir\u00e9-e au sort pour racheter une place pour {{ show.title }} le {{ show.date }} ({{ show.location }}) \u00e0 {{ show.price|floatformat:2 }}\u20ac.\r\nTu peux contacter le/la vendeur-se \u00e0 l'adresse {{ vendeur.email }}.\r\n\r\nChaleureusement,\r\nLe BdA",
+ "description": "Mail envoy\u00e9 au gagnant d'un tirage BdA-Revente"
+ },
+ "pk": 5
},
{
"model": "custommail.custommail",
- "pk": 6,
"fields": {
"shortname": "bda-revente-loser",
"subject": "BdA-Revente : {{ show.title }}",
- "description": "Notification envoy\u00e9e aux perdants d'un tirage de revente.",
- "body": "Bonjour {{ acheteur.first_name }},\r\n\r\nTu t'\u00e9tais inscrit-e pour la revente de la place de {{ vendeur.get_full_name }}\r\npour {{ show.title }}.\r\nMalheureusement, une autre personne a \u00e9t\u00e9 tir\u00e9e au sort pour racheter la place.\r\nTu pourras certainement retenter ta chance pour une autre revente !\r\n\r\n\u00c0 tr\u00e8s bient\u00f4t,\r\nLe Bureau des Arts"
- }
+ "body": "Bonjour {{ acheteur.first_name }},\r\n\r\nTu t'\u00e9tais inscrit-e pour la revente de la place de {{ vendeur.get_full_name }}\r\npour {{ show.title }}.\r\nMalheureusement, une autre personne a \u00e9t\u00e9 tir\u00e9e au sort pour racheter la place.\r\nTu pourras certainement retenter ta chance pour une autre revente !\r\n\r\n\u00c0 tr\u00e8s bient\u00f4t,\r\nLe Bureau des Arts",
+ "description": "Notification envoy\u00e9e aux perdants d'un tirage de revente."
+ },
+ "pk": 6
},
{
"model": "custommail.custommail",
- "pk": 7,
"fields": {
"shortname": "bda-revente-seller",
"subject": "BdA-Revente : {{ show.title }}",
- "description": "Notification envoy\u00e9e au vendeur d'une place pour lui indiquer qu'elle vient d'\u00eatre attribu\u00e9e",
- "body": "Bonjour {{ vendeur.first_name }},\r\n\r\nLa personne tir\u00e9e au sort pour racheter ta place pour {{ show.title }} est {{ acheteur.get_full_name }}.\r\nTu peux le/la contacter \u00e0 l'adresse {{ acheteur.email }}, ou en r\u00e9pondant \u00e0 ce mail.\r\n\r\nChaleureusement,\r\nLe BdA"
- }
+ "body": "Bonjour {{ vendeur.first_name }},\r\n\r\nLa personne tir\u00e9e au sort pour racheter ta place pour {{ show.title }} est {{ acheteur.get_full_name }}.\r\nTu peux le/la contacter \u00e0 l'adresse {{ acheteur.email }}, ou en r\u00e9pondant \u00e0 ce mail.\r\n\r\nChaleureusement,\r\nLe BdA",
+ "description": "Notification envoy\u00e9e au vendeur d'une place pour lui indiquer qu'elle vient d'\u00eatre attribu\u00e9e"
+ },
+ "pk": 7
},
{
"model": "custommail.custommail",
- "pk": 8,
"fields": {
"shortname": "bda-revente-new",
"subject": "BdA-Revente : {{ show.title }}",
- "description": "Notification signalant au vendeur d'une place que sa mise en vente a bien eu lieu et lui donnant quelques informations compl\u00e9mentaires.",
- "body": "Bonjour {{ vendeur.first_name }},\r\n\r\nTu t\u2019es bien inscrit-e pour la revente de {{ show.title }}.\r\n\r\n{% with revente.date_tirage as time %}\r\nLe tirage au sort entre tout-e-s les racheteuse-eur-s potentiel-le-s aura lieu\r\nle {{ time|date:\"DATE_FORMAT\" }} \u00e0 {{ time|time:\"TIME_FORMAT\" }} (dans {{time|timeuntil }}).\r\nSi personne ne s\u2019est inscrit pour racheter la place, celle-ci apparaitra parmi\r\nles \u00ab Places disponibles imm\u00e9diatement \u00e0 la revente \u00bb sur GestioCOF.\r\n{% endwith %}\r\n\r\nBonne revente !\r\nLe Bureau des Arts"
- }
+ "body": "Bonjour {{ vendeur.first_name }},\r\n\r\nTu t\u2019es bien inscrit-e pour la revente de {{ show.title }}.\r\n\r\n{% with revente.date_tirage as time %}\r\nLe tirage au sort entre tout-e-s les racheteuse-eur-s potentiel-le-s aura lieu\r\nle {{ time|date:\"DATE_FORMAT\" }} \u00e0 {{ time|time:\"TIME_FORMAT\" }} (dans {{time|timeuntil }}).\r\nSi personne ne s\u2019est inscrit pour racheter la place, celle-ci apparaitra parmi\r\nles \u00ab Places disponibles imm\u00e9diatement \u00e0 la revente \u00bb sur GestioCOF.\r\n{% endwith %}\r\n\r\nBonne revente !\r\nLe Bureau des Arts",
+ "description": "Notification signalant au vendeur d'une place que sa mise en vente a bien eu lieu et lui donnant quelques informations compl\u00e9mentaires."
+ },
+ "pk": 8
},
{
"model": "custommail.custommail",
- "pk": 9,
"fields": {
"shortname": "bda-buy-shotgun",
"subject": "BdA-Revente : {{ show.title }}",
- "description": "Mail envoy\u00e9 au revendeur lors d'un achat au shotgun.",
- "body": "Bonjour {{ vendeur.first_name }} !\r\n\r\nJe souhaiterais racheter ta place pour {{ show.title }} le {{ show.date }} ({{ show.location }}) \u00e0 {{ show.price|floatformat:2 }}\u20ac.\r\nContacte-moi si tu es toujours int\u00e9ress\u00e9\u00b7e !\r\n\r\n{{ acheteur.get_full_name }} ({{ acheteur.email }})"
- }
+ "body": "Bonjour {{ vendeur.first_name }} !\r\n\r\nJe souhaiterais racheter ta place pour {{ show.title }} le {{ show.date }} ({{ show.location }}) \u00e0 {{ show.price|floatformat:2 }}\u20ac.\r\nContacte-moi si tu es toujours int\u00e9ress\u00e9\u00b7e !\r\n\r\n{{ acheteur.get_full_name }} ({{ acheteur.email }})",
+ "description": "Mail envoy\u00e9 au revendeur lors d'un achat au shotgun."
+ },
+ "pk": 9
},
{
"model": "custommail.custommail",
- "pk": 10,
"fields": {
"shortname": "petit-cours-mail-eleve",
"subject": "Petits cours ENS par le COF",
- "description": "Mail envoy\u00e9 aux personnes dont ont a donn\u00e9 les contacts \u00e0 des demandeurs de petits cours",
- "body": "Salut,\r\n\r\nLe COF a re\u00e7u une demande de petit cours qui te correspond. Tu es en haut de la liste d'attente donc on a transmis tes coordonn\u00e9es, ainsi que celles de 2 autres qui correspondaient aussi (c'est la vie, on donne les num\u00e9ros 3 par 3 pour que ce soit plus souple). Voici quelques infos sur l'annonce en question :\r\n\r\n\u00a4 Nom : {{ demande.name }}\r\n\r\n\u00a4 P\u00e9riode : {{ demande.quand }}\r\n\r\n\u00a4 Fr\u00e9quence : {{ demande.freq }}\r\n\r\n\u00a4 Lieu (si pr\u00e9f\u00e9r\u00e9) : {{ demande.lieu }}\r\n\r\n\u00a4 Niveau : {{ demande.get_niveau_display }}\r\n\r\n\u00a4 Remarques diverses (d\u00e9sol\u00e9 pour les balises HTML) : {{ demande.remarques }}\r\n\r\n{% if matieres|length > 1 %}\u00a4 Mati\u00e8res :\r\n{% for matiere in matieres %} \u00a4 {{ matiere }}\r\n{% endfor %}{% else %}\u00a4 Mati\u00e8re : {% for matiere in matieres %}{{ matiere }}\r\n{% endfor %}{% endif %}\r\nVoil\u00e0, cette personne te contactera peut-\u00eatre sous peu, tu pourras voir les d\u00e9tails directement avec elle (prix, modalit\u00e9s, ...). Pour indication, 30 Euro/h semble \u00eatre la moyenne.\r\n\r\nSi tu te rends compte qu'en fait tu ne peux pas/plus donner de cours en ce moment, \u00e7a serait cool que tu d\u00e9coches la case \"Recevoir des propositions de petits cours\" sur GestioCOF. Ensuite d\u00e8s que tu voudras r\u00e9appara\u00eetre tu pourras recocher la case et tu seras \u00e0 nouveau sur la liste.\r\n\r\n\u00c0 bient\u00f4t,\r\n\r\n--\r\nLe COF, pour les petits cours"
- }
+ "body": "Salut,\r\n\r\nLe COF a re\u00e7u une demande de petit cours qui te correspond. Tu es en haut de la liste d'attente donc on a transmis tes coordonn\u00e9es, ainsi que celles de 2 autres qui correspondaient aussi (c'est la vie, on donne les num\u00e9ros 3 par 3 pour que ce soit plus souple). Voici quelques infos sur l'annonce en question :\r\n\r\n\u00a4 Nom : {{ demande.name }}\r\n\r\n\u00a4 P\u00e9riode : {{ demande.quand }}\r\n\r\n\u00a4 Fr\u00e9quence : {{ demande.freq }}\r\n\r\n\u00a4 Lieu (si pr\u00e9f\u00e9r\u00e9) : {{ demande.lieu }}\r\n\r\n\u00a4 Niveau : {{ demande.get_niveau_display }}\r\n\r\n\u00a4 Remarques diverses (d\u00e9sol\u00e9 pour les balises HTML) : {{ demande.remarques }}\r\n\r\n{% if matieres|length > 1 %}\u00a4 Mati\u00e8res :\r\n{% for matiere in matieres %} \u00a4 {{ matiere }}\r\n{% endfor %}{% else %}\u00a4 Mati\u00e8re : {% for matiere in matieres %}{{ matiere }}\r\n{% endfor %}{% endif %}\r\nVoil\u00e0, cette personne te contactera peut-\u00eatre sous peu, tu pourras voir les d\u00e9tails directement avec elle (prix, modalit\u00e9s, ...). Pour indication, 30 Euro/h semble \u00eatre la moyenne.\r\n\r\nSi tu te rends compte qu'en fait tu ne peux pas/plus donner de cours en ce moment, \u00e7a serait cool que tu d\u00e9coches la case \"Recevoir des propositions de petits cours\" sur GestioCOF. Ensuite d\u00e8s que tu voudras r\u00e9appara\u00eetre tu pourras recocher la case et tu seras \u00e0 nouveau sur la liste.\r\n\r\n\u00c0 bient\u00f4t,\r\n\r\n--\r\nLe COF, pour les petits cours",
+ "description": "Mail envoy\u00e9 aux personnes dont ont a donn\u00e9 les contacts \u00e0 des demandeurs de petits cours"
+ },
+ "pk": 10
},
{
"model": "custommail.custommail",
- "pk": 11,
"fields": {
"shortname": "petits-cours-mail-demandeur",
"subject": "Cours particuliers ENS",
- "description": "Mail envoy\u00e9 aux personnent qui demandent des petits cours lorsque leur demande est trait\u00e9e.\r\n\r\n(Ne pas toucher \u00e0 {{ extra|safe }})",
- "body": "Bonjour,\r\n\r\nJe vous contacte au sujet de votre annonce pass\u00e9e sur le site du COF pour rentrer en contact avec un \u00e9l\u00e8ve normalien pour des cours particuliers. Voici les coordonn\u00e9es d'\u00e9l\u00e8ves qui sont motiv\u00e9s par de tels cours et correspondent aux crit\u00e8res que vous nous aviez transmis :\r\n\r\n{% for matiere, proposed in proposals %}\u00a4 {{ matiere }} :{% for user in proposed %}\r\n \u00a4 {{ user.get_full_name }}{% if user.profile.phone %}, {{ user.profile.phone }}{% endif %}{% if user.email %}, {{ user.email }}{% endif %}{% endfor %}\r\n\r\n{% endfor %}{% if unsatisfied %}Nous n'avons cependant pas pu trouver d'\u00e9l\u00e8ve disponible pour des cours de {% for matiere in unsatisfied %}{% if forloop.counter0 > 0 %}, {% endif %}{{ matiere }}{% endfor %}.\r\n\r\n{% endif %}Si pour une raison ou une autre ces num\u00e9ros ne suffisaient pas, n'h\u00e9sitez pas \u00e0 r\u00e9pondre \u00e0 cet e-mail et je vous en ferai parvenir d'autres sans probl\u00e8me.\r\n{% if extra|length > 0 %}\r\n{{ extra|safe }}\r\n{% endif %}\r\nCordialement,\r\n\r\n--\r\nLe COF, BdE de l'ENS"
- }
+ "body": "Bonjour,\r\n\r\nJe vous contacte au sujet de votre annonce pass\u00e9e sur le site du COF pour rentrer en contact avec un \u00e9l\u00e8ve normalien pour des cours particuliers. Voici les coordonn\u00e9es d'\u00e9l\u00e8ves qui sont motiv\u00e9s par de tels cours et correspondent aux crit\u00e8res que vous nous aviez transmis :\r\n\r\n{% for matiere, proposed in proposals %}\u00a4 {{ matiere }} :{% for user in proposed %}\r\n \u00a4 {{ user.get_full_name }}{% if user.profile.phone %}, {{ user.profile.phone }}{% endif %}{% if user.email %}, {{ user.email }}{% endif %}{% endfor %}\r\n\r\n{% endfor %}{% if unsatisfied %}Nous n'avons cependant pas pu trouver d'\u00e9l\u00e8ve disponible pour des cours de {% for matiere in unsatisfied %}{% if forloop.counter0 > 0 %}, {% endif %}{{ matiere }}{% endfor %}.\r\n\r\n{% endif %}Si pour une raison ou une autre ces num\u00e9ros ne suffisaient pas, n'h\u00e9sitez pas \u00e0 r\u00e9pondre \u00e0 cet e-mail et je vous en ferai parvenir d'autres sans probl\u00e8me.\r\n{% if extra|length > 0 %}\r\n{{ extra|safe }}\r\n{% endif %}\r\nCordialement,\r\n\r\n--\r\nLe COF, BdE de l'ENS",
+ "description": "Mail envoy\u00e9 aux personnes qui demandent des petits cours lorsque leur demande est trait\u00e9e.\r\n\r\n(Ne pas toucher \u00e0 {{ extra|safe }})"
+ },
+ "pk": 11
},
{
"model": "custommail.custommail",
- "pk": 12,
"fields": {
"shortname": "bda-attributions",
"subject": "R\u00e9sultats du tirage au sort",
- "description": "Mail annon\u00e7ant les r\u00e9sultats du tirage au sort du BdA aux gagnants d'une ou plusieurs places",
- "body": "Cher-e {{ member.first_name }},\r\n\r\nTu t'es inscrit-e pour le tirage au sort du BdA. Tu as \u00e9t\u00e9 s\u00e9lectionn\u00e9-e\r\npour les spectacles suivants :\r\n{% for place in places %}\r\n- 1 place pour {{ place }}{% endfor %}\r\n\r\n*Paiement*\r\nL'int\u00e9gralit\u00e9 de ces places de spectacles est \u00e0 r\u00e9gler d\u00e8s maintenant et AVANT\r\nvendredi prochain, au bureau du COF pendant les heures de permanences (du lundi au vendredi\r\nentre 12h et 14h, et entre 18h et 20h). Des facilit\u00e9s de paiement sont bien\r\n\u00e9videmment possibles : nous pouvons ne pas encaisser le ch\u00e8que imm\u00e9diatement,\r\nou bien d\u00e9couper votre paiement en deux fois. Pour ceux qui ne pourraient pas\r\nvenir payer au bureau, merci de nous contacter par mail.\r\n\r\n*Mode de retrait des places*\r\nAu moment du paiement, certaines places vous seront remises directement,\r\nd'autres seront \u00e0 r\u00e9cup\u00e9rer au cours de l'ann\u00e9e, d'autres encore seront\r\nnominatives et \u00e0 retirer le soir m\u00eame dans les the\u00e2tres correspondants.\r\nPour chaque spectacle, vous recevrez un mail quelques jours avant la\r\nrepr\u00e9sentation vous indiquant le mode de retrait.\r\n\r\nNous vous rappelons que l'obtention de places du BdA vous engage \u00e0\r\nrespecter les r\u00e8gles de fonctionnement :\r\nhttp://www.cof.ens.fr/bda/?page_id=1370\r\nUn syst\u00e8me de revente des places via les mails BdA-revente disponible\r\ndirectement sur votre compte GestioCOF.\r\n\r\nEn vous souhaitant de tr\u00e8s beaux spectacles tout au long de l'ann\u00e9e,\r\n--\r\nLe Bureau des Arts"
- }
+ "body": "Cher-e {{ member.first_name }},\r\n\r\nTu t'es inscrit-e pour le tirage au sort du BdA. Tu as \u00e9t\u00e9 s\u00e9lectionn\u00e9-e\r\npour les spectacles suivants :\r\n{% for place in places %}\r\n- 1 place pour {{ place }}{% endfor %}\r\n\r\n*Paiement*\r\nL'int\u00e9gralit\u00e9 de ces places de spectacles est \u00e0 r\u00e9gler d\u00e8s maintenant et AVANT\r\nvendredi prochain, au bureau du COF pendant les heures de permanences (du lundi au vendredi\r\nentre 12h et 14h, et entre 18h et 20h). Des facilit\u00e9s de paiement sont bien\r\n\u00e9videmment possibles : nous pouvons ne pas encaisser le ch\u00e8que imm\u00e9diatement,\r\nou bien d\u00e9couper votre paiement en deux fois. Pour ceux qui ne pourraient pas\r\nvenir payer au bureau, merci de nous contacter par mail.\r\n\r\n*Mode de retrait des places*\r\nAu moment du paiement, certaines places vous seront remises directement,\r\nd'autres seront \u00e0 r\u00e9cup\u00e9rer au cours de l'ann\u00e9e, d'autres encore seront\r\nnominatives et \u00e0 retirer le soir m\u00eame dans les the\u00e2tres correspondants.\r\nPour chaque spectacle, vous recevrez un mail quelques jours avant la\r\nrepr\u00e9sentation vous indiquant le mode de retrait.\r\n\r\nNous vous rappelons que l'obtention de places du BdA vous engage \u00e0\r\nrespecter les r\u00e8gles de fonctionnement :\r\nhttp://www.cof.ens.fr/bda/?page_id=1370\r\nUn syst\u00e8me de revente des places via les mails BdA-revente disponible\r\ndirectement sur votre compte GestioCOF.\r\n\r\nEn vous souhaitant de tr\u00e8s beaux spectacles tout au long de l'ann\u00e9e,\r\n--\r\nLe Bureau des Arts",
+ "description": "Mail annon\u00e7ant les r\u00e9sultats du tirage au sort du BdA aux gagnants d'une ou plusieurs places"
+ },
+ "pk": 12
},
{
"model": "custommail.custommail",
- "pk": 13,
"fields": {
"shortname": "bda-attributions-decus",
"subject": "R\u00e9sultats du tirage au sort",
- "description": "Mail annon\u00e7ant les r\u00e9sultats du tirage au sort du BdA aux personnes n'ayant pas obtenu de place",
- "body": "Cher-e {{ member.first_name }},\r\n\r\nTu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as\r\nobtenu aucune place.\r\n\r\nNous proposons cependant de nombreuses offres hors-tirage tout au long de\r\nl'ann\u00e9e, et nous t'invitons \u00e0 nous contacter si l'une d'entre elles\r\nt'int\u00e9resse !\r\n--\r\nLe Bureau des Arts"
- }
+ "body": "Cher-e {{ member.first_name }},\r\n\r\nTu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as\r\nobtenu aucune place.\r\n\r\nNous proposons cependant de nombreuses offres hors-tirage tout au long de\r\nl'ann\u00e9e, et nous t'invitons \u00e0 nous contacter si l'une d'entre elles\r\nt'int\u00e9resse !\r\n--\r\nLe Bureau des Arts",
+ "description": "Mail annon\u00e7ant les r\u00e9sultats du tirage au sort du BdA aux personnes n'ayant pas obtenu de place"
+ },
+ "pk": 13
},
{
- "model": "custommail.custommailvariable",
- "pk": 1,
+ "model": "custommail.variable",
"fields": {
- "name": "member",
- "description": "Utilisateur de GestioCOF",
"custommail": 1,
- "type": 1
- }
-},
-{
- "model": "custommail.custommailvariable",
- "pk": 2,
- "fields": {
+ "type": 1,
"name": "member",
- "description": "Utilisateur ayant eu une place pour ce spectacle",
- "custommail": 2,
- "type": 1
- }
+ "description": "Utilisateur de GestioCOF"
+ },
+ "pk": 1
},
{
- "model": "custommail.custommailvariable",
- "pk": 3,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 2,
+ "type": 1,
+ "name": "member",
+ "description": "Utilisateur ayant eu une place pour ce spectacle"
+ },
+ "pk": 2
+},
+{
+ "model": "custommail.variable",
+ "fields": {
+ "custommail": 2,
+ "type": 3,
"name": "show",
- "description": "Spectacle",
- "custommail": 2,
- "type": 3
- }
+ "description": "Spectacle"
+ },
+ "pk": 3
},
{
- "model": "custommail.custommailvariable",
- "pk": 4,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 2,
+ "type": 2,
"name": "nb_attr",
- "description": "Nombre de places obtenues",
- "custommail": 2,
- "type": 2
- }
+ "description": "Nombre de places obtenues"
+ },
+ "pk": 4
},
{
- "model": "custommail.custommailvariable",
- "pk": 5,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 3,
+ "type": 4,
"name": "revente",
- "description": "Revente mentionn\u00e9e dans le mail",
- "custommail": 3,
- "type": 4
- }
+ "description": "Revente mentionn\u00e9e dans le mail"
+ },
+ "pk": 5
},
{
- "model": "custommail.custommailvariable",
- "pk": 6,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 3,
+ "type": 1,
"name": "member",
- "description": "Personne int\u00e9ress\u00e9e par la place",
- "custommail": 3,
- "type": 1
- }
+ "description": "Personne int\u00e9ress\u00e9e par la place"
+ },
+ "pk": 6
},
{
- "model": "custommail.custommailvariable",
- "pk": 7,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 3,
+ "type": 3,
"name": "show",
- "description": "Spectacle",
- "custommail": 3,
- "type": 3
- }
+ "description": "Spectacle"
+ },
+ "pk": 7
},
{
- "model": "custommail.custommailvariable",
- "pk": 8,
+ "model": "custommail.variable",
"fields": {
- "name": "site",
- "description": "Site web (gestioCOF)",
"custommail": 3,
- "type": 5
- }
+ "type": 5,
+ "name": "site",
+ "description": "Site web (gestioCOF)"
+ },
+ "pk": 8
},
{
- "model": "custommail.custommailvariable",
- "pk": 9,
+ "model": "custommail.variable",
"fields": {
- "name": "site",
- "description": "Site web (gestioCOF)",
"custommail": 4,
- "type": 5
- }
+ "type": 5,
+ "name": "site",
+ "description": "Site web (gestioCOF)"
+ },
+ "pk": 9
},
{
- "model": "custommail.custommailvariable",
- "pk": 10,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 4,
+ "type": 3,
"name": "show",
- "description": "Spectacle",
- "custommail": 4,
- "type": 3
- }
+ "description": "Spectacle"
+ },
+ "pk": 10
},
{
- "model": "custommail.custommailvariable",
- "pk": 11,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 4,
+ "type": 1,
"name": "member",
- "description": "Personne int\u00e9ress\u00e9e par la place",
- "custommail": 4,
- "type": 1
- }
+ "description": "Personne int\u00e9ress\u00e9e par la place"
+ },
+ "pk": 11
},
{
- "model": "custommail.custommailvariable",
- "pk": 12,
+ "model": "custommail.variable",
"fields": {
- "name": "acheteur",
- "description": "Gagnant-e du tirage",
"custommail": 5,
- "type": 1
- }
-},
-{
- "model": "custommail.custommailvariable",
- "pk": 13,
- "fields": {
- "name": "vendeur",
- "description": "Personne qui vend une place",
- "custommail": 5,
- "type": 1
- }
-},
-{
- "model": "custommail.custommailvariable",
- "pk": 14,
- "fields": {
- "name": "show",
- "description": "Spectacle",
- "custommail": 5,
- "type": 3
- }
-},
-{
- "model": "custommail.custommailvariable",
- "pk": 15,
- "fields": {
- "name": "show",
- "description": "Spectacle",
- "custommail": 6,
- "type": 3
- }
-},
-{
- "model": "custommail.custommailvariable",
- "pk": 16,
- "fields": {
- "name": "vendeur",
- "description": "Personne qui vend une place",
- "custommail": 6,
- "type": 1
- }
-},
-{
- "model": "custommail.custommailvariable",
- "pk": 17,
- "fields": {
+ "type": 1,
"name": "acheteur",
- "description": "Personne inscrite au tirage qui n'a pas eu la place",
- "custommail": 6,
- "type": 1
- }
+ "description": "Gagnant-e du tirage"
+ },
+ "pk": 12
},
{
- "model": "custommail.custommailvariable",
- "pk": 18,
- "fields": {
- "name": "acheteur",
- "description": "Gagnant-e du tirage",
- "custommail": 7,
- "type": 1
- }
-},
-{
- "model": "custommail.custommailvariable",
- "pk": 19,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 5,
+ "type": 1,
"name": "vendeur",
- "description": "Personne qui vend une place",
- "custommail": 7,
- "type": 1
- }
+ "description": "Personne qui vend une place"
+ },
+ "pk": 13
},
{
- "model": "custommail.custommailvariable",
- "pk": 20,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 5,
+ "type": 3,
"name": "show",
- "description": "Spectacle",
- "custommail": 7,
- "type": 3
- }
+ "description": "Spectacle"
+ },
+ "pk": 14
},
{
- "model": "custommail.custommailvariable",
- "pk": 21,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 6,
+ "type": 3,
"name": "show",
- "description": "Spectacle",
+ "description": "Spectacle"
+ },
+ "pk": 15
+},
+{
+ "model": "custommail.variable",
+ "fields": {
+ "custommail": 6,
+ "type": 1,
+ "name": "vendeur",
+ "description": "Personne qui vend une place"
+ },
+ "pk": 16
+},
+{
+ "model": "custommail.variable",
+ "fields": {
+ "custommail": 6,
+ "type": 1,
+ "name": "acheteur",
+ "description": "Personne inscrite au tirage qui n'a pas eu la place"
+ },
+ "pk": 17
+},
+{
+ "model": "custommail.variable",
+ "fields": {
+ "custommail": 7,
+ "type": 1,
+ "name": "acheteur",
+ "description": "Gagnant-e du tirage"
+ },
+ "pk": 18
+},
+{
+ "model": "custommail.variable",
+ "fields": {
+ "custommail": 7,
+ "type": 1,
+ "name": "vendeur",
+ "description": "Personne qui vend une place"
+ },
+ "pk": 19
+},
+{
+ "model": "custommail.variable",
+ "fields": {
+ "custommail": 7,
+ "type": 3,
+ "name": "show",
+ "description": "Spectacle"
+ },
+ "pk": 20
+},
+{
+ "model": "custommail.variable",
+ "fields": {
"custommail": 8,
- "type": 3
- }
+ "type": 3,
+ "name": "show",
+ "description": "Spectacle"
+ },
+ "pk": 21
},
{
- "model": "custommail.custommailvariable",
- "pk": 22,
+ "model": "custommail.variable",
"fields": {
- "name": "vendeur",
- "description": "Personne qui vend la place",
"custommail": 8,
- "type": 1
- }
+ "type": 1,
+ "name": "vendeur",
+ "description": "Personne qui vend la place"
+ },
+ "pk": 22
},
{
- "model": "custommail.custommailvariable",
- "pk": 23,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 8,
+ "type": 4,
"name": "revente",
- "description": "Revente mentionn\u00e9e dans le mail",
- "custommail": 8,
- "type": 4
- }
+ "description": "Revente mentionn\u00e9e dans le mail"
+ },
+ "pk": 23
},
{
- "model": "custommail.custommailvariable",
- "pk": 24,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 9,
+ "type": 1,
"name": "vendeur",
- "description": "Personne qui vend la place",
- "custommail": 9,
- "type": 1
- }
+ "description": "Personne qui vend la place"
+ },
+ "pk": 24
},
{
- "model": "custommail.custommailvariable",
- "pk": 25,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 9,
+ "type": 3,
"name": "show",
- "description": "Spectacle",
- "custommail": 9,
- "type": 3
- }
+ "description": "Spectacle"
+ },
+ "pk": 25
},
{
- "model": "custommail.custommailvariable",
- "pk": 26,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 9,
+ "type": 1,
"name": "acheteur",
- "description": "Personne qui prend la place au shotgun",
- "custommail": 9,
- "type": 1
- }
+ "description": "Personne qui prend la place au shotgun"
+ },
+ "pk": 26
},
{
- "model": "custommail.custommailvariable",
- "pk": 27,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 10,
+ "type": 6,
"name": "demande",
- "description": "Demande de petit cours",
- "custommail": 10,
- "type": 6
- }
+ "description": "Demande de petit cours"
+ },
+ "pk": 27
},
{
- "model": "custommail.custommailvariable",
- "pk": 28,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 10,
+ "type": 7,
"name": "matieres",
- "description": "Liste des mati\u00e8res concern\u00e9es par la demande",
- "custommail": 10,
- "type": 7
- }
+ "description": "Liste des mati\u00e8res concern\u00e9es par la demande"
+ },
+ "pk": 28
},
{
- "model": "custommail.custommailvariable",
- "pk": 29,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 11,
+ "type": 10,
"name": "proposals",
- "description": "Liste associant une liste d'enseignants \u00e0 chaque mati\u00e8re",
- "custommail": 11,
- "type": 10
- }
+ "description": "Liste associant une liste d'enseignants \u00e0 chaque mati\u00e8re"
+ },
+ "pk": 29
},
{
- "model": "custommail.custommailvariable",
- "pk": 30,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 11,
+ "type": 7,
"name": "unsatisfied",
- "description": "Liste des mati\u00e8res pour lesquelles on n'a pas d'enseigant \u00e0 proposer",
- "custommail": 11,
- "type": 7
- }
+ "description": "Liste des mati\u00e8res pour lesquelles on n'a pas d'enseigant \u00e0 proposer"
+ },
+ "pk": 30
},
{
- "model": "custommail.custommailvariable",
- "pk": 31,
+ "model": "custommail.variable",
"fields": {
+ "custommail": 12,
+ "type": 11,
"name": "places",
- "description": "Places de spectacle du participant",
- "custommail": 12,
- "type": 11
- }
+ "description": "Places de spectacle du participant"
+ },
+ "pk": 31
},
{
- "model": "custommail.custommailvariable",
- "pk": 32,
+ "model": "custommail.variable",
"fields": {
- "name": "member",
- "description": "Participant du tirage au sort",
"custommail": 12,
- "type": 1
- }
+ "type": 1,
+ "name": "member",
+ "description": "Participant du tirage au sort"
+ },
+ "pk": 32
},
{
- "model": "custommail.custommailvariable",
- "pk": 33,
+ "model": "custommail.variable",
"fields": {
- "name": "member",
- "description": "Participant du tirage au sort",
"custommail": 13,
- "type": 1
- }
+ "type": 1,
+ "name": "member",
+ "description": "Participant du tirage au sort"
+ },
+ "pk": 33
}
]
diff --git a/gestioncof/migrations/0001_initial.py b/gestioncof/migrations/0001_initial.py
index b942645d..c6bb6151 100644
--- a/gestioncof/migrations/0001_initial.py
+++ b/gestioncof/migrations/0001_initial.py
@@ -48,7 +48,7 @@ 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', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
options={
'verbose_name': 'Profil COF',
@@ -91,7 +91,7 @@ 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='gestioncof.Event')),
+ ('event', models.ForeignKey(related_name='commentfields', to='gestioncof.Event', on_delete=models.CASCADE)),
],
options={
'verbose_name': 'Champ',
@@ -102,7 +102,7 @@ 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='gestioncof.EventCommentField')),
+ ('commentfield', models.ForeignKey(related_name='values', to='gestioncof.EventCommentField', on_delete=models.CASCADE)),
],
),
migrations.CreateModel(
@@ -111,7 +111,7 @@ 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='gestioncof.Event')),
+ ('event', models.ForeignKey(related_name='options', to='gestioncof.Event', on_delete=models.CASCADE)),
],
options={
'verbose_name': 'Option',
@@ -122,7 +122,7 @@ 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='gestioncof.EventOption')),
+ ('event_option', models.ForeignKey(related_name='choices', to='gestioncof.EventOption', on_delete=models.CASCADE)),
],
options={
'verbose_name': 'Choix',
@@ -133,10 +133,10 @@ 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='gestioncof.Event')),
+ ('event', models.ForeignKey(to='gestioncof.Event', on_delete=models.CASCADE)),
('filledcomments', models.ManyToManyField(to='gestioncof.EventCommentField', through='gestioncof.EventCommentValue')),
('options', models.ManyToManyField(to='gestioncof.EventOptionChoice')),
- ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
+ ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
options={
'verbose_name': 'Inscription',
@@ -240,7 +240,7 @@ 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='gestioncof.Survey')),
+ ('survey', models.ForeignKey(related_name='questions', to='gestioncof.Survey', on_delete=models.CASCADE)),
],
options={
'verbose_name': 'Question',
@@ -251,7 +251,7 @@ 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='gestioncof.SurveyQuestion')),
+ ('survey_question', models.ForeignKey(related_name='answers', to='gestioncof.SurveyQuestion', on_delete=models.CASCADE)),
],
options={
'verbose_name': 'R\xe9ponse',
@@ -265,12 +265,12 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='surveyanswer',
name='survey',
- field=models.ForeignKey(to='gestioncof.Survey'),
+ field=models.ForeignKey(to='gestioncof.Survey', on_delete=models.CASCADE),
),
migrations.AddField(
model_name='surveyanswer',
name='user',
- field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
+ field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='petitcoursdemande',
@@ -280,47 +280,47 @@ 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(blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='petitcoursattributioncounter',
name='matiere',
- field=models.ForeignKey(verbose_name='Matiere', to='gestioncof.PetitCoursSubject'),
+ field=models.ForeignKey(verbose_name='Matiere', to='gestioncof.PetitCoursSubject', on_delete=models.CASCADE),
),
migrations.AddField(
model_name='petitcoursattributioncounter',
name='user',
- field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
+ field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='petitcoursattribution',
name='demande',
- field=models.ForeignKey(verbose_name='Demande', to='gestioncof.PetitCoursDemande'),
+ field=models.ForeignKey(verbose_name='Demande', to='gestioncof.PetitCoursDemande', on_delete=models.CASCADE),
),
migrations.AddField(
model_name='petitcoursattribution',
name='matiere',
- field=models.ForeignKey(verbose_name='Mati\xe8re', to='gestioncof.PetitCoursSubject'),
+ field=models.ForeignKey(verbose_name='Mati\xe8re', to='gestioncof.PetitCoursSubject', on_delete=models.CASCADE),
),
migrations.AddField(
model_name='petitcoursattribution',
name='user',
- field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
+ field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='petitcoursability',
name='matiere',
- field=models.ForeignKey(verbose_name='Mati\xe8re', to='gestioncof.PetitCoursSubject'),
+ field=models.ForeignKey(verbose_name='Mati\xe8re', to='gestioncof.PetitCoursSubject', on_delete=models.CASCADE),
),
migrations.AddField(
model_name='petitcoursability',
name='user',
- field=models.ForeignKey(to=settings.AUTH_USER_MODEL),
+ field=models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='eventcommentvalue',
name='registration',
- field=models.ForeignKey(related_name='comments', to='gestioncof.EventRegistration'),
+ field=models.ForeignKey(related_name='comments', to='gestioncof.EventRegistration', on_delete=models.CASCADE),
),
migrations.AlterUniqueTogether(
name='surveyanswer',
diff --git a/gestioncof/migrations/0006_add_calendar.py b/gestioncof/migrations/0006_add_calendar.py
index 004d3602..27852f61 100644
--- a/gestioncof/migrations/0006_add_calendar.py
+++ b/gestioncof/migrations/0006_add_calendar.py
@@ -23,7 +23,8 @@ 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(to=settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE)),
],
),
migrations.AlterModelOptions(
diff --git a/gestioncof/migrations/0013_pei.py b/gestioncof/migrations/0013_pei.py
new file mode 100644
index 00000000..2fbddf1f
--- /dev/null
+++ b/gestioncof/migrations/0013_pei.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gestioncof', '0012_merge'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='cofprofile',
+ name='occupation',
+ field=models.CharField(
+ verbose_name='Occupation',
+ max_length=9,
+ default='1A',
+ choices=[
+ ('exterieur', 'Extérieur'),
+ ('1A', '1A'),
+ ('2A', '2A'),
+ ('3A', '3A'),
+ ('4A', '4A'),
+ ('archicube', 'Archicube'),
+ ('doctorant', 'Doctorant'),
+ ('CST', 'CST'),
+ ('PEI', 'PEI')
+ ]),
+ ),
+ migrations.AlterField(
+ model_name='cofprofile',
+ name='type_cotiz',
+ field=models.CharField(
+ verbose_name='Type de cotisation',
+ max_length=9,
+ default='normalien',
+ choices=[
+ ('etudiant', 'Normalien étudiant'),
+ ('normalien', 'Normalien élève'),
+ ('exterieur', 'Extérieur'),
+ ('gratis', 'Gratuit')
+ ]),
+ ),
+ ]
diff --git a/gestioncof/models.py b/gestioncof/models.py
index 6aa6f9cd..0d816155 100644
--- a/gestioncof/models.py
+++ b/gestioncof/models.py
@@ -8,23 +8,6 @@ from gestioncof.petits_cours_models import choices_length
from bda.models import Spectacle
-OCCUPATION_CHOICES = (
- ('exterieur', _("Extérieur")),
- ('1A', _("1A")),
- ('2A', _("2A")),
- ('3A', _("3A")),
- ('4A', _("4A")),
- ('archicube', _("Archicube")),
- ('doctorant', _("Doctorant")),
- ('CST', _("CST")),
-)
-
-TYPE_COTIZ_CHOICES = (
- ('etudiant', _("Normalien étudiant")),
- ('normalien', _("Normalien élève")),
- ('exterieur', _("Extérieur")),
-)
-
TYPE_COMMENT_FIELD = (
('text', _("Texte long")),
('char', _("Texte court")),
@@ -32,7 +15,44 @@ TYPE_COMMENT_FIELD = (
class CofProfile(models.Model):
- user = models.OneToOneField(User, related_name="profile")
+ STATUS_EXTE = "exterieur"
+ STATUS_1A = "1A"
+ STATUS_2A = "2A"
+ STATUS_3A = "3A"
+ STATUS_4A = "4A"
+ STATUS_ARCHI = "archicube"
+ STATUS_DOCTORANT = "doctorant"
+ STATUS_CST = "CST"
+ STATUS_PEI = "PEI"
+
+ OCCUPATION_CHOICES = (
+ (STATUS_EXTE, _("Extérieur")),
+ (STATUS_1A, _("1A")),
+ (STATUS_2A, _("2A")),
+ (STATUS_3A, _("3A")),
+ (STATUS_4A, _("4A")),
+ (STATUS_ARCHI, _("Archicube")),
+ (STATUS_DOCTORANT, _("Doctorant")),
+ (STATUS_CST, _("CST")),
+ (STATUS_PEI, _("PEI")),
+ )
+
+ COTIZ_ETUDIANT = "etudiant"
+ COTIZ_NORMALIEN = "normalien"
+ COTIZ_EXTE = "exterieur"
+ COTIZ_GRATIS = "gratis"
+
+ TYPE_COTIZ_CHOICES = (
+ (COTIZ_ETUDIANT, _("Normalien étudiant")),
+ (COTIZ_NORMALIEN, _("Normalien élève")),
+ (COTIZ_EXTE, _("Extérieur")),
+ (COTIZ_GRATIS, _("Gratuit")),
+ )
+
+ user = models.OneToOneField(
+ User, on_delete=models.CASCADE,
+ related_name="profile",
+ )
login_clipper = models.CharField(
"Login clipper", max_length=32, blank=True
)
@@ -113,7 +133,10 @@ class Event(models.Model):
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")
@@ -127,9 +150,14 @@ class EventCommentField(models.Model):
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):
@@ -137,7 +165,10 @@ class EventCommentValue(models.Model):
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)
@@ -149,7 +180,10 @@ class EventOption(models.Model):
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:
@@ -161,8 +195,8 @@ class EventOptionChoice(models.Model):
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)
@@ -190,7 +224,10 @@ class Survey(models.Model):
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)
@@ -202,7 +239,10 @@ class SurveyQuestion(models.Model):
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:
@@ -213,8 +253,8 @@ class SurveyQuestionAnswer(models.Model):
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")
@@ -230,7 +270,7 @@ class SurveyAnswer(models.Model):
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/gestioncof/petits_cours_models.py b/gestioncof/petits_cours_models.py
index 753e8674..bf2cfde9 100644
--- a/gestioncof/petits_cours_models.py
+++ b/gestioncof/petits_cours_models.py
@@ -35,8 +35,11 @@ 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 +87,10 @@ 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 +132,15 @@ 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 +157,11 @@ 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
@@ -157,14 +172,16 @@ class PetitCoursAttributionCounter(models.Model):
compteurs de tout le monde.
"""
counter, created = cls.objects.get_or_create(
- user=user, matiere=matiere)
+ user=user,
+ matiere=matiere,
+ )
if created:
mincount = (
cls.objects.filter(matiere=matiere).exclude(user=user)
.aggregate(Min('count'))
['count__min']
)
- counter.count = mincount
+ counter.count = mincount or 0
counter.save()
return counter
diff --git a/gestioncof/petits_cours_views.py b/gestioncof/petits_cours_views.py
index 087c9cef..52a29883 100644
--- a/gestioncof/petits_cours_views.py
+++ b/gestioncof/petits_cours_views.py
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
import json
-from datetime import datetime
from custommail.shortcuts import render_custom_mail
from django.shortcuts import render, get_object_or_404, redirect
@@ -13,6 +12,7 @@ from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db import transaction
+from django.utils import timezone
from gestioncof.models import CofProfile
from gestioncof.petits_cours_models import (
@@ -287,7 +287,7 @@ def _traitement_post(request, demande):
attrib.save()
demande.traitee = True
demande.traitee_par = request.user
- demande.processed = datetime.now()
+ demande.processed = timezone.now()
demande.save()
return render(request,
"gestioncof/traitement_demande_petit_cours_success.html",
diff --git a/gestioncof/templates/admin/base_site.html b/gestioncof/templates/admin/base_site.html
deleted file mode 100644
index 03fd0d17..00000000
--- a/gestioncof/templates/admin/base_site.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% extends "admin/base.html" %}
-
-{% block extrahead %}
-
- {% include 'autocomplete_light/static.html' %}
-{% endblock %}
diff --git a/gestioncof/templates/admin/index.html b/gestioncof/templates/admin/index.html
deleted file mode 100644
index 965c71fa..00000000
--- a/gestioncof/templates/admin/index.html
+++ /dev/null
@@ -1,78 +0,0 @@
-{% extends "admin/base_site.html" %}
-
-
-{% load i18n grp_tags log %}
-
-
-{% block javascripts %}
- {{ block.super }}
-{% endblock %}
-
-
-{% block breadcrumbs %}
-
-{% endblock %}
-{% block content_title %}
- {% if title %}
-
- {% endif %}
-{% endblock %}
-
-
-{% block content %}
-
-
-
- {% for app in app_list %}
-
-
- {% for model in app.models %}
-
- {% if model.perms.change %}
{{ model.name }}{% else %}
{{ model.name }}{% endif %}
- {% if model.perms.add or model.perms.change %}
-
- {% endif %}
-
- {% endfor %}
-
- {% empty %}
-
{% trans "You don´t have permission to edit anything." %}
- {% endfor %}
-
-
-
-
{% trans 'Recent Actions' %}
-
-
{% trans 'My Actions' %}
- {% get_admin_log 20 as admin_log for_user user %}
- {% if not admin_log %}
-
{% trans 'None available' %}
- {% else %}
-
- {% for entry in admin_log %}
- -
- {% if entry.is_deletion %}
- {{ entry.object_repr }}
- {% else %}
- {{ entry.object_repr }}
- {% endif %}
- {% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}
-
- {% endfor %}
-
- {% endif %}
-
-
-
-
-{% endblock %}
-
diff --git a/gestioncof/templates/gestioncof/base_header.html b/gestioncof/templates/gestioncof/base_header.html
index 21441875..e5f757a7 100644
--- a/gestioncof/templates/gestioncof/base_header.html
+++ b/gestioncof/templates/gestioncof/base_header.html
@@ -3,7 +3,7 @@
{% block content %}
diff --git a/gestioncof/templates/gestioncof/event.html b/gestioncof/templates/gestioncof/event.html
index 52f893db..f388bc25 100644
--- a/gestioncof/templates/gestioncof/event.html
+++ b/gestioncof/templates/gestioncof/event.html
@@ -5,7 +5,7 @@
{% if event.details %}
{{ event.details }}
{% endif %}
-