Merge branch 'master' into Kerl/clean_staticfiles

This commit is contained in:
Martin Pépin 2016-12-26 00:54:31 +01:00
commit ab80db8bed
18 changed files with 175 additions and 120 deletions

2
Vagrantfile vendored
View file

@ -10,7 +10,7 @@ Vagrant.configure(2) do |config|
# For a complete reference, please see the online documentation at # For a complete reference, please see the online documentation at
# https://docs.vagrantup.com. # 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 # On associe le port 80 dans la machine virtuelle avec le port 8080 de notre
# ordinateur, et le port 8000 avec le port 8000. # ordinateur, et le port 8000 avec le port 8000.

View file

@ -225,7 +225,7 @@ class SpectacleReventeAdmin(admin.ModelAdmin):
list_display = ("spectacle", "seller", "date", "soldTo") list_display = ("spectacle", "seller", "date", "soldTo")
raw_id_fields = ("attribution",) raw_id_fields = ("attribution",)
readonly_fields = ("shotgun", "expiration_time") readonly_fields = ("date_tirage",)
search_fields = ['attribution__spectacle__title', search_fields = ['attribution__spectacle__title',
'seller__user__username', 'seller__user__username',
'seller__user__first_name', 'seller__user__first_name',

View file

@ -68,9 +68,8 @@ class AnnulForm(forms.Form):
self.fields['attributions'].queryset = participant.attribution_set\ self.fields['attributions'].queryset = participant.attribution_set\
.filter(spectacle__date__gte=timezone.now(), .filter(spectacle__date__gte=timezone.now(),
revente__isnull=False, revente__isnull=False,
revente__date__gt=timezone.now()-timedelta(hours=1))\ revente__date__gt=timezone.now()-timedelta(hours=1),
.filter(Q(revente__soldTo__isnull=True) | revente__soldTo__isnull=True)
Q(revente__soldTo=participant))
class InscriptionReventeForm(forms.Form): class InscriptionReventeForm(forms.Form):

View file

@ -36,7 +36,7 @@ class Command(BaseCommand):
revente.send_notif() revente.send_notif()
self.stdout.write("Mail d'inscription à une revente envoyé") self.stdout.write("Mail d'inscription à une revente envoyé")
# Check si tirage à faire # Check si tirage à faire
elif (now >= revente.expiration_time and elif (now >= revente.date_tirage and
not revente.tirage_done): not revente.tirage_done):
self.stdout.write(str(now)) self.stdout.write(str(now))
revente.tirage() revente.tirage()

View file

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.utils import timezone
from datetime import timedelta
def forwards_func(apps, schema_editor):
SpectacleRevente = apps.get_model("bda", "SpectacleRevente")
for revente in SpectacleRevente.objects.all():
is_expired = timezone.now() > revente.date_tirage()
is_direct = (revente.attribution.spectacle.date >= revente.date and
timezone.now() > revente.date + timedelta(minutes=15))
revente.shotgun = is_expired or is_direct
revente.save()
class Migration(migrations.Migration):
dependencies = [
('bda', '0009_revente'),
]
operations = [
migrations.AddField(
model_name='spectaclerevente',
name='shotgun',
field=models.BooleanField(default=False, verbose_name='Disponible imm\xe9diatement'),
),
migrations.RunPython(forwards_func, migrations.RunPython.noop),
]

View file

@ -229,32 +229,20 @@ class SpectacleRevente(models.Model):
default=False) default=False)
tirage_done = models.BooleanField("Tirage effectué", tirage_done = models.BooleanField("Tirage effectué",
default=False) default=False)
shotgun = models.BooleanField("Disponible immédiatement",
default=False)
@property @property
def expiration_time(self): def date_tirage(self):
"""Renvoie la date du tirage au sort de la revente."""
# L'acheteur doit être connu au plus 12h avant le spectacle # L'acheteur doit être connu au plus 12h avant le spectacle
remaining_time = (self.attribution.spectacle.date remaining_time = (self.attribution.spectacle.date
- self.date - timedelta(hours=13)) - self.date - timedelta(hours=13))
# Au minimum, on attend 2 jours avant le tirage # Au minimum, on attend 2 jours avant le tirage
delay = min(remaining_time, timedelta(days=2)) delay = min(remaining_time, timedelta(days=2))
# On a aussi 1h pour changer d'avis # Le vendeur a aussi 1h pour changer d'avis
return self.date + delay + timedelta(hours=1) return self.date + delay + timedelta(hours=1)
def expiration_time_str(self):
return self.expiration_time \
.astimezone(timezone.get_current_timezone()) \
.strftime('%d/%m/%y à %H:%M')
@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
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))
def __str__(self): def __str__(self):
return "%s -- %s" % (self.seller, return "%s -- %s" % (self.seller,
self.attribution.spectacle.title) self.attribution.spectacle.title)
@ -312,6 +300,9 @@ class SpectacleRevente(models.Model):
connection = mail.get_connection() connection = mail.get_connection()
connection.send_messages(mails_to_send) connection.send_messages(mails_to_send)
self.notif_sent = True self.notif_sent = True
# Flag inutile, sauf si l'horloge interne merde
self.tirage_done = True
self.shotgun = True
self.save() self.save()
def tirage(self): def tirage(self):
@ -371,5 +362,10 @@ class SpectacleRevente(models.Model):
reply_to=[settings.MAIL_DATA['revente']['REPLYTO']], reply_to=[settings.MAIL_DATA['revente']['REPLYTO']],
)) ))
mail.get_connection().send_messages(mails) mail.get_connection().send_messages(mails)
# Si personne ne veut de la place, elle part au shotgun
else:
self.shotgun = True
self.tirage_done = True self.tirage_done = True
self.save() self.save()

View file

@ -3,7 +3,7 @@
{% block realcontent %} {% block realcontent %}
<h2>Inscription à une revente</h2> <h2>Inscription à une revente</h2>
<p class="success"> Votre inscription pour a bien été enregistrée !</p> <p class="success"> Votre inscription a bien été enregistrée !</p>
<p>Le tirage au sort pour cette revente ({{spectacle}}) sera effectué le {{date}}. <p>Le tirage au sort pour cette revente ({{spectacle}}) sera effectué le {{date}}.
{% endblock %} {% endblock %}

View file

@ -2,5 +2,12 @@
{% block realcontent %} {% block realcontent %}
<h2>Nope</h2> <h2>Nope</h2>
<p>Cette revente n'est pas disponible actuellement, désolé !</p> {% if revente.shotgun %}
<p>Le tirage au sort de cette revente a déjà été effectué !</p>
<p>Si personne n'était intéressé, elle est maintenant disponible
<a href="{% url "bda-buy-revente" revente.attribution.spectacle.id %}">ici</a>.</p>
{% else %}
<p> Il n'est pas encore possible de s'inscrire à cette revente, réessaie dans quelque temps !</p>
{% endif %}
{% endblock %} {% endblock %}

View file

@ -2,7 +2,7 @@ Bonjour {{ vendeur.first_name }},
Tu tes bien inscrit-e pour la revente de {{ spectacle.title }}. Tu tes bien inscrit-e pour la revente de {{ spectacle.title }}.
{% with revente.expiration_time as time %} {% with revente.date_tirage as time %}
Le tirage au sort entre tout-e-s les racheteuse-eur-s potentiel-le-s aura lieu 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 }}). le {{ time|date:"DATE_FORMAT" }} à {{ time|time:"TIME_FORMAT" }} (dans {{time|timeuntil }}).
Si personne ne sest inscrit pour racheter la place, celle-ci apparaitra parmi Si personne ne sest inscrit pour racheter la place, celle-ci apparaitra parmi

View file

@ -3,10 +3,12 @@ Bonjour {{ user.first_name }}
Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date }}) Une place pour le spectacle {{ spectacle.title }} ({{ spectacle.date }})
a été postée sur BdA-Revente. a été postée sur BdA-Revente.
{% with revente.date_tirage as time %}
Si ce spectacle t'intéresse toujours, merci de nous le signaler en cliquant 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 %}. sur ce lien : http://{{ domain }}{% url "bda-revente-interested" revente.id %}.
Dans le cas où plusieurs personnes seraient intéressées, nous procèderons à 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 {{ time|date:"DATE_FORMAT" }} à {{ time|time:"TIME_FORMAT" }} (dans {{time|timeuntil}}).
{% endwith %}
Chaleureusement, Chaleureusement,
Le BdA Le BdA

View file

@ -8,7 +8,10 @@
{% endif %} {% endif %}
{% if deja_revente %} {% if deja_revente %}
<p class="success">Des reventes existent déjà pour certains de ces spectacles ; vérifie les places disponibles sans tirage !</p> <p class="success">Des reventes existent déjà pour certains de ces spectacles ; vérifie les places disponibles sans tirage !</p>
{% elif inscrit_revente %}
<p class="success">Tu as été inscrit à une revente en cours pour ce spectacle !</p>
{% endif %} {% endif %}
<form action="" class="form-horizontal" method="post"> <form action="" class="form-horizontal" method="post">
{% csrf_token %} {% csrf_token %}
<div class="form-group"> <div class="form-group">

View file

@ -271,6 +271,7 @@ def revente(request, tirage_id):
if not participant.paid: if not participant.paid:
return render(request, "bda-notpaid.html", {}) return render(request, "bda-notpaid.html", {})
if request.method == 'POST': if request.method == 'POST':
# On met en vente une place
if 'resell' in request.POST: if 'resell' in request.POST:
resellform = ResellForm(participant, request.POST, prefix='resell') resellform = ResellForm(participant, request.POST, prefix='resell')
annulform = AnnulForm(participant, prefix='annul') annulform = AnnulForm(participant, prefix='annul')
@ -279,27 +280,36 @@ def revente(request, tirage_id):
attributions = resellform.cleaned_data["attributions"] attributions = resellform.cleaned_data["attributions"]
with transaction.atomic(): with transaction.atomic():
for attribution in attributions: for attribution in attributions:
revente, created = SpectacleRevente.objects.get_or_create( revente, created = \
SpectacleRevente.objects.get_or_create(
attribution=attribution, attribution=attribution,
defaults={'seller': participant}) defaults={'seller': participant})
if not created: if not created:
revente.seller = participant revente.seller = participant
revente.date = timezone.now() revente.date = timezone.now()
mail_subject = "BdA-Revente : {:s}".format(attribution.spectacle.title) revente.soldTo = None
mail_body = loader.render_to_string('bda/mails/revente-new.txt', { revente.notif_sent = False
'vendeur': participant.user, revente.tirage_done = False
revente.shotgun = False
mail_subject = "BdA-Revente : {:s}".format(
attribution.spectacle.title)
mail_body = loader.render_to_string(
'bda/mails/revente-new.txt',
{'vendeur': participant.user,
'spectacle': attribution.spectacle, 'spectacle': attribution.spectacle,
'revente': revente, 'revente': revente}
}) )
mails.append(mail.EmailMessage( mails.append(mail.EmailMessage(
mail_subject, mail_body, mail_subject, mail_body,
from_email=settings.MAIL_DATA['revente']['FROM'], from_email=settings.MAIL_DATA['revente']['FROM'],
to=[participant.user.email], to=[participant.user.email],
reply_to=[settings.MAIL_DATA['revente']['REPLYTO']], reply_to=[
settings.MAIL_DATA['revente']['REPLYTO']
],
)) ))
revente.save() revente.save()
mail.get_connection().send_messages(mails) mail.get_connection().send_messages(mails)
# On annule une revente
elif 'annul' in request.POST: elif 'annul' in request.POST:
annulform = AnnulForm(participant, request.POST, prefix='annul') annulform = AnnulForm(participant, request.POST, prefix='annul')
resellform = ResellForm(participant, prefix='resell') resellform = ResellForm(participant, prefix='resell')
@ -307,7 +317,8 @@ def revente(request, tirage_id):
attributions = annulform.cleaned_data["attributions"] attributions = annulform.cleaned_data["attributions"]
for attribution in attributions: for attribution in attributions:
attribution.revente.delete() attribution.revente.delete()
# On confirme une vente en transférant la place à la personne qui a
# gagné le tirage
elif 'transfer' in request.POST: elif 'transfer' in request.POST:
resellform = ResellForm(participant, prefix='resell') resellform = ResellForm(participant, prefix='resell')
annulform = AnnulForm(participant, prefix='annul') annulform = AnnulForm(participant, prefix='annul')
@ -320,7 +331,9 @@ def revente(request, tirage_id):
attrib = revente.attribution attrib = revente.attribution
attrib.participant = revente.soldTo attrib.participant = revente.soldTo
attrib.save() attrib.save()
# On annule la revente après le tirage au sort (par exemple si
# la personne qui a gagné le tirage ne se manifeste pas). La place est
# alors remise en vente
elif 'reinit' in request.POST: elif 'reinit' in request.POST:
resellform = ResellForm(participant, prefix='resell') resellform = ResellForm(participant, prefix='resell')
annulform = AnnulForm(participant, prefix='annul') annulform = AnnulForm(participant, prefix='annul')
@ -334,6 +347,7 @@ def revente(request, tirage_id):
revente.soldTo = None revente.soldTo = None
revente.notif_sent = False revente.notif_sent = False
revente.tirage_done = False revente.tirage_done = False
revente.shotgun = False
if revente.answered_mail: if revente.answered_mail:
revente.answered_mail.clear() revente.answered_mail.clear()
revente.save() revente.save()
@ -354,8 +368,7 @@ def revente(request, tirage_id):
sold = participant.attribution_set.filter( sold = participant.attribution_set.filter(
spectacle__date__gte=timezone.now(), spectacle__date__gte=timezone.now(),
revente__isnull=False, revente__isnull=False,
revente__soldTo__isnull=False).exclude( revente__soldTo__isnull=False)
revente__soldTo=participant)
return render(request, "bda-revente.html", return render(request, "bda-revente.html",
{'tirage': tirage, 'overdue': overdue, "sold": sold, {'tirage': tirage, 'overdue': overdue, "sold": sold,
@ -367,13 +380,14 @@ def revente_interested(request, revente_id):
revente = get_object_or_404(SpectacleRevente, id=revente_id) revente = get_object_or_404(SpectacleRevente, id=revente_id)
participant, created = Participant.objects.get_or_create( participant, created = Participant.objects.get_or_create(
user=request.user, tirage=revente.attribution.spectacle.tirage) user=request.user, tirage=revente.attribution.spectacle.tirage)
if timezone.now() < revente.date + timedelta(hours=1) or revente.shotgun: if (timezone.now() < revente.date + timedelta(hours=1)) or revente.shotgun:
return render(request, "bda-wrongtime.html", {}) return render(request, "bda-wrongtime.html",
{"revente": revente})
revente.answered_mail.add(participant) revente.answered_mail.add(participant)
return render(request, "bda-interested.html", return render(request, "bda-interested.html",
{"spectacle": revente.attribution.spectacle, {"spectacle": revente.attribution.spectacle,
"date": revente.expiration_time}) "date": revente.date_tirage})
@login_required @login_required
@ -381,23 +395,9 @@ def list_revente(request, tirage_id):
tirage = get_object_or_404(Tirage, id=tirage_id) tirage = get_object_or_404(Tirage, id=tirage_id)
participant, created = Participant.objects.get_or_create( participant, created = Participant.objects.get_or_create(
user=request.user, tirage=tirage) user=request.user, tirage=tirage)
spectacles = tirage.spectacle_set.filter(
date__gte=timezone.now())
shotgun = []
deja_revente = False deja_revente = False
success = False success = False
for spectacle in spectacles: inscrit_revente = False
revente_objects = SpectacleRevente.objects.filter(
attribution__spectacle=spectacle,
soldTo__isnull=True)
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)
if request.method == 'POST': if request.method == 'POST':
form = InscriptionReventeForm(tirage, request.POST) form = InscriptionReventeForm(tirage, request.POST)
if form.is_valid(): if form.is_valid():
@ -407,15 +407,24 @@ def list_revente(request, tirage_id):
for spectacle in choices: for spectacle in choices:
qset = SpectacleRevente.objects.filter( qset = SpectacleRevente.objects.filter(
attribution__spectacle=spectacle) attribution__spectacle=spectacle)
if qset.exists(): if qset.filter(shotgun=True, soldTo__isnull=True).exists():
# On l'inscrit à l'un des tirages au sort # Une place est disponible au shotgun, on suggère à
for revente in qset.all(): # l'utilisateur d'aller la récupérer
if revente.shotgun and not revente.soldTo:
deja_revente = True deja_revente = True
else: else:
revente.answered_mail.add(participant) # La place n'est pas disponible au shotgun, si des reventes
revente.save() # pour ce spectacle existent déjà, on inscrit la personne à
break # la revente ayant le moins d'inscrits
min_resell = (
qset.filter(shotgun=False)
.annotate(nb_subscribers=Count('answered_mail'))
.order_by('nb_subscribers')
.first()
)
if min_resell is not None:
min_resell.answered_mail.add(participant)
min_resell.save()
inscrit_revente = True
success = True success = True
else: else:
form = InscriptionReventeForm( form = InscriptionReventeForm(
@ -423,8 +432,9 @@ def list_revente(request, tirage_id):
initial={'spectacles': participant.choicesrevente.all()}) initial={'spectacles': participant.choicesrevente.all()})
return render(request, "liste-reventes.html", return render(request, "liste-reventes.html",
{"form": form, 'shotgun': shotgun, {"form": form,
"deja_revente": deja_revente, "success": success}) "deja_revente": deja_revente, "success": success,
"inscrit_revente": inscrit_revente})
@login_required @login_required
@ -436,15 +446,16 @@ def buy_revente(request, spectacle_id):
reventes = SpectacleRevente.objects.filter( reventes = SpectacleRevente.objects.filter(
attribution__spectacle=spectacle, attribution__spectacle=spectacle,
soldTo__isnull=True) soldTo__isnull=True)
# Si l'utilisateur veut racheter une place qu'il est en train de revendre,
# on supprime la revente en question.
if reventes.filter(seller=participant).exists(): if reventes.filter(seller=participant).exists():
revente = reventes.filter(seller=participant)[0] revente = reventes.filter(seller=participant)[0]
revente.delete() revente.delete()
return HttpResponseRedirect(reverse("bda-shotgun", return HttpResponseRedirect(reverse("bda-shotgun",
args=[tirage.id])) args=[tirage.id]))
reventes_shotgun = []
for revente in reventes.all(): reventes_shotgun = list(reventes.filter(shotgun=True).all())
if revente.shotgun:
reventes_shotgun.append(revente)
if not reventes_shotgun: if not reventes_shotgun:
return render(request, "bda-no-revente.html", {}) return render(request, "bda-no-revente.html", {})
@ -478,14 +489,11 @@ def revente_shotgun(request, tirage_id):
date__gte=timezone.now()) date__gte=timezone.now())
shotgun = [] shotgun = []
for spectacle in spectacles: for spectacle in spectacles:
revente_objects = SpectacleRevente.objects.filter( reventes = SpectacleRevente.objects.filter(
attribution__spectacle=spectacle, attribution__spectacle=spectacle,
shotgun=True,
soldTo__isnull=True) soldTo__isnull=True)
revente_count = 0 if reventes.exists():
for revente in revente_objects:
if revente.shotgun:
revente_count += 1
if revente_count:
shotgun.append(spectacle) shotgun.append(spectacle)
return render(request, "bda-shotgun.html", return render(request, "bda-shotgun.html",

View file

@ -6,4 +6,4 @@ Formats français.
from __future__ import unicode_literals from __future__ import unicode_literals
DATETIME_FORMAT = r'j F Y \à H:i' DATETIME_FORMAT = r'l j F Y \à H:i'

View file

@ -1,24 +1,27 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""
Fichier principal de configuration des urls du projet GestioCOF
"""
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from __future__ import unicode_literals from __future__ import unicode_literals
import autocomplete_light
from django.conf import settings from django.conf import settings
from django.conf.urls import include, url from django.conf.urls import include, url
from django.conf.urls.static import static from django.conf.urls.static import static
from django.contrib import admin from django.contrib import admin
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
import autocomplete_light
from django.contrib.auth import views as django_views from django.contrib.auth import views as django_views
from django_cas_ng import views as django_cas_views from django_cas_ng import views as django_cas_views
from gestioncof import views as gestioncof_views, csv_views from gestioncof import views as gestioncof_views, csv_views
from gestioncof.urls import export_patterns, petitcours_patterns, \ from gestioncof.urls import export_patterns, petitcours_patterns, \
surveys_patterns, events_patterns, calendar_patterns, \ surveys_patterns, events_patterns, calendar_patterns, \
clubs_patterns clubs_patterns
from gestioncof.autocomplete import autocomplete from gestioncof.autocomplete import autocomplete
autocomplete_light.autodiscover() autocomplete_light.autodiscover()
@ -92,4 +95,5 @@ if settings.DEBUG:
# Si on est en production, MEDIA_ROOT est servi par Apache. # 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. # Il faut dire à Django de servir MEDIA_ROOT lui-même en développement.
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)

View file

@ -550,7 +550,6 @@ def export_members(request):
return response return response
@buro_required
def csv_export_mega(filename, qs): def csv_export_mega(filename, qs):
response = HttpResponse(content_type='text/csv') response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=' + filename response['Content-Disposition'] = 'attachment; filename=' + filename
@ -572,12 +571,12 @@ def csv_export_mega(filename, qs):
@buro_required @buro_required
def export_mega_remarksonly(request): def export_mega_remarksonly(request):
filename = 'remarques_mega_2015.csv' filename = 'remarques_mega_2016.csv'
response = HttpResponse(content_type='text/csv') response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=' + filename response['Content-Disposition'] = 'attachment; filename=' + filename
writer = unicodecsv.writer(response) writer = unicodecsv.writer(response)
event = Event.objects.get(title="Mega 15") event = Event.objects.get(title="Mega 2016")
commentfield = event.commentfields.get(name="Commentaires") commentfield = event.commentfields.get(name="Commentaires")
for val in commentfield.values.all(): for val in commentfield.values.all():
reg = val.registration reg = val.registration
@ -600,42 +599,40 @@ def export_mega_bytype(request, type):
if type not in types: if type not in types:
raise Http404 raise Http404
event = Event.objects.get(title="Mega 15") event = Event.objects.get(title="Mega 2016")
type_option = event.options.get(name="Type") type_option = event.options.get(name="Type")
participant_type = type_option.choices.get(value=types[type]).id participant_type = type_option.choices.get(value=types[type]).id
qs = EventRegistration.objects.filter(event=event).filter( qs = EventRegistration.objects.filter(event=event).filter(
options__id__exact=participant_type) options__id__exact=participant_type)
return csv_export_mega(type + '_mega_2015.csv', qs) return csv_export_mega(type + '_mega_2016.csv', qs)
@buro_required @buro_required
def export_mega_orgas(request): def export_mega_orgas(request):
event = Event.objects.get(title="Mega 15") event = Event.objects.get(title="Mega 2016")
type_option = event.options.get(name="Type") type_option = event.options.get(name="Conscrit ou orga ?")
participant_type_a = type_option.choices.get(value="Conscrit étudiant").id participant_type = type_option.choices.get(value="Vieux").id
participant_type_b = type_option.choices.get(value="Conscrit élève").id
qs = EventRegistration.objects.filter(event=event).exclude( qs = EventRegistration.objects.filter(event=event).exclude(
options__id__in=(participant_type_a, participant_type_b)) options__id=participant_type)
return csv_export_mega('orgas_mega_15.csv', qs) return csv_export_mega('orgas_mega_2016.csv', qs)
@buro_required @buro_required
def export_mega_participants(request): def export_mega_participants(request):
event = Event.objects.get(title="Mega 15") event = Event.objects.get(title="Mega 2016")
type_option = event.options.get(name="Type") type_option = event.options.get(name="Conscrit ou orga ?")
participant_type_a = type_option.choices.get(value="Conscrit étudiant").id participant_type = type_option.choices.get(value="Conscrit").id
participant_type_b = type_option.choices.get(value="Conscrit élève").id
qs = EventRegistration.objects.filter(event=event).filter( qs = EventRegistration.objects.filter(event=event).filter(
options__id__in=(participant_type_a, participant_type_b)) options__id=participant_type)
return csv_export_mega('participants_mega_15.csv', qs) return csv_export_mega('participants_mega_2016.csv', qs)
@buro_required @buro_required
def export_mega(request): def export_mega(request):
event = Event.objects.filter(title="Mega 15") event = Event.objects.filter(title="Mega 2016")
qs = EventRegistration.objects.filter(event=event) \ qs = EventRegistration.objects.filter(event=event) \
.order_by("user__username") .order_by("user__username")
return csv_export_mega('all_mega_2015.csv', qs) return csv_export_mega('all_mega_2016.csv', qs)
@buro_required @buro_required

View file

@ -8,7 +8,7 @@ DBNAME="cof_gestion"
DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4"
# Installation de paquets utiles # Installation de paquets utiles
apt-get update && apt-get install -y mercurial python-pip python-dev \ apt-get update && apt-get install -y python3-pip python3-dev python3-venv \
libmysqlclient-dev libjpeg-dev git redis-server libmysqlclient-dev libjpeg-dev git redis-server
pip install -U pip pip install -U pip
@ -30,10 +30,10 @@ a2ensite gestiocof
a2dissite 000-default a2dissite 000-default
service apache2 restart service apache2 restart
mkdir /var/www/static 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` # Mise en place du .bash_profile pour tout configurer lors du `vagrant ssh`
cat > ~vagrant/.bash_profile <<EOF cat >> ~ubuntu/.bashrc <<EOF
# On utilise la version de développement de GestioCOF # On utilise la version de développement de GestioCOF
export DJANGO_SETTINGS_MODULE='cof.settings_dev' export DJANGO_SETTINGS_MODULE='cof.settings_dev'
@ -45,25 +45,29 @@ export DBPASSWD="$DBPASSWD"
# Permet d'utiliser les utilitaires pythons locaux # Permet d'utiliser les utilitaires pythons locaux
export PATH="\$PATH:\$HOME/.local/bin" export PATH="\$PATH:\$HOME/.local/bin"
# Charge le virtualenv
source ~/venv/bin/activate
# On va dans /vagrant où se trouve le code de gestioCOF # On va dans /vagrant où se trouve le code de gestioCOF
cd /vagrant cd /vagrant
EOF EOF
chown vagrant: ~vagrant/.bash_profile
# On va dans /vagrant où se trouve gestioCOF # On va dans /vagrant où se trouve gestioCOF
cd /vagrant cd /vagrant
# Installation des dépendances python # Installation du virtualenv, on utilise désormais python3
sudo -H -u vagrant pip install --user -r requirements.txt -r requirements-devel.txt sudo -H -u ubuntu python3 -m venv ~ubuntu/venv
sudo -H -u ubuntu ~ubuntu/venv/bin/pip install -U pip
sudo -H -u ubuntu ~ubuntu/venv/bin/pip install -r requirements.txt -r requirements-devel.txt
# Préparation de Django # 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 sudo -H -u ubuntu DJANGO_SETTINGS_MODULE='cof.settings_dev' DBUSER=$DBUSER DBNAME=$DBNAME DBPASSWD=$DBPASSWD bash provisioning/prepare_django.sh
# Installation du cron pour les mails de rappels # Installation du cron pour les mails de rappels
sudo -H -u vagrant crontab provisioning/cron.dev sudo -H -u ubuntu crontab provisioning/cron.dev
# On installe Daphne et on demande à supervisor de le lancer # On installe Daphne et on demande à supervisor de le lancer
pip install daphne sudo -H -u ubuntu ~ubuntu/venv/bin/pip install daphne
apt-get install -y supervisor apt-get install -y supervisor
cp /vagrant/provisioning/supervisor.conf /etc/supervisor/conf.d/gestiocof.conf cp /vagrant/provisioning/supervisor.conf /etc/supervisor/conf.d/gestiocof.conf
sed "s/{DBUSER}/$DBUSER/" -i /etc/supervisor/conf.d/gestiocof.conf sed "s/{DBUSER}/$DBUSER/" -i /etc/supervisor/conf.d/gestiocof.conf

View file

@ -1,5 +1,7 @@
#!/bin/bash
# Doit être lancé par bootstrap.sh # Doit être lancé par bootstrap.sh
source ~/venv/bin/activate
python manage.py migrate python manage.py migrate
python manage.py loaddata users root bda gestion sites python manage.py loaddata users root bda gestion sites
python manage.py collectstatic --noinput python manage.py collectstatic --noinput

View file

@ -1,7 +1,7 @@
[program:worker] [program:worker]
command=/usr/bin/python /vagrant/manage.py runworker command=/home/ubuntu/venv/bin/python /vagrant/manage.py runworker
directory=/vagrant/ directory=/vagrant/
user=vagrant user=ubuntu
environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev"
autostart=true autostart=true
autorestart=true autorestart=true
@ -10,11 +10,11 @@ stopasgroup=true
redirect_stderr=true redirect_stderr=true
[program:interface] [program:interface]
command=/usr/local/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" environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev"
directory=/vagrant/ directory=/vagrant/
redirect_stderr=true redirect_stderr=true
autostart=true autostart=true
autorestart=true autorestart=true
stopasgroup=true stopasgroup=true
user=vagrant user=ubuntu