diff --git a/bda/migrations/0011_tirage_appear_catalogue.py b/bda/migrations/0011_tirage_appear_catalogue.py new file mode 100644 index 00000000..c2a2479d --- /dev/null +++ b/bda/migrations/0011_tirage_appear_catalogue.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0010_spectaclerevente_shotgun'), + ] + + operations = [ + migrations.AddField( + model_name='tirage', + name='appear_catalogue', + field=models.BooleanField( + default=False, + verbose_name='Tirage à afficher dans le catalogue' + ), + ), + ] diff --git a/bda/models.py b/bda/models.py index df73a209..15acf686 100644 --- a/bda/models.py +++ b/bda/models.py @@ -18,6 +18,7 @@ class Tirage(models.Model): fermeture = models.DateTimeField("Date et heure de fermerture du tirage") tokens = models.TextField("Graine(s) du tirage", blank=True) active = models.BooleanField("Tirage actif", default=False) + appear_catalogue = models.BooleanField("Tirage à afficher dans le catalogue", default=False) enable_do_tirage = models.BooleanField("Le tirage peut être lancé", default=False) @@ -78,6 +79,15 @@ class Spectacle(models.Model): self.price ) + def getImgUrl(self): + """ + Cette fonction permet d'obtenir l'URL de l'image, si elle existe + """ + try: + return self.image.url + except: + return None + def send_rappel(self): """ Envoie un mail de rappel à toutes les personnes qui ont une place pour diff --git a/bda/urls.py b/bda/urls.py index bbbf8e39..df660740 100644 --- a/bda/urls.py +++ b/bda/urls.py @@ -47,4 +47,6 @@ urlpatterns = [ url(r'^mails-rappel/(?P\d+)$', views.send_rappel), url(r'^descriptions/(?P\d+)$', views.descriptions_spectacles, name='bda-descriptions'), + url(r'^catalogue/(?P[a-z]+)$', views.catalogue, + name='bda-catalogue'), ] diff --git a/bda/views.py b/bda/views.py index 096aacf5..41e5d08b 100644 --- a/bda/views.py +++ b/bda/views.py @@ -3,11 +3,11 @@ import random import hashlib import time +import json from datetime import timedelta from custommail.shortcuts import ( send_mass_custom_mail, send_custom_mail, render_custom_mail ) - from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.contrib import messages @@ -15,18 +15,24 @@ from django.db import models, transaction from django.core import serializers from django.db.models import Count, Q, Sum from django.forms.models import inlineformset_factory -from django.http import HttpResponseBadRequest, HttpResponseRedirect +from django.http import ( + HttpResponseBadRequest, HttpResponseRedirect, JsonResponse +) from django.core.urlresolvers import reverse from django.conf import settings from django.utils import timezone, formats from django.views.generic.list import ListView - +from django.core.exceptions import ObjectDoesNotExist from gestioncof.decorators import cof_required, buro_required -from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ - Tirage, SpectacleRevente +from bda.models import ( + Spectacle, Participant, ChoixSpectacle, Attribution, Tirage, + SpectacleRevente, Salle, Quote, CategorieSpectacle +) from bda.algorithm import Algorithm -from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ - InscriptionReventeForm, SoldForm +from bda.forms import ( + BaseBdaFormSet, TokenForm, ResellForm, AnnulForm, InscriptionReventeForm, + SoldForm +) @cof_required @@ -639,3 +645,98 @@ def descriptions_spectacles(request, tirage_id): return HttpResponseBadRequest( "La variable GET 'location' doit contenir un entier") return render(request, 'descriptions.html', {'shows': shows_qs.all()}) + + +def catalogue(request, request_type): + """ + Vue destinée à communiquer avec un client AJAX, fournissant soit : + - la liste des tirages + - les catégories et salles d'un tirage + - les descriptions d'un tirage (filtrées selon la catégorie et la salle) + """ + if request_type == "list": + # Dans ce cas on retourne la liste des tirages et de leur id en JSON + data_return = list( + Tirage.objects.filter(appear_catalogue=True).values('id', 'title')) + return JsonResponse(data_return, safe=False) + if request_type == "details": + # Dans ce cas on retourne une liste des catégories et des salles + tirage_id = request.GET.get('id', '') + try: + tirage = Tirage.objects.get(id=tirage_id) + except ObjectDoesNotExist: + return HttpResponseBadRequest( + "Aucun tirage correspondant à l'id " + + tirage_id) + except ValueError: + return HttpResponseBadRequest( + "Mauvais format d'identifiant : " + + tirage_id) + categories = list( + CategorieSpectacle.objects.filter( + spectacle__in=tirage.spectacle_set.all()) + .distinct().values('id', 'name')) + locations = list( + Salle.objects.filter( + spectacle__in=tirage.spectacle_set.all()) + .distinct().values('id', 'name')) + data_return = {'categories': categories, 'locations': locations} + return JsonResponse(data_return, safe=False) + if request_type == "descriptions": + # Ici on retourne les descriptions correspondant à la catégorie et + # à la salle spécifiées + + tirage_id = request.GET.get('id', '') + categories = request.GET.get('category', '[0]') + locations = request.GET.get('location', '[0]') + try: + category_id = json.loads(categories) + location_id = json.loads(locations) + tirage = Tirage.objects.get(id=tirage_id) + + shows_qs = tirage.spectacle_set + if not(0 in category_id): + shows_qs = shows_qs.filter( + category__id__in=category_id) + if not(0 in location_id): + shows_qs = shows_qs.filter( + location__id__in=location_id) + except ObjectDoesNotExist: + return HttpResponseBadRequest( + "Impossible de trouver des résultats correspondant " + "à ces caractéristiques : " + + "id = " + tirage_id + + ", catégories = " + categories + + ", salles = " + locations) + except ValueError: # Contient JSONDecodeError + return HttpResponseBadRequest( + "Impossible de parser les paramètres donnés : " + + "id = " + request.GET.get('id', '') + + ", catégories = " + request.GET.get('category', '[0]') + + ", salles = " + request.GET.get('location', '[0]')) + + # On convertit les descriptions à envoyer en une liste facilement + # JSONifiable (il devrait y avoir un moyen plus efficace en + # redéfinissant le serializer de JSON) + data_return = [{ + 'title': spectacle.title, + 'category': str(spectacle.category), + 'date': str(formats.date_format( + timezone.localtime(spectacle.date), + "SHORT_DATETIME_FORMAT")), + 'location': str(spectacle.location), + 'vips': spectacle.vips, + 'description': spectacle.description, + 'slots_description': spectacle.slots_description, + 'quotes': list(Quote.objects.filter(spectacle=spectacle).values( + 'author', 'text')), + 'image': spectacle.getImgUrl(), + 'ext_link': spectacle.ext_link, + 'price': spectacle.price, + 'slots': spectacle.slots + } + for spectacle in shows_qs.all() + ] + return JsonResponse(data_return, safe=False) + # Si la requête n'est pas de la forme attendue, on quitte avec une erreur + return HttpResponseBadRequest() diff --git a/kfet/migrations/0049_merge.py b/kfet/migrations/0049_merge.py new file mode 100644 index 00000000..0ce9a525 --- /dev/null +++ b/kfet/migrations/0049_merge.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('kfet', '0048_article_hidden'), + ('kfet', '0048_default_datetime'), + ] + + operations = [ + ] diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 1360a4be..f7246ec3 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -1381,11 +1381,19 @@ $(document).ready(function() { } } for (var i=0; i= -5) { + article_line.addClass('low-stock'); + } else { + article_line.removeClass('low-stock'); + } + article_line.find('.stock') .text(article['stock']); + + var i = 0; + while (i < articlesList.length && articlesList[i][1] != article.id) i++ ; + articlesList[i][4] = article.stock ; } if (data['addcost']) { settings['addcost_for'] = data['addcost']['for'];