From f44b3fc33c4df8e28ff4d7341e726cda152bb39d Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Fri, 22 Jul 2016 22:48:09 +0200 Subject: [PATCH 001/103] creates initial models --- bda/admin.py | 21 ++++++++++++++++++++- bda/models.py | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/bda/admin.py b/bda/admin.py index 8f5915d5..3717e438 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -9,7 +9,7 @@ from django.core.mail import send_mail from django.contrib import admin from django.db.models import Sum, Count from bda.models import Spectacle, Salle, Participant, ChoixSpectacle,\ - Attribution, Tirage + Attribution, Tirage, SpectacleRevente from django import forms from datetime import timedelta @@ -204,9 +204,28 @@ class SalleAdmin(admin.ModelAdmin): search_fields = ('name', 'address') +class SpectacleReventeAdmin(admin.ModelAdmin): + model = SpectacleRevente + + def spectacle(self, obj): + return obj.attribution.spectacle + + def participant(self, obj): + return obj.attribution.participant + + list_display = ("spectacle", "participant", "date", "sold") + readonly_fields = ("shotgun",) + list_filter = ("sold", ) + search_fields = ("spectacle__title", + "participant__user__username", + "participant__user__firstname", + "participant__user__lastname",) + + admin.site.register(Spectacle, SpectacleAdmin) admin.site.register(Salle, SalleAdmin) admin.site.register(Participant, ParticipantAdmin) admin.site.register(Attribution, AttributionAdmin) admin.site.register(ChoixSpectacle, ChoixSpectacleAdmin) admin.site.register(Tirage, TirageAdmin) +admin.site.register(SpectacleRevente, SpectacleReventeAdmin) diff --git a/bda/models.py b/bda/models.py index 41037643..405236b9 100644 --- a/bda/models.py +++ b/bda/models.py @@ -5,6 +5,7 @@ from __future__ import print_function from __future__ import unicode_literals import calendar +import datetime from django.db import models from django.contrib.auth.models import User @@ -179,3 +180,25 @@ class Attribution(models.Model): def __str__(self): return "%s -- %s" % (self.participant, self.spectacle) + + +@python_2_unicode_compatible +class SpectacleRevente(models.Model): + attribution = models.OneToOneField(Attribution) + date = models.DateTimeField("Date de mise en vente", + default=timezone.now) + sold = models.BooleanField("Vendue", default=False) + + def get_expiration_time(self): + remaining_time = (self.attribution.spectacle.date - self.date) + delay = max(datetime.timedelta(hours=2), + min(remaining_time/2, datetime.timedelta(days=2))) + return self.date + delay + expiration_time = property(get_expiration_time) + + def get_shotgun(self): + return timezone.now > self.expiration_time + shotgun = property(get_shotgun) + + def __str__(self): + return "%s" % self.attribution From 6793194adccb275f5a79d8a1d61bd1812f58d6ad Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 23 Jul 2016 22:21:30 +0200 Subject: [PATCH 002/103] fix affichage admin --- bda/admin.py | 3 ++- bda/models.py | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/bda/admin.py b/bda/admin.py index 3717e438..05947534 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -214,7 +214,8 @@ class SpectacleReventeAdmin(admin.ModelAdmin): return obj.attribution.participant list_display = ("spectacle", "participant", "date", "sold") - readonly_fields = ("shotgun",) + raw_id_fields = ("attribution",) + readonly_fields = ("shotgun", "expiration_time") list_filter = ("sold", ) search_fields = ("spectacle__title", "participant__user__username", diff --git a/bda/models.py b/bda/models.py index 405236b9..b0dd8aeb 100644 --- a/bda/models.py +++ b/bda/models.py @@ -179,7 +179,8 @@ class Attribution(models.Model): given = models.BooleanField("Donnée", default=False) def __str__(self): - return "%s -- %s" % (self.participant, self.spectacle) + return "%s -- %s, %s" % (self.participant.user, self.spectacle.title, + self.spectacle.date) @python_2_unicode_compatible @@ -192,13 +193,14 @@ class SpectacleRevente(models.Model): def get_expiration_time(self): remaining_time = (self.attribution.spectacle.date - self.date) delay = max(datetime.timedelta(hours=2), - min(remaining_time/2, datetime.timedelta(days=2))) + min(remaining_time//2, datetime.timedelta(days=2))) return self.date + delay expiration_time = property(get_expiration_time) def get_shotgun(self): - return timezone.now > self.expiration_time + return timezone.now() > self.expiration_time shotgun = property(get_shotgun) def __str__(self): - return "%s" % self.attribution + return "%s -- %s" % (self.attribution.participant.user, + self.attribution.spectacle.title) From ca39dc813bfaee8842346ca684cf390abcf83f74 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 23 Jul 2016 22:21:50 +0200 Subject: [PATCH 003/103] migration --- bda/migrations/0006_spectaclerevente.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 bda/migrations/0006_spectaclerevente.py diff --git a/bda/migrations/0006_spectaclerevente.py b/bda/migrations/0006_spectaclerevente.py new file mode 100644 index 00000000..a1bf12f6 --- /dev/null +++ b/bda/migrations/0006_spectaclerevente.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0005_encoding'), + ] + + operations = [ + migrations.CreateModel( + name='SpectacleRevente', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date de mise en vente')), + ('sold', models.BooleanField(default=False, verbose_name='Vendue')), + ('attribution', models.OneToOneField(to='bda.Attribution')), + ], + ), + ] From 2aaf9f681ec103a9c1c1f934058670af3a92bdf2 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 23 Jul 2016 22:22:17 +0200 Subject: [PATCH 004/103] interface de revente de places --- bda/templates/bda-revente.html | 37 ++++++++++++++++++---------------- bda/views.py | 25 +++++++++++++++-------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/bda/templates/bda-revente.html b/bda/templates/bda-revente.html index c901a7d1..9527a28b 100644 --- a/bda/templates/bda-revente.html +++ b/bda/templates/bda-revente.html @@ -1,26 +1,29 @@ {% extends "base_title.html" %} {% load staticfiles %} -{% block extra_head %} - -{% endblock %} - {% block realcontent %}

Revente de place

-
+{% if no_resell %} +

Places non revendues

+ {% csrf_token %} -{% if form.spectacle.errors %}
  • Sélectionnez un spetacle
{% endif %} -

-

-Bonjour,
-
-Je souhaite revendre {{ form.count }} place(s) pour {{ form.spectacle }}.
-Contactez-moi par email si vous êtes intéressé !
-
-{{ user.get_full_name }} ({{ user.email }}) -
-

- +
    + {% for attribution in no_resell %} +
  1. {{attribution.spectacle}}
  2. + {% endfor %} +
+ +
+{%endif%} +

Places en cours de revente

+
+ {% csrf_token %} +
    + {% for attribution in resell %} +
  1. {{attribution.spectacle}}
  2. + {% endfor %} +
+
{% endblock %} diff --git a/bda/views.py b/bda/views.py index fbf75359..ab445052 100644 --- a/bda/views.py +++ b/bda/views.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required +from django.contrib import messages from django.db import models from django.db.models import Count from django.core import serializers @@ -21,10 +22,10 @@ import time from gestioncof.decorators import cof_required, buro_required from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ - Tirage, render_template + Tirage, render_template, SpectacleRevente from bda.algorithm import Algorithm -from bda.forms import BaseBdaFormSet, TokenForm, ResellForm +from bda.forms import BaseBdaFormSet, TokenForm @cof_required @@ -302,13 +303,21 @@ def revente(request, tirage_id): if not participant.paid: return render(request, "bda-notpaid.html", {}) if request.POST: - form = ResellForm(participant, request.POST) - if form.is_valid(): - return do_resell(request, form) - else: - form = ResellForm(participant) + for attr_id in request.POST.getlist('resell'): + attribution = Attribution.objects.get(id=int(attr_id)) + revente = SpectacleRevente(attribution=attribution) + revente.save() + for attr_id in request.POST.getlist('annul'): + revente = SpectacleRevente.objects.get(attribution__pk=attr_id) + revente.delete() + + attributions = participant.attribution_set.filter( + spectacle__date__gte=timezone.now) + resell = attributions.filter(spectaclerevente__isnull=False) + no_resell = attributions.filter(spectaclerevente__isnull=True) return render(request, "bda-revente.html", - {"form": form, 'tirage': tirage}) + {"participant": participant, 'tirage': tirage, + "resell": resell, "no_resell": no_resell}) @buro_required From 8f7b036fbcc8135b9c7681ef111776b7e5fc42b8 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sun, 24 Jul 2016 00:48:05 +0200 Subject: [PATCH 005/103] annulations reventes --- bda/models.py | 9 +++++++-- bda/templates/bda-revente.html | 8 ++++++-- bda/views.py | 10 +++++----- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/bda/models.py b/bda/models.py index b0dd8aeb..1e80b248 100644 --- a/bda/models.py +++ b/bda/models.py @@ -185,7 +185,8 @@ class Attribution(models.Model): @python_2_unicode_compatible class SpectacleRevente(models.Model): - attribution = models.OneToOneField(Attribution) + attribution = models.OneToOneField(Attribution, + related_name="revente") date = models.DateTimeField("Date de mise en vente", default=timezone.now) sold = models.BooleanField("Vendue", default=False) @@ -194,13 +195,17 @@ class SpectacleRevente(models.Model): remaining_time = (self.attribution.spectacle.date - self.date) delay = max(datetime.timedelta(hours=2), min(remaining_time//2, datetime.timedelta(days=2))) - return self.date + delay + return self.date + delay + datetime.timedelta(hours=1) expiration_time = property(get_expiration_time) def get_shotgun(self): return timezone.now() > self.expiration_time shotgun = property(get_shotgun) + def get_cancellable(self): + return timezone.now() < self.date + datetime.timedelta(hours=1) + cancellable = property(get_cancellable) + def __str__(self): return "%s -- %s" % (self.attribution.participant.user, self.attribution.spectacle.title) diff --git a/bda/templates/bda-revente.html b/bda/templates/bda-revente.html index 9527a28b..16fbc0e2 100644 --- a/bda/templates/bda-revente.html +++ b/bda/templates/bda-revente.html @@ -16,14 +16,18 @@ {%endif%} +{% if resell %}

Places en cours de revente

{% csrf_token %}
    {% for attribution in resell %} -
  1. {{attribution.spectacle}}
  2. + + {% csrf_token %} + +
  3. {{attribution.spectacle}} {% if attribution.revente.cancellable %}{%endif%}
  4. {% endfor %}
-
+{% endif %} {% endblock %} diff --git a/bda/views.py b/bda/views.py index ab445052..82c09b55 100644 --- a/bda/views.py +++ b/bda/views.py @@ -6,7 +6,6 @@ from __future__ import unicode_literals from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required -from django.contrib import messages from django.db import models from django.db.models import Count from django.core import serializers @@ -307,14 +306,15 @@ def revente(request, tirage_id): attribution = Attribution.objects.get(id=int(attr_id)) revente = SpectacleRevente(attribution=attribution) revente.save() - for attr_id in request.POST.getlist('annul'): - revente = SpectacleRevente.objects.get(attribution__pk=attr_id) + if 'annul' in request.POST: + revente = SpectacleRevente.objects\ + .get(attribution__pk=request.POST['annul']) revente.delete() attributions = participant.attribution_set.filter( spectacle__date__gte=timezone.now) - resell = attributions.filter(spectaclerevente__isnull=False) - no_resell = attributions.filter(spectaclerevente__isnull=True) + resell = attributions.filter(revente__isnull=False) + no_resell = attributions.filter(revente__isnull=True) return render(request, "bda-revente.html", {"participant": participant, 'tirage': tirage, "resell": resell, "no_resell": no_resell}) From 49afda933a9c3724501da264a7a6c9ead2b0b609 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 25 Jul 2016 02:51:19 +0200 Subject: [PATCH 006/103] model changes --- bda/admin.py | 3 +-- bda/models.py | 7 ++++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bda/admin.py b/bda/admin.py index 05947534..2b24dbb7 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -213,10 +213,9 @@ class SpectacleReventeAdmin(admin.ModelAdmin): def participant(self, obj): return obj.attribution.participant - list_display = ("spectacle", "participant", "date", "sold") + list_display = ("spectacle", "participant", "date", "soldTo") raw_id_fields = ("attribution",) readonly_fields = ("shotgun", "expiration_time") - list_filter = ("sold", ) search_fields = ("spectacle__title", "participant__user__username", "participant__user__firstname", diff --git a/bda/models.py b/bda/models.py index 1e80b248..77b7d00c 100644 --- a/bda/models.py +++ b/bda/models.py @@ -132,6 +132,8 @@ class Participant(models.Model): max_length=6, choices=PAYMENT_TYPES, blank=True) tirage = models.ForeignKey(Tirage) + choicesrevente = models.ManyToManyField(Spectacle, + related_name="revente") def __str__(self): return "%s - %s" % (self.user, self.tirage.title) @@ -189,7 +191,10 @@ class SpectacleRevente(models.Model): related_name="revente") date = models.DateTimeField("Date de mise en vente", default=timezone.now) - sold = models.BooleanField("Vendue", default=False) + interested = models.ManyToManyField(Participant, + related_name="wanted", + blank=True, null=True) + soldTo = models.ForeignKey(Participant, blank=True, null=True) def get_expiration_time(self): remaining_time = (self.attribution.spectacle.date - self.date) From 7f87bfe8e206331445cd8f49f8c9492f1a6bf3f0 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 25 Jul 2016 02:51:45 +0200 Subject: [PATCH 007/103] new urls for revente --- bda/urls.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bda/urls.py b/bda/urls.py index 4e5811a1..747b49ce 100644 --- a/bda/urls.py +++ b/bda/urls.py @@ -38,4 +38,10 @@ urlpatterns = patterns( "bda.views.unpaid", name="bda-unpaid"), url(r'^mails-rappel/(?P\d+)$', "bda.views.send_rappel"), + url(r'^liste-revente/(?P\d+)$', + "bda.views.list_revente", + name="bda-liste-revente"), + url(r'^buy-revente/(?P\d+)$', + "bda.views.buy_revente", + name="bda-buy-revente"), ) From 78096bd6d0164398374f159228f74798a2a9c78a Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 25 Jul 2016 02:52:49 +0200 Subject: [PATCH 008/103] achat des reventes au shotgun --- bda/templates/liste-reventes.html | 23 +++++++++++++++ bda/templates/revente-confirm.html | 14 +++++++++ bda/views.py | 46 ++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 bda/templates/liste-reventes.html create mode 100644 bda/templates/revente-confirm.html diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html new file mode 100644 index 00000000..6ae20388 --- /dev/null +++ b/bda/templates/liste-reventes.html @@ -0,0 +1,23 @@ +{% extends "base_title.html" %} +{% load staticfiles %} + +{% block realcontent %} +

Inscriptions pour BDA-Revente

+
+ {% csrf_token %} +
    + {% for spectacle in spectacles %} +
  • {{spectacle}}
  • + {%endfor%} +
+ +
+ + {% if shotgun %} +

Places disponibles immédiatement

+
    + {% for spectacle in shotgun %} +
  • {{spectacle}}
  • + {% endfor %} + {% endif %} +{% endblock %} diff --git a/bda/templates/revente-confirm.html b/bda/templates/revente-confirm.html new file mode 100644 index 00000000..d1a348aa --- /dev/null +++ b/bda/templates/revente-confirm.html @@ -0,0 +1,14 @@ +{% extends "base_title.html" %} +{% load staticfiles %} + +{# TODO: ajouter template du mail ? Changer formulation #} +{%block realcontent %} +Vous êtes sur le point de racheter une place pour {{spectacle.title}} à {{selected.attribution.participant.user.get_full_name}} ; confirmez-vous ceci ? Un mail lui sera envoyé pour le/la notifier et vous permettre d'entrer en contact. + +
    +{% csrf_token %} + + +
    + +{%endblock%} diff --git a/bda/views.py b/bda/views.py index 82c09b55..3c42f94d 100644 --- a/bda/views.py +++ b/bda/views.py @@ -4,6 +4,8 @@ from __future__ import division from __future__ import print_function from __future__ import unicode_literals +import random + from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.db import models @@ -320,6 +322,50 @@ def revente(request, tirage_id): "resell": resell, "no_resell": no_resell}) +@login_required +def list_revente(request, tirage_id): + tirage = get_object_or_404(Tirage, id=tirage_id) + participant, created = Participant.objects.get_or_create( + user=request.user, tirage=tirage) + spectacles = tirage.spectacle_set.all() + shotgun = [] + for spectacle in spectacles: + spectacle.am_interested = spectacle.revente.filter( + pk=participant.id).exists() + revente_objects = SpectacleRevente.objects.filter( + attribution__spectacle=spectacle) + revente_count = 0 + for revente in revente_objects: + if revente.shotgun: + revente_count += 1 + if revente_count: + spectacle.revente_count = revente_count + shotgun.append(spectacle) + return render(request, "liste-reventes.html", + {"participant": participant, 'tirage': tirage, + "spectacles": spectacles, 'shotgun': shotgun}) + + +@login_required +def buy_revente(request, spectacle_id): + spectacle = get_object_or_404(Spectacle, id=spectacle_id) + tirage = spectacle.tirage + participant, created = Participant.objects.get_or_create( + user=request.user, tirage=tirage) + reventes = SpectacleRevente.objects.filter( + attribution__spectacle=spectacle) + if request.POST: + revente = SpectacleRevente.objects.get(pk=request.POST['id']) + revente.soldTo = participant + revente.save() + + if reventes.exists(): + idx = random.randint(0, reventes.count() - 1) + selected = reventes.all()[idx] + return render(request, "revente-confirm.html", + {"selected": selected, "spectacle": spectacle}) + + @buro_required def spectacle(request, tirage_id, spectacle_id): tirage = get_object_or_404(Tirage, id=tirage_id) From 92dd9a18a252b5cb4f256b5a8c9f9307538d34a5 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 25 Jul 2016 02:54:04 +0200 Subject: [PATCH 009/103] migrations --- bda/migrations/0006_revente.py | 38 +++++++++++++++++++++++++ bda/migrations/0006_spectaclerevente.py | 24 ---------------- 2 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 bda/migrations/0006_revente.py delete mode 100644 bda/migrations/0006_spectaclerevente.py diff --git a/bda/migrations/0006_revente.py b/bda/migrations/0006_revente.py new file mode 100644 index 00000000..8aa7c0f8 --- /dev/null +++ b/bda/migrations/0006_revente.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0005_encoding'), + ] + + operations = [ + migrations.CreateModel( + name='SpectacleRevente', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date de mise en vente')), + ('attribution', models.OneToOneField(related_name='revente', to='bda.Attribution')), + ], + ), + migrations.AddField( + model_name='participant', + name='choicesrevente', + field=models.ManyToManyField(related_name='revente', to='bda.Spectacle'), + ), + migrations.AddField( + model_name='spectaclerevente', + name='interested', + field=models.ManyToManyField(related_name='wanted', to='bda.Participant'), + ), + migrations.AddField( + model_name='spectaclerevente', + name='soldTo', + field=models.ForeignKey(blank=True, to='bda.Participant', null=True), + ), + ] diff --git a/bda/migrations/0006_spectaclerevente.py b/bda/migrations/0006_spectaclerevente.py deleted file mode 100644 index a1bf12f6..00000000 --- a/bda/migrations/0006_spectaclerevente.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('bda', '0005_encoding'), - ] - - operations = [ - migrations.CreateModel( - name='SpectacleRevente', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date de mise en vente')), - ('sold', models.BooleanField(default=False, verbose_name='Vendue')), - ('attribution', models.OneToOneField(to='bda.Attribution')), - ], - ), - ] From 90581af528639ab6f3824f578f9bfa8176795ab2 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 25 Jul 2016 03:01:12 +0200 Subject: [PATCH 010/103] ajoute lien sur la page d'accueil --- gestioncof/templates/home.html | 1 + 1 file changed, 1 insertion(+) diff --git a/gestioncof/templates/home.html b/gestioncof/templates/home.html index ed567455..015e835f 100644 --- a/gestioncof/templates/home.html +++ b/gestioncof/templates/home.html @@ -33,6 +33,7 @@
  • État des demandes
  • Mes places
  • Revendre une place
  • +
  • Inscription à BDA-Revente

{% endfor %} From d12a21d44c3d9155db7100cceb5f5f5ac20247cb Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 25 Jul 2016 23:03:33 +0200 Subject: [PATCH 011/103] use forms --- bda/forms.py | 13 ++++++++----- bda/models.py | 2 +- bda/templates/bda-revente.html | 22 +--------------------- bda/views.py | 28 +++++++++++----------------- 4 files changed, 21 insertions(+), 44 deletions(-) diff --git a/bda/forms.py b/bda/forms.py index 9f5e3890..b1acf3d9 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -6,7 +6,8 @@ from __future__ import unicode_literals from django import forms from django.forms.models import BaseInlineFormSet -from bda.models import Spectacle +from django.utils import timezone +from bda.models import Attribution class BaseBdaFormSet(BaseInlineFormSet): @@ -42,10 +43,12 @@ class SpectacleModelChoiceField(forms.ModelChoiceField): class ResellForm(forms.Form): - count = forms.ChoiceField(choices=(("1", "1"), ("2", "2"),)) - spectacle = SpectacleModelChoiceField(queryset=Spectacle.objects.none()) + attributions = forms.ModelMultipleChoiceField( + queryset=Attribution.objects.none(), + widget=forms.CheckboxSelectMultiple) def __init__(self, participant, *args, **kwargs): super(ResellForm, self).__init__(*args, **kwargs) - self.fields['spectacle'].queryset = participant.attributions.all() \ - .distinct() + self.fields['attributions'].queryset = participant.attribution_set\ + .filter(spectacle__date__gte=timezone.now(), + revente__isnull=True) diff --git a/bda/models.py b/bda/models.py index 77b7d00c..91af3e99 100644 --- a/bda/models.py +++ b/bda/models.py @@ -193,7 +193,7 @@ class SpectacleRevente(models.Model): default=timezone.now) interested = models.ManyToManyField(Participant, related_name="wanted", - blank=True, null=True) + blank=True) soldTo = models.ForeignKey(Participant, blank=True, null=True) def get_expiration_time(self): diff --git a/bda/templates/bda-revente.html b/bda/templates/bda-revente.html index 16fbc0e2..0b6e14a6 100644 --- a/bda/templates/bda-revente.html +++ b/bda/templates/bda-revente.html @@ -4,30 +4,10 @@ {% block realcontent %}

Revente de place

-{% if no_resell %}

Places non revendues

{% csrf_token %} -
    - {% for attribution in no_resell %} -
  1. {{attribution.spectacle}}
  2. - {% endfor %} -
+ {{form}}
-{%endif%} -{% if resell %} -

Places en cours de revente

-
- {% csrf_token %} -
    - {% for attribution in resell %} - - {% csrf_token %} - -
  1. {{attribution.spectacle}} {% if attribution.revente.cancellable %}{%endif%}
  2. - {% endfor %} -
-
-{% endif %} {% endblock %} diff --git a/bda/views.py b/bda/views.py index 3c42f94d..4c31a635 100644 --- a/bda/views.py +++ b/bda/views.py @@ -26,7 +26,7 @@ from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ Tirage, render_template, SpectacleRevente from bda.algorithm import Algorithm -from bda.forms import BaseBdaFormSet, TokenForm +from bda.forms import BaseBdaFormSet, TokenForm, ResellForm @cof_required @@ -303,23 +303,17 @@ def revente(request, tirage_id): user=request.user, tirage=tirage) if not participant.paid: return render(request, "bda-notpaid.html", {}) - if request.POST: - for attr_id in request.POST.getlist('resell'): - attribution = Attribution.objects.get(id=int(attr_id)) - revente = SpectacleRevente(attribution=attribution) - revente.save() - if 'annul' in request.POST: - revente = SpectacleRevente.objects\ - .get(attribution__pk=request.POST['annul']) - revente.delete() - - attributions = participant.attribution_set.filter( - spectacle__date__gte=timezone.now) - resell = attributions.filter(revente__isnull=False) - no_resell = attributions.filter(revente__isnull=True) + if request.method == 'POST': + form = ResellForm(participant, request.POST) + if form.is_valid(): + attributions = form.cleaned_data["attributions"] + for attribution in attributions: + revente = SpectacleRevente(attribution=attribution) + revente.save() + else: + form = ResellForm(participant) return render(request, "bda-revente.html", - {"participant": participant, 'tirage': tirage, - "resell": resell, "no_resell": no_resell}) + {'tirage': tirage, "form": form}) @login_required From 460a135fa591126f9b92c8cfccfc7a3378ef9b58 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 27 Jul 2016 13:08:00 +0200 Subject: [PATCH 012/103] use forms --- bda/forms.py | 40 +++++++++++++++++---- bda/templates/bda-revente.html | 17 +++++++-- bda/templates/liste-reventes.html | 6 +--- bda/views.py | 58 +++++++++++++++++++++++-------- 4 files changed, 94 insertions(+), 27 deletions(-) diff --git a/bda/forms.py b/bda/forms.py index b1acf3d9..60fdb0fd 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -4,10 +4,12 @@ from __future__ import division from __future__ import print_function from __future__ import unicode_literals +from datetime import timedelta + from django import forms from django.forms.models import BaseInlineFormSet from django.utils import timezone -from bda.models import Attribution +from bda.models import Attribution, Spectacle class BaseBdaFormSet(BaseInlineFormSet): @@ -36,19 +38,45 @@ class TokenForm(forms.Form): token = forms.CharField(widget=forms.widgets.Textarea()) -class SpectacleModelChoiceField(forms.ModelChoiceField): +class AttributionModelMultipleChoiceField(forms.ModelMultipleChoiceField): def label_from_instance(self, obj): - return "%s le %s (%s) à %.02f€" % (obj.title, obj.date_no_seconds(), - obj.location, obj.price) + return "%s" % obj.spectacle class ResellForm(forms.Form): - attributions = forms.ModelMultipleChoiceField( + attributions = AttributionModelMultipleChoiceField( queryset=Attribution.objects.none(), - widget=forms.CheckboxSelectMultiple) + widget=forms.CheckboxSelectMultiple, + required=False) def __init__(self, participant, *args, **kwargs): super(ResellForm, self).__init__(*args, **kwargs) self.fields['attributions'].queryset = participant.attribution_set\ .filter(spectacle__date__gte=timezone.now(), revente__isnull=True) + + +class AnnulForm(forms.Form): + attributions = AttributionModelMultipleChoiceField( + queryset=Attribution.objects.none(), + widget=forms.CheckboxSelectMultiple, + required=False) + + def __init__(self, participant, *args, **kwargs): + super(AnnulForm, self).__init__(*args, **kwargs) + self.fields['attributions'].queryset = participant.attribution_set\ + .filter(spectacle__date__gte=timezone.now(), + revente__isnull=False, + revente__date__gte=timezone.now()-timedelta(hours=1)) + + +class InscriptionReventeForm(forms.Form): + spectacles = forms.ModelMultipleChoiceField( + queryset=Spectacle.objects.none(), + widget=forms.CheckboxSelectMultiple, + required=False) + + def __init__(self, tirage, *args, **kwargs): + super(InscriptionReventeForm, self).__init__(*args, **kwargs) + self.fields['spectacles'].queryset = tirage.spectacle_set.filter( + date__gte=timezone.now()) diff --git a/bda/templates/bda-revente.html b/bda/templates/bda-revente.html index 0b6e14a6..e7fd6e6d 100644 --- a/bda/templates/bda-revente.html +++ b/bda/templates/bda-revente.html @@ -7,7 +7,20 @@

Places non revendues

{% csrf_token %} - {{form}} - + {{resellform}} +
+ +

Places en cours de revente

+
+ {% csrf_token %} +
    + {% for box in annulform.attributions %} +
  • {{box.choice_label}}{{box.tag}}
  • + {% endfor %} + {% for attrib in overdue %} +
  • {{attrib.spectacle}}
  • + {%endfor%} +
+ {% endblock %} diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 6ae20388..4b48825f 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -5,11 +5,7 @@

Inscriptions pour BDA-Revente

{% csrf_token %} -
    - {% for spectacle in spectacles %} -
  • {{spectacle}}
  • - {%endfor%} -
+ {{form}}
diff --git a/bda/views.py b/bda/views.py index 4c31a635..fe180ada 100644 --- a/bda/views.py +++ b/bda/views.py @@ -26,7 +26,8 @@ from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ Tirage, render_template, SpectacleRevente from bda.algorithm import Algorithm -from bda.forms import BaseBdaFormSet, TokenForm, ResellForm +from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ + InscriptionReventeForm @cof_required @@ -304,16 +305,35 @@ def revente(request, tirage_id): if not participant.paid: return render(request, "bda-notpaid.html", {}) if request.method == 'POST': - form = ResellForm(participant, request.POST) - if form.is_valid(): - attributions = form.cleaned_data["attributions"] - for attribution in attributions: - revente = SpectacleRevente(attribution=attribution) - revente.save() + if 'resell' in request.POST: + resellform = ResellForm(participant, request.POST, prefix='resell') + annulform = AnnulForm(participant, prefix='annul') + if resellform.is_valid(): + attributions = resellform.cleaned_data["attributions"] + for attribution in attributions: + revente = SpectacleRevente(attribution=attribution) + revente.save() + elif 'annul' in request.POST: + annulform = AnnulForm(participant, request.POST, prefix='annul') + resellform = ResellForm(participant, prefix='resell') + if annulform.is_valid(): + attributions = annulform.cleaned_data["attributions"] + for attribution in attributions: + attribution.revente.delete() + else: + resellform = ResellForm(participant, prefix='resell') + annulform = AnnulForm(participant, prefix='annul') else: - form = ResellForm(participant) + resellform = ResellForm(participant, prefix='resell') + annulform = AnnulForm(participant, prefix='annul') + overdue = participant.attribution_set.filter( + spectacle__date__gte=timezone.now(), + revente__isnull=False, + revente__date__lte=timezone.now()-timedelta(hours=1)) + return render(request, "bda-revente.html", - {'tirage': tirage, "form": form}) + {'tirage': tirage, 'overdue': overdue, + "annulform": annulform, "resellform": resellform}) @login_required @@ -321,11 +341,10 @@ def list_revente(request, tirage_id): tirage = get_object_or_404(Tirage, id=tirage_id) participant, created = Participant.objects.get_or_create( user=request.user, tirage=tirage) - spectacles = tirage.spectacle_set.all() + spectacles = tirage.spectacle_set.filter( + date__gte=timezone.now()) shotgun = [] for spectacle in spectacles: - spectacle.am_interested = spectacle.revente.filter( - pk=participant.id).exists() revente_objects = SpectacleRevente.objects.filter( attribution__spectacle=spectacle) revente_count = 0 @@ -335,9 +354,20 @@ def list_revente(request, tirage_id): if revente_count: spectacle.revente_count = revente_count shotgun.append(spectacle) + + if request.method == 'POST': + form = InscriptionReventeForm(tirage, request.POST) + if form.is_valid(): + choices = form.cleaned_data['spectacles'] + participant.choicesrevente = choices + participant.save() + else: + form = InscriptionReventeForm( + tirage, + initial={'spectacles': participant.choicesrevente.all()}) + return render(request, "liste-reventes.html", - {"participant": participant, 'tirage': tirage, - "spectacles": spectacles, 'shotgun': shotgun}) + {"form": form, 'shotgun': shotgun}) @login_required From d4198d16d733fd3788fb3d6dfa955e3930d92a23 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 27 Jul 2016 23:37:48 +0200 Subject: [PATCH 013/103] migration --- bda/migrations/0007_auto_20160727_2336.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 bda/migrations/0007_auto_20160727_2336.py diff --git a/bda/migrations/0007_auto_20160727_2336.py b/bda/migrations/0007_auto_20160727_2336.py new file mode 100644 index 00000000..c8b4674a --- /dev/null +++ b/bda/migrations/0007_auto_20160727_2336.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0006_revente'), + ] + + operations = [ + migrations.AlterField( + model_name='spectaclerevente', + name='interested', + field=models.ManyToManyField(related_name='wanted', to='bda.Participant', blank=True), + ), + ] From 5b18eace20bf241b2d9d8dae0ff4b2ea0ad3bd2b Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Fri, 29 Jul 2016 01:50:08 +0200 Subject: [PATCH 014/103] send mail --- bda/models.py | 24 ++++++++++++++++++++---- bda/templates/mail-revente.txt | 8 ++++++++ cof/settings_dev.py | 3 +++ 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 bda/templates/mail-revente.txt diff --git a/bda/models.py b/bda/models.py index 91af3e99..d1d3ba7e 100644 --- a/bda/models.py +++ b/bda/models.py @@ -207,10 +207,26 @@ class SpectacleRevente(models.Model): return timezone.now() > self.expiration_time shotgun = property(get_shotgun) - def get_cancellable(self): - return timezone.now() < self.date + datetime.timedelta(hours=1) - cancellable = property(get_cancellable) - def __str__(self): return "%s -- %s" % (self.attribution.participant.user, self.attribution.spectacle.title) + + def send_notif(self): + # On récupère la liste des inscrits + inscrits = self.attribution.spectacle.revente.select_related('user') + + mails_to_send = [] + mail_object = "%s" % (self.attribution.spectacle) + for participant in inscrits: + mail_body = render_template('mail-revente.txt', { + 'user': participant.user, + 'spectacle': self.spectacle, + 'revente': self}) + mail_tot = mail.EmailMessage( + mail_object, mail_body, + settings.REVENTE_FROM, [participant.email], + [], headers={'Reply-To': settings.REVENTE_REPLY_TO}) + mails_to_send.append(mail_tot) + + connection = mail.get_connection() + connection.send_messages(mails_to_send) diff --git a/bda/templates/mail-revente.txt b/bda/templates/mail-revente.txt new file mode 100644 index 00000000..16655696 --- /dev/null +++ b/bda/templates/mail-revente.txt @@ -0,0 +1,8 @@ +Bonjour {{ user.get_full_name }} + +Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BDA-Revente. + +Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : {% url "bda-inscr-revente" revente.id %}. Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à un tirage au sort le {{revente.date_no_seconds}} + +Chaleureusement, +Le BDA diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 502cb0ee..0666ee9f 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -142,6 +142,9 @@ PETITS_COURS_REPLYTO = "cof@ens.fr" RAPPEL_FROM = 'Le BdA ' RAPPEL_REPLY_TO = RAPPEL_FROM +REVENTE_FROM = 'BDA-Revente ' +REVENTE_REPLY_TO = REVENTE_FROM + LOGIN_URL = "/login" LOGIN_REDIRECT_URL = "/" From 32d98faf0da1aae43c7c6c7b0bc86cd31ab07940 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 3 Sep 2016 05:21:27 +0200 Subject: [PATCH 015/103] minor fixes --- bda/models.py | 3 ++- bda/views.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/bda/models.py b/bda/models.py index 90ca9449..7856b517 100644 --- a/bda/models.py +++ b/bda/models.py @@ -158,7 +158,8 @@ class Participant(models.Model): blank=True) tirage = models.ForeignKey(Tirage) choicesrevente = models.ManyToManyField(Spectacle, - related_name="revente") + related_name="revente", + blank=True) def __str__(self): return "%s - %s" % (self.user, self.tirage.title) diff --git a/bda/views.py b/bda/views.py index 0c48ab6c..1ae1b425 100644 --- a/bda/views.py +++ b/bda/views.py @@ -20,6 +20,7 @@ from django.utils import timezone from django.views.generic.list import ListView import time +from datetime import timedelta from gestioncof.decorators import cof_required, buro_required from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ From c26bb5c30925b123fbe734034936883275ef5a39 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 3 Sep 2016 05:22:41 +0200 Subject: [PATCH 016/103] adds bda-revente to home --- gestioncof/templates/home.html | 1 + 1 file changed, 1 insertion(+) diff --git a/gestioncof/templates/home.html b/gestioncof/templates/home.html index 0907adc6..0cd32ebf 100644 --- a/gestioncof/templates/home.html +++ b/gestioncof/templates/home.html @@ -43,6 +43,7 @@ {% else %}
  • Mes places
  • Revendre une place
  • +
  • S'inscrire à BDA-Revente
  • {% endif %} {% endfor %} From a32278d76520d84dbe6ab5092f5b56ef5b7b8d9f Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 3 Sep 2016 05:23:05 +0200 Subject: [PATCH 017/103] styling forms --- bda/templates/bda-revente.html | 47 +++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/bda/templates/bda-revente.html b/bda/templates/bda-revente.html index fcad757b..61bf5452 100644 --- a/bda/templates/bda-revente.html +++ b/bda/templates/bda-revente.html @@ -1,26 +1,55 @@ {% extends "base_title.html" %} -{% load staticfiles %} +{% load bootstrap %} {% block realcontent %}

    Revente de place

    Places non revendues

    -
    + {% csrf_token %} - {{resellform}} - +
    +
    +
      + {% for box in resellform.attributions %} +
    • + {{box.tag}} + {{box.choice_label}} +
    • + {% endfor %} +
    +
    +
    +
    + +
    - +

    Places en cours de revente

    {% csrf_token %} -
      - {% for box in annulform.attributions %} -
    • {{box.choice_label}}{{box.tag}}
    • - {% endfor %} +
      +
      +
        + {% for box in annulform.attributions %} +
      • + {{box.tag}} + {{box.choice_label}} +
      • + {% endfor %} + {% for attrib in overdue %} +
      • + + {{attrib.spectacle}} +
      • + {% endfor %} +
      +
      +
      + {{annulform | bootstrap}} {% for attrib in overdue %}
    • {{attrib.spectacle}}
    • {%endfor%}
    +
    {% endblock %} From 798f5226020012cfdcb1b5f2e84da3edca03460e Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 3 Sep 2016 05:25:01 +0200 Subject: [PATCH 018/103] migration --- bda/migrations/0008_revente.py | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 bda/migrations/0008_revente.py diff --git a/bda/migrations/0008_revente.py b/bda/migrations/0008_revente.py new file mode 100644 index 00000000..4db2c9de --- /dev/null +++ b/bda/migrations/0008_revente.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0007_extends_spectacle'), + ] + + operations = [ + migrations.CreateModel( + name='SpectacleRevente', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date de mise en vente')), + ('attribution', models.OneToOneField(related_name='revente', to='bda.Attribution')), + ], + ), + migrations.AddField( + model_name='participant', + name='choicesrevente', + field=models.ManyToManyField(related_name='revente', to='bda.Spectacle', blank=True), + ), + migrations.AddField( + model_name='spectaclerevente', + name='interested', + field=models.ManyToManyField(related_name='wanted', to='bda.Participant', blank=True), + ), + migrations.AddField( + model_name='spectaclerevente', + name='soldTo', + field=models.ForeignKey(blank=True, to='bda.Participant', null=True), + ), + ] From 026e585eb7622fa46b9b7c7741175876908afa65 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 3 Sep 2016 12:07:16 +0200 Subject: [PATCH 019/103] delete unused migrations --- bda/migrations/0006_revente.py | 38 ----------------------- bda/migrations/0007_auto_20160727_2336.py | 19 ------------ 2 files changed, 57 deletions(-) delete mode 100644 bda/migrations/0006_revente.py delete mode 100644 bda/migrations/0007_auto_20160727_2336.py diff --git a/bda/migrations/0006_revente.py b/bda/migrations/0006_revente.py deleted file mode 100644 index 8aa7c0f8..00000000 --- a/bda/migrations/0006_revente.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('bda', '0005_encoding'), - ] - - operations = [ - migrations.CreateModel( - name='SpectacleRevente', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date de mise en vente')), - ('attribution', models.OneToOneField(related_name='revente', to='bda.Attribution')), - ], - ), - migrations.AddField( - model_name='participant', - name='choicesrevente', - field=models.ManyToManyField(related_name='revente', to='bda.Spectacle'), - ), - migrations.AddField( - model_name='spectaclerevente', - name='interested', - field=models.ManyToManyField(related_name='wanted', to='bda.Participant'), - ), - migrations.AddField( - model_name='spectaclerevente', - name='soldTo', - field=models.ForeignKey(blank=True, to='bda.Participant', null=True), - ), - ] diff --git a/bda/migrations/0007_auto_20160727_2336.py b/bda/migrations/0007_auto_20160727_2336.py deleted file mode 100644 index c8b4674a..00000000 --- a/bda/migrations/0007_auto_20160727_2336.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('bda', '0006_revente'), - ] - - operations = [ - migrations.AlterField( - model_name='spectaclerevente', - name='interested', - field=models.ManyToManyField(related_name='wanted', to='bda.Participant', blank=True), - ), - ] From 285e3cb78f77445412f9d91023e346e6717279e9 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 3 Sep 2016 18:46:56 +0200 Subject: [PATCH 020/103] styling forms --- bda/templates/bda-revente.html | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/bda/templates/bda-revente.html b/bda/templates/bda-revente.html index 61bf5452..0a5cffb3 100644 --- a/bda/templates/bda-revente.html +++ b/bda/templates/bda-revente.html @@ -45,11 +45,6 @@ - {{annulform | bootstrap}} - {% for attrib in overdue %} -
  • {{attrib.spectacle}}
  • - {%endfor%} - - + {% endblock %} From 46f91adc08ad9dfafa882ce900055712876695f2 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 3 Sep 2016 18:47:38 +0200 Subject: [PATCH 021/103] revente des places au shotgun --- bda/templates/bda-success.html | 8 ++----- bda/templates/liste-reventes.html | 11 +++++----- bda/templates/revente-confirm.html | 15 ++++++++----- bda/views.py | 34 ++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/bda/templates/bda-success.html b/bda/templates/bda-success.html index ebcc87a7..5e970eb7 100644 --- a/bda/templates/bda-success.html +++ b/bda/templates/bda-success.html @@ -1,12 +1,8 @@ {% extends "base_title.html" %} {% load staticfiles %} -{% block extra_head %} - -{% endblock %} - {% block realcontent %} -

    Revente de place

    -

    Votre offre de revente de {{ places }} pour {{ show.title }} le {{ show.date_no_seconds }} ({{ show.location }}) à {{ show.price }}€ a bien été envoyée.

    +

    Revente de place

    +

    Un mail a bien été envoyé à {{seller.get_full_name}} ({{seller.email}}), pour racheter une place pour {{spectacle.title}} !

    {% endblock %} diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 4b48825f..9e4acb92 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -1,16 +1,17 @@ {% extends "base_title.html" %} -{% load staticfiles %} +{% load bootstrap %} {% block realcontent %}

    Inscriptions pour BDA-Revente

    -
    + {% csrf_token %} - {{form}} - + {{form | bootstrap}} +
    {% if shotgun %} -

    Places disponibles immédiatement

    +
    +

    Places disponibles immédiatement

      {% for spectacle in shotgun %}
    • {{spectacle}}
    • diff --git a/bda/templates/revente-confirm.html b/bda/templates/revente-confirm.html index d1a348aa..60cac8b8 100644 --- a/bda/templates/revente-confirm.html +++ b/bda/templates/revente-confirm.html @@ -1,14 +1,19 @@ {% extends "base_title.html" %} {% load staticfiles %} -{# TODO: ajouter template du mail ? Changer formulation #} {%block realcontent %} -Vous êtes sur le point de racheter une place pour {{spectacle.title}} à {{selected.attribution.participant.user.get_full_name}} ; confirmez-vous ceci ? Un mail lui sera envoyé pour le/la notifier et vous permettre d'entrer en contact. +

      Rachat d'une place

      +Note : ce mail sera envoyé à une personne au hasard revendant sa place. +
      +Bonjour !
       
      +Je souhaiterais racheter ta place pour {{spectacle.title}} le {{spectacle.date}} ({{spectacle.location}}) à {{spectacle.price}}€. 
      +Contacte-moi si tu es toujours intéressé-e !
      +
      +{{user.get_full_name}} ({{user.email}})
      +
      {% csrf_token %} - - +
      - {%endblock%} diff --git a/bda/views.py b/bda/views.py index 1ae1b425..40bd924d 100644 --- a/bda/views.py +++ b/bda/views.py @@ -323,7 +323,8 @@ def list_revente(request, tirage_id): shotgun = [] for spectacle in spectacles: revente_objects = SpectacleRevente.objects.filter( - attribution__spectacle=spectacle) + attribution__spectacle=spectacle, + soldTo__isnull=True) revente_count = 0 for revente in revente_objects: if revente.shotgun: @@ -354,17 +355,36 @@ def buy_revente(request, spectacle_id): participant, created = Participant.objects.get_or_create( user=request.user, tirage=tirage) reventes = SpectacleRevente.objects.filter( - attribution__spectacle=spectacle) + attribution__spectacle=spectacle, + soldTo__isnull=True) + + if not reventes.exists(): + return render(request, "bda-no-revente.html", {}) + if request.POST: - revente = SpectacleRevente.objects.get(pk=request.POST['id']) + idx = random.randint(0, reventes.count() - 1) + revente = reventes.all()[idx] revente.soldTo = participant revente.save() + mail = """Bonjour ! + +Je souhaiterais racheter ta place pour %s le %s (%s) à %.02f€. +Contacte-moi si tu es toujours intéressé·e ! + +%s (%s)""" % (spectacle.title, spectacle.date_no_seconds(), + spectacle.location, spectacle.price, + request.user.get_full_name(), request.user.email) + send_mail("BdA-Revente : %s" % spectacle.title, mail, + request.user.email, + [revente.attribution.participant.user.email], + fail_silently=False) + return render(request, "bda-success.html", + {"seller": revente.attribution.participant.user, + "spectacle": spectacle}) - if reventes.exists(): - idx = random.randint(0, reventes.count() - 1) - selected = reventes.all()[idx] return render(request, "revente-confirm.html", - {"selected": selected, "spectacle": spectacle}) + {"spectacle": spectacle, + "user": request.user}) @buro_required From a607f353429cead4a5af4d452edcd6b15091cc50 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 3 Sep 2016 19:39:28 +0200 Subject: [PATCH 022/103] =?UTF-8?q?inscription=20des=20d=C3=A9=C3=A7us=20?= =?UTF-8?q?=C3=A0=20BdA-Revente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/views.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bda/views.py b/bda/views.py index 40bd924d..3641b776 100644 --- a/bda/views.py +++ b/bda/views.py @@ -235,6 +235,11 @@ def do_tirage(request, tirage_id): Attribution(spectacle=show, participant=member) for show, members, _ in results for member, _, _, _ in members]) + # On inscrit à BdA-Revente ceux qui n'ont pas eu les places voulues + for (show, _, losers) in results: + for (loser, _, _, _) in losers: + loser.choicesrevente.add(show) + loser.save() return render(request, "bda-attrib-extra.html", data) else: return render(request, "bda-attrib.html", data) From e9e0be7960cf7c7e5f48d2f18e6f8486efe0de0d Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sun, 4 Sep 2016 11:14:09 +0200 Subject: [PATCH 023/103] =?UTF-8?q?g=C3=A8re=20les=20places=20demand=C3=A9?= =?UTF-8?q?es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/models.py | 32 +++++++++++++++++++++++++++++++ bda/templates/bda-interested.html | 9 +++++++++ bda/urls.py | 3 +++ bda/views.py | 16 +++++++++++++++- 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 bda/templates/bda-interested.html diff --git a/bda/models.py b/bda/models.py index 7856b517..c3621a45 100644 --- a/bda/models.py +++ b/bda/models.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import calendar import datetime +import random from django.db import models from django.contrib.auth.models import User @@ -256,3 +257,34 @@ class SpectacleRevente(models.Model): connection = mail.get_connection() connection.send_messages(mails_to_send) + + def tirage(self): + inscrits = self.interested + spectacle = self.attribution.spectacle + user = self.attribution.participant.user + if inscrits.exists(): + idx = random.randint(0, inscrits.count() - 1) + winner = inscrits.all()[idx] + self.soldTo = winner + mail_buyer = """Bonjour, + +Tu as été tiré-e au sort pour racheter une place pour %s le %s (%s) à %0.02f€. +Tu peux contacter le vendeur à l'adresse %s. + +Chaleureusement, +Le BdA""" % (spectacle.title, spectacle.date_no_seconds(), + spectacle.location, spectacle.price, user.email) + + mail.send_mail("BdA-Revente : %s" % spectacle.title, + mail_buyer, "bda@ens.fr", [winner.user.email], + fail_silently=False) + mail_seller = """Bonjour, +La personne tirée au sort pour racheter ta place pour %s est %s. +Tu peux le/la contacter à l'adresse %s. + +Chaleureusement, +Le BdA""" % (spectacle.title, winner.user.get_full_name(), winner.user.email) + + mail.send_mail("BdA-Revente : %s" % spectacle.title, + mail_seller, "bda@ens.fr", [user.email], + fail_silently=False) diff --git a/bda/templates/bda-interested.html b/bda/templates/bda-interested.html new file mode 100644 index 00000000..acfb1d1e --- /dev/null +++ b/bda/templates/bda-interested.html @@ -0,0 +1,9 @@ +{% extends "base_title.html" %} +{% load staticfiles %} + +{% block realcontent %} +

      Inscription à une revente

      +

      Votre inscription pour a bien été enregistrée !

      +

      Le tirage au sort pour cette revente ({{spectacle}}) sera effectué le {{date}}. + +{% endblock %} diff --git a/bda/urls.py b/bda/urls.py index 13a163f4..94b797fa 100644 --- a/bda/urls.py +++ b/bda/urls.py @@ -38,6 +38,9 @@ urlpatterns = [ url(r'^buy-revente/(?P\d+)$', "bda.views.buy_revente", name="bda-buy-revente"), + url(r'^revente-interested/(?P\d+)$', + "bda.views.revente_interested", + name='bda-revente-interested'), url(r'^mails-rappel/(?P\d+)$', views.send_rappel), url(r'^descriptions/(?P\d+)$', views.descriptions_spectacles, name='bda-descriptions'), diff --git a/bda/views.py b/bda/views.py index 3641b776..a3fd9168 100644 --- a/bda/views.py +++ b/bda/views.py @@ -318,6 +318,20 @@ def revente(request, tirage_id): "annulform": annulform, "resellform": resellform}) +@login_required +def revente_interested(request, revente_id): + revente = get_object_or_404(SpectacleRevente, id=revente_id) + participant, created = Participant.objects.get_or_create( + user=request.user, tirage=revente.attribution.spectacle.tirage) + if timezone.now() < revente.date + timedelta(hours=1) or revente.shotgun: + return render(request, "bda-wrongtime.html", {}) + + revente.interested.add(participant) + return render(request, "bda-interested.html", + {"spectacle": revente.attribution.spectacle, + "date": revente.expiration_time}) + + @login_required def list_revente(request, tirage_id): tirage = get_object_or_404(Tirage, id=tirage_id) @@ -373,7 +387,7 @@ def buy_revente(request, spectacle_id): revente.save() mail = """Bonjour ! -Je souhaiterais racheter ta place pour %s le %s (%s) à %.02f€. +Je souhaiterais racheter ta place pour %s le %s (%s) à %.02f€. Contacte-moi si tu es toujours intéressé·e ! %s (%s)""" % (spectacle.title, spectacle.date_no_seconds(), From 0b40ebb6f75d15f5fafcd06c48f2a926461a81b0 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sun, 4 Sep 2016 11:14:53 +0200 Subject: [PATCH 024/103] corrections de templates --- bda/templates/bda-no-revente.html | 6 ++++++ bda/templates/mail-revente.txt | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 bda/templates/bda-no-revente.html diff --git a/bda/templates/bda-no-revente.html b/bda/templates/bda-no-revente.html new file mode 100644 index 00000000..eabb3dc7 --- /dev/null +++ b/bda/templates/bda-no-revente.html @@ -0,0 +1,6 @@ +{% extends "base_title.html" %} + +{% block realcontent %} +

      BdA-Revente

      +

      Il n'y a plus de places en revente pour ce spectacle, désolé !

      +{% endblock %} diff --git a/bda/templates/mail-revente.txt b/bda/templates/mail-revente.txt index 16655696..adc61eb9 100644 --- a/bda/templates/mail-revente.txt +++ b/bda/templates/mail-revente.txt @@ -1,8 +1,8 @@ Bonjour {{ user.get_full_name }} -Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BDA-Revente. +Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BdA-Revente. -Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : {% url "bda-inscr-revente" revente.id %}. Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à un tirage au sort le {{revente.date_no_seconds}} +Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : {% url "bda-interested-revente" revente.id %}. Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à un tirage au sort le {{revente.date_no_seconds}} Chaleureusement, -Le BDA +Le BdA From 3bc9880db1f0c92bd29669d81ab03185715d0c23 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 5 Sep 2016 02:29:49 +0200 Subject: [PATCH 025/103] revente de revente + confirmation de transfert de places --- bda/forms.py | 7 +++-- bda/models.py | 10 ++++--- bda/templates/bda-revente.html | 23 +++++++++++++++ bda/views.py | 53 ++++++++++++++++++++++++++++++---- 4 files changed, 80 insertions(+), 13 deletions(-) diff --git a/bda/forms.py b/bda/forms.py index 60fdb0fd..0c886e0f 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -52,8 +52,8 @@ class ResellForm(forms.Form): def __init__(self, participant, *args, **kwargs): super(ResellForm, self).__init__(*args, **kwargs) self.fields['attributions'].queryset = participant.attribution_set\ - .filter(spectacle__date__gte=timezone.now(), - revente__isnull=True) + .filter(spectacle__date__gte=timezone.now())\ + .exclude(revente__seller=participant) class AnnulForm(forms.Form): @@ -67,7 +67,8 @@ class AnnulForm(forms.Form): self.fields['attributions'].queryset = participant.attribution_set\ .filter(spectacle__date__gte=timezone.now(), revente__isnull=False, - revente__date__gte=timezone.now()-timedelta(hours=1)) + revente__date__gte=timezone.now()-timedelta(hours=1), + revente__seller=participant) class InscriptionReventeForm(forms.Form): diff --git a/bda/models.py b/bda/models.py index c3621a45..428dbfb7 100644 --- a/bda/models.py +++ b/bda/models.py @@ -221,6 +221,8 @@ class SpectacleRevente(models.Model): interested = models.ManyToManyField(Participant, related_name="wanted", blank=True) + seller = models.ForeignKey(Participant, + related_name="original_shows") soldTo = models.ForeignKey(Participant, blank=True, null=True) def get_expiration_time(self): @@ -235,7 +237,7 @@ class SpectacleRevente(models.Model): shotgun = property(get_shotgun) def __str__(self): - return "%s -- %s" % (self.attribution.participant.user, + return "%s -- %s" % (self.seller, self.attribution.spectacle.title) def send_notif(self): @@ -261,7 +263,7 @@ class SpectacleRevente(models.Model): def tirage(self): inscrits = self.interested spectacle = self.attribution.spectacle - user = self.attribution.participant.user + seller = self.seller if inscrits.exists(): idx = random.randint(0, inscrits.count() - 1) winner = inscrits.all()[idx] @@ -273,7 +275,7 @@ Tu peux contacter le vendeur à l'adresse %s. Chaleureusement, Le BdA""" % (spectacle.title, spectacle.date_no_seconds(), - spectacle.location, spectacle.price, user.email) + spectacle.location, spectacle.price, seller.email) mail.send_mail("BdA-Revente : %s" % spectacle.title, mail_buyer, "bda@ens.fr", [winner.user.email], @@ -286,5 +288,5 @@ Chaleureusement, Le BdA""" % (spectacle.title, winner.user.get_full_name(), winner.user.email) mail.send_mail("BdA-Revente : %s" % spectacle.title, - mail_seller, "bda@ens.fr", [user.email], + mail_seller, "bda@ens.fr", [seller.email], fail_silently=False) diff --git a/bda/templates/bda-revente.html b/bda/templates/bda-revente.html index 0a5cffb3..a5f64678 100644 --- a/bda/templates/bda-revente.html +++ b/bda/templates/bda-revente.html @@ -24,6 +24,7 @@
      +{% if annulform.attributions or overdue %}

      Places en cours de revente

      {% csrf_token %} @@ -45,6 +46,28 @@
    + {% if annulform.attributions %} + {% endif %} +{% endif %} +
    +{% if sold %} +

    Places revendues

    + + {% for attrib in sold %} + + + {% csrf_token %} + + + + + + + {% endfor %} +
    {{attrib.spectacle}}{{attrib.revente.soldTo.user.get_full_name}}
    +{% endif %} {% endblock %} diff --git a/bda/views.py b/bda/views.py index a3fd9168..8c92f4ab 100644 --- a/bda/views.py +++ b/bda/views.py @@ -9,7 +9,7 @@ import random from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.db import models -from django.db.models import Count +from django.db.models import Count, Q from django.core import serializers from django.forms.models import inlineformset_factory from django.http import HttpResponseBadRequest @@ -293,8 +293,14 @@ def revente(request, tirage_id): if resellform.is_valid(): attributions = resellform.cleaned_data["attributions"] for attribution in attributions: - revente = SpectacleRevente(attribution=attribution) + revente, created = SpectacleRevente.objects.get_or_create( + attribution=attribution, + defaults={'seller': participant}) + if not created: + revente.seller = participant + revente.date = timezone.now() revente.save() + elif 'annul' in request.POST: annulform = AnnulForm(participant, request.POST, prefix='annul') resellform = ResellForm(participant, prefix='resell') @@ -302,19 +308,54 @@ def revente(request, tirage_id): attributions = annulform.cleaned_data["attributions"] for attribution in attributions: attribution.revente.delete() + + elif 'transfer' in request.POST: + resellform = ResellForm(participant, prefix='resell') + annulform = AnnulForm(participant, prefix='annul') + + revente_id = request.POST['transfer'][0] + rev = SpectacleRevente.objects.filter(soldTo__isnull=False, + id=revente_id) + if rev.exists(): + revente = rev.get() + attrib = revente.attribution + attrib.participant = revente.soldTo + attrib.save() + + elif 'reinit' in request.POST: + resellform = ResellForm(participant, prefix='resell') + annulform = AnnulForm(participant, prefix='annul') + revente_id = request.POST['transfer'][0] + rev = SpectacleRevente.objects.filter(soldTo__isnull=False, + id=revente_id) + if rev.exists(): + revente = rev.get() + revente.date = timezone.now() - timedelta(hours=1) + revente.soldTo = None + revente.interested = None + # schedule job + else: resellform = ResellForm(participant, prefix='resell') annulform = AnnulForm(participant, prefix='annul') else: resellform = ResellForm(participant, prefix='resell') annulform = AnnulForm(participant, prefix='annul') + overdue = participant.attribution_set.filter( spectacle__date__gte=timezone.now(), revente__isnull=False, - revente__date__lte=timezone.now()-timedelta(hours=1)) + revente__seller=participant, + revente__date__lte=timezone.now()-timedelta(hours=1)).filter( + Q(revente__soldTo__isnull=True) | Q(revente__soldTo=participant)) + sold = participant.attribution_set.filter( + spectacle__date__gte=timezone.now(), + revente__isnull=False, + revente__soldTo__isnull=False).exclude( + revente__soldTo=participant) return render(request, "bda-revente.html", - {'tirage': tirage, 'overdue': overdue, + {'tirage': tirage, 'overdue': overdue, "sold": sold, "annulform": annulform, "resellform": resellform}) @@ -395,10 +436,10 @@ Contacte-moi si tu es toujours intéressé·e ! request.user.get_full_name(), request.user.email) send_mail("BdA-Revente : %s" % spectacle.title, mail, request.user.email, - [revente.attribution.participant.user.email], + [revente.seller.user.email], fail_silently=False) return render(request, "bda-success.html", - {"seller": revente.attribution.participant.user, + {"seller": revente.seller.user, "spectacle": spectacle}) return render(request, "revente-confirm.html", From de522a0035443ab93cdb93533b53c7b3f7c8b8bd Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 5 Sep 2016 02:38:46 +0200 Subject: [PATCH 026/103] fixes + deprecated migration --- bda/forms.py | 6 +++-- bda/migrations/0008_revente.py | 38 ------------------------------- bda/templates/liste-reventes.html | 2 +- 3 files changed, 5 insertions(+), 41 deletions(-) delete mode 100644 bda/migrations/0008_revente.py diff --git a/bda/forms.py b/bda/forms.py index 0c886e0f..c2eec894 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -8,6 +8,7 @@ from datetime import timedelta from django import forms from django.forms.models import BaseInlineFormSet +from django.db.models import Q from django.utils import timezone from bda.models import Attribution, Spectacle @@ -67,8 +68,9 @@ class AnnulForm(forms.Form): self.fields['attributions'].queryset = participant.attribution_set\ .filter(spectacle__date__gte=timezone.now(), revente__isnull=False, - revente__date__gte=timezone.now()-timedelta(hours=1), - revente__seller=participant) + revente__date__gte=timezone.now()-timedelta(hours=1))\ + .filter(Q(revente__soldTo__isnull=True) | + Q(revente__soldTo=participant)) class InscriptionReventeForm(forms.Form): diff --git a/bda/migrations/0008_revente.py b/bda/migrations/0008_revente.py deleted file mode 100644 index 4db2c9de..00000000 --- a/bda/migrations/0008_revente.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('bda', '0007_extends_spectacle'), - ] - - operations = [ - migrations.CreateModel( - name='SpectacleRevente', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date de mise en vente')), - ('attribution', models.OneToOneField(related_name='revente', to='bda.Attribution')), - ], - ), - migrations.AddField( - model_name='participant', - name='choicesrevente', - field=models.ManyToManyField(related_name='revente', to='bda.Spectacle', blank=True), - ), - migrations.AddField( - model_name='spectaclerevente', - name='interested', - field=models.ManyToManyField(related_name='wanted', to='bda.Participant', blank=True), - ), - migrations.AddField( - model_name='spectaclerevente', - name='soldTo', - field=models.ForeignKey(blank=True, to='bda.Participant', null=True), - ), - ] diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 9e4acb92..1920256f 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -12,7 +12,7 @@ {% if shotgun %}

    Places disponibles immédiatement

    -
      +
        {% for spectacle in shotgun %}
      • {{spectacle}}
      • {% endfor %} From b6655047ed8791cbe467b2a2b5033b1ac42fab87 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 5 Sep 2016 03:10:06 +0200 Subject: [PATCH 027/103] verbose names --- bda/admin.py | 11 ++++------- bda/models.py | 9 +++++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/bda/admin.py b/bda/admin.py index b604d65b..37fdf9c7 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -216,16 +216,13 @@ class SpectacleReventeAdmin(admin.ModelAdmin): def spectacle(self, obj): return obj.attribution.spectacle - def participant(self, obj): - return obj.attribution.participant - - list_display = ("spectacle", "participant", "date", "soldTo") + list_display = ("spectacle", "seller", "date", "soldTo") raw_id_fields = ("attribution",) readonly_fields = ("shotgun", "expiration_time") search_fields = ("spectacle__title", - "participant__user__username", - "participant__user__firstname", - "participant__user__lastname",) + "seller__user__username", + "seller__user__firstname", + "seller__user__lastname",) admin.site.register(CategorieSpectacle) diff --git a/bda/models.py b/bda/models.py index 428dbfb7..baed138e 100644 --- a/bda/models.py +++ b/bda/models.py @@ -222,8 +222,10 @@ class SpectacleRevente(models.Model): related_name="wanted", blank=True) seller = models.ForeignKey(Participant, - related_name="original_shows") - soldTo = models.ForeignKey(Participant, blank=True, null=True) + related_name="original_shows", + verbose_name="Vendeur") + soldTo = models.ForeignKey(Participant, blank=True, null=True, + verbose_name="Vendue à") def get_expiration_time(self): remaining_time = (self.attribution.spectacle.date - self.date) @@ -240,6 +242,9 @@ class SpectacleRevente(models.Model): return "%s -- %s" % (self.seller, self.attribution.spectacle.title) + class Meta: + verbose_name = "Revente" + def send_notif(self): # On récupère la liste des inscrits inscrits = self.attribution.spectacle.revente.select_related('user') From f0553d709e6388211477f6afecf8d00f9fbce9bb Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 5 Sep 2016 03:32:29 +0200 Subject: [PATCH 028/103] check lors de l'inscription pour des places en revente --- bda/templates/liste-reventes.html | 3 +++ bda/views.py | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 1920256f..2a5ddc95 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -3,6 +3,9 @@ {% block realcontent %}

        Inscriptions pour BDA-Revente

        + {% if deja_revente %} +

        Des reventes existent déjà pour certains de ces spectacles ; vérifie les places disponibles sans tirage !

        + {% endif %}
        {% csrf_token %} {{form | bootstrap}} diff --git a/bda/views.py b/bda/views.py index 8c92f4ab..dc1f4cb2 100644 --- a/bda/views.py +++ b/bda/views.py @@ -381,6 +381,7 @@ def list_revente(request, tirage_id): spectacles = tirage.spectacle_set.filter( date__gte=timezone.now()) shotgun = [] + deja_revente = False for spectacle in spectacles: revente_objects = SpectacleRevente.objects.filter( attribution__spectacle=spectacle, @@ -399,13 +400,25 @@ def list_revente(request, tirage_id): choices = form.cleaned_data['spectacles'] participant.choicesrevente = choices participant.save() + for spectacle in choices: + qset = SpectacleRevente.objects.filter( + attribution__spectacle=spectacle) + if qset.exists(): + # On l'inscrit à l'un des tirages au sort + for revente in qset.all(): + if not revente.shotgun: + revente.interested.add(participant) + break + deja_revente = True + else: form = InscriptionReventeForm( tirage, initial={'spectacles': participant.choicesrevente.all()}) return render(request, "liste-reventes.html", - {"form": form, 'shotgun': shotgun}) + {"form": form, 'shotgun': shotgun, + "deja_revente": deja_revente}) @login_required From 2a56f8e255b86e6a9bdc0fc89d3b097a48e9d894 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sun, 11 Sep 2016 13:32:38 +0200 Subject: [PATCH 029/103] buy more than one place --- bda/forms.py | 8 ++++++++ bda/views.py | 29 ++++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/bda/forms.py b/bda/forms.py index c2eec894..f50c496b 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -44,6 +44,14 @@ class AttributionModelMultipleChoiceField(forms.ModelMultipleChoiceField): return "%s" % obj.spectacle +class BuyResellForm(forms.Form): + num = forms.ChoiceField(choices=[]) + + def __init__(self, spectacle, *args, **kwargs): + super(BuyResellForm, self).__init__(*args, **kwargs) + self.fields['num'].choices = range(1, spectacle.revente.count()) + + class ResellForm(forms.Form): attributions = AttributionModelMultipleChoiceField( queryset=Attribution.objects.none(), diff --git a/bda/views.py b/bda/views.py index dc1f4cb2..7b3b30e9 100644 --- a/bda/views.py +++ b/bda/views.py @@ -28,7 +28,7 @@ from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ from bda.algorithm import Algorithm from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ - InscriptionReventeForm + InscriptionReventeForm, BuyResellForm @cof_required @@ -435,11 +435,14 @@ def buy_revente(request, spectacle_id): return render(request, "bda-no-revente.html", {}) if request.POST: - idx = random.randint(0, reventes.count() - 1) - revente = reventes.all()[idx] - revente.soldTo = participant - revente.save() - mail = """Bonjour ! + form = BuyResellForm(spectacle, request.POST) + if form.is_valid(): + num = form.cleaned_data['num'] + reventes = random.sample(reventes.all(), num) + for revente in reventes: + revente.soldTo = participant + revente.save() + mail = """Bonjour ! Je souhaiterais racheter ta place pour %s le %s (%s) à %.02f€. Contacte-moi si tu es toujours intéressé·e ! @@ -447,13 +450,13 @@ Contacte-moi si tu es toujours intéressé·e ! %s (%s)""" % (spectacle.title, spectacle.date_no_seconds(), spectacle.location, spectacle.price, request.user.get_full_name(), request.user.email) - send_mail("BdA-Revente : %s" % spectacle.title, mail, - request.user.email, - [revente.seller.user.email], - fail_silently=False) - return render(request, "bda-success.html", - {"seller": revente.seller.user, - "spectacle": spectacle}) + send_mail("BdA-Revente : %s" % spectacle.title, mail, + request.user.email, + [revente.seller.user.email], + fail_silently=False) + return render(request, "bda-success.html", + {"seller": revente.seller.user, + "spectacle": spectacle}) return render(request, "revente-confirm.html", {"spectacle": spectacle, From f67933891072a91cecd8e9d918155ea5fd3befb2 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 19 Sep 2016 16:08:12 +0200 Subject: [PATCH 030/103] scrap buying many resells --- bda/forms.py | 8 -------- bda/models.py | 3 +-- bda/templates/revente-confirm.html | 7 ++++--- bda/views.py | 28 ++++++++++++---------------- 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/bda/forms.py b/bda/forms.py index f50c496b..c2eec894 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -44,14 +44,6 @@ class AttributionModelMultipleChoiceField(forms.ModelMultipleChoiceField): return "%s" % obj.spectacle -class BuyResellForm(forms.Form): - num = forms.ChoiceField(choices=[]) - - def __init__(self, spectacle, *args, **kwargs): - super(BuyResellForm, self).__init__(*args, **kwargs) - self.fields['num'].choices = range(1, spectacle.revente.count()) - - class ResellForm(forms.Form): attributions = AttributionModelMultipleChoiceField( queryset=Attribution.objects.none(), diff --git a/bda/models.py b/bda/models.py index ad9df179..9b467f9c 100644 --- a/bda/models.py +++ b/bda/models.py @@ -272,8 +272,7 @@ class SpectacleRevente(models.Model): spectacle = self.attribution.spectacle seller = self.seller if inscrits.exists(): - idx = random.randint(0, inscrits.count() - 1) - winner = inscrits.all()[idx] + winner = random.choice(inscrits.all()) self.soldTo = winner mail_buyer = """Bonjour, diff --git a/bda/templates/revente-confirm.html b/bda/templates/revente-confirm.html index 60cac8b8..d7614c25 100644 --- a/bda/templates/revente-confirm.html +++ b/bda/templates/revente-confirm.html @@ -1,9 +1,11 @@ {% extends "base_title.html" %} {% load staticfiles %} + {%block realcontent %}

        Rachat d'une place

        -Note : ce mail sera envoyé à une personne au hasard revendant sa place. + +{% csrf_token %}
         Bonjour !
         
        @@ -12,8 +14,7 @@ Contacte-moi si tu es toujours intéressé-e !
         
         {{user.get_full_name}} ({{user.email}})
         
        - -{% csrf_token %} +

        Note : ce mail sera envoyé à une personne au hasard revendant sa place.

        {%endblock%} diff --git a/bda/views.py b/bda/views.py index 7b3b30e9..7ea26df4 100644 --- a/bda/views.py +++ b/bda/views.py @@ -28,7 +28,7 @@ from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ from bda.algorithm import Algorithm from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ - InscriptionReventeForm, BuyResellForm + InscriptionReventeForm @cof_required @@ -435,14 +435,10 @@ def buy_revente(request, spectacle_id): return render(request, "bda-no-revente.html", {}) if request.POST: - form = BuyResellForm(spectacle, request.POST) - if form.is_valid(): - num = form.cleaned_data['num'] - reventes = random.sample(reventes.all(), num) - for revente in reventes: - revente.soldTo = participant - revente.save() - mail = """Bonjour ! + revente = random.choice(reventes.all(), 1) + revente.soldTo = participant + revente.save() + mail = """Bonjour ! Je souhaiterais racheter ta place pour %s le %s (%s) à %.02f€. Contacte-moi si tu es toujours intéressé·e ! @@ -450,13 +446,13 @@ Contacte-moi si tu es toujours intéressé·e ! %s (%s)""" % (spectacle.title, spectacle.date_no_seconds(), spectacle.location, spectacle.price, request.user.get_full_name(), request.user.email) - send_mail("BdA-Revente : %s" % spectacle.title, mail, - request.user.email, - [revente.seller.user.email], - fail_silently=False) - return render(request, "bda-success.html", - {"seller": revente.seller.user, - "spectacle": spectacle}) + send_mail("BdA-Revente : %s" % spectacle.title, mail, + request.user.email, + [revente.seller.user.email], + fail_silently=False) + return render(request, "bda-success.html", + {"seller": revente.participant.user, + "spectacle": spectacle}) return render(request, "revente-confirm.html", {"spectacle": spectacle, From 051a979a9baecf2b46b35fb14e800ec43f448178 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 21 Sep 2016 15:30:41 +0200 Subject: [PATCH 031/103] added cron management --- bda/management/commands/manage_reventes.py | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 bda/management/commands/manage_reventes.py diff --git a/bda/management/commands/manage_reventes.py b/bda/management/commands/manage_reventes.py new file mode 100644 index 00000000..9fea3f6a --- /dev/null +++ b/bda/management/commands/manage_reventes.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from django.core.management import BaseCommand +from django.utils import timezone +from datetime import timedelta +from bda.models import SpectacleRevente + + +class Command(BaseCommand): + help = "Envoie les mails de notification et effectue " \ + "les tirages au sort des reventes" + + def handle(self, *args, **options): + now = timezone.now() + reventes = SpectacleRevente.objects.all() + for revente in reventes: + # Check si < 24h + if (revente.attribution.spectacle.date <= + revente.date + timedelta(days=1)) and \ + now >= revente.date + timedelta(minutes=15) and \ + not revente.notif_sent: + revente.mail_shotgun() + # Check si délai de retrait dépassé + elif (now >= revente.date + timedelta(hours=1) and + not revente.notif_sent): + revente.send_notif() + # Check si tirage à faire + elif (now >= revente.expiration_time and + not revente.tirage_done): + revente.tirage() From 6b63f0f30f6bab9e5938c0ee9511dbf867ef7792 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 21 Sep 2016 15:39:01 +0200 Subject: [PATCH 032/103] end --- bda/models.py | 51 ++++++++++++++++++++++++++++------ bda/templates/mail-shotgun.txt | 8 ++++++ bda/views.py | 11 ++++++-- 3 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 bda/templates/mail-shotgun.txt diff --git a/bda/models.py b/bda/models.py index 9b467f9c..b97db2c2 100644 --- a/bda/models.py +++ b/bda/models.py @@ -5,8 +5,8 @@ from __future__ import print_function from __future__ import unicode_literals import calendar -import datetime import random +from datetime import timedelta from django.db import models from django.contrib.auth.models import User @@ -229,15 +229,29 @@ class SpectacleRevente(models.Model): soldTo = models.ForeignKey(Participant, blank=True, null=True, verbose_name="Vendue à") + notif_sent = models.BooleanField("Notification envoyée", + default=False) + tirage_done = models.BooleanField("Tirage effectué", + default=False) + def get_expiration_time(self): - remaining_time = (self.attribution.spectacle.date - self.date) - delay = max(datetime.timedelta(hours=2), - min(remaining_time//2, datetime.timedelta(days=2))) - return self.date + delay + datetime.timedelta(hours=1) + # L'acheteur doit être connu au plus 12h avant le spectacle + remaining_time = (self.attribution.spectacle.date + - self.date - timedelta(hours=13)) + # Au minimum, on attend 2 jours avant le tirage + delay = min(remaining_time, timedelta(days=2)) + # On a aussi 1h pour changer d'avis + return self.date + delay + timedelta(hours=1) expiration_time = property(get_expiration_time) def get_shotgun(self): - return timezone.now() > self.expiration_time + # Soit on a dépassé le délai du tirage, soit il reste peu de + # temps avant le spectacle + # On se laisse 5min de marge pour cron + return (timezone.now() > self.expiration_time + timedelta(minutes=5) or + (self.attribution.spectacle.date <= timezone.now() + + timedelta(days=1))) and (timezone.now() >= self.date + + timedelta(minutes=15)) shotgun = property(get_shotgun) def __str__(self): @@ -248,7 +262,6 @@ class SpectacleRevente(models.Model): verbose_name = "Revente" def send_notif(self): - # On récupère la liste des inscrits inscrits = self.attribution.spectacle.revente.select_related('user') mails_to_send = [] @@ -260,12 +273,33 @@ class SpectacleRevente(models.Model): 'revente': self}) mail_tot = mail.EmailMessage( mail_object, mail_body, - settings.REVENTE_FROM, [participant.email], + settings.REVENTE_FROM, [participant.user.email], [], headers={'Reply-To': settings.REVENTE_REPLY_TO}) mails_to_send.append(mail_tot) connection = mail.get_connection() connection.send_messages(mails_to_send) + self.notif_sent = True + + def mail_shotgun(self): + inscrits = self.attribution.spectacle.revente.select_related('user') + + mails_to_send = [] + mail_object = "%s" % (self.attribution.spectacle) + for participant in inscrits: + mail_body = render_template('mail-shotgun.txt', { + 'user': participant.user, + 'spectacle': self.spectacle, + 'mail': self.attribution.participant.user.email}) + mail_tot = mail.EmailMessage( + mail_object, mail_body, + settings.REVENTE_FROM, [participant.user.email], + [], headers={'Reply-To': settings.REVENTE_REPLY_TO}) + mails_to_send.append(mail_tot) + + connection = mail.get_connection() + connection.send_messages(mails_to_send) + self.notif_sent = True def tirage(self): inscrits = self.interested @@ -296,3 +330,4 @@ Le BdA""" % (spectacle.title, winner.user.get_full_name(), winner.user.email) mail.send_mail("BdA-Revente : %s" % spectacle.title, mail_seller, "bda@ens.fr", [seller.email], fail_silently=False) + self.tirage_done = True diff --git a/bda/templates/mail-shotgun.txt b/bda/templates/mail-shotgun.txt new file mode 100644 index 00000000..8c4e7bd9 --- /dev/null +++ b/bda/templates/mail-shotgun.txt @@ -0,0 +1,8 @@ +Bonjour {{ user.get_full_name }} + +Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BdA-Revente. + +Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour cette place : elle est disponible immédiatement à l'addresse {{url "bda-buy-revente" spectacle.id}}, à la disposition de tous. + +Chaleureusement, +Le BdA diff --git a/bda/views.py b/bda/views.py index 7ea26df4..3b36379f 100644 --- a/bda/views.py +++ b/bda/views.py @@ -12,7 +12,8 @@ from django.db import models from django.db.models import Count, Q from django.core import serializers from django.forms.models import inlineformset_factory -from django.http import HttpResponseBadRequest +from django.http import HttpResponseBadRequest, HttpResponseRedirect +from django.core.urlresolvers import reverse import hashlib from django.core.mail import send_mail @@ -325,7 +326,7 @@ def revente(request, tirage_id): elif 'reinit' in request.POST: resellform = ResellForm(participant, prefix='resell') annulform = AnnulForm(participant, prefix='annul') - revente_id = request.POST['transfer'][0] + revente_id = request.POST['reinit'][0] rev = SpectacleRevente.objects.filter(soldTo__isnull=False, id=revente_id) if rev.exists(): @@ -333,7 +334,6 @@ def revente(request, tirage_id): revente.date = timezone.now() - timedelta(hours=1) revente.soldTo = None revente.interested = None - # schedule job else: resellform = ResellForm(participant, prefix='resell') @@ -430,6 +430,11 @@ def buy_revente(request, spectacle_id): reventes = SpectacleRevente.objects.filter( attribution__spectacle=spectacle, soldTo__isnull=True) + if reventes.filter(seller=participant).exists(): + revente = reventes.filter(seller=participant)[0] + revente.delete() + return HttpResponseRedirect(reverse("bda-liste-revente", + args=[tirage.id])) if not reventes.exists(): return render(request, "bda-no-revente.html", {}) From 81d1bc27506943c198b77cd12db055bf00c8f31c Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 21 Sep 2016 15:40:31 +0200 Subject: [PATCH 033/103] migration --- bda/migrations/0009_revente.py | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 bda/migrations/0009_revente.py diff --git a/bda/migrations/0009_revente.py b/bda/migrations/0009_revente.py new file mode 100644 index 00000000..258762c7 --- /dev/null +++ b/bda/migrations/0009_revente.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0008_py3'), + ] + + operations = [ + migrations.CreateModel( + name='SpectacleRevente', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date de mise en vente')), + ('notif_sent', models.BooleanField(default=False, verbose_name='Notification envoy\xe9e')), + ('tirage_done', models.BooleanField(default=False, verbose_name='Tirage effectu\xe9')), + ('attribution', models.OneToOneField(related_name='revente', to='bda.Attribution')), + ], + options={ + 'verbose_name': 'Revente', + }, + ), + migrations.AddField( + model_name='participant', + name='choicesrevente', + field=models.ManyToManyField(related_name='revente', to='bda.Spectacle', blank=True), + ), + migrations.AddField( + model_name='spectaclerevente', + name='interested', + field=models.ManyToManyField(related_name='wanted', to='bda.Participant', blank=True), + ), + migrations.AddField( + model_name='spectaclerevente', + name='seller', + field=models.ForeignKey(related_name='original_shows', verbose_name='Vendeur', to='bda.Participant'), + ), + migrations.AddField( + model_name='spectaclerevente', + name='soldTo', + field=models.ForeignKey(verbose_name='Vendue \xe0', blank=True, to='bda.Participant', null=True), + ), + ] From a5e6a8e635694e26cd209a9b4a286a7b1b4d6702 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sun, 25 Sep 2016 12:12:31 +0200 Subject: [PATCH 034/103] fix message liste_revente --- bda/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bda/views.py b/bda/views.py index 3b36379f..241bc90d 100644 --- a/bda/views.py +++ b/bda/views.py @@ -406,11 +406,11 @@ def list_revente(request, tirage_id): if qset.exists(): # On l'inscrit à l'un des tirages au sort for revente in qset.all(): - if not revente.shotgun: + if revente.shotgun: + deja_revente = True + else: revente.interested.add(participant) break - deja_revente = True - else: form = InscriptionReventeForm( tirage, From bbfce33c3f9cb75cf69d4970cfd6524ac9b55950 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sun, 25 Sep 2016 14:39:18 +0200 Subject: [PATCH 035/103] corrects bug with bda-buy --- bda/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bda/views.py b/bda/views.py index 241bc90d..bac7415d 100644 --- a/bda/views.py +++ b/bda/views.py @@ -440,7 +440,7 @@ def buy_revente(request, spectacle_id): return render(request, "bda-no-revente.html", {}) if request.POST: - revente = random.choice(reventes.all(), 1) + revente = random.choice(reventes.all()) revente.soldTo = participant revente.save() mail = """Bonjour ! @@ -456,7 +456,7 @@ Contacte-moi si tu es toujours intéressé·e ! [revente.seller.user.email], fail_silently=False) return render(request, "bda-success.html", - {"seller": revente.participant.user, + {"seller": revente.attribution.participant.user, "spectacle": spectacle}) return render(request, "revente-confirm.html", From 8a3f4b7431ed8588116cd8f602caa8cb8b87d851 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sun, 25 Sep 2016 14:39:38 +0200 Subject: [PATCH 036/103] template fixes --- bda/templates/bda-notpaid.html | 2 +- bda/templates/bda-wrongtime.html | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 bda/templates/bda-wrongtime.html diff --git a/bda/templates/bda-notpaid.html b/bda/templates/bda-notpaid.html index b25c2ba3..0dd4e4df 100644 --- a/bda/templates/bda-notpaid.html +++ b/bda/templates/bda-notpaid.html @@ -1,6 +1,6 @@ {% extends "base_title.html" %} {% block realcontent %} -

        Nope

        +

        Nope

        Avant de revendre des places, il faut aller les payer !

        {% endblock %} diff --git a/bda/templates/bda-wrongtime.html b/bda/templates/bda-wrongtime.html new file mode 100644 index 00000000..5e17926b --- /dev/null +++ b/bda/templates/bda-wrongtime.html @@ -0,0 +1,6 @@ +{% extends "base_title.html" %} + +{% block realcontent %} +

        Nope

        +

        Cette revente n'est pas disponible actuellement, désolé !

        +{% endblock %} From 15e755334dde6a1ca56ee70ea1af1fba2d480c56 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 26 Sep 2016 15:31:09 +0200 Subject: [PATCH 037/103] cron --- bda/management/commands/manage_reventes.py | 4 ++++ provisioning/cron.dev | 1 + provisioning/cron.md | 11 +++++++++++ 3 files changed, 16 insertions(+) diff --git a/bda/management/commands/manage_reventes.py b/bda/management/commands/manage_reventes.py index 9fea3f6a..f45357b1 100644 --- a/bda/management/commands/manage_reventes.py +++ b/bda/management/commands/manage_reventes.py @@ -14,6 +14,7 @@ class Command(BaseCommand): def handle(self, *args, **options): now = timezone.now() + self.stdout.write(now) reventes = SpectacleRevente.objects.all() for revente in reventes: # Check si < 24h @@ -22,11 +23,14 @@ class Command(BaseCommand): now >= revente.date + timedelta(minutes=15) and \ not revente.notif_sent: revente.mail_shotgun() + self.stdout.write("Mail de disponibilité immédiate envoyé") # Check si délai de retrait dépassé elif (now >= revente.date + timedelta(hours=1) and not revente.notif_sent): revente.send_notif() + self.stdout.write("Mail d'inscription à une revente envoyé") # Check si tirage à faire elif (now >= revente.expiration_time and not revente.tirage_done): revente.tirage() + self.stdout.write("Tirage effectué, mails envoyés") diff --git a/provisioning/cron.dev b/provisioning/cron.dev index d249d547..6cd2ca81 100644 --- a/provisioning/cron.dev +++ b/provisioning/cron.dev @@ -7,3 +7,4 @@ DBNAME="cof_gestion" DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" 19 */12 * * * date >> /vagrant/rappels.log ; python /vagrant/manage.py sendrappels >> /vagrant/rappels.log 2>&1 +*/5 * * * * python /vagrant/manage.py manage_revente >> /vagrant/reventes.log 2>&1 diff --git a/provisioning/cron.md b/provisioning/cron.md index 8b3f608e..840a8716 100644 --- a/provisioning/cron.md +++ b/provisioning/cron.md @@ -14,3 +14,14 @@ envoyés). - Garde les logs peut être une bonne idée. Exemple : voir le fichier `provisioning/cron.dev`. + +## Gestion des mails de revente + +Il faut effectuer très régulièrement la commande `manage_reventes` de GestioCOF, +qui gère toutes les actions associées à BdA-Revente : envoi des mails de notification, +tirages. + +- Pour l'instant un délai de 5 min est hardcodé +- Garde des logs ; ils vont finir par être assez lourds si on a beaucoup de reventes. + +Exemple : provisioning/cron.dev From 59b8f406b652ffb1ddd9a20a726d3e5461264cf7 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 26 Sep 2016 15:53:58 +0200 Subject: [PATCH 038/103] fix bug shotgun --- bda/views.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bda/views.py b/bda/views.py index bac7415d..12c57d49 100644 --- a/bda/views.py +++ b/bda/views.py @@ -406,7 +406,7 @@ def list_revente(request, tirage_id): if qset.exists(): # On l'inscrit à l'un des tirages au sort for revente in qset.all(): - if revente.shotgun: + if revente.shotgun and not revente.soldTo: deja_revente = True else: revente.interested.add(participant) @@ -435,12 +435,16 @@ def buy_revente(request, spectacle_id): revente.delete() return HttpResponseRedirect(reverse("bda-liste-revente", args=[tirage.id])) + reventes_shotgun = [] + for revente in reventes.all(): + if revente.shotgun: + reventes_shotgun.append(revente) - if not reventes.exists(): + if reventes_shotgun.empty(): return render(request, "bda-no-revente.html", {}) if request.POST: - revente = random.choice(reventes.all()) + revente = random.choice(reventes_shotgun) revente.soldTo = participant revente.save() mail = """Bonjour ! From 3943c3ab9ff39b363804695fa2b7209119266ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 26 Sep 2016 16:03:33 +0200 Subject: [PATCH 039/103] PEP8 --- bda/migrations/0009_revente.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/bda/migrations/0009_revente.py b/bda/migrations/0009_revente.py index 258762c7..0c039700 100644 --- a/bda/migrations/0009_revente.py +++ b/bda/migrations/0009_revente.py @@ -15,11 +15,17 @@ class Migration(migrations.Migration): migrations.CreateModel( name='SpectacleRevente', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date de mise en vente')), - ('notif_sent', models.BooleanField(default=False, verbose_name='Notification envoy\xe9e')), - ('tirage_done', models.BooleanField(default=False, verbose_name='Tirage effectu\xe9')), - ('attribution', models.OneToOneField(related_name='revente', to='bda.Attribution')), + ('id', models.AutoField(verbose_name='ID', serialize=False, + auto_created=True, primary_key=True)), + ('date', models.DateTimeField( + default=django.utils.timezone.now, + verbose_name='Date de mise en vente')), + ('notif_sent', models.BooleanField( + default=False, verbose_name='Notification envoy\xe9e')), + ('tirage_done', models.BooleanField( + default=False, verbose_name='Tirage effectu\xe9')), + ('attribution', models.OneToOneField(related_name='revente', + to='bda.Attribution')), ], options={ 'verbose_name': 'Revente', @@ -28,21 +34,26 @@ class Migration(migrations.Migration): migrations.AddField( model_name='participant', name='choicesrevente', - field=models.ManyToManyField(related_name='revente', to='bda.Spectacle', blank=True), + field=models.ManyToManyField(related_name='revente', + to='bda.Spectacle', blank=True), ), migrations.AddField( model_name='spectaclerevente', name='interested', - field=models.ManyToManyField(related_name='wanted', to='bda.Participant', blank=True), + field=models.ManyToManyField(related_name='wanted', + to='bda.Participant', blank=True), ), migrations.AddField( model_name='spectaclerevente', name='seller', - field=models.ForeignKey(related_name='original_shows', verbose_name='Vendeur', to='bda.Participant'), + field=models.ForeignKey(related_name='original_shows', + verbose_name='Vendeur', + to='bda.Participant'), ), migrations.AddField( model_name='spectaclerevente', name='soldTo', - field=models.ForeignKey(verbose_name='Vendue \xe0', blank=True, to='bda.Participant', null=True), + field=models.ForeignKey(verbose_name='Vendue \xe0', blank=True, + to='bda.Participant', null=True), ), ] From bc4b06fc9246446a8de367eaee794e3cfad84327 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 26 Sep 2016 20:41:59 +0200 Subject: [PATCH 040/103] fix save --- bda/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bda/models.py b/bda/models.py index b97db2c2..61937723 100644 --- a/bda/models.py +++ b/bda/models.py @@ -280,6 +280,7 @@ class SpectacleRevente(models.Model): connection = mail.get_connection() connection.send_messages(mails_to_send) self.notif_sent = True + self.save() def mail_shotgun(self): inscrits = self.attribution.spectacle.revente.select_related('user') @@ -300,6 +301,7 @@ class SpectacleRevente(models.Model): connection = mail.get_connection() connection.send_messages(mails_to_send) self.notif_sent = True + self.save() def tirage(self): inscrits = self.interested @@ -331,3 +333,4 @@ Le BdA""" % (spectacle.title, winner.user.get_full_name(), winner.user.email) mail_seller, "bda@ens.fr", [seller.email], fail_silently=False) self.tirage_done = True + self.save() From 4a8d17f3543a75ccfe1eeb5e2d64b9d98105caa5 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 26 Sep 2016 20:44:22 +0200 Subject: [PATCH 041/103] change property --- bda/models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bda/models.py b/bda/models.py index 61937723..c3b28d5b 100644 --- a/bda/models.py +++ b/bda/models.py @@ -234,7 +234,8 @@ class SpectacleRevente(models.Model): tirage_done = models.BooleanField("Tirage effectué", default=False) - def get_expiration_time(self): + @property + def expiration_time(self): # L'acheteur doit être connu au plus 12h avant le spectacle remaining_time = (self.attribution.spectacle.date - self.date - timedelta(hours=13)) @@ -242,9 +243,9 @@ class SpectacleRevente(models.Model): delay = min(remaining_time, timedelta(days=2)) # On a aussi 1h pour changer d'avis return self.date + delay + timedelta(hours=1) - expiration_time = property(get_expiration_time) - def get_shotgun(self): + @property + def shotgun(self): # Soit on a dépassé le délai du tirage, soit il reste peu de # temps avant le spectacle # On se laisse 5min de marge pour cron @@ -252,7 +253,6 @@ class SpectacleRevente(models.Model): (self.attribution.spectacle.date <= timezone.now() + timedelta(days=1))) and (timezone.now() >= self.date + timedelta(minutes=15)) - shotgun = property(get_shotgun) def __str__(self): return "%s -- %s" % (self.seller, From 77511d8acdd21c4cb4d20f6fd32d4a27a15a3568 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Tue, 27 Sep 2016 15:44:27 +0200 Subject: [PATCH 042/103] more coherent names --- bda/models.py | 14 +++++++------- bda/views.py | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bda/models.py b/bda/models.py index c3b28d5b..1074e58b 100644 --- a/bda/models.py +++ b/bda/models.py @@ -161,7 +161,7 @@ class Participant(models.Model): blank=True) tirage = models.ForeignKey(Tirage) choicesrevente = models.ManyToManyField(Spectacle, - related_name="revente", + related_name="subscribed", blank=True) def __str__(self): @@ -220,9 +220,9 @@ class SpectacleRevente(models.Model): related_name="revente") date = models.DateTimeField("Date de mise en vente", default=timezone.now) - interested = models.ManyToManyField(Participant, - related_name="wanted", - blank=True) + answered_mail = models.ManyToManyField(Participant, + related_name="wanted", + blank=True) seller = models.ForeignKey(Participant, related_name="original_shows", verbose_name="Vendeur") @@ -262,7 +262,7 @@ class SpectacleRevente(models.Model): verbose_name = "Revente" def send_notif(self): - inscrits = self.attribution.spectacle.revente.select_related('user') + inscrits = self.attribution.spectacle.subscribed.select_related('user') mails_to_send = [] mail_object = "%s" % (self.attribution.spectacle) @@ -283,7 +283,7 @@ class SpectacleRevente(models.Model): self.save() def mail_shotgun(self): - inscrits = self.attribution.spectacle.revente.select_related('user') + inscrits = self.attribution.spectacle.subscribed.select_related('user') mails_to_send = [] mail_object = "%s" % (self.attribution.spectacle) @@ -304,7 +304,7 @@ class SpectacleRevente(models.Model): self.save() def tirage(self): - inscrits = self.interested + inscrits = self.answered_mail spectacle = self.attribution.spectacle seller = self.seller if inscrits.exists(): diff --git a/bda/views.py b/bda/views.py index 79212710..e9a000cb 100644 --- a/bda/views.py +++ b/bda/views.py @@ -333,7 +333,7 @@ def revente(request, tirage_id): revente = rev.get() revente.date = timezone.now() - timedelta(hours=1) revente.soldTo = None - revente.interested = None + revente.answered_mail = None else: resellform = ResellForm(participant, prefix='resell') @@ -367,7 +367,7 @@ def revente_interested(request, revente_id): if timezone.now() < revente.date + timedelta(hours=1) or revente.shotgun: return render(request, "bda-wrongtime.html", {}) - revente.interested.add(participant) + revente.answered_mail.add(participant) return render(request, "bda-interested.html", {"spectacle": revente.attribution.spectacle, "date": revente.expiration_time}) @@ -409,7 +409,7 @@ def list_revente(request, tirage_id): if revente.shotgun and not revente.soldTo: deja_revente = True else: - revente.interested.add(participant) + revente.answered_mail.add(participant) break else: form = InscriptionReventeForm( From a9d44aa16e1e119989fa26bb82ff047b774172ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Tue, 27 Sep 2016 16:19:23 +0200 Subject: [PATCH 043/103] Correction des noms dans la migration --- bda/migrations/0009_revente.py | 41 ++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/bda/migrations/0009_revente.py b/bda/migrations/0009_revente.py index 0c039700..1cca4e86 100644 --- a/bda/migrations/0009_revente.py +++ b/bda/migrations/0009_revente.py @@ -15,17 +15,15 @@ class Migration(migrations.Migration): migrations.CreateModel( name='SpectacleRevente', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, - auto_created=True, primary_key=True)), + ('id', models.AutoField(serialize=False, primary_key=True, + auto_created=True, verbose_name='ID')), ('date', models.DateTimeField( - default=django.utils.timezone.now, - verbose_name='Date de mise en vente')), + verbose_name='Date de mise en vente', + default=django.utils.timezone.now)), ('notif_sent', models.BooleanField( - default=False, verbose_name='Notification envoy\xe9e')), + verbose_name='Notification envoyée', default=False)), ('tirage_done', models.BooleanField( - default=False, verbose_name='Tirage effectu\xe9')), - ('attribution', models.OneToOneField(related_name='revente', - to='bda.Attribution')), + verbose_name='Tirage effectué', default=False)), ], options={ 'verbose_name': 'Revente', @@ -34,26 +32,35 @@ class Migration(migrations.Migration): migrations.AddField( model_name='participant', name='choicesrevente', - field=models.ManyToManyField(related_name='revente', - to='bda.Spectacle', blank=True), + field=models.ManyToManyField(to='bda.Spectacle', + related_name='subscribed', + blank=True), ), migrations.AddField( model_name='spectaclerevente', - name='interested', - field=models.ManyToManyField(related_name='wanted', - to='bda.Participant', blank=True), + name='answered_mail', + field=models.ManyToManyField(to='bda.Participant', + related_name='wanted', + blank=True), + ), + migrations.AddField( + model_name='spectaclerevente', + name='attribution', + field=models.OneToOneField(to='bda.Attribution', + related_name='revente'), ), migrations.AddField( model_name='spectaclerevente', name='seller', - field=models.ForeignKey(related_name='original_shows', + field=models.ForeignKey(to='bda.Participant', verbose_name='Vendeur', - to='bda.Participant'), + related_name='original_shows'), ), migrations.AddField( model_name='spectaclerevente', name='soldTo', - field=models.ForeignKey(verbose_name='Vendue \xe0', blank=True, - to='bda.Participant', null=True), + field=models.ForeignKey(to='bda.Participant', + verbose_name='Vendue à', null=True, + blank=True), ), ] From 103b2880f751375a66e845f2ee36f8f69bdd9637 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Tue, 27 Sep 2016 16:57:39 +0200 Subject: [PATCH 044/103] BdA --- bda/templates/liste-reventes.html | 2 +- cof/settings_dev.py | 2 +- gestioncof/admin.py | 4 ++-- gestioncof/templates/home.html | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 2a5ddc95..2a236176 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -2,7 +2,7 @@ {% load bootstrap %} {% block realcontent %} -

        Inscriptions pour BDA-Revente

        +

        Inscriptions pour BdA-Revente

        {% if deja_revente %}

        Des reventes existent déjà pour certains de ces spectacles ; vérifie les places disponibles sans tirage !

        {% endif %} diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 7d270648..0ed4a618 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -152,7 +152,7 @@ PETITS_COURS_REPLYTO = "cof@ens.fr" RAPPEL_FROM = 'Le BdA ' RAPPEL_REPLY_TO = RAPPEL_FROM -REVENTE_FROM = 'BDA-Revente ' +REVENTE_FROM = 'BdA-Revente ' REVENTE_REPLY_TO = REVENTE_FROM LOGIN_URL = "/gestion/login" diff --git a/gestioncof/admin.py b/gestioncof/admin.py index 58b37115..eb8ad6c0 100644 --- a/gestioncof/admin.py +++ b/gestioncof/admin.py @@ -144,9 +144,9 @@ User.profile_phone = ProfileInfo("phone", "Téléphone") User.profile_occupation = ProfileInfo("occupation", "Occupation") User.profile_departement = ProfileInfo("departement", "Departement") User.profile_mailing_cof = ProfileInfo("mailing_cof", "ML COF", True) -User.profile_mailing_bda = ProfileInfo("mailing_bda", "ML BDA", True) +User.profile_mailing_bda = ProfileInfo("mailing_bda", "ML BdA", True) User.profile_mailing_bda_revente = ProfileInfo("mailing_bda_revente", - "ML BDA-R", True) + "ML BdA-R", True) class UserProfileAdmin(UserAdmin): diff --git a/gestioncof/templates/home.html b/gestioncof/templates/home.html index 0cd32ebf..35a6bc06 100644 --- a/gestioncof/templates/home.html +++ b/gestioncof/templates/home.html @@ -43,7 +43,7 @@ {% else %}
      • Mes places
      • Revendre une place
      • -
      • S'inscrire à BDA-Revente
      • +
      • S'inscrire à BdA-Revente
      • {% endif %}
      {% endfor %} @@ -83,7 +83,7 @@ {% endfor %}
    -

    Gestion tirages BDA

    +

    Gestion tirages BdA

    {% if active_tirages %} {% for tirage in active_tirages %} From 284dc12b7c1a9b212ec2bbad47e51ea0e9e61d34 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Tue, 27 Sep 2016 17:35:29 +0200 Subject: [PATCH 045/103] success message --- bda/templates/liste-reventes.html | 3 +++ bda/views.py | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 2a236176..78f3ac08 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -3,6 +3,9 @@ {% block realcontent %}

    Inscriptions pour BdA-Revente

    + {% if success %} +

    Ton inscription a bien été prise en compte !

    + {% endif %} {% if deja_revente %}

    Des reventes existent déjà pour certains de ces spectacles ; vérifie les places disponibles sans tirage !

    {% endif %} diff --git a/bda/views.py b/bda/views.py index e9a000cb..c72e5b1d 100644 --- a/bda/views.py +++ b/bda/views.py @@ -382,6 +382,7 @@ def list_revente(request, tirage_id): date__gte=timezone.now()) shotgun = [] deja_revente = False + success = False for spectacle in spectacles: revente_objects = SpectacleRevente.objects.filter( attribution__spectacle=spectacle, @@ -410,7 +411,9 @@ def list_revente(request, tirage_id): deja_revente = True else: revente.answered_mail.add(participant) + revente.save() break + success = True else: form = InscriptionReventeForm( tirage, @@ -418,7 +421,7 @@ def list_revente(request, tirage_id): return render(request, "liste-reventes.html", {"form": form, 'shotgun': shotgun, - "deja_revente": deja_revente}) + "deja_revente": deja_revente, "success": success}) @login_required From 7abdccfbdb3da53341e06ff6edb60e0d8061eaf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Tue, 27 Sep 2016 17:57:53 +0200 Subject: [PATCH 046/103] =?UTF-8?q?Meilleure=20gestion=20des=20donn=C3=A9e?= =?UTF-8?q?s=20mails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les valeurs de champs FROM, REPLY-TO et BCC des mails envoyés par GestioCOF sont enregistrées dans un dictionnaire `settings.MAIL_DATA` plutôt que d'être toutes enregistrées comme variables indépendantes --- bda/models.py | 17 +++++++++++------ cof/settings_dev.py | 21 ++++++++++++--------- gestioncof/petits_cours_views.py | 6 +++--- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/bda/models.py b/bda/models.py index 1074e58b..cc96e525 100644 --- a/bda/models.py +++ b/bda/models.py @@ -119,8 +119,9 @@ class Spectacle(models.Model): 'show': self}) mail_tot = mail.EmailMessage( mail_object, mail_body, - settings.RAPPEL_FROM, [member.email], - [], headers={'Reply-To': settings.RAPPEL_REPLY_TO}) + settings.MAIL_DATA['rappels']['FROM'], [member.email], + [], headers={ + 'Reply-To': settings.MAIL_DATA['rappels']['REPLYTO']}) mails_to_send.append(mail_tot) # On envoie les mails connection = mail.get_connection() @@ -273,8 +274,10 @@ class SpectacleRevente(models.Model): 'revente': self}) mail_tot = mail.EmailMessage( mail_object, mail_body, - settings.REVENTE_FROM, [participant.user.email], - [], headers={'Reply-To': settings.REVENTE_REPLY_TO}) + settings.MAIL_DATA['revente']['FROM'], + [participant.user.email], + [], headers={ + 'Reply-To': settings.MAIL_DATA['revente']['REPLYTO']}) mails_to_send.append(mail_tot) connection = mail.get_connection() @@ -294,8 +297,10 @@ class SpectacleRevente(models.Model): 'mail': self.attribution.participant.user.email}) mail_tot = mail.EmailMessage( mail_object, mail_body, - settings.REVENTE_FROM, [participant.user.email], - [], headers={'Reply-To': settings.REVENTE_REPLY_TO}) + settings.MAIL_DATA['revente']['FROM'], + [participant.user.email], + [], headers={ + 'Reply-To': settings.MAIL_DATA['revente']['REPLYTO']}) mails_to_send.append(mail_tot) connection = mail.get_connection() diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 7d270648..5e092635 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -145,15 +145,18 @@ ADMIN_MEDIA_PREFIX = '/static/grappelli/' GRAPPELLI_ADMIN_HEADLINE = "GestioCOF" GRAPPELLI_ADMIN_TITLE = "GestioCOF" -PETITS_COURS_FROM = "Le COF " -PETITS_COURS_BCC = "archivescof@gmail.com" -PETITS_COURS_REPLYTO = "cof@ens.fr" - -RAPPEL_FROM = 'Le BdA ' -RAPPEL_REPLY_TO = RAPPEL_FROM - -REVENTE_FROM = 'BDA-Revente ' -REVENTE_REPLY_TO = REVENTE_FROM +MAIL_DATA = { + 'petits_cours': { + 'FROM': "Le COF ", + 'BCC': "archivescof@gmail.com", + 'REPLYTO': "cof@ens.fr"}, + 'rappels': { + 'FROM': 'Le BdA ', + 'REPLYTO': 'Le BdA '}, + 'revente': { + 'FROM': 'BDA-Revente ', + 'REPLYTO': 'BDA-Revente '}, +} LOGIN_URL = "/gestion/login" LOGIN_REDIRECT_URL = "/gestion/" diff --git a/gestioncof/petits_cours_views.py b/gestioncof/petits_cours_views.py index 1a31115d..e9fe511e 100644 --- a/gestioncof/petits_cours_views.py +++ b/gestioncof/petits_cours_views.py @@ -282,9 +282,9 @@ def _traitement_post(request, demande): {"proposals": proposals_list, "unsatisfied": unsatisfied, "extra": extra}) - frommail = settings.PETITS_COURS_FROM - bccaddress = settings.PETITS_COURS_BCC - replyto = settings.PETITS_COURS_REPLYTO + frommail = settings.MAIL_DATA['petits_cours']['FROM'] + bccaddress = settings.MAIL_DATA['petits_cours']['BCC'] + replyto = settings.MAIL_DATA['petits_cours']['REPLYTO'] mails_to_send = [] for (user, msg) in proposed_mails: msg = EmailMessage("Petits cours ENS par le COF", msg, From ad0c398292d552e2c3a04be2e49726da2583812d Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Wed, 28 Sep 2016 16:47:46 +0200 Subject: [PATCH 047/103] fix error 500 shotgun --- bda/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/views.py b/bda/views.py index c72e5b1d..4f1ba977 100644 --- a/bda/views.py +++ b/bda/views.py @@ -443,7 +443,7 @@ def buy_revente(request, spectacle_id): if revente.shotgun: reventes_shotgun.append(revente) - if reventes_shotgun.empty(): + if not reventes_shotgun: return render(request, "bda-no-revente.html", {}) if request.POST: From 1dad85882b7ce5b5b4ab20e32a3625e6fb27bb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 30 Sep 2016 00:35:51 +0200 Subject: [PATCH 048/103] Ajoute le BdA dans les destinataires des rappels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modifie légérement la façon dont est généré le mail au passage --- bda/models.py | 13 ++++++++----- bda/templates/mail-rappel.txt | 8 ++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/bda/models.py b/bda/models.py index 1074e58b..4b2acdd3 100644 --- a/bda/models.py +++ b/bda/models.py @@ -105,21 +105,24 @@ class Spectacle(models.Model): for attr in Attribution.objects.filter(spectacle=self).all(): member = attr.participant.user if member.id in members: - members[member.id].nb_attr = 2 + members[member.id][1] = 2 else: - member.nb_attr = 1 - members[member.id] = member + members[member.id] = [member.get_full_name(), 1, member.email] + # Pour le BdA + members[0] = ['BdA', 1, 'bda@ens.fr'] + members[-1] = ['BdA', 2, 'bda@ens.fr'] # On écrit un mail personnalisé à chaque participant mails_to_send = [] mail_object = "%s - %s - %s" % (self.title, self.date_no_seconds(), self.location) for member in members.values(): mail_body = render_template('mail-rappel.txt', { - 'member': member, + 'name': member[0], + 'nb_attr': member[1], 'show': self}) mail_tot = mail.EmailMessage( mail_object, mail_body, - settings.RAPPEL_FROM, [member.email], + settings.RAPPEL_FROM, [member[2]], [], headers={'Reply-To': settings.RAPPEL_REPLY_TO}) mails_to_send.append(mail_tot) # On envoie les mails diff --git a/bda/templates/mail-rappel.txt b/bda/templates/mail-rappel.txt index 5152b1db..4759a849 100644 --- a/bda/templates/mail-rappel.txt +++ b/bda/templates/mail-rappel.txt @@ -1,14 +1,14 @@ -Bonjour {{ member.get_full_name }}, +Bonjour {{ name }}, -Nous te rappellons que tu as eu la chance d'obtenir {{ member.nb_attr|pluralize:"une place,deux places" }} +Nous te rappellons que tu as eu la chance d'obtenir {{ nb_attr|pluralize:"une place,deux places" }} pour {{ show.title }}, le {{ show.date_no_seconds }} au {{ show.location }}. N'oublie pas de t'y rendre ! -{% if member.nb_attr == 2 %} +{% if nb_attr == 2 %} Tu as obtenu deux places pour ce spectacle. Nous te rappelons que ces places sont strictement réservées aux personnes de moins de 28 ans. {% endif %} {% if show.listing %}Pour ce spectacle, tu as reçu des places sur listing. Il te faudra donc te rendre 15 minutes en avance sur les lieux de la représentation -pour retirer {{ member.nb_attr|pluralize:"ta place,tes places" }}. +pour retirer {{ nb_attr|pluralize:"ta place,tes places" }}. {% else %}Pour assister à ce spectacle, tu dois présenter les billets qui ont été distribués au burô. {% endif %} From 018f493b163b4326897ae4478ca782458997ceca Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 3 Oct 2016 14:47:13 +0200 Subject: [PATCH 049/103] fix date writing --- bda/management/commands/manage_reventes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/management/commands/manage_reventes.py b/bda/management/commands/manage_reventes.py index f45357b1..5fa3806b 100644 --- a/bda/management/commands/manage_reventes.py +++ b/bda/management/commands/manage_reventes.py @@ -14,7 +14,7 @@ class Command(BaseCommand): def handle(self, *args, **options): now = timezone.now() - self.stdout.write(now) + self.stdout.write(now.__str__()) reventes = SpectacleRevente.objects.all() for revente in reventes: # Check si < 24h From 60a11a8ba470aa4a830a67e26a3d34585b3f7c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 3 Oct 2016 16:08:29 +0200 Subject: [PATCH 050/103] Changement mineur dans le mail --- bda/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/models.py b/bda/models.py index 4b2acdd3..e45393f1 100644 --- a/bda/models.py +++ b/bda/models.py @@ -107,7 +107,7 @@ class Spectacle(models.Model): if member.id in members: members[member.id][1] = 2 else: - members[member.id] = [member.get_full_name(), 1, member.email] + members[member.id] = [member.first_name, 1, member.email] # Pour le BdA members[0] = ['BdA', 1, 'bda@ens.fr'] members[-1] = ['BdA', 2, 'bda@ens.fr'] From 7fbf0e48091ed19e199bd48a682472acc503d885 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 3 Oct 2016 16:47:22 +0200 Subject: [PATCH 051/103] fix manage_reventes --- bda/management/commands/manage_reventes.py | 4 +++- bda/models.py | 4 ++-- bda/templates/mail-revente.txt | 2 +- bda/templates/mail-shotgun.txt | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/bda/management/commands/manage_reventes.py b/bda/management/commands/manage_reventes.py index 5fa3806b..45b9c91a 100644 --- a/bda/management/commands/manage_reventes.py +++ b/bda/management/commands/manage_reventes.py @@ -14,7 +14,6 @@ class Command(BaseCommand): def handle(self, *args, **options): now = timezone.now() - self.stdout.write(now.__str__()) reventes = SpectacleRevente.objects.all() for revente in reventes: # Check si < 24h @@ -22,15 +21,18 @@ class Command(BaseCommand): revente.date + timedelta(days=1)) and \ now >= revente.date + timedelta(minutes=15) and \ not revente.notif_sent: + self.stdout.write(str(now)) revente.mail_shotgun() self.stdout.write("Mail de disponibilité immédiate envoyé") # Check si délai de retrait dépassé elif (now >= revente.date + timedelta(hours=1) and not revente.notif_sent): + self.stdout.write(str(now)) revente.send_notif() self.stdout.write("Mail d'inscription à une revente envoyé") # Check si tirage à faire elif (now >= revente.expiration_time and not revente.tirage_done): + self.stdout.write(str(now)) revente.tirage() self.stdout.write("Tirage effectué, mails envoyés") diff --git a/bda/models.py b/bda/models.py index 1074e58b..085bd548 100644 --- a/bda/models.py +++ b/bda/models.py @@ -269,7 +269,7 @@ class SpectacleRevente(models.Model): for participant in inscrits: mail_body = render_template('mail-revente.txt', { 'user': participant.user, - 'spectacle': self.spectacle, + 'spectacle': self.attribution.spectacle, 'revente': self}) mail_tot = mail.EmailMessage( mail_object, mail_body, @@ -290,7 +290,7 @@ class SpectacleRevente(models.Model): for participant in inscrits: mail_body = render_template('mail-shotgun.txt', { 'user': participant.user, - 'spectacle': self.spectacle, + 'spectacle': self.attribution.spectacle, 'mail': self.attribution.participant.user.email}) mail_tot = mail.EmailMessage( mail_object, mail_body, diff --git a/bda/templates/mail-revente.txt b/bda/templates/mail-revente.txt index adc61eb9..94cab1b1 100644 --- a/bda/templates/mail-revente.txt +++ b/bda/templates/mail-revente.txt @@ -2,7 +2,7 @@ Bonjour {{ user.get_full_name }} Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BdA-Revente. -Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : {% url "bda-interested-revente" revente.id %}. Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à un tirage au sort le {{revente.date_no_seconds}} +Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : {% url "bda-revente-interested" revente.id %}. Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à un tirage au sort le {{revente.date_no_seconds}} Chaleureusement, Le BdA diff --git a/bda/templates/mail-shotgun.txt b/bda/templates/mail-shotgun.txt index 8c4e7bd9..4f972cf9 100644 --- a/bda/templates/mail-shotgun.txt +++ b/bda/templates/mail-shotgun.txt @@ -2,7 +2,7 @@ Bonjour {{ user.get_full_name }} Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BdA-Revente. -Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour cette place : elle est disponible immédiatement à l'addresse {{url "bda-buy-revente" spectacle.id}}, à la disposition de tous. +Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour cette place : elle est disponible immédiatement à l'addresse {%url "bda-buy-revente" spectacle.id%}, à la disposition de tous. Chaleureusement, Le BdA From f686c99239ddc4ce49e4c49874be0f811c173781 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 3 Oct 2016 18:52:09 +0200 Subject: [PATCH 052/103] =?UTF-8?q?ajoute=20boutons=20pour=20tout=20(d?= =?UTF-8?q?=C3=A9)s=C3=A9lectionner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/templates/liste-reventes.html | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 78f3ac08..a619ed4c 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -11,7 +11,20 @@ {% endif %}
    {% csrf_token %} - {{form | bootstrap}} +
    +

    Spectacles

    +
    + + + +
    +
      + {% for checkbox in form.spectacles %} +
    • {{checkbox}}
    • + {%endfor%} +
    +
    +
    @@ -23,4 +36,13 @@
  • {{spectacle}}
  • {% endfor %} {% endif %} + + {% endblock %} From 5e848e4442b528fb33056d02fca853551ee514d6 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 3 Oct 2016 19:37:21 +0200 Subject: [PATCH 053/103] fix date mail revente --- bda/models.py | 7 +++++-- bda/templates/mail-revente.txt | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bda/models.py b/bda/models.py index 085bd548..d1b5ba3c 100644 --- a/bda/models.py +++ b/bda/models.py @@ -270,7 +270,10 @@ class SpectacleRevente(models.Model): mail_body = render_template('mail-revente.txt', { 'user': participant.user, 'spectacle': self.attribution.spectacle, - 'revente': self}) + 'time': self.date.astimezone( + timezone.get_current_timezone()) \ + .strftime('%d %b %Y %H:%M'), + 'id': self.id}) mail_tot = mail.EmailMessage( mail_object, mail_body, settings.REVENTE_FROM, [participant.user.email], @@ -313,7 +316,7 @@ class SpectacleRevente(models.Model): mail_buyer = """Bonjour, Tu as été tiré-e au sort pour racheter une place pour %s le %s (%s) à %0.02f€. -Tu peux contacter le vendeur à l'adresse %s. +Tu peux contacter le/la vendeur-se à l'adresse %s. Chaleureusement, Le BdA""" % (spectacle.title, spectacle.date_no_seconds(), diff --git a/bda/templates/mail-revente.txt b/bda/templates/mail-revente.txt index 94cab1b1..4dff5b7e 100644 --- a/bda/templates/mail-revente.txt +++ b/bda/templates/mail-revente.txt @@ -2,7 +2,8 @@ Bonjour {{ user.get_full_name }} Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BdA-Revente. -Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : {% url "bda-revente-interested" revente.id %}. Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à un tirage au sort le {{revente.date_no_seconds}} +Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : {% url "bda-revente-interested" id %}. +Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à un tirage au sort le {{time}}. Chaleureusement, Le BdA From dff0b3ffdddeec754ec8664b1d850b94c4cb8ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 3 Oct 2016 20:06:33 +0200 Subject: [PATCH 054/103] Corrections dans les mails de revente - full_name -> first_name - Date - Url --- bda/models.py | 10 +++++++++- bda/templates/mail-revente.txt | 10 +++++++--- bda/templates/mail-shotgun.txt | 9 ++++++--- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/bda/models.py b/bda/models.py index 085bd548..90ea6b1d 100644 --- a/bda/models.py +++ b/bda/models.py @@ -8,6 +8,7 @@ import calendar import random from datetime import timedelta +from django.contrib.sites.models import Site from django.db import models from django.contrib.auth.models import User from django.template import loader, Context @@ -244,6 +245,11 @@ class SpectacleRevente(models.Model): # On a aussi 1h pour changer d'avis return self.date + delay + timedelta(hours=1) + def expiration_time_str(self): + return self.expiration_time \ + .astimezone(timezone.get_current_timezone()) \ + .strftime('%D à %H:%M') + @property def shotgun(self): # Soit on a dépassé le délai du tirage, soit il reste peu de @@ -270,7 +276,8 @@ class SpectacleRevente(models.Model): mail_body = render_template('mail-revente.txt', { 'user': participant.user, 'spectacle': self.attribution.spectacle, - 'revente': self}) + 'revente': self, + 'domain': Site.objects.get_current().domain}) mail_tot = mail.EmailMessage( mail_object, mail_body, settings.REVENTE_FROM, [participant.user.email], @@ -291,6 +298,7 @@ class SpectacleRevente(models.Model): mail_body = render_template('mail-shotgun.txt', { 'user': participant.user, 'spectacle': self.attribution.spectacle, + 'domain': Site.objects.get_current(), 'mail': self.attribution.participant.user.email}) mail_tot = mail.EmailMessage( mail_object, mail_body, diff --git a/bda/templates/mail-revente.txt b/bda/templates/mail-revente.txt index 94cab1b1..6d125988 100644 --- a/bda/templates/mail-revente.txt +++ b/bda/templates/mail-revente.txt @@ -1,8 +1,12 @@ -Bonjour {{ user.get_full_name }} +Bonjour {{ user.first_name }} -Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BdA-Revente. +Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date_no_seconds }}) +a été postée sur BdA-Revente. -Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : {% url "bda-revente-interested" revente.id %}. Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à un tirage au sort le {{revente.date_no_seconds}} +Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant +sur ce lien : http://{{ domain }}{% url "bda-revente-interested" revente.id %}. +Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à +un tirage au sort le {{ revente.expiration_time_str }} Chaleureusement, Le BdA diff --git a/bda/templates/mail-shotgun.txt b/bda/templates/mail-shotgun.txt index 4f972cf9..899d5c85 100644 --- a/bda/templates/mail-shotgun.txt +++ b/bda/templates/mail-shotgun.txt @@ -1,8 +1,11 @@ -Bonjour {{ user.get_full_name }} +Bonjour {{ user.first_name }} -Une place pour le spectacle {{ spectacle.title }} ({{spectacle.date_no_seconds}}) a été postée sur BdA-Revente. +Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date_no_seconds }}) +a été postée sur BdA-Revente. -Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour cette place : elle est disponible immédiatement à l'addresse {%url "bda-buy-revente" spectacle.id%}, à la disposition de tous. +Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour +cette place : elle est disponible immédiatement à l'addresse +http://{{ domain }}{% url "bda-buy-revente" spectacle.id %}, à la disposition de tous. Chaleureusement, Le BdA From a49bb5a799c6c1fbc535cc6650f2232f07bef349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 3 Oct 2016 20:21:42 +0200 Subject: [PATCH 055/103] Typos --- bda/models.py | 2 +- bda/templates/mail-revente.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bda/models.py b/bda/models.py index 90ea6b1d..72590dac 100644 --- a/bda/models.py +++ b/bda/models.py @@ -321,7 +321,7 @@ class SpectacleRevente(models.Model): mail_buyer = """Bonjour, Tu as été tiré-e au sort pour racheter une place pour %s le %s (%s) à %0.02f€. -Tu peux contacter le vendeur à l'adresse %s. +Tu peux contacter le/la vendeur-se à l'adresse %s. Chaleureusement, Le BdA""" % (spectacle.title, spectacle.date_no_seconds(), diff --git a/bda/templates/mail-revente.txt b/bda/templates/mail-revente.txt index 6d125988..899afe3b 100644 --- a/bda/templates/mail-revente.txt +++ b/bda/templates/mail-revente.txt @@ -6,7 +6,7 @@ a été postée sur BdA-Revente. Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant sur ce lien : http://{{ domain }}{% url "bda-revente-interested" revente.id %}. Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à -un tirage au sort le {{ revente.expiration_time_str }} +un tirage au sort le {{ revente.expiration_time_str }}. Chaleureusement, Le BdA From 0a85eaa0cf0c14c3bb256c05cd260d0c2d2897ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Thu, 6 Oct 2016 10:28:13 +0200 Subject: [PATCH 056/103] Hot fix `participant.email` -> `participant.user.email` --- bda/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bda/models.py b/bda/models.py index 0debec36..d61f6b9b 100644 --- a/bda/models.py +++ b/bda/models.py @@ -333,7 +333,7 @@ Tu peux contacter le/la vendeur-se à l'adresse %s. Chaleureusement, Le BdA""" % (spectacle.title, spectacle.date_no_seconds(), - spectacle.location, spectacle.price, seller.email) + spectacle.location, spectacle.price, seller.user.email) mail.send_mail("BdA-Revente : %s" % spectacle.title, mail_buyer, "bda@ens.fr", [winner.user.email], @@ -346,7 +346,7 @@ Chaleureusement, Le BdA""" % (spectacle.title, winner.user.get_full_name(), winner.user.email) mail.send_mail("BdA-Revente : %s" % spectacle.title, - mail_seller, "bda@ens.fr", [seller.email], + mail_seller, "bda@ens.fr", [seller.user.email], fail_silently=False) self.tirage_done = True self.save() From d1456d7c683702fb672b90d859cfcaa00df423e0 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 6 Oct 2016 13:46:18 +0200 Subject: [PATCH 057/103] =?UTF-8?q?d=C3=A9placement=20shotgun?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/templates/bda-shotgun.html | 14 ++++++++++++++ bda/templates/liste-reventes.html | 9 --------- bda/urls.py | 3 +++ bda/views.py | 22 ++++++++++++++++++++++ gestioncof/templates/home.html | 1 + 5 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 bda/templates/bda-shotgun.html diff --git a/bda/templates/bda-shotgun.html b/bda/templates/bda-shotgun.html new file mode 100644 index 00000000..e10fae00 --- /dev/null +++ b/bda/templates/bda-shotgun.html @@ -0,0 +1,14 @@ +{% extends "base_title.html" %} + +{% block realcontent %} +

    Places disponibles immédiatement

    + {% if shotgun %} +
      + {% for spectacle in shotgun %} +
    • {{spectacle}}
    • + {% endfor %} + {% else %} +

      Pas de places disponibles immédiatement, désolé !

      + {% endif %} + +{% endblock %} diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index a619ed4c..d08d4010 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -28,15 +28,6 @@ - {% if shotgun %} -
      -

      Places disponibles immédiatement

      -
        - {% for spectacle in shotgun %} -
      • {{spectacle}}
      • - {% endfor %} - {% endif %} - {% endblock %} From 173c5a840b253ce838471e48dc85be85f94950bf Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 6 Oct 2016 18:51:19 +0200 Subject: [PATCH 060/103] fix links --- bda/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bda/views.py b/bda/views.py index 0f183421..01758e18 100644 --- a/bda/views.py +++ b/bda/views.py @@ -436,7 +436,7 @@ def buy_revente(request, spectacle_id): if reventes.filter(seller=participant).exists(): revente = reventes.filter(seller=participant)[0] revente.delete() - return HttpResponseRedirect(reverse("bda-liste-revente", + return HttpResponseRedirect(reverse("bda-revente-shotgun", args=[tirage.id])) reventes_shotgun = [] for revente in reventes.all(): @@ -489,7 +489,7 @@ def revente_shotgun(request, tirage_id): spectacle.revente_count = revente_count shotgun.append(spectacle) - return render(request, "revente-shotgun.html", + return render(request, "bda-shotgun.html", {"shotgun": shotgun}) From b249d61c2d75cccbd1a0da24e8f371490e44a105 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Fri, 7 Oct 2016 23:49:55 +0200 Subject: [PATCH 061/103] fix recherche dans spectaclerevente --- bda/admin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bda/admin.py b/bda/admin.py index 37fdf9c7..2991ebf5 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -219,8 +219,7 @@ class SpectacleReventeAdmin(admin.ModelAdmin): list_display = ("spectacle", "seller", "date", "soldTo") raw_id_fields = ("attribution",) readonly_fields = ("shotgun", "expiration_time") - search_fields = ("spectacle__title", - "seller__user__username", + search_fields = ("seller__user__username", "seller__user__firstname", "seller__user__lastname",) From db65799f3ded0e629a11aa44ea1252b6563fc601 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 8 Oct 2016 20:00:58 +0200 Subject: [PATCH 062/103] does not belong here --- bda/templates/liste-reventes.html | 9 --------- 1 file changed, 9 deletions(-) diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 5eac7100..b9987497 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -14,13 +14,4 @@ {{form | bootstrap}} - - {% endblock %} From 546cd92d6d7a70201766d92949be2a63943cf7ae Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Sat, 8 Oct 2016 20:07:15 +0200 Subject: [PATCH 063/103] Ajoute bouton select all --- bda/templates/liste-reventes.html | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/bda/templates/liste-reventes.html b/bda/templates/liste-reventes.html index 78f3ac08..a619ed4c 100644 --- a/bda/templates/liste-reventes.html +++ b/bda/templates/liste-reventes.html @@ -11,7 +11,20 @@ {% endif %}
        {% csrf_token %} - {{form | bootstrap}} +
        +

        Spectacles

        +
        + + + +
        +
          + {% for checkbox in form.spectacles %} +
        • {{checkbox}}
        • + {%endfor%} +
        +
        +
        @@ -23,4 +36,13 @@
      • {{spectacle}}
      • {% endfor %} {% endif %} + + {% endblock %} From fdf1c65de4e1965adf6a3ba7d7b7ef92d3295807 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 10 Oct 2016 17:10:45 +0200 Subject: [PATCH 064/103] =?UTF-8?q?date=20au=20format=20fran=C3=A7ais?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/models.py b/bda/models.py index 3642ee83..6f0dd74d 100644 --- a/bda/models.py +++ b/bda/models.py @@ -253,7 +253,7 @@ class SpectacleRevente(models.Model): def expiration_time_str(self): return self.expiration_time \ .astimezone(timezone.get_current_timezone()) \ - .strftime('%D à %H:%M') + .strftime('%d/%m/%y à %H:%M') @property def shotgun(self): From 36cd6231055dfc6c494c30e3997079ad7df98abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Tue, 11 Oct 2016 14:59:30 +0200 Subject: [PATCH 065/103] Corrections des typos - Ligne vide - `lastname` -> `last_name` - `firstname` -> `first_name` - `spectacle__title` -> `attribution__spectacle__title` --- bda/admin.py | 7 ++++--- bda/models.py | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bda/admin.py b/bda/admin.py index 2991ebf5..e07a5d49 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -219,9 +219,10 @@ class SpectacleReventeAdmin(admin.ModelAdmin): list_display = ("spectacle", "seller", "date", "soldTo") raw_id_fields = ("attribution",) readonly_fields = ("shotgun", "expiration_time") - search_fields = ("seller__user__username", - "seller__user__firstname", - "seller__user__lastname",) + search_fields = ['attribution__spectacle__title', + 'seller__user__username', + 'seller__user__first_name', + 'seller__user__last_name'] admin.site.register(CategorieSpectacle) diff --git a/bda/models.py b/bda/models.py index 3642ee83..d61f6b9b 100644 --- a/bda/models.py +++ b/bda/models.py @@ -228,7 +228,6 @@ class SpectacleRevente(models.Model): answered_mail = models.ManyToManyField(Participant, related_name="wanted", blank=True) - seller = models.ForeignKey(Participant, related_name="original_shows", verbose_name="Vendeur") From 6c5a2124c46894c4ddc211caebc4adb4e8be3a1b Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 13 Oct 2016 15:30:59 +0200 Subject: [PATCH 066/103] scrap aborted modif --- bda/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bda/views.py b/bda/views.py index 494b0f36..3776385d 100644 --- a/bda/views.py +++ b/bda/views.py @@ -488,7 +488,6 @@ def revente_shotgun(request, tirage_id): if revente.shotgun: revente_count += 1 if revente_count: - spectacle.revente_count = revente_count shotgun.append(spectacle) return render(request, "bda-shotgun.html", From cde83025eed9092db47bc764d492a9ae7906a843 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 13 Oct 2016 16:01:30 +0200 Subject: [PATCH 067/103] change urls for 1.10 --- bda/urls.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bda/urls.py b/bda/urls.py index 4f3aa67e..bbbf8e39 100644 --- a/bda/urls.py +++ b/bda/urls.py @@ -33,16 +33,16 @@ urlpatterns = [ views.unpaid, name="bda-unpaid"), url(r'^liste-revente/(?P\d+)$', - "bda.views.list_revente", + views.list_revente, name="bda-liste-revente"), url(r'^buy-revente/(?P\d+)$', - "bda.views.buy_revente", + views.buy_revente, name="bda-buy-revente"), url(r'^revente-interested/(?P\d+)$', - "bda.views.revente_interested", + views.revente_interested, name='bda-revente-interested'), url(r'^revente-immediat/(?P\d+)$', - "bda.views.revente_shotgun", + views.revente_shotgun, name="bda-shotgun"), url(r'^mails-rappel/(?P\d+)$', views.send_rappel), url(r'^descriptions/(?P\d+)$', views.descriptions_spectacles, From cf68abc789a6f5e6a646616e4df64dc111b63b4d Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 13 Oct 2016 16:02:52 +0200 Subject: [PATCH 068/103] wrong url --- bda/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/views.py b/bda/views.py index 3776385d..b9ce0825 100644 --- a/bda/views.py +++ b/bda/views.py @@ -438,7 +438,7 @@ def buy_revente(request, spectacle_id): if reventes.filter(seller=participant).exists(): revente = reventes.filter(seller=participant)[0] revente.delete() - return HttpResponseRedirect(reverse("bda-revente-shotgun", + return HttpResponseRedirect(reverse("bda-shotgun", args=[tirage.id])) reventes_shotgun = [] for revente in reventes.all(): From 56a1f8e634fbf29b80863e9e3fa559c6ab618048 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 27 Oct 2016 23:46:57 -0200 Subject: [PATCH 069/103] add transfer & reinit functions --- bda/admin.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/bda/admin.py b/bda/admin.py index e07a5d49..d0483281 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -13,6 +13,7 @@ from bda.models import Spectacle, Salle, Participant, ChoixSpectacle,\ from django import forms from datetime import timedelta +from django.utils import timezone import autocomplete_light @@ -224,6 +225,28 @@ class SpectacleReventeAdmin(admin.ModelAdmin): 'seller__user__first_name', 'seller__user__last_name'] + actions = ['transfer', 'reinit', ] + actions_on_bottom = True + + def transfer(self, request, queryset): + for revente in queryset.all(): + if revente.soldTo: + attrib = revente.attribution + attrib.participant = revente.soldTo + attrib.save() + transfer.short_description = "Transférer les reventes sélectionnées" + + def reinit(self, request, queryset): + for revente in queryset.all(): + revente.date = timezone.now() - timedelta(hours=1) + revente.soldTo = None + revente.notif_sent = False + revente.tirage_done = False + if revente.answered_mail: + revente.answered_mail.clear() + revente.save() + reinit.short_description = "Réinitialiser les reventes sélectionnées" + admin.site.register(CategorieSpectacle) admin.site.register(Spectacle, SpectacleAdmin) From e408437ab158d6ae74654fa98be1f9303d07a350 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 27 Oct 2016 23:47:11 -0200 Subject: [PATCH 070/103] fix reinit --- bda/views.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bda/views.py b/bda/views.py index b9ce0825..756525f2 100644 --- a/bda/views.py +++ b/bda/views.py @@ -333,6 +333,8 @@ def revente(request, tirage_id): revente = rev.get() revente.date = timezone.now() - timedelta(hours=1) revente.soldTo = None + revente.notif_sent = False + revente.tirage_done = False if revente.answered_mail: revente.answered_mail.clear() revente.save() From 8d1f599577d9044229f16cc3225ffdcd2dc252b9 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Fri, 28 Oct 2016 14:15:37 -0200 Subject: [PATCH 071/103] filter sold attributions --- bda/admin.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bda/admin.py b/bda/admin.py index d0483281..668cc6dd 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -229,11 +229,10 @@ class SpectacleReventeAdmin(admin.ModelAdmin): actions_on_bottom = True def transfer(self, request, queryset): - for revente in queryset.all(): - if revente.soldTo: - attrib = revente.attribution - attrib.participant = revente.soldTo - attrib.save() + for revente in queryset.exclude(soldTo__isnull=True).all(): + attrib = revente.attribution + attrib.participant = revente.soldTo + attrib.save() transfer.short_description = "Transférer les reventes sélectionnées" def reinit(self, request, queryset): From 249edb8d6826c98c29ec15b88c839405b7dbfdc1 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Fri, 28 Oct 2016 17:52:16 -0200 Subject: [PATCH 072/103] =?UTF-8?q?guillemets=20=C3=A0=20value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/templates/bda-revente.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bda/templates/bda-revente.html b/bda/templates/bda-revente.html index a5f64678..569a3f3a 100644 --- a/bda/templates/bda-revente.html +++ b/bda/templates/bda-revente.html @@ -62,9 +62,9 @@ {{attrib.spectacle}} {{attrib.revente.soldTo.user.get_full_name}} + value="{{attrib.revente.id}}">Transférer + value="{{attrib.revente.id}}">Réinitialiser {% endfor %} From 33545b028e7f10f9e1b1481e5a2cdde970cc2537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 4 Nov 2016 08:35:17 +0100 Subject: [PATCH 073/103] Messages et docstrings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ajout d'un message à l'aide de `message_user` lorsque les actions sont effectuées - Ajouts de docstrings là où c'est préconisé par pylint. --- bda/admin.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/bda/admin.py b/bda/admin.py index 668cc6dd..87a269d4 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -5,15 +5,15 @@ from __future__ import print_function from __future__ import unicode_literals from django.core.mail import send_mail - from django.contrib import admin from django.db.models import Sum, Count +from django.template.defaultfilters import pluralize +from django.utils import timezone +from django import forms from bda.models import Spectacle, Salle, Participant, ChoixSpectacle,\ Attribution, Tirage, Quote, CategorieSpectacle, SpectacleRevente -from django import forms from datetime import timedelta -from django.utils import timezone import autocomplete_light @@ -212,9 +212,15 @@ class SalleAdmin(admin.ModelAdmin): class SpectacleReventeAdmin(admin.ModelAdmin): + """ + Administration des reventes de spectacles + """ model = SpectacleRevente def spectacle(self, obj): + """ + Raccourci vers le spectacle associé à la revente. + """ return obj.attribution.spectacle list_display = ("spectacle", "seller", "date", "soldTo") @@ -225,17 +231,32 @@ class SpectacleReventeAdmin(admin.ModelAdmin): 'seller__user__first_name', 'seller__user__last_name'] - actions = ['transfer', 'reinit', ] + actions = ['transfer', 'reinit'] actions_on_bottom = True def transfer(self, request, queryset): - for revente in queryset.exclude(soldTo__isnull=True).all(): + """ + Effectue le transfert des reventes pour lesquels on connaît l'acheteur. + """ + reventes = queryset.exclude(soldTo__isnull=True).all() + count = reventes.count() + for revente in reventes: attrib = revente.attribution attrib.participant = revente.soldTo attrib.save() + self.message_user( + request, + "%d attribution%s %s été transférée%s avec succès." % ( + count, pluralize(count), + pluralize(count, "a,ont"), pluralize(count)) + ) transfer.short_description = "Transférer les reventes sélectionnées" def reinit(self, request, queryset): + """ + Réinitialise les reventes. + """ + count = queryset.count() for revente in queryset.all(): revente.date = timezone.now() - timedelta(hours=1) revente.soldTo = None @@ -244,6 +265,12 @@ class SpectacleReventeAdmin(admin.ModelAdmin): if revente.answered_mail: revente.answered_mail.clear() revente.save() + self.message_user( + request, + "%d attribution%s %s été réinitialisée%s avec succès." % ( + count, pluralize(count), + pluralize(count, "a,ont"), pluralize(count)) + ) reinit.short_description = "Réinitialiser les reventes sélectionnées" From 6642f03720e1b195809e366bec23d3c8a30f1bed Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sat, 5 Nov 2016 18:04:54 +0100 Subject: [PATCH 074/103] Ajoute un UID aux VEVENTs du calendrier dynamique Fixes #102. --- gestioncof/views.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gestioncof/views.py b/gestioncof/views.py index 80f528f7..4f1e5009 100644 --- a/gestioncof/views.py +++ b/gestioncof/views.py @@ -14,6 +14,7 @@ from django.http import Http404, HttpResponse, HttpResponseForbidden from django.contrib.auth.decorators import login_required from django.contrib.auth.views import login as django_login_view from django.contrib.auth.models import User +from django.contrib.sites.models import Site from django.utils import timezone import django.utils.six as six @@ -710,12 +711,15 @@ def calendar_ics(request, token): tirage__active=True) shows = shows.distinct() vcal = Calendar() + site = Site.objects.get_current() for show in shows: vevent = Vevent() vevent.add('dtstart', show.date) vevent.add('dtend', show.date + timedelta(seconds=7200)) vevent.add('summary', show.title) vevent.add('location', show.location.name) + vevent.add('uid', 'show-{:d}-{:d}@{:s}'.format( + show.pk, show.tirage_id, site.domain)) vcal.add_component(vevent) if subscription.subscribe_to_events: for event in Event.objects.filter(old=False).all(): @@ -725,6 +729,8 @@ def calendar_ics(request, token): vevent.add('summary', event.title) vevent.add('location', event.location) vevent.add('description', event.description) + vevent.add('uid', 'event-{:d}@{:s}'.format( + event.pk, site.domain)) vcal.add_component(vevent) response = HttpResponse(content=vcal.to_ical()) response['Content-Type'] = "text/calendar" From 34032c9a00d17d42e234e71f341ac20bd7de3631 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sat, 5 Nov 2016 18:25:35 +0100 Subject: [PATCH 075/103] Utilise une version officielle de django-cas-ng MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le fix de Xapantu pour la double authentification a été intégré à la version 3.5.5 de django-cas-ng. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2d1109eb..aed65e6b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ configparser==3.5.0 Django==1.8 django-autocomplete-light==2.3.3 django-autoslug==1.9.3 -git+https://github.com/xapantu/django-cas-ng.git#egg=django-cas-ng +django-cas-ng==3.5.5 django-grappelli==2.8.1 django-recaptcha==1.0.5 mysqlclient==1.3.7 From 9846ed201b25659bac8508617bb1fd6f73572318 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sat, 5 Nov 2016 18:31:40 +0100 Subject: [PATCH 076/103] Normalise les logins clipper venant du CAS Le CAS de l'ENS autorise les logins avec des espaces/une casse variable, par exemple il considere equivalents les logins ' bCLeMeNt ' et 'bclement'. Ceci peut etre la cause de creation de doublons sur gestioCOF en cas de faute de frappe (ou utilisateur malicieux ;-) ) Ce patch normalise les logins a la sortie du CAS (strip + lowercase) pour eviter des desagrements. --- gestioncof/shared.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gestioncof/shared.py b/gestioncof/shared.py index 87021a00..8fe17d43 100644 --- a/gestioncof/shared.py +++ b/gestioncof/shared.py @@ -29,6 +29,12 @@ class COFCASBackend(CASBackend): request.session['attributes'] = attributes if not username: return None + + # Le CAS de l'ENS accepte les logins avec des espaces au début + # et à la fin, ainsi qu’avec une casse variable. On normalise pour + # éviter les doublons. + username = username.strip().lower() + profiles = CofProfile.objects.filter(login_clipper=username) if len(profiles) > 0: profile = profiles.order_by('-is_cof')[0] From ba2d90d906e7eb510764b4bac8d61f3d250f196b Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sat, 5 Nov 2016 20:04:25 +0100 Subject: [PATCH 077/103] [bda-revente] Envoie un mails aux perdants d'un tirage de revente --- bda/models.py | 64 +++++++++++++++++---------- bda/templates/mail-revente-loser.txt | 9 ++++ bda/templates/mail-revente-seller.txt | 7 +++ bda/templates/mail-revente-winner.txt | 7 +++ requirements.txt | 2 +- 5 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 bda/templates/mail-revente-loser.txt create mode 100644 bda/templates/mail-revente-seller.txt create mode 100644 bda/templates/mail-revente-winner.txt diff --git a/bda/models.py b/bda/models.py index 08f17bbe..6fb22189 100644 --- a/bda/models.py +++ b/bda/models.py @@ -320,33 +320,51 @@ class SpectacleRevente(models.Model): self.save() def tirage(self): - inscrits = self.answered_mail + inscrits = list(self.answered_mail.all()) spectacle = self.attribution.spectacle seller = self.seller - if inscrits.exists(): - winner = random.choice(inscrits.all()) + + if inscrits: + mails = [] + mail_subject = "BdA-Revente : {:s}".format(spectacle.title) + + # Envoie un mail au gagnant et au vendeur + winner = random.choice(inscrits) self.soldTo = winner - mail_buyer = """Bonjour, + context = { + 'acheteur': winner.user, + 'vendeur': seller.user, + 'spectacle': spectacle, + } + mails.append(mail.EmailMessage( + mail_subject, loader.render_to_string('mail-revente-winner.txt', context), + from_email=settings.MAIL_DATA['revente']['FROM'], + to=[winner.user.email], + reply_to=[seller.user.email], + )) + mails.append(mail.EmailMessage( + mail_subject, loader.render_to_string('mail-revente-seller.txt', context), + from_email=settings.MAIL_DATA['revente']['FROM'], + to=[seller.user.email], + reply_to=[winner.user.email], + )) -Tu as été tiré-e au sort pour racheter une place pour %s le %s (%s) à %0.02f€. -Tu peux contacter le/la vendeur-se à l'adresse %s. + # Envoie un mail aux perdants + for inscrit in inscrits: + if inscrit == winner: + continue -Chaleureusement, -Le BdA""" % (spectacle.title, spectacle.date_no_seconds(), - spectacle.location, spectacle.price, seller.user.email) - - mail.send_mail("BdA-Revente : %s" % spectacle.title, - mail_buyer, "bda@ens.fr", [winner.user.email], - fail_silently=False) - mail_seller = """Bonjour, -La personne tirée au sort pour racheter ta place pour %s est %s. -Tu peux le/la contacter à l'adresse %s. - -Chaleureusement, -Le BdA""" % (spectacle.title, winner.user.get_full_name(), winner.user.email) - - mail.send_mail("BdA-Revente : %s" % spectacle.title, - mail_seller, "bda@ens.fr", [seller.user.email], - fail_silently=False) + mail_body = loader.render_to_string('mail-revente-loser.txt', { + 'acheteur': inscrit.user, + 'vendeur': seller.user, + 'spectacle': spectacle, + }) + mails.append(mail.EmailMessage( + mail_subject, mail_body, + from_email=settings.MAIL_DATA['revente']['FROM'], + to=[inscrit.user.email], + reply_to=[settings.MAIL_DATA['revente']['REPLYTO']], + )) + mail.get_connection().send_messages(mails) self.tirage_done = True self.save() diff --git a/bda/templates/mail-revente-loser.txt b/bda/templates/mail-revente-loser.txt new file mode 100644 index 00000000..6b50944d --- /dev/null +++ b/bda/templates/mail-revente-loser.txt @@ -0,0 +1,9 @@ +Bonjour {{ acheteur.first_name }}, + +Tu t'étais inscrit-e pour la revente de la place de {{ vendeur.get_full_name }} +pour {{ spectacle.title }}. +Malheureusement, une autre personne a été tirée au sort pour racheter la place. +Tu pourras certainement retenter ta chance pour une autre revente ! + +À très bientôt, +Le Bureau des Arts diff --git a/bda/templates/mail-revente-seller.txt b/bda/templates/mail-revente-seller.txt new file mode 100644 index 00000000..ec99b98b --- /dev/null +++ b/bda/templates/mail-revente-seller.txt @@ -0,0 +1,7 @@ +Bonjour {{ vendeur.first_name }}, + +La personne tirée au sort pour racheter ta place pour {{ spectacle.title }} est {{ acheteur.get_full_name }}. +Tu peux le/la contacter à l'adresse {{ acheteur.email }}, ou en répondant à ce mail. + +Chaleureusement, +Le BdA diff --git a/bda/templates/mail-revente-winner.txt b/bda/templates/mail-revente-winner.txt new file mode 100644 index 00000000..8ca7236a --- /dev/null +++ b/bda/templates/mail-revente-winner.txt @@ -0,0 +1,7 @@ +Bonjour {{ acheteur.first_name }}, + +Tu as été tiré-e au sort pour racheter une place pour {{ spectacle.title }} le {{ spectacle.date_no_seconds }} ({{ spectacle.location }}) à {{ spectacle.price|floatformat:2 }}€. +Tu peux contacter le/la vendeur-se à l'adresse {{ vendeur.email }}, ou en répondant à ce mail. + +Chaleureusement, +Le BdA diff --git a/requirements.txt b/requirements.txt index 2d1109eb..5fffab61 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ configparser==3.5.0 -Django==1.8 +Django==1.8.* django-autocomplete-light==2.3.3 django-autoslug==1.9.3 git+https://github.com/xapantu/django-cas-ng.git#egg=django-cas-ng From b40fc6204f93152d4d195754e77d752fc23299ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 5 Nov 2016 21:59:49 +0100 Subject: [PATCH 078/103] Changements mineurs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Suppression de la variable `ALLOWED_HOSTS` de `cof/settings.dev` de sorte quand django utilise le default (qui est adapté à notre usage) - Correction d'indentation - Suppression d'un "-e" dans le fichier `requirements.txt` --- cof/settings_dev.py | 5 +---- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cof/settings_dev.py b/cof/settings_dev.py index b2bda35d..6747963b 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -29,9 +29,6 @@ SECRET_KEY = 'q()(zn4m63i%5cp4)f+ww4-28_w+ly3q9=6imw2ciu&_(5_4ah' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = ['127.0.0.1'] - - # Application definition INSTALLED_APPS = ( 'gestioncof', @@ -126,7 +123,7 @@ STATIC_URL = '/static/' STATIC_ROOT = '/var/www/static/' STATICFILES_DIRS = ( - os.path.join(BASE_DIR, 'static/'), + os.path.join(BASE_DIR, 'static/'), ) # Media upload (through ImageField, SiteField) diff --git a/requirements.txt b/requirements.txt index 79a1d71c..23f4d618 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,7 @@ django-bootstrap-form==3.2.1 asgiref==0.14.0 daphne==0.14.3 asgi-redis==0.14.0 --e git+https://github.com/Aureplop/channels.git#egg=channel +git+https://github.com/Aureplop/channels.git#egg=channel statistics==1.0.3.5 future==0.15.2 django-widget-tweaks==1.4.1 From 981ff48e3d8e232816ac743d357704b71fd32605 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sat, 5 Nov 2016 22:35:46 +0100 Subject: [PATCH 079/103] Envoie un mail de confirmation lors d'une mise en vente Ce mail contient la date du tirage. --- bda/templates/mail-revente-new.txt | 13 +++++++++++ bda/views.py | 37 ++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 bda/templates/mail-revente-new.txt diff --git a/bda/templates/mail-revente-new.txt b/bda/templates/mail-revente-new.txt new file mode 100644 index 00000000..ffba3083 --- /dev/null +++ b/bda/templates/mail-revente-new.txt @@ -0,0 +1,13 @@ +Bonjour {{ vendeur.first_name }}, + +Tu t’es bien inscrit-e pour la revente de {{ spectacle.title }}. + +{% with revente.expiration_time as time %} +Le tirage au sort entre tout-e-s les racheteuse-eur-s potentiel-le-s aura lieu +le {{ time|date:"DATE_FORMAT" }} à {{ time|time:"TIME_FORMAT" }} (dans {{time|timeuntil }}). +Si personne ne s’est inscrit pour racheter la place, celle-ci apparaitra parmi +les « Places disponibles immédiatement à la revente » sur GestioCOF. +{% endwith %} + +Bonne revente ! +Le Bureau des Arts diff --git a/bda/views.py b/bda/views.py index 756525f2..8beeb84b 100644 --- a/bda/views.py +++ b/bda/views.py @@ -8,15 +8,17 @@ import random from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required -from django.db import models +from django.db import models, transaction from django.db.models import Count, Q -from django.core import serializers +from django.core import serializers, mail from django.forms.models import inlineformset_factory from django.http import HttpResponseBadRequest, HttpResponseRedirect from django.core.urlresolvers import reverse +from django.conf import settings import hashlib from django.core.mail import send_mail +from django.template import loader from django.utils import timezone from django.views.generic.list import ListView @@ -292,15 +294,30 @@ def revente(request, tirage_id): resellform = ResellForm(participant, request.POST, prefix='resell') annulform = AnnulForm(participant, prefix='annul') if resellform.is_valid(): + mails = [] attributions = resellform.cleaned_data["attributions"] - for attribution in attributions: - revente, created = SpectacleRevente.objects.get_or_create( - attribution=attribution, - defaults={'seller': participant}) - if not created: - revente.seller = participant - revente.date = timezone.now() - revente.save() + with transaction.atomic(): + for attribution in attributions: + revente, created = SpectacleRevente.objects.get_or_create( + attribution=attribution, + defaults={'seller': participant}) + if not created: + revente.seller = participant + revente.date = timezone.now() + mail_subject = "BdA-Revente : {:s}".format(attribution.spectacle.title) + mail_body = loader.render_to_string('mail-revente-new.txt', { + 'vendeur': participant.user, + 'spectacle': attribution.spectacle, + 'revente': revente, + }) + mails.append(mail.EmailMessage( + mail_subject, mail_body, + from_email=settings.MAIL_DATA['revente']['FROM'], + to=[participant.user.email], + reply_to=[settings.MAIL_DATA['revente']['REPLYTO']], + )) + revente.save() + mail.get_connection().send_messages(mails) elif 'annul' in request.POST: annulform = AnnulForm(participant, request.POST, prefix='annul') From 0cca9f0861af044ef875fbafdf8538db037f17d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 6 Nov 2016 15:39:14 +0100 Subject: [PATCH 080/103] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20django=5Fde?= =?UTF-8?q?bug=5Ftoolbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cof/settings_dev.py | 1 + cof/urls.py | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 6747963b..5cb0c826 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -53,6 +53,7 @@ INSTALLED_APPS = ( ) MIDDLEWARE_CLASSES = ( + 'debug_toolbar.middleware.DebugToolbarMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', diff --git a/cof/urls.py b/cof/urls.py index 263fc3a0..f5b507f1 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -1,24 +1,27 @@ # -*- coding: utf-8 -*- +""" +Fichier principal de configuration des urls du projet GestioCOF +""" + from __future__ import division from __future__ import print_function from __future__ import unicode_literals +import autocomplete_light + from django.conf import settings from django.conf.urls import include, url from django.conf.urls.static import static from django.contrib import admin from django.views.generic.base import TemplateView - -import autocomplete_light - from django.contrib.auth import views as django_views from django_cas_ng import views as django_cas_views + from gestioncof import views as gestioncof_views, csv_views from gestioncof.urls import export_patterns, petitcours_patterns, \ surveys_patterns, events_patterns, calendar_patterns, \ clubs_patterns - from gestioncof.autocomplete import autocomplete autocomplete_light.autodiscover() @@ -89,6 +92,13 @@ my_urlpatterns = [ # Si on est en production, MEDIA_ROOT est servi par Apache. # Il faut dire à Django de servir MEDIA_ROOT lui-même en développement. +if settings.DEBUG: + import debug_toolbar + my_urlpatterns += [ + url(r'^__debug__/', + include(debug_toolbar.urls)), + ] + urlpatterns = [ url(r'^gestion/', include(my_urlpatterns)) ] From 41b54cec9e41fb399887cac485ef8d865a5ead4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 6 Nov 2016 15:39:50 +0100 Subject: [PATCH 081/103] Utilisation d'un virtualenv --- provisioning/bootstrap.sh | 14 ++++++++++---- provisioning/prepare_django.sh | 6 +++--- provisioning/supervisor.conf | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index f072e6fc..55c7bacb 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -8,7 +8,7 @@ DBNAME="cof_gestion" DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" # Installation de paquets utiles -apt-get update && apt-get install -y mercurial python-pip python-dev \ +apt-get update && apt-get install -y mercurial python3-pip python3-dev \ libmysqlclient-dev libjpeg-dev git redis-server # Configuration et installation de mysql. Le mot de passe root est le même que @@ -44,6 +44,9 @@ export DBPASSWD="$DBPASSWD" # Permet d'utiliser les utilitaires pythons locaux export PATH="\$PATH:\$HOME/.local/bin" +# Charge le virtualenv +source ~/venv/bin/activate + # On va dans /vagrant où se trouve le code de gestioCOF cd /vagrant EOF @@ -52,8 +55,11 @@ chown vagrant: ~vagrant/.bash_profile # On va dans /vagrant où se trouve gestioCOF cd /vagrant -# Installation des dépendances python -sudo -H -u vagrant pip install --user -r requirements.txt -r requirements-devel.txt +# Installation du virtualenv, on utilise désormais python3 +pip3 install -U pip +pip3 install virtualenv +sudo -H -u vagrant virtualenv ~vagrant/venv -p /usr/bin/python3 +sudo -H -u vagrant ~vagrant/venv/bin/pip install -r requirements.txt -r requirements-devel.txt # Préparation de Django sudo -H -u vagrant DJANGO_SETTINGS_MODULE='cof.settings_dev' DBUSER=$DBUSER DBNAME=$DBNAME DBPASSWD=$DBPASSWD sh provisioning/prepare_django.sh @@ -62,7 +68,7 @@ sudo -H -u vagrant DJANGO_SETTINGS_MODULE='cof.settings_dev' DBUSER=$DBUSER DBNA sudo -H -u vagrant crontab provisioning/cron.dev # On installe Daphne et on demande à supervisor de le lancer -pip install daphne +~vagrant/venv/bin/pip install daphne apt-get install -y supervisor cp /vagrant/provisioning/supervisor.conf /etc/supervisor/conf.d/gestiocof.conf sed "s/{DBUSER}/$DBUSER/" -i /etc/supervisor/conf.d/gestiocof.conf diff --git a/provisioning/prepare_django.sh b/provisioning/prepare_django.sh index 8988e834..f4f8c199 100644 --- a/provisioning/prepare_django.sh +++ b/provisioning/prepare_django.sh @@ -1,5 +1,5 @@ # Doit être lancé par bootstrap.sh -python manage.py migrate -python manage.py loaddata users root bda gestion sites -python manage.py collectstatic --noinput +~/venv/bin/python manage.py migrate +~/venv/bin/python manage.py loaddata users root bda gestion sites +~/venv/bin/python manage.py collectstatic --noinput diff --git a/provisioning/supervisor.conf b/provisioning/supervisor.conf index 4c46b952..fe8b4e56 100644 --- a/provisioning/supervisor.conf +++ b/provisioning/supervisor.conf @@ -1,5 +1,5 @@ [program:worker] -command=/usr/bin/python /vagrant/manage.py runworker +command=/home/vagrant/venv/bin/python /vagrant/manage.py runworker directory=/vagrant/ user=vagrant environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" @@ -10,7 +10,7 @@ stopasgroup=true redirect_stderr=true [program:interface] -command=/usr/local/bin/daphne -b 127.0.0.1 -p 8001 cof.asgi:channel_layer +command=/home/vagrant/venv/bin/daphne -b 127.0.0.1 -p 8001 cof.asgi:channel_layer environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" directory=/vagrant/ redirect_stderr=true From d1c6c2151a954a80c1ca156f3895cf9dd70076ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 6 Nov 2016 19:01:30 +0100 Subject: [PATCH 082/103] Ubuntu 16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On passe à ubuntu 16 ce qui permet d'utiliser python3.5 et le paquet python3-venv. Fichier `provisioning/prepare_django.sh` plus propre --- Vagrantfile | 2 +- provisioning/bootstrap.sh | 20 +++++++++----------- provisioning/prepare_django.sh | 8 +++++--- provisioning/supervisor.conf | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Vagrantfile b/Vagrantfile index c84c3dd9..e12a45ed 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -10,7 +10,7 @@ Vagrant.configure(2) do |config| # For a complete reference, please see the online documentation at # https://docs.vagrantup.com. - config.vm.box = "ubuntu/trusty64" + config.vm.box = "ubuntu/xenial64" # On associe le port 80 dans la machine virtuelle avec le port 8080 de notre # ordinateur, et le port 8000 avec le port 8000. diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index 55c7bacb..7c3e1b46 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -8,7 +8,7 @@ DBNAME="cof_gestion" DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" # Installation de paquets utiles -apt-get update && apt-get install -y mercurial python3-pip python3-dev \ +apt-get update && apt-get install -y python3-pip python3-dev python3-venv \ libmysqlclient-dev libjpeg-dev git redis-server # Configuration et installation de mysql. Le mot de passe root est le même que @@ -29,10 +29,10 @@ a2ensite gestiocof a2dissite 000-default service apache2 restart mkdir /var/www/static -chown -R vagrant:www-data /var/www/static +chown -R ubuntu:www-data /var/www/static # Mise en place du .bash_profile pour tout configurer lors du `vagrant ssh` -cat > ~vagrant/.bash_profile <> ~ubuntu/.bashrc < Date: Sun, 6 Nov 2016 19:28:47 +0100 Subject: [PATCH 083/103] typo --- provisioning/bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index 7c3e1b46..1b3c39d3 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -66,7 +66,7 @@ sudo -H -u ubuntu DJANGO_SETTINGS_MODULE='cof.settings_dev' DBUSER=$DBUSER DBNAM sudo -H -u ubuntu crontab provisioning/cron.dev # On installe Daphne et on demande à supervisor de le lancer -~ubuntu/venv/bin/pip install daphne +sudo -H -u ubuntu ~ubuntu/venv/bin/pip install daphne apt-get install -y supervisor cp /vagrant/provisioning/supervisor.conf /etc/supervisor/conf.d/gestiocof.conf sed "s/{DBUSER}/$DBUSER/" -i /etc/supervisor/conf.d/gestiocof.conf From d77a4dde3e342cec3668e972a4bdce19c627fefb Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sun, 6 Nov 2016 01:36:10 +0100 Subject: [PATCH 084/103] GestioCOF devrait fonctionner sur / aussi bien que sur /gestion --- cof/settings_dev.py | 10 +++------- cof/urls.py | 20 ++++++++------------ kfet/routing.py | 4 +--- provisioning/apache.conf | 10 ++++++++++ provisioning/bootstrap.sh | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 6747963b..11c2faf9 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -135,10 +135,6 @@ MEDIA_URL = '/media/' # Various additional settings SITE_ID = 1 -# URL prefix for admin static files -- CSS, JavaScript and images. -# Make sure to use a trailing slash. -# Examples: "http://foo.com/static/admin/", "/static/admin/". -ADMIN_MEDIA_PREFIX = '/static/grappelli/' GRAPPELLI_ADMIN_HEADLINE = "GestioCOF" GRAPPELLI_ADMIN_TITLE = "GestioCOF" @@ -155,12 +151,12 @@ MAIL_DATA = { 'REPLYTO': 'BdA-Revente '}, } -LOGIN_URL = "/gestion/login" -LOGIN_REDIRECT_URL = "/gestion/" +LOGIN_URL = "cof-login" +LOGIN_REDIRECT_URL = "home" CAS_SERVER_URL = 'https://cas.eleves.ens.fr/' CAS_IGNORE_REFERER = True -CAS_REDIRECT_URL = '/gestion/' +CAS_REDIRECT_URL = '/' CAS_EMAIL_FORMAT = "%s@clipper.ens.fr" AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', diff --git a/cof/urls.py b/cof/urls.py index 263fc3a0..f3d6905e 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -24,7 +24,7 @@ from gestioncof.autocomplete import autocomplete autocomplete_light.autodiscover() admin.autodiscover() -my_urlpatterns = [ +urlpatterns = [ # Page d'accueil url(r'^$', gestioncof_views.home, name='home'), # Le BdA @@ -48,7 +48,7 @@ my_urlpatterns = [ url(r'^cas/logout$', django_cas_views.logout), url(r'^outsider/login$', gestioncof_views.login_ext), url(r'^outsider/logout$', django_views.logout, {'next_page': 'home'}), - url(r'^login$', gestioncof_views.login), + url(r'^login$', gestioncof_views.login, name="cof-login"), url(r'^logout$', gestioncof_views.logout), # Infos persos url(r'^profile$', gestioncof_views.profile), @@ -81,14 +81,10 @@ my_urlpatterns = [ 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), - url(r'^k-fet/', include('kfet.urls')) -] + \ - (static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) - if settings.DEBUG - else []) -# Si on est en production, MEDIA_ROOT est servi par Apache. -# Il faut dire à Django de servir MEDIA_ROOT lui-même en développement. - -urlpatterns = [ - url(r'^gestion/', include(my_urlpatterns)) + url(r'^k-fet/', include('kfet.urls')), ] + +if settings.DEBUG: + # Si on est en production, MEDIA_ROOT est servi par Apache. + # Il faut dire à Django de servir MEDIA_ROOT lui-même en développement. + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/kfet/routing.py b/kfet/routing.py index 9c816c92..63e0c963 100644 --- a/kfet/routing.py +++ b/kfet/routing.py @@ -8,7 +8,5 @@ from channels.routing import route, route_class from kfet import consumers channel_routing = [ - route_class(consumers.KPsul, path=r"^/gestion/ws/k-fet/k-psul/$"), - #route("websocket.connect", ws_kpsul_history_connect), - #route('websocket.receive', ws_message) + route_class(consumers.KPsul, path=r"^ws/k-fet/k-psul/$"), ] diff --git a/provisioning/apache.conf b/provisioning/apache.conf index 001c6ec9..cc815592 100644 --- a/provisioning/apache.conf +++ b/provisioning/apache.conf @@ -6,6 +6,16 @@ ProxyRequests Off ProxyPass /static/ ! ProxyPass /media/ ! + # Pour utiliser un sous-dossier (typiquement /gestion/), il faut faire a la + # place des lignes suivantes: + # + # RequestHeader set Daphne-Root-Path /gestion + # ProxyPass /gestion/ws/ ws://127.0.0.1:8001/gestion/ws/ + # ProxyPass /gestion http://127.0.0.1:8001/gestion + # ProxyPassReverse /gestion http://127.0.0.1:8001/gestion + # + # Penser egalement a changer les /static/ et /media/ dans la config apache + # ainsi que dans les settings django. ProxyPass /ws/ ws://127.0.0.1:8001/ws/ ProxyPass / http://127.0.0.1:8001/ ProxyPassReverse / http://127.0.0.1:8001/ diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index f072e6fc..152e903a 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -23,7 +23,7 @@ mysql -uroot -p$DBPASSWD -e "CREATE DATABASE $DBNAME; GRANT ALL PRIVILEGES ON $D # Installation et configuration d'Apache apt-get install -y apache2 -a2enmod proxy proxy_http +a2enmod proxy proxy_http proxy_wstunnel headers cp /vagrant/provisioning/apache.conf /etc/apache2/sites-available/gestiocof.conf a2ensite gestiocof a2dissite 000-default From a63f1da2e11c7ce172229af1140ffd466508632f Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sun, 6 Nov 2016 19:44:05 +0100 Subject: [PATCH 085/103] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20django=5Fde?= =?UTF-8?q?bug=5Ftoolbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cof/settings_dev.py | 1 + cof/urls.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 11c2faf9..8a622318 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -53,6 +53,7 @@ INSTALLED_APPS = ( ) MIDDLEWARE_CLASSES = ( + 'debug_toolbar.middleware.DebugToolbarMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', diff --git a/cof/urls.py b/cof/urls.py index f3d6905e..5134456a 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -85,6 +85,11 @@ urlpatterns = [ ] if settings.DEBUG: + import debug_toolbar + urlpatterns += [ + url(r'^__debug__/', include(debug_toolbar.urls)), + ] + # Si on est en production, MEDIA_ROOT est servi par Apache. # Il faut dire à Django de servir MEDIA_ROOT lui-même en développement. urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) From 76a88be4ef729d32e4e2b29d5f05fdd20886fd93 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Tue, 8 Nov 2016 10:28:00 -0200 Subject: [PATCH 086/103] check date spectacle --- bda/views.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bda/views.py b/bda/views.py index b9ce0825..9b667cc2 100644 --- a/bda/views.py +++ b/bda/views.py @@ -331,11 +331,12 @@ def revente(request, tirage_id): id=revente_id) if rev.exists(): revente = rev.get() - revente.date = timezone.now() - timedelta(hours=1) - revente.soldTo = None - if revente.answered_mail: - revente.answered_mail.clear() - revente.save() + if revente.attribution.spectacle.date > timezone.now(): + revente.date = timezone.now() - timedelta(hours=1) + revente.soldTo = None + if revente.answered_mail: + revente.answered_mail.clear() + revente.save() else: resellform = ResellForm(participant, prefix='resell') From 929672a2a97d22d379ed8ecd811313dd38ec8664 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Tue, 8 Nov 2016 10:41:12 -0200 Subject: [PATCH 087/103] check date admin --- bda/admin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bda/admin.py b/bda/admin.py index 87a269d4..a9b3c51f 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -257,7 +257,8 @@ class SpectacleReventeAdmin(admin.ModelAdmin): Réinitialise les reventes. """ count = queryset.count() - for revente in queryset.all(): + for revente in queryset.filter( + attribution__spectacle__date__gte=timezone.now()): revente.date = timezone.now() - timedelta(hours=1) revente.soldTo = None revente.notif_sent = False From cce574a11b6085a198e134f85021593ab974d1d3 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Tue, 8 Nov 2016 09:48:55 +0100 Subject: [PATCH 088/103] Supprime do_resell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La fonction utilitaire `bda.views.do_resell` n’est plus utilisée depuis la nouvelle version de bda-revente. --- bda/views.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/bda/views.py b/bda/views.py index 8beeb84b..5f84228b 100644 --- a/bda/views.py +++ b/bda/views.py @@ -263,25 +263,6 @@ def tirage(request, tirage_id): return render(request, "bda-token.html", {"form": form}) -def do_resell(request, form): - spectacle = form.cleaned_data["spectacle"] - count = form.cleaned_data["count"] - places = "2 places" if count == "2" else "une place" - mail = """Bonjour, - -Je souhaite revendre %s pour %s le %s (%s) à %.02f€. -Contactez moi par email si vous êtes intéressé·e·s ! - -%s (%s)""" % (places, spectacle.title, spectacle.date_no_seconds(), - spectacle.location, spectacle.price, - request.user.get_full_name(), request.user.email) - send_mail("%s" % spectacle, mail, - request.user.email, ["bda-revente@lists.ens.fr"], - fail_silently=False) - return render(request, "bda-success.html", - {"show": spectacle, "places": places}) - - @login_required def revente(request, tirage_id): tirage = get_object_or_404(Tirage, id=tirage_id) From 1f1419c5f19b0b0c6e8415d9581b40b68a9a5340 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Tue, 8 Nov 2016 07:34:19 +0100 Subject: [PATCH 089/103] Supprime `render_template` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GestioCOF définit une fonction `render_template` qui permet de calculer l'interpolation d'un gabarit en une chaîne de caractères, par exemple pour l'envoi de mails. Ce patch supprime cette fonction et remplace son utilisation par la fonction `django.template.loader.render_to_string` au comportement identique. --- bda/models.py | 20 +++++++--------- bda/views.py | 6 ++--- gestioncof/petits_cours_views.py | 39 +++++++++++++++----------------- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/bda/models.py b/bda/models.py index 6fb22189..41550507 100644 --- a/bda/models.py +++ b/bda/models.py @@ -11,19 +11,13 @@ from datetime import timedelta from django.contrib.sites.models import Site from django.db import models from django.contrib.auth.models import User -from django.template import loader, Context +from django.template import loader from django.core import mail from django.conf import settings from django.utils import timezone from django.utils.encoding import python_2_unicode_compatible -def render_template(template_name, data): - tmpl = loader.get_template(template_name) - ctxt = Context(data) - return tmpl.render(ctxt) - - @python_2_unicode_compatible class Tirage(models.Model): title = models.CharField("Titre", max_length=300) @@ -117,7 +111,7 @@ class Spectacle(models.Model): mail_object = "%s - %s - %s" % (self.title, self.date_no_seconds(), self.location) for member in members.values(): - mail_body = render_template('mail-rappel.txt', { + mail_body = loader.render_to_string('mail-rappel.txt', { 'name': member[0], 'nb_attr': member[1], 'show': self}) @@ -277,7 +271,7 @@ class SpectacleRevente(models.Model): mails_to_send = [] mail_object = "%s" % (self.attribution.spectacle) for participant in inscrits: - mail_body = render_template('mail-revente.txt', { + mail_body = loader.render_to_string('mail-revente.txt', { 'user': participant.user, 'spectacle': self.attribution.spectacle, 'revente': self, @@ -301,7 +295,7 @@ class SpectacleRevente(models.Model): mails_to_send = [] mail_object = "%s" % (self.attribution.spectacle) for participant in inscrits: - mail_body = render_template('mail-shotgun.txt', { + mail_body = loader.render_to_string('mail-shotgun.txt', { 'user': participant.user, 'spectacle': self.attribution.spectacle, 'domain': Site.objects.get_current(), @@ -337,13 +331,15 @@ class SpectacleRevente(models.Model): 'spectacle': spectacle, } mails.append(mail.EmailMessage( - mail_subject, loader.render_to_string('mail-revente-winner.txt', context), + mail_subject, + loader.render_to_string('mail-revente-winner.txt', context), from_email=settings.MAIL_DATA['revente']['FROM'], to=[winner.user.email], reply_to=[seller.user.email], )) mails.append(mail.EmailMessage( - mail_subject, loader.render_to_string('mail-revente-seller.txt', context), + mail_subject, + loader.render_to_string('mail-revente-seller.txt', context), from_email=settings.MAIL_DATA['revente']['FROM'], to=[seller.user.email], reply_to=[winner.user.email], diff --git a/bda/views.py b/bda/views.py index 8beeb84b..ddc0596e 100644 --- a/bda/views.py +++ b/bda/views.py @@ -27,7 +27,7 @@ from datetime import timedelta from gestioncof.decorators import cof_required, buro_required from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ - Tirage, render_template, SpectacleRevente + Tirage, SpectacleRevente from bda.algorithm import Algorithm from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ @@ -571,11 +571,11 @@ def send_rappel(request, spectacle_id): # Mails d'exemples fake_member = request.user fake_member.nb_attr = 1 - exemple_mail_1place = render_template('mail-rappel.txt', { + exemple_mail_1place = loader.render_to_string('mail-rappel.txt', { 'member': fake_member, 'show': show}) fake_member.nb_attr = 2 - exemple_mail_2places = render_template('mail-rappel.txt', { + exemple_mail_2places = loader.render_to_string('mail-rappel.txt', { 'member': fake_member, 'show': show}) # Contexte diff --git a/gestioncof/petits_cours_views.py b/gestioncof/petits_cours_views.py index e9fe511e..d49e942f 100644 --- a/gestioncof/petits_cours_views.py +++ b/gestioncof/petits_cours_views.py @@ -14,7 +14,7 @@ from django.contrib.auth.models import User from django.views.generic import ListView from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt -from django.template import loader, Context +from django.template import loader from django.conf import settings from django.contrib.auth.decorators import login_required from django.db.models import Min @@ -33,12 +33,6 @@ import base64 import simplejson -def render_template(template_path, data): - tmpl = loader.get_template(template_path) - context = Context(data) - return tmpl.render(context) - - class DemandeListView(ListView): model = PetitCoursDemande template_name = "petits_cours_demandes_list.html" @@ -137,14 +131,14 @@ def _finalize_traitement(request, demande, proposals, proposed_for, proposed_for = proposed_for.items() attribdata = list(attribdata.items()) proposed_mails = _generate_eleve_email(demande, proposed_for) - mainmail = render_template("petits-cours-mail-demandeur.txt", - {"proposals": proposals, - "unsatisfied": unsatisfied, - "extra": - '' - }) + mainmail = loader.render_to_string("petits-cours-mail-demandeur.txt", { + "proposals": proposals, + "unsatisfied": unsatisfied, + "extra": + '' + }) return render(request, "traitement_demande_petit_cours.html", {"demande": demande, "unsatisfied": unsatisfied, @@ -163,8 +157,10 @@ def _finalize_traitement(request, demande, proposals, proposed_for, def _generate_eleve_email(demande, proposed_for): proposed_mails = [] for user, matieres in proposed_for: - msg = render_template("petits-cours-mail-eleve.txt", - {"demande": demande, "matieres": matieres}) + msg = loader.render_to_string("petits-cours-mail-eleve.txt", { + "demande": demande, + "matieres": matieres + }) proposed_mails.append((user, msg)) return proposed_mails @@ -278,10 +274,11 @@ def _traitement_post(request, demande): proposals_list = proposals.items() proposed_for = proposed_for.items() proposed_mails = _generate_eleve_email(demande, proposed_for) - mainmail = render_template("petits-cours-mail-demandeur.txt", - {"proposals": proposals_list, - "unsatisfied": unsatisfied, - "extra": extra}) + mainmail = loader.render_to_string("petits-cours-mail-demandeur.txt", { + "proposals": proposals_list, + "unsatisfied": unsatisfied, + "extra": extra, + }) frommail = settings.MAIL_DATA['petits_cours']['FROM'] bccaddress = settings.MAIL_DATA['petits_cours']['BCC'] replyto = settings.MAIL_DATA['petits_cours']['REPLYTO'] From 53a44134929a983403740599cfa73d1504a67178 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Tue, 8 Nov 2016 09:53:54 +0100 Subject: [PATCH 090/103] =?UTF-8?q?D=C3=A9place=20les=20gabarits=20d?= =?UTF-8?q?=E2=80=99email=20du=20bda=20dans=20un=20dossier=20sp=C3=A9cifiq?= =?UTF-8?q?ue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/models.py | 12 ++++++------ .../{mail-rappel.txt => bda/mails/rappel.txt} | 0 .../mails/revente-loser.txt} | 0 .../mails/revente-new.txt} | 0 .../mails/revente-seller.txt} | 0 .../mails/revente-winner.txt} | 0 .../{mail-revente.txt => bda/mails/revente.txt} | 0 .../{mail-shotgun.txt => bda/mails/shotgun.txt} | 0 bda/views.py | 6 +++--- 9 files changed, 9 insertions(+), 9 deletions(-) rename bda/templates/{mail-rappel.txt => bda/mails/rappel.txt} (100%) rename bda/templates/{mail-revente-loser.txt => bda/mails/revente-loser.txt} (100%) rename bda/templates/{mail-revente-new.txt => bda/mails/revente-new.txt} (100%) rename bda/templates/{mail-revente-seller.txt => bda/mails/revente-seller.txt} (100%) rename bda/templates/{mail-revente-winner.txt => bda/mails/revente-winner.txt} (100%) rename bda/templates/{mail-revente.txt => bda/mails/revente.txt} (100%) rename bda/templates/{mail-shotgun.txt => bda/mails/shotgun.txt} (100%) diff --git a/bda/models.py b/bda/models.py index 41550507..5c87be1e 100644 --- a/bda/models.py +++ b/bda/models.py @@ -111,7 +111,7 @@ class Spectacle(models.Model): mail_object = "%s - %s - %s" % (self.title, self.date_no_seconds(), self.location) for member in members.values(): - mail_body = loader.render_to_string('mail-rappel.txt', { + mail_body = loader.render_to_string('bda/mails/rappel.txt', { 'name': member[0], 'nb_attr': member[1], 'show': self}) @@ -271,7 +271,7 @@ class SpectacleRevente(models.Model): mails_to_send = [] mail_object = "%s" % (self.attribution.spectacle) for participant in inscrits: - mail_body = loader.render_to_string('mail-revente.txt', { + mail_body = loader.render_to_string('bda/mails/revente.txt', { 'user': participant.user, 'spectacle': self.attribution.spectacle, 'revente': self, @@ -295,7 +295,7 @@ class SpectacleRevente(models.Model): mails_to_send = [] mail_object = "%s" % (self.attribution.spectacle) for participant in inscrits: - mail_body = loader.render_to_string('mail-shotgun.txt', { + mail_body = loader.render_to_string('bda/mails/shotgun.txt', { 'user': participant.user, 'spectacle': self.attribution.spectacle, 'domain': Site.objects.get_current(), @@ -332,14 +332,14 @@ class SpectacleRevente(models.Model): } mails.append(mail.EmailMessage( mail_subject, - loader.render_to_string('mail-revente-winner.txt', context), + loader.render_to_string('bda/mails/revente-winner.txt', context), from_email=settings.MAIL_DATA['revente']['FROM'], to=[winner.user.email], reply_to=[seller.user.email], )) mails.append(mail.EmailMessage( mail_subject, - loader.render_to_string('mail-revente-seller.txt', context), + loader.render_to_string('bda/mails/revente-seller.txt', context), from_email=settings.MAIL_DATA['revente']['FROM'], to=[seller.user.email], reply_to=[winner.user.email], @@ -350,7 +350,7 @@ class SpectacleRevente(models.Model): if inscrit == winner: continue - mail_body = loader.render_to_string('mail-revente-loser.txt', { + mail_body = loader.render_to_string('bda/mails/revente-loser.txt', { 'acheteur': inscrit.user, 'vendeur': seller.user, 'spectacle': spectacle, diff --git a/bda/templates/mail-rappel.txt b/bda/templates/bda/mails/rappel.txt similarity index 100% rename from bda/templates/mail-rappel.txt rename to bda/templates/bda/mails/rappel.txt diff --git a/bda/templates/mail-revente-loser.txt b/bda/templates/bda/mails/revente-loser.txt similarity index 100% rename from bda/templates/mail-revente-loser.txt rename to bda/templates/bda/mails/revente-loser.txt diff --git a/bda/templates/mail-revente-new.txt b/bda/templates/bda/mails/revente-new.txt similarity index 100% rename from bda/templates/mail-revente-new.txt rename to bda/templates/bda/mails/revente-new.txt diff --git a/bda/templates/mail-revente-seller.txt b/bda/templates/bda/mails/revente-seller.txt similarity index 100% rename from bda/templates/mail-revente-seller.txt rename to bda/templates/bda/mails/revente-seller.txt diff --git a/bda/templates/mail-revente-winner.txt b/bda/templates/bda/mails/revente-winner.txt similarity index 100% rename from bda/templates/mail-revente-winner.txt rename to bda/templates/bda/mails/revente-winner.txt diff --git a/bda/templates/mail-revente.txt b/bda/templates/bda/mails/revente.txt similarity index 100% rename from bda/templates/mail-revente.txt rename to bda/templates/bda/mails/revente.txt diff --git a/bda/templates/mail-shotgun.txt b/bda/templates/bda/mails/shotgun.txt similarity index 100% rename from bda/templates/mail-shotgun.txt rename to bda/templates/bda/mails/shotgun.txt diff --git a/bda/views.py b/bda/views.py index ddc0596e..fb183d6c 100644 --- a/bda/views.py +++ b/bda/views.py @@ -305,7 +305,7 @@ def revente(request, tirage_id): revente.seller = participant revente.date = timezone.now() mail_subject = "BdA-Revente : {:s}".format(attribution.spectacle.title) - mail_body = loader.render_to_string('mail-revente-new.txt', { + mail_body = loader.render_to_string('bda/mails/revente-new.txt', { 'vendeur': participant.user, 'spectacle': attribution.spectacle, 'revente': revente, @@ -571,11 +571,11 @@ def send_rappel(request, spectacle_id): # Mails d'exemples fake_member = request.user fake_member.nb_attr = 1 - exemple_mail_1place = loader.render_to_string('mail-rappel.txt', { + exemple_mail_1place = loader.render_to_string('bda/mails/rappel.txt', { 'member': fake_member, 'show': show}) fake_member.nb_attr = 2 - exemple_mail_2places = loader.render_to_string('mail-rappel.txt', { + exemple_mail_2places = loader.render_to_string('bda/mails/rappel.txt', { 'member': fake_member, 'show': show}) # Contexte From afed3479b0959331a281bffedd1b4810cdbfedf3 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Tue, 8 Nov 2016 10:01:01 +0100 Subject: [PATCH 091/103] Remplace le dernier email en dur par un template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Il restait un unique email (envoyé lors de l’achat d’une place au shotgun) dont le texte est inscrit en dur dans `bda.views`. Pour éviter d’avoir trop de systèmes d’envoi de mails différents, il utilise maintenant une template dans `bda/mails` comme le reste des emails envoyés par l’application bda. --- bda/templates/bda/mails/buy-shotgun.txt | 6 ++++++ bda/views.py | 13 +++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 bda/templates/bda/mails/buy-shotgun.txt diff --git a/bda/templates/bda/mails/buy-shotgun.txt b/bda/templates/bda/mails/buy-shotgun.txt new file mode 100644 index 00000000..d06e0a39 --- /dev/null +++ b/bda/templates/bda/mails/buy-shotgun.txt @@ -0,0 +1,6 @@ +Bonjour {{ vendeur.first_name }} ! + +Je souhaiterais racheter ta place pour {{ spectacle.title }} le {{ spectacle.date_no_seconds }} ({{ spectacle.location }}) à {{ spectacle.price|floatformat:2 }}€. +Contacte-moi si tu es toujours intéressé·e ! + +{{ acheteur.get_full_name }} ({{ acheteur.email }}) diff --git a/bda/views.py b/bda/views.py index fb183d6c..28e8054e 100644 --- a/bda/views.py +++ b/bda/views.py @@ -471,14 +471,11 @@ def buy_revente(request, spectacle_id): revente = random.choice(reventes_shotgun) revente.soldTo = participant revente.save() - mail = """Bonjour ! - -Je souhaiterais racheter ta place pour %s le %s (%s) à %.02f€. -Contacte-moi si tu es toujours intéressé·e ! - -%s (%s)""" % (spectacle.title, spectacle.date_no_seconds(), - spectacle.location, spectacle.price, - request.user.get_full_name(), request.user.email) + mail = loader.render_to_string('bda/mails/buy-shotgun.txt', { + 'spectacle': spectacle, + 'acheteur': request.user, + 'vendeur': revente.seller.user, + }) send_mail("BdA-Revente : %s" % spectacle.title, mail, request.user.email, [revente.seller.user.email], From afab33f5a1cd123b8ef3929cf77a1ad3a1b53c91 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Tue, 8 Nov 2016 10:57:40 +0100 Subject: [PATCH 092/103] Supprime Spectacle.__repr__ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La méthode `bda.models.Spectacle.__repr__` est buggée (elle retourne une chaîne unicode alors que `__repr__` doit *toujours* renvoyer une chaîne ASCII) et pose des problèmes de crash lors de l’affichage d’objets `Spectacle` dans le REPL python. La méthode `__repr__` héritée de `django.db.models.Model` devrait être suffisante. --- bda/models.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bda/models.py b/bda/models.py index 6fb22189..ccc49222 100644 --- a/bda/models.py +++ b/bda/models.py @@ -86,9 +86,6 @@ class Spectacle(models.Model): verbose_name = "Spectacle" ordering = ("date", "title",) - def __repr__(self): - return "[%s]" % self - def timestamp(self): return "%d" % calendar.timegm(self.date.utctimetuple()) From 567c9a0a6d58c5d542613f4112ec57817739859b Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Tue, 8 Nov 2016 10:24:17 +0100 Subject: [PATCH 093/103] Meilleur affichage des dates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configure la localisation (i10n) de Django afin d’afficher un format plus user-friendly par défaut pour les dates (par exemple, afficher "21 septembre 2016 à 15:00" plutôt que "21 septembre 2016 15:00"). Ceci permet d’éliminer les utilisations de `date_no_seconds` pour simplement les remplacer par l’affichage de la date, le format par défaut étant maintenant satisfaisant. Attention : le bon fonctionnement de ceci nécessite de changer les settings afin d’utiliser le module `cof.locale` comme module de localisation (définir `FORMAT_MODULE_PATH = "cof.locale"`). Le module `cof.locale` définit le format d’affichage des dates+heures (`DATETIME_FORMAT`) afin d’incorporer le "à" qui n'est pas présent dans la localisation française de Django. --- bda/models.py | 23 +++++++++------------- bda/templates/bda-attrib.html | 2 +- bda/templates/bda/mails/buy-shotgun.txt | 2 +- bda/templates/bda/mails/rappel.txt | 2 +- bda/templates/bda/mails/revente-winner.txt | 2 +- bda/templates/bda/mails/revente.txt | 2 +- bda/templates/bda/mails/shotgun.txt | 2 +- bda/templates/etat-places.html | 2 +- bda/templates/resume_places.html | 2 +- bda/templates/spectacle_list.html | 2 +- cof/locale/__init__.py | 0 cof/locale/fr/__init__.py | 0 cof/locale/fr/formats.py | 4 ++++ cof/settings_dev.py | 2 ++ 14 files changed, 24 insertions(+), 23 deletions(-) create mode 100644 cof/locale/__init__.py create mode 100644 cof/locale/fr/__init__.py create mode 100644 cof/locale/fr/formats.py diff --git a/bda/models.py b/bda/models.py index 5c87be1e..cb642b4f 100644 --- a/bda/models.py +++ b/bda/models.py @@ -14,7 +14,7 @@ from django.contrib.auth.models import User from django.template import loader from django.core import mail from django.conf import settings -from django.utils import timezone +from django.utils import timezone, formats from django.utils.encoding import python_2_unicode_compatible @@ -28,12 +28,8 @@ class Tirage(models.Model): enable_do_tirage = models.BooleanField("Le tirage peut être lancé", default=False) - def date_no_seconds(self): - return self.fermeture.astimezone(timezone.get_current_timezone()) \ - .strftime('%d %b %Y %H:%M') - def __str__(self): - return "%s - %s" % (self.title, self.date_no_seconds()) + return "%s - %s" % (self.title, formats.localize(timezone.template_localtime(self.fermeture))) @python_2_unicode_compatible @@ -86,13 +82,13 @@ class Spectacle(models.Model): def timestamp(self): return "%d" % calendar.timegm(self.date.utctimetuple()) - def date_no_seconds(self): - return self.date.astimezone(timezone.get_current_timezone()) \ - .strftime('%d %b %Y %H:%M') - def __str__(self): - return "%s - %s, %s, %.02f€" % (self.title, self.date_no_seconds(), - self.location, self.price) + return "%s - %s, %s, %.02f€" % ( + self.title, + formats.localize(timezone.template_localtime(self.date)), + self.location, + self.price + ) def send_rappel(self): # On récupère la liste des participants @@ -108,8 +104,7 @@ class Spectacle(models.Model): members[-1] = ['BdA', 2, 'bda@ens.fr'] # On écrit un mail personnalisé à chaque participant mails_to_send = [] - mail_object = "%s - %s - %s" % (self.title, self.date_no_seconds(), - self.location) + mail_object = str(self) for member in members.values(): mail_body = loader.render_to_string('bda/mails/rappel.txt', { 'name': member[0], diff --git a/bda/templates/bda-attrib.html b/bda/templates/bda-attrib.html index 5c705a79..5c22d2b3 100644 --- a/bda/templates/bda-attrib.html +++ b/bda/templates/bda-attrib.html @@ -22,7 +22,7 @@ {% for show, members, losers in results %}
        -

        {{ show.title }} - {{ show.date_no_seconds }} @ {{ show.location }}

        +

        {{ show.title }} - {{ show.date }} @ {{ show.location }}

        {{ show.nrequests }} demandes pour {{ show.slots }} places {{ show.price }}€ par place{% if user.profile.is_buro and show.nrequests < show.slots %}, {{ show.deficit }}€ de déficit{% endif %} diff --git a/bda/templates/bda/mails/buy-shotgun.txt b/bda/templates/bda/mails/buy-shotgun.txt index d06e0a39..d7855143 100644 --- a/bda/templates/bda/mails/buy-shotgun.txt +++ b/bda/templates/bda/mails/buy-shotgun.txt @@ -1,6 +1,6 @@ Bonjour {{ vendeur.first_name }} ! -Je souhaiterais racheter ta place pour {{ spectacle.title }} le {{ spectacle.date_no_seconds }} ({{ spectacle.location }}) à {{ spectacle.price|floatformat:2 }}€. +Je souhaiterais racheter ta place pour {{ spectacle.title }} le {{ spectacle.date }} ({{ spectacle.location }}) à {{ spectacle.price|floatformat:2 }}€. Contacte-moi si tu es toujours intéressé·e ! {{ acheteur.get_full_name }} ({{ acheteur.email }}) diff --git a/bda/templates/bda/mails/rappel.txt b/bda/templates/bda/mails/rappel.txt index 4759a849..c6433f8a 100644 --- a/bda/templates/bda/mails/rappel.txt +++ b/bda/templates/bda/mails/rappel.txt @@ -1,7 +1,7 @@ Bonjour {{ name }}, Nous te rappellons que tu as eu la chance d'obtenir {{ nb_attr|pluralize:"une place,deux places" }} -pour {{ show.title }}, le {{ show.date_no_seconds }} au {{ show.location }}. N'oublie pas de t'y rendre ! +pour {{ show.title }}, le {{ show.date }} au {{ show.location }}. N'oublie pas de t'y rendre ! {% if nb_attr == 2 %} Tu as obtenu deux places pour ce spectacle. Nous te rappelons que ces places sont strictement réservées aux personnes de moins de 28 ans. diff --git a/bda/templates/bda/mails/revente-winner.txt b/bda/templates/bda/mails/revente-winner.txt index 8ca7236a..01ecfb86 100644 --- a/bda/templates/bda/mails/revente-winner.txt +++ b/bda/templates/bda/mails/revente-winner.txt @@ -1,6 +1,6 @@ Bonjour {{ acheteur.first_name }}, -Tu as été tiré-e au sort pour racheter une place pour {{ spectacle.title }} le {{ spectacle.date_no_seconds }} ({{ spectacle.location }}) à {{ spectacle.price|floatformat:2 }}€. +Tu as été tiré-e au sort pour racheter une place pour {{ spectacle.title }} le {{ spectacle.date }} ({{ spectacle.location }}) à {{ spectacle.price|floatformat:2 }}€. Tu peux contacter le/la vendeur-se à l'adresse {{ vendeur.email }}, ou en répondant à ce mail. Chaleureusement, diff --git a/bda/templates/bda/mails/revente.txt b/bda/templates/bda/mails/revente.txt index 899afe3b..397a58d8 100644 --- a/bda/templates/bda/mails/revente.txt +++ b/bda/templates/bda/mails/revente.txt @@ -1,6 +1,6 @@ Bonjour {{ user.first_name }} -Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date_no_seconds }}) +Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date }}) a été postée sur BdA-Revente. Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant diff --git a/bda/templates/bda/mails/shotgun.txt b/bda/templates/bda/mails/shotgun.txt index 899d5c85..53462fb3 100644 --- a/bda/templates/bda/mails/shotgun.txt +++ b/bda/templates/bda/mails/shotgun.txt @@ -1,6 +1,6 @@ Bonjour {{ user.first_name }} -Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date_no_seconds }}) +Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date }}) a été postée sur BdA-Revente. Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour diff --git a/bda/templates/etat-places.html b/bda/templates/etat-places.html index ebd15c38..4aa72ba1 100644 --- a/bda/templates/etat-places.html +++ b/bda/templates/etat-places.html @@ -18,7 +18,7 @@ {% for spectacle in spectacles %} {{ spectacle.title }} - {{ spectacle.date_no_seconds }} + {{ spectacle.date }} {{ spectacle.location }} {{ spectacle.slots }} places {{ spectacle.total }} demandes diff --git a/bda/templates/resume_places.html b/bda/templates/resume_places.html index 9ca5c78f..614a1656 100644 --- a/bda/templates/resume_places.html +++ b/bda/templates/resume_places.html @@ -11,7 +11,7 @@ {{place.spectacle.title}} {{place.spectacle.location}} - {{place.spectacle.date_no_seconds}} + {{place.spectacle.date}} {% if place.double %}deux places{%else%}une place{% endif %} {% endfor %} diff --git a/bda/templates/spectacle_list.html b/bda/templates/spectacle_list.html index 816461db..c7456f6e 100644 --- a/bda/templates/spectacle_list.html +++ b/bda/templates/spectacle_list.html @@ -19,7 +19,7 @@ {% for spectacle in object_list %} {{ spectacle.title }} - {{ spectacle.date_no_seconds }} + {{ spectacle.date }} {{ spectacle.location }} {{ spectacle.price |floatformat }}€ diff --git a/cof/locale/__init__.py b/cof/locale/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cof/locale/fr/__init__.py b/cof/locale/fr/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cof/locale/fr/formats.py b/cof/locale/fr/formats.py new file mode 100644 index 00000000..2a926447 --- /dev/null +++ b/cof/locale/fr/formats.py @@ -0,0 +1,4 @@ +# -*- encoding: utf-8 -*- +from __future__ import unicode_literals + +DATETIME_FORMAT = r'j F Y \à H:i' diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 6747963b..12a58b26 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -202,3 +202,5 @@ def show_toolbar(request): DEBUG_TOOLBAR_CONFIG = { 'SHOW_TOOLBAR_CALLBACK': show_toolbar, } + +FORMAT_MODULE_PATH = 'cof.locale' From 03f7dff813867c37fc42e6d41f243cc958c13550 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sat, 12 Nov 2016 11:09:40 +0100 Subject: [PATCH 094/103] Garde la locale par defaut dans les management commands --- bda/management/commands/manage_reventes.py | 1 + bda/management/commands/sendrappels.py | 1 + 2 files changed, 2 insertions(+) diff --git a/bda/management/commands/manage_reventes.py b/bda/management/commands/manage_reventes.py index 45b9c91a..a10c1ca5 100644 --- a/bda/management/commands/manage_reventes.py +++ b/bda/management/commands/manage_reventes.py @@ -11,6 +11,7 @@ from bda.models import SpectacleRevente class Command(BaseCommand): help = "Envoie les mails de notification et effectue " \ "les tirages au sort des reventes" + leave_locale_alone = True def handle(self, *args, **options): now = timezone.now() diff --git a/bda/management/commands/sendrappels.py b/bda/management/commands/sendrappels.py index 1e8da240..aa54337b 100644 --- a/bda/management/commands/sendrappels.py +++ b/bda/management/commands/sendrappels.py @@ -11,6 +11,7 @@ from bda.models import Spectacle class Command(BaseCommand): help = 'Envoie les mails de rappel des spectacles dont la date ' \ 'approche.\nNe renvoie pas les mails déjà envoyés.' + leave_locale_alone = True def handle(self, *args, **options): now = timezone.now() From 3c362014b0c2bb4da178ddd6f1573eb063ae766c Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sun, 13 Nov 2016 12:22:48 +0100 Subject: [PATCH 095/103] =?UTF-8?q?Remplace=20simplejson=20par=20json=20de?= =?UTF-8?q?=20la=20biblioth=C3=A8que=20standard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gestioncof/petits_cours_views.py | 6 +++--- requirements.txt | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gestioncof/petits_cours_views.py b/gestioncof/petits_cours_views.py index e9fe511e..c3e43ea8 100644 --- a/gestioncof/petits_cours_views.py +++ b/gestioncof/petits_cours_views.py @@ -30,7 +30,7 @@ from captcha.fields import ReCaptchaField from datetime import datetime import base64 -import simplejson +import json def render_template(template_path, data): @@ -153,7 +153,7 @@ def _finalize_traitement(request, demande, proposals, proposed_for, "proposed_mails": proposed_mails, "mainmail": mainmail, "attribdata": - base64.b64encode(simplejson.dumps(attribdata) + base64.b64encode(json.dumps(attribdata) .encode('utf_8')), "redo": redo, "errors": errors, @@ -262,7 +262,7 @@ def _traitement_post(request, demande): extra = request.POST["extra"].strip() redo = "redo" in request.POST attribdata = request.POST["attribdata"] - attribdata = dict(simplejson.loads(base64.b64decode(attribdata))) + attribdata = dict(json.loads(base64.b64decode(attribdata))) for matiere in demande.matieres.all(): if matiere.id not in attribdata: unsatisfied.append(matiere) diff --git a/requirements.txt b/requirements.txt index 23f4d618..f7f6deca 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,6 @@ django-grappelli==2.8.1 django-recaptcha==1.0.5 mysqlclient==1.3.7 Pillow==3.3.0 -simplejson==3.8.2 six==1.10.0 unicodecsv==0.14.1 icalendar==3.10 From a5ee17d0b5b2e040f71280e58b6bdadbf6cfa567 Mon Sep 17 00:00:00 2001 From: Basile Clement Date: Sun, 13 Nov 2016 11:29:28 +0100 Subject: [PATCH 096/103] Lance les tests de gestioCOF sur gitlab-ci --- .gitlab-ci.yml | 40 ++++++++++++++++++++++++++++++++++++++++ cof/settings_dev.py | 3 ++- requirements-devel.txt | 1 + 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..f420a9f5 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,40 @@ +services: + - mysql:latest + - redis:latest + +variables: + # GestioCOF settings + DJANGO_SETTINGS_MODULE: "cof.settings_dev" + DBNAME: "cof_gestion" + DBUSER: "cof_gestion" + DBPASSWD: "cof_password" + DBHOST: "mysql" + REDIS_HOST: "redis" + + # Cached packages + PYTHONPATH: "$CI_PROJECT_DIR/vendor/python" + + # mysql service configuration + MYSQL_DATABASE: "$DBNAME" + MYSQL_USER: "$DBUSER" + MYSQL_PASSWORD: "$DBPASSWD" + MYSQL_ROOT_PASSWORD: "root_password" + + +cache: + paths: + - vendor/python + - vendor/pip + - vendor/apt + +before_script: + - mkdir -p vendor/{python,pip,apt} + - apt-get update -q && apt-get -o dir::cache::archives="vendor/apt" install -yqq mysql-client + - mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host="$DBHOST" + -e "GRANT ALL ON test_$DBNAME.* TO '$DBUSER'@'%'" + - pip install --cache-dir vendor/pip -t vendor/python -r requirements-devel.txt + +test: + stage: test + script: + - python manage.py test diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 6747963b..1c3476dd 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -98,6 +98,7 @@ DATABASES = { 'NAME': os.environ['DBNAME'], 'USER': os.environ['DBUSER'], 'PASSWORD': os.environ['DBPASSWD'], + 'HOST': os.environ.get('DBHOST', 'localhost'), } } @@ -179,7 +180,7 @@ CHANNEL_LAYERS = { "default": { "BACKEND": "asgi_redis.RedisChannelLayer", "CONFIG": { - "hosts": [("localhost", 6379)], + "hosts": [(os.environ.get("REDIS_HOST", "localhost"), 6379)], }, "ROUTING": "cof.routing.channel_routing", } diff --git a/requirements-devel.txt b/requirements-devel.txt index dc8dbc45..425dfc36 100644 --- a/requirements-devel.txt +++ b/requirements-devel.txt @@ -1,2 +1,3 @@ +-r requirements.txt django-debug-toolbar ipython From 107079ce1f4c0986a17843b8cfc379263775e4a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 14 Nov 2016 06:39:55 +0100 Subject: [PATCH 097/103] Fix pip version --- provisioning/bootstrap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index 152e903a..a873973f 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -10,6 +10,7 @@ DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" # Installation de paquets utiles apt-get update && apt-get install -y mercurial python-pip python-dev \ libmysqlclient-dev libjpeg-dev git redis-server +pip install -U pip # Configuration et installation de mysql. Le mot de passe root est le même que # le mot de passe pour l'utilisateur local - pour rappel, ceci est une instance From 9960e7e37eccc216d983d15fbd75097d9dbbe0b2 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 17 Nov 2016 16:51:36 -0200 Subject: [PATCH 098/103] rebase kfet --- kfet/templates/kfet/transfers_create.html | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/kfet/templates/kfet/transfers_create.html b/kfet/templates/kfet/transfers_create.html index 294db1e5..83a09762 100644 --- a/kfet/templates/kfet/transfers_create.html +++ b/kfet/templates/kfet/transfers_create.html @@ -34,12 +34,12 @@ - + {{ form.from_acc }} {{ form.amount }} - + {{ form.to_acc }} @@ -71,18 +71,21 @@ $(document).ready(function () { var $next = $form.next('.transfer_form').find('.from_acc input'); } var $input_id = $input.next('input'); - getAccountData(trigramme, function(data) { - $input_id.val(data.id); - $data.text(data.name); - $next.focus(); - }); + if (isValidTrigramme(trigramme)) { + getAccountData(trigramme, function(data) { + $input_id.val(data.id); + $data.text(data.name); + $next.focus(); + }); + } else { + $input_id.val(''); + $data.text(''); + } } $('.input_from_acc, .input_to_acc').on('input', function() { var tri = $(this).val().toUpperCase(); - if (isValidTrigramme(tri)) { - updateAccountData(tri, $(this)); - } + updateAccountData(tri, $(this)); }); $('#transfers_form').on('submit', function(e) { From 92b422697b3075d01577c0dc1d973f854d888818 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Thu, 17 Nov 2016 17:44:44 -0200 Subject: [PATCH 099/103] rebase kfet --- kfet/templates/kfet/kpsul.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 0eceebd2..babd4175 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -924,7 +924,7 @@ $(document).ready(function() { } }); }, - onClose: function() { this._lastFocused = articleSelect; } + onClose: function() { this._lastFocused = (articleSelect.val() ? articleNb : articleSelect) ; } }); } From f93b095e0fba71b3d94cb5529e56990ecdbabef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 20 Nov 2016 16:39:26 +0100 Subject: [PATCH 100/103] Styling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ou comment faire plaisir à pylint sur les bouts de code concernés par cette MR --- bda/management/commands/manage_reventes.py | 17 +++-- bda/management/commands/sendrappels.py | 9 ++- bda/models.py | 83 +++++++++++++--------- bda/templates/bda/mails/shotgun.txt | 2 +- cof/locale/fr/formats.py | 5 ++ cof/settings_dev.py | 2 +- 6 files changed, 77 insertions(+), 41 deletions(-) diff --git a/bda/management/commands/manage_reventes.py b/bda/management/commands/manage_reventes.py index a10c1ca5..310bb618 100644 --- a/bda/management/commands/manage_reventes.py +++ b/bda/management/commands/manage_reventes.py @@ -1,14 +1,21 @@ # -*- coding: utf-8 -*- +""" +Gestion en ligne de commande des reventes. +""" + from __future__ import unicode_literals +from datetime import timedelta from django.core.management import BaseCommand from django.utils import timezone -from datetime import timedelta from bda.models import SpectacleRevente class Command(BaseCommand): + """ + Objet `BaseCommand`, cf ``self.help`` pour plus d'informations. + """ help = "Envoie les mails de notification et effectue " \ "les tirages au sort des reventes" leave_locale_alone = True @@ -19,21 +26,21 @@ class Command(BaseCommand): for revente in reventes: # Check si < 24h if (revente.attribution.spectacle.date <= - revente.date + timedelta(days=1)) and \ - now >= revente.date + timedelta(minutes=15) and \ + revente.date + timedelta(days=1)) and \ + now >= revente.date + timedelta(minutes=15) and \ not revente.notif_sent: self.stdout.write(str(now)) revente.mail_shotgun() self.stdout.write("Mail de disponibilité immédiate envoyé") # Check si délai de retrait dépassé elif (now >= revente.date + timedelta(hours=1) and - not revente.notif_sent): + not revente.notif_sent): self.stdout.write(str(now)) revente.send_notif() self.stdout.write("Mail d'inscription à une revente envoyé") # Check si tirage à faire elif (now >= revente.expiration_time and - not revente.tirage_done): + not revente.tirage_done): self.stdout.write(str(now)) revente.tirage() self.stdout.write("Tirage effectué, mails envoyés") diff --git a/bda/management/commands/sendrappels.py b/bda/management/commands/sendrappels.py index aa54337b..3c42170c 100644 --- a/bda/management/commands/sendrappels.py +++ b/bda/management/commands/sendrappels.py @@ -1,14 +1,21 @@ # -*- coding: utf-8 -*- +""" +Gestion en ligne de commande des mails de rappel. +""" + from __future__ import unicode_literals +from datetime import timedelta from django.core.management.base import BaseCommand from django.utils import timezone -from datetime import timedelta from bda.models import Spectacle class Command(BaseCommand): + """ + Objet Command, cf ``self.help`` pour plus d'informations. + """ help = 'Envoie les mails de rappel des spectacles dont la date ' \ 'approche.\nNe renvoie pas les mails déjà envoyés.' leave_locale_alone = True diff --git a/bda/models.py b/bda/models.py index cb642b4f..29e3dccd 100644 --- a/bda/models.py +++ b/bda/models.py @@ -29,7 +29,8 @@ class Tirage(models.Model): default=False) def __str__(self): - return "%s - %s" % (self.title, formats.localize(timezone.template_localtime(self.fermeture))) + return "%s - %s" % (self.title, formats.localize( + timezone.template_localtime(self.fermeture))) @python_2_unicode_compatible @@ -91,6 +92,10 @@ class Spectacle(models.Model): ) def send_rappel(self): + """ + Envoie un mail de rappel à toutes les personnes qui ont une place pour + ce spectacle. + """ # On récupère la liste des participants members = {} for attr in Attribution.objects.filter(spectacle=self).all(): @@ -107,14 +112,14 @@ class Spectacle(models.Model): mail_object = str(self) for member in members.values(): mail_body = loader.render_to_string('bda/mails/rappel.txt', { - 'name': member[0], - 'nb_attr': member[1], - 'show': self}) + 'name': member[0], + 'nb_attr': member[1], + 'show': self}) mail_tot = mail.EmailMessage( - mail_object, mail_body, - settings.MAIL_DATA['rappels']['FROM'], [member[2]], - [], headers={ - 'Reply-To': settings.MAIL_DATA['rappels']['REPLYTO']}) + mail_object, mail_body, + settings.MAIL_DATA['rappels']['FROM'], [member[2]], + [], headers={ + 'Reply-To': settings.MAIL_DATA['rappels']['REPLYTO']}) mails_to_send.append(mail_tot) # On envoie les mails connection = mail.get_connection() @@ -267,16 +272,16 @@ class SpectacleRevente(models.Model): mail_object = "%s" % (self.attribution.spectacle) for participant in inscrits: mail_body = loader.render_to_string('bda/mails/revente.txt', { - 'user': participant.user, - 'spectacle': self.attribution.spectacle, - 'revente': self, - 'domain': Site.objects.get_current().domain}) + 'user': participant.user, + 'spectacle': self.attribution.spectacle, + 'revente': self, + 'domain': Site.objects.get_current().domain}) mail_tot = mail.EmailMessage( - mail_object, mail_body, - settings.MAIL_DATA['revente']['FROM'], - [participant.user.email], - [], headers={ - 'Reply-To': settings.MAIL_DATA['revente']['REPLYTO']}) + mail_object, mail_body, + settings.MAIL_DATA['revente']['FROM'], + [participant.user.email], + [], headers={ + 'Reply-To': settings.MAIL_DATA['revente']['REPLYTO']}) mails_to_send.append(mail_tot) connection = mail.get_connection() @@ -285,22 +290,26 @@ class SpectacleRevente(models.Model): self.save() def mail_shotgun(self): + """ + Envoie un mail à toutes les personnes intéréssées par le spectacle pour + leur indiquer qu'il est désormais disponible au shotgun. + """ inscrits = self.attribution.spectacle.subscribed.select_related('user') mails_to_send = [] mail_object = "%s" % (self.attribution.spectacle) for participant in inscrits: mail_body = loader.render_to_string('bda/mails/shotgun.txt', { - 'user': participant.user, - 'spectacle': self.attribution.spectacle, - 'domain': Site.objects.get_current(), - 'mail': self.attribution.participant.user.email}) + 'user': participant.user, + 'spectacle': self.attribution.spectacle, + 'domain': Site.objects.get_current(), + 'mail': self.attribution.participant.user.email}) mail_tot = mail.EmailMessage( - mail_object, mail_body, - settings.MAIL_DATA['revente']['FROM'], - [participant.user.email], - [], headers={ - 'Reply-To': settings.MAIL_DATA['revente']['REPLYTO']}) + mail_object, mail_body, + settings.MAIL_DATA['revente']['FROM'], + [participant.user.email], + [], headers={ + 'Reply-To': settings.MAIL_DATA['revente']['REPLYTO']}) mails_to_send.append(mail_tot) connection = mail.get_connection() @@ -309,6 +318,11 @@ class SpectacleRevente(models.Model): self.save() def tirage(self): + """ + Lance le tirage au sort associé à la revente. Un gagnant est choisi + parmis les personnes intéressées par le spectacle. Les personnes sont + ensuites prévenues par mail du résultat du tirage. + """ inscrits = list(self.answered_mail.all()) spectacle = self.attribution.spectacle seller = self.seller @@ -327,14 +341,16 @@ class SpectacleRevente(models.Model): } mails.append(mail.EmailMessage( mail_subject, - loader.render_to_string('bda/mails/revente-winner.txt', context), + loader.render_to_string('bda/mails/revente-winner.txt', + context), from_email=settings.MAIL_DATA['revente']['FROM'], to=[winner.user.email], reply_to=[seller.user.email], )) mails.append(mail.EmailMessage( mail_subject, - loader.render_to_string('bda/mails/revente-seller.txt', context), + loader.render_to_string('bda/mails/revente-seller.txt', + context), from_email=settings.MAIL_DATA['revente']['FROM'], to=[seller.user.email], reply_to=[winner.user.email], @@ -345,11 +361,12 @@ class SpectacleRevente(models.Model): if inscrit == winner: continue - mail_body = loader.render_to_string('bda/mails/revente-loser.txt', { - 'acheteur': inscrit.user, - 'vendeur': seller.user, - 'spectacle': spectacle, - }) + mail_body = loader.render_to_string( + 'bda/mails/revente-loser.txt', + {'acheteur': inscrit.user, + 'vendeur': seller.user, + 'spectacle': spectacle} + ) mails.append(mail.EmailMessage( mail_subject, mail_body, from_email=settings.MAIL_DATA['revente']['FROM'], diff --git a/bda/templates/bda/mails/shotgun.txt b/bda/templates/bda/mails/shotgun.txt index 53462fb3..69bc704c 100644 --- a/bda/templates/bda/mails/shotgun.txt +++ b/bda/templates/bda/mails/shotgun.txt @@ -4,7 +4,7 @@ Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date }}) a été postée sur BdA-Revente. Puisque ce spectacle a lieu dans moins de 24h, il n'y a pas de tirage au sort pour -cette place : elle est disponible immédiatement à l'addresse +cette place : elle est disponible immédiatement à l'adresse http://{{ domain }}{% url "bda-buy-revente" spectacle.id %}, à la disposition de tous. Chaleureusement, diff --git a/cof/locale/fr/formats.py b/cof/locale/fr/formats.py index 2a926447..879d5ab8 100644 --- a/cof/locale/fr/formats.py +++ b/cof/locale/fr/formats.py @@ -1,4 +1,9 @@ # -*- encoding: utf-8 -*- + +""" +Formats français. +""" + from __future__ import unicode_literals DATETIME_FORMAT = r'j F Y \à H:i' diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 12a58b26..0650eed4 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -45,7 +45,7 @@ INSTALLED_APPS = ( 'autocomplete_light', 'captcha', 'django_cas_ng', - 'debug_toolbar', +# 'debug_toolbar', 'bootstrapform', 'kfet', 'channels', From debc10213e0818bc28144ea66d4d5c3c2ab11439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 20 Nov 2016 16:52:07 +0100 Subject: [PATCH 101/103] Typo + docstrings inutiles --- bda/management/commands/manage_reventes.py | 3 --- bda/management/commands/sendrappels.py | 3 --- cof/settings_dev.py | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/bda/management/commands/manage_reventes.py b/bda/management/commands/manage_reventes.py index 310bb618..4b90bc57 100644 --- a/bda/management/commands/manage_reventes.py +++ b/bda/management/commands/manage_reventes.py @@ -13,9 +13,6 @@ from bda.models import SpectacleRevente class Command(BaseCommand): - """ - Objet `BaseCommand`, cf ``self.help`` pour plus d'informations. - """ help = "Envoie les mails de notification et effectue " \ "les tirages au sort des reventes" leave_locale_alone = True diff --git a/bda/management/commands/sendrappels.py b/bda/management/commands/sendrappels.py index 3c42170c..88cf9d5c 100644 --- a/bda/management/commands/sendrappels.py +++ b/bda/management/commands/sendrappels.py @@ -13,9 +13,6 @@ from bda.models import Spectacle class Command(BaseCommand): - """ - Objet Command, cf ``self.help`` pour plus d'informations. - """ help = 'Envoie les mails de rappel des spectacles dont la date ' \ 'approche.\nNe renvoie pas les mails déjà envoyés.' leave_locale_alone = True diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 0650eed4..12a58b26 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -45,7 +45,7 @@ INSTALLED_APPS = ( 'autocomplete_light', 'captcha', 'django_cas_ng', -# 'debug_toolbar', + 'debug_toolbar', 'bootstrapform', 'kfet', 'channels', From 9a9ff69f5560386e30ffee244b37f202a14676c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 20 Nov 2016 18:42:47 +0100 Subject: [PATCH 102/103] Ajoute le jour en toutes lettres dans les dates --- cof/locale/fr/formats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cof/locale/fr/formats.py b/cof/locale/fr/formats.py index 879d5ab8..710fa6ed 100644 --- a/cof/locale/fr/formats.py +++ b/cof/locale/fr/formats.py @@ -6,4 +6,4 @@ Formats français. from __future__ import unicode_literals -DATETIME_FORMAT = r'j F Y \à H:i' +DATETIME_FORMAT = r'l j F Y \à H:i' From 4249524842d657a04e39bfdeb1d2c395ae2a74c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 21 Nov 2016 01:26:56 +0100 Subject: [PATCH 103/103] Typo vagrant -> ubuntu --- provisioning/supervisor.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/provisioning/supervisor.conf b/provisioning/supervisor.conf index 41e75fbd..c806a13d 100644 --- a/provisioning/supervisor.conf +++ b/provisioning/supervisor.conf @@ -1,5 +1,5 @@ [program:worker] -command=/home/vagrant/venv/bin/python /vagrant/manage.py runworker +command=/home/ubuntu/venv/bin/python /vagrant/manage.py runworker directory=/vagrant/ user=ubuntu environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" @@ -10,7 +10,7 @@ stopasgroup=true redirect_stderr=true [program:interface] -command=/home/vagrant/venv/bin/daphne -b 127.0.0.1 -p 8001 cof.asgi:channel_layer +command=/home/ubuntu/venv/bin/daphne -b 127.0.0.1 -p 8001 cof.asgi:channel_layer environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" directory=/vagrant/ redirect_stderr=true