Merge branch 'master' into aureplop/kpsul_js_refactor

This commit is contained in:
Aurélien Delobelle 2017-04-10 13:08:23 +02:00
commit c75b2946e3
10 changed files with 231 additions and 131 deletions

View file

@ -18,7 +18,10 @@ class Tirage(models.Model):
fermeture = models.DateTimeField("Date et heure de fermerture du tirage") fermeture = models.DateTimeField("Date et heure de fermerture du tirage")
tokens = models.TextField("Graine(s) du tirage", blank=True) tokens = models.TextField("Graine(s) du tirage", blank=True)
active = models.BooleanField("Tirage actif", default=False) active = models.BooleanField("Tirage actif", default=False)
appear_catalogue = models.BooleanField("Tirage à afficher dans le catalogue", default=False) appear_catalogue = models.BooleanField(
"Tirage à afficher dans le catalogue",
default=False
)
enable_do_tirage = models.BooleanField("Le tirage peut être lancé", enable_do_tirage = models.BooleanField("Le tirage peut être lancé",
default=False) default=False)

View file

@ -1,22 +1,79 @@
# -*- coding: utf-8 -*- import json
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application. from django.test import TestCase, Client
""" from django.utils import timezone
from __future__ import division from .models import Tirage, Spectacle, Salle, CategorieSpectacle
from __future__ import print_function
from __future__ import unicode_literals
from django.test import TestCase class TestBdAViews(TestCase):
def setUp(self):
self.tirage = Tirage.objects.create(
title="Test tirage",
appear_catalogue=True,
ouverture=timezone.now(),
fermeture=timezone.now(),
)
self.category = CategorieSpectacle.objects.create(name="Category")
self.location = Salle.objects.create(name="here")
Spectacle.objects.bulk_create([
Spectacle(
title="foo", date=timezone.now(), location=self.location,
price=0, slots=42, tirage=self.tirage, listing=False,
category=self.category
),
Spectacle(
title="bar", date=timezone.now(), location=self.location,
price=1, slots=142, tirage=self.tirage, listing=False,
category=self.category
),
Spectacle(
title="baz", date=timezone.now(), location=self.location,
price=2, slots=242, tirage=self.tirage, listing=False,
category=self.category
),
])
def test_catalogue(self):
"""Test the catalogue JSON API"""
client = Client()
class SimpleTest(TestCase): # The `list` hooh
def test_basic_addition(self): resp = client.get("/bda/catalogue/list")
""" self.assertJSONEqual(
Tests that 1 + 1 always equals 2. resp.content.decode("utf-8"),
""" [{"id": self.tirage.id, "title": self.tirage.title}]
self.assertEqual(1 + 1, 2) )
# The `details` hook
resp = client.get(
"/bda/catalogue/details?id={}".format(self.tirage.id)
)
self.assertJSONEqual(
resp.content.decode("utf-8"),
{
"categories": [{
"id": self.category.id,
"name": self.category.name
}],
"locations": [{
"id": self.location.id,
"name": self.location.name
}],
}
)
# The `descriptions` hook
resp = client.get(
"/bda/catalogue/descriptions?id={}".format(self.tirage.id)
)
raw = resp.content.decode("utf-8")
try:
results = json.loads(raw)
except ValueError:
self.fail("Not valid JSON: {}".format(raw))
self.assertEqual(len(results), 3)
self.assertEqual(
{(s["title"], s["price"], s["slots"]) for s in results},
{("foo", 0, 42), ("bar", 1, 142), ("baz", 2, 242)}
)

View file

@ -22,7 +22,6 @@ from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
from django.utils import timezone, formats from django.utils import timezone, formats
from django.views.generic.list import ListView from django.views.generic.list import ListView
from django.core.exceptions import ObjectDoesNotExist
from gestioncof.decorators import cof_required, buro_required from gestioncof.decorators import cof_required, buro_required
from bda.models import ( from bda.models import (
Spectacle, Participant, ChoixSpectacle, Attribution, Tirage, Spectacle, Participant, ChoixSpectacle, Attribution, Tirage,
@ -657,29 +656,35 @@ def catalogue(request, request_type):
if request_type == "list": if request_type == "list":
# Dans ce cas on retourne la liste des tirages et de leur id en JSON # Dans ce cas on retourne la liste des tirages et de leur id en JSON
data_return = list( data_return = list(
Tirage.objects.filter(appear_catalogue=True).values('id', 'title')) Tirage.objects.filter(appear_catalogue=True).values('id', 'title')
)
return JsonResponse(data_return, safe=False) return JsonResponse(data_return, safe=False)
if request_type == "details": if request_type == "details":
# Dans ce cas on retourne une liste des catégories et des salles # Dans ce cas on retourne une liste des catégories et des salles
tirage_id = request.GET.get('id', '') tirage_id = request.GET.get('id', None)
try: if tirage_id is None:
tirage = Tirage.objects.get(id=tirage_id)
except ObjectDoesNotExist:
return HttpResponseBadRequest( return HttpResponseBadRequest(
"Aucun tirage correspondant à l'id " "Missing GET parameter: id <int>"
+ tirage_id) )
try:
tirage = get_object_or_404(Tirage, id=int(tirage_id))
except ValueError: except ValueError:
return HttpResponseBadRequest( return HttpResponseBadRequest(
"Mauvais format d'identifiant : " "Bad format: int expected for `id`"
+ tirage_id) )
shows = tirage.spectacle_set.values_list("id", flat=True)
categories = list( categories = list(
CategorieSpectacle.objects.filter( CategorieSpectacle.objects
spectacle__in=tirage.spectacle_set.all()) .filter(spectacle__in=shows)
.distinct().values('id', 'name')) .distinct()
.values('id', 'name')
)
locations = list( locations = list(
Salle.objects.filter( Salle.objects
spectacle__in=tirage.spectacle_set.all()) .filter(spectacle__in=shows)
.distinct().values('id', 'name')) .distinct()
.values('id', 'name')
)
data_return = {'categories': categories, 'locations': locations} data_return = {'categories': categories, 'locations': locations}
return JsonResponse(data_return, safe=False) return JsonResponse(data_return, safe=False)
if request_type == "descriptions": if request_type == "descriptions":
@ -687,33 +692,35 @@ def catalogue(request, request_type):
# à la salle spécifiées # à la salle spécifiées
tirage_id = request.GET.get('id', '') tirage_id = request.GET.get('id', '')
categories = request.GET.get('category', '[0]') categories = request.GET.get('category', '[]')
locations = request.GET.get('location', '[0]') locations = request.GET.get('location', '[]')
try: try:
category_id = json.loads(categories) tirage_id = int(tirage_id)
location_id = json.loads(locations) categories_id = json.loads(categories)
tirage = Tirage.objects.get(id=tirage_id) locations_id = json.loads(locations)
# Integers expected
shows_qs = tirage.spectacle_set if not all(isinstance(id, int) for id in categories_id):
if not(0 in category_id): raise ValueError
shows_qs = shows_qs.filter( if not all(isinstance(id, int) for id in locations_id):
category__id__in=category_id) raise ValueError
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 except ValueError: # Contient JSONDecodeError
return HttpResponseBadRequest( return HttpResponseBadRequest(
"Impossible de parser les paramètres donnés : " "Parse error, please ensure the GET parameters have the "
+ "id = " + request.GET.get('id', '') "following types:\n"
+ ", catégories = " + request.GET.get('category', '[0]') "id: int, category: [int], location: [int]\n"
+ ", salles = " + request.GET.get('location', '[0]')) "Data received:\n"
"id = {}, category = {}, locations = {}"
.format(request.GET.get('id', ''),
request.GET.get('category', '[]'),
request.GET.get('location', '[]'))
)
tirage = get_object_or_404(Tirage, id=tirage_id)
shows_qs = tirage.spectacle_set
if categories_id:
shows_qs = shows_qs.filter(category__id__in=categories_id)
if locations_id:
shows_qs = shows_qs.filter(location__id__in=locations_id)
# On convertit les descriptions à envoyer en une liste facilement # On convertit les descriptions à envoyer en une liste facilement
# JSONifiable (il devrait y avoir un moyen plus efficace en # JSONifiable (il devrait y avoir un moyen plus efficace en

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('kfet', '0052_category_addcost'),
]
operations = [
migrations.AlterField(
model_name='account',
name='created_at',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

View file

@ -41,7 +41,7 @@ class Account(models.Model):
max_digits = 6, decimal_places = 2, max_digits = 6, decimal_places = 2,
default = 0) default = 0)
is_frozen = models.BooleanField("est gelé", default = False) is_frozen = models.BooleanField("est gelé", default = False)
created_at = models.DateTimeField(auto_now_add = True, null = True) created_at = models.DateTimeField(default=timezone.now)
# Optional # Optional
PROMO_CHOICES = [(r,r) for r in range(1980, date.today().year+1)] PROMO_CHOICES = [(r,r) for r in range(1980, date.today().year+1)]
promo = models.IntegerField( promo = models.IntegerField(

View file

@ -86,6 +86,16 @@ textarea {
color:#FFF; color:#FFF;
} }
.buttons .nav-pills > li > a {
border-radius:0;
border:1px solid rgba(200,16,46,0.9);
}
.buttons .nav-pills > li.active > a {
background-color:rgba(200,16,46,0.9);
background-clip:padding-box;
}
.row-page-header { .row-page-header {
background-color:rgba(200,16,46,1); background-color:rgba(200,16,46,1);
color:#FFF; color:#FFF;

View file

@ -56,45 +56,40 @@ $(document).ready(function() {
<div class="col-sm-8 col-md-9 col-content-right"> <div class="col-sm-8 col-md-9 col-content-right">
{% include "kfet/base_messages.html" %} {% include "kfet/base_messages.html" %}
<div class="content-right"> <div class="content-right">
{% if addcosts %}
<div class="content-right-block">
<h2>Gagné des majorations</h2>
<div>
<ul>
{% for addcost in addcosts %}
<li>{{ addcost.date|date:'l j F' }}: +{{ addcost.sum_addcosts }}€</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
{% if account.user == request.user %}
<div class="content-right-block content-right-block-transparent">
<h2>Statistiques</h2>
<div class="row">
<div class="col-sm-12 nopadding">
<div class="panel-md-margin">
<h3>Ma balance</h3>
<div id="stat_balance"></div>
</div>
</div>
</div><!-- /row -->
<div class="row">
<div class="col-sm-12 nopadding">
<div class="panel-md-margin">
<h3>Ma consommation</h3>
<div id="stat_last"></div>
</div>
</div>
</div><!-- /row -->
</div>
{% endif %}
<div class="content-right-block"> <div class="content-right-block">
<h2>Historique</h2> <div class="col-sm-12 nopadding">
<div id="history"> {% if account.user == request.user %}
</div> <div class='tab-content'>
</div> <div class="tab-pane fade in active" id="tab_stats">
</div> <h2>Statistiques</h2>
<div class="panel-md-margin">
<h3>Ma balance</h3>
<div id="stat_balance"></div>
<h3>Ma consommation</h3>
<div id="stat_last"></div>
</div>
</div>
<div class="tab-pane fade" id="tab_history">
{% endif %}
{% if addcosts %}
<h2>Gagné des majorations</h2>
<div>
<ul>
{% for addcost in addcosts %}
<li>{{ addcost.date|date:'l j F' }}: +{{ addcost.sum_addcosts }}€</li>
{% endfor %}
</ul>
</div>
{% endif %}
<h2>Historique</h2>
<div id="history"></div>
{% if account.user == request.user %}
</div>
</div><!-- tab-content -->
{% endif %}
</div><!-- col-sm-12 -->
</div><!-- content-right-block -->
</div><!-- content-right-->
</div> </div>
</div> </div>

View file

@ -20,40 +20,42 @@
<div class="content-right"> <div class="content-right">
<div class="content-right-block"> <div class="content-right-block">
<h2>Carte</h2> <h2>Carte</h2>
<div class="column-row"> <div class="column-row">
<div class="column-sm-1 column-md-2 column-lg-3"> <div class="column-sm-1 column-md-2 column-lg-3">
<div class="unbreakable carte-inverted"> <div class="unbreakable carte-inverted">
<h3>Pressions du moment</h3> {% if pressions %}
<ul class="carte"> <h3>Pressions du moment</h3>
{% for article in pressions %} <ul class="carte">
<li class="carte-line"> {% for article in pressions %}
<div class="filler"></div> <li class="carte-line">
<span class="carte-label">{{ article.name }}</span> <div class="filler"></div>
<span class="carte-ukf">{{ article.price | ukf:False}} UKF</span> <span class="carte-label">{{ article.name }}</span>
</li> <span class="carte-ukf">{{ article.price | ukf:False}} UKF</span>
{% endfor %} </li>
</ul>
</div><!-- endblock unbreakable -->
{% for article in articles %}
{% ifchanged article.category %}
{% if not forloop.first %}
</ul>
</div><!-- endblock unbreakable -->
{% endif %}
<div class="unbreakable">
<h3>{{ article.category.name }}</h3>
<ul class="carte">
{% endifchanged %}
<li class="carte-line">
<div class="filler"></div>
<span class="carte-label">{{ article.name }}</span>
<span class="carte-ukf">{{ article.price | ukf:False}} UKF</span>
</li>
{% if foorloop.last %}
</ul>
</div><!-- endblock unbreakable -->
{% endif %}
{% endfor %} {% endfor %}
</ul>
{% endif %}
</div><!-- endblock unbreakable -->
{% for article in articles %}
{% ifchanged article.category %}
{% if not forloop.first %}
</ul>
</div><!-- endblock unbreakable -->
{% endif %}
<div class="unbreakable">
<h3>{{ article.category.name }}</h3>
<ul class="carte">
{% endifchanged %}
<li class="carte-line">
<div class="filler"></div>
<span class="carte-label">{{ article.name }}</span>
<span class="carte-ukf">{{ article.price | ukf:False}} UKF</span>
</li>
{% if forloop.last %}
</ul>
</div><!-- endblock unbreakable -->
{% endif %}
{% endfor %}
</div> </div>
</div> </div>
</div> </div>

View file

@ -291,7 +291,7 @@ $(document).ready(function() {
var reduc_divisor = 1; var reduc_divisor = 1;
if (kpsul.account_manager.account.is_cof) if (kpsul.account_manager.account.is_cof)
reduc_divisor = 1 + Config.get('subvention_cof') / 100; reduc_divisor = 1 + Config.get('subvention_cof') / 100;
return amount_euro / reduc_divisor; return (amount_euro / reduc_divisor).toFixed(2);
} }
function addPurchase(article, nb) { function addPurchase(article, nb) {
@ -306,7 +306,7 @@ $(document).ready(function() {
} }
}); });
if (!existing) { if (!existing) {
var amount_euro = amountEuroPurchase(article, nb).toFixed(2); var amount_euro = amountEuroPurchase(article, nb);
var index = addPurchaseToFormset(article.id, nb, amount_euro); var index = addPurchaseToFormset(article.id, nb, amount_euro);
var article_basket_html = $(item_basket_default_html); var article_basket_html = $(item_basket_default_html);
article_basket_html article_basket_html

View file

@ -36,6 +36,12 @@
</div> </div>
</div> </div>
<div class="buttons"> <div class="buttons">
{% if account.user == request.user %}
<ul class='nav nav-pills nav-justified'>
<li class="active"><a data-toggle="pill" href="#tab_stats">Statistiques</a></li>
<li><a data-toggle="pill" href="#tab_history">Historique</a></li>
</ul>
{% endif %}
<a class="btn btn-primary btn-lg" href="{% url 'kfet.account.update' account.trigramme %}"> <a class="btn btn-primary btn-lg" href="{% url 'kfet.account.update' account.trigramme %}">
Modifier Modifier
</a> </a>