Merge branch 'master' into qwann/k-fet/kfet_open
This commit is contained in:
commit
531a4611d3
7 changed files with 182 additions and 93 deletions
|
@ -18,7 +18,10 @@ 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)
|
||||
appear_catalogue = models.BooleanField(
|
||||
"Tirage à afficher dans le catalogue",
|
||||
default=False
|
||||
)
|
||||
enable_do_tirage = models.BooleanField("Le tirage peut être lancé",
|
||||
default=False)
|
||||
|
||||
|
|
89
bda/tests.py
89
bda/tests.py
|
@ -1,22 +1,79 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
This file demonstrates writing tests using the unittest module. These will pass
|
||||
when you run "manage.py test".
|
||||
import json
|
||||
|
||||
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 __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from .models import Tirage, Spectacle, Salle, CategorieSpectacle
|
||||
|
||||
|
||||
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):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.assertEqual(1 + 1, 2)
|
||||
# The `list` hooh
|
||||
resp = client.get("/bda/catalogue/list")
|
||||
self.assertJSONEqual(
|
||||
resp.content.decode("utf-8"),
|
||||
[{"id": self.tirage.id, "title": self.tirage.title}]
|
||||
)
|
||||
|
||||
# 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)}
|
||||
)
|
||||
|
|
87
bda/views.py
87
bda/views.py
|
@ -22,7 +22,6 @@ 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,
|
||||
|
@ -657,29 +656,35 @@ def catalogue(request, request_type):
|
|||
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'))
|
||||
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:
|
||||
tirage_id = request.GET.get('id', None)
|
||||
if tirage_id is None:
|
||||
return HttpResponseBadRequest(
|
||||
"Aucun tirage correspondant à l'id "
|
||||
+ tirage_id)
|
||||
"Missing GET parameter: id <int>"
|
||||
)
|
||||
try:
|
||||
tirage = get_object_or_404(Tirage, id=int(tirage_id))
|
||||
except ValueError:
|
||||
return HttpResponseBadRequest(
|
||||
"Mauvais format d'identifiant : "
|
||||
+ tirage_id)
|
||||
"Bad format: int expected for `id`"
|
||||
)
|
||||
shows = tirage.spectacle_set.values_list("id", flat=True)
|
||||
categories = list(
|
||||
CategorieSpectacle.objects.filter(
|
||||
spectacle__in=tirage.spectacle_set.all())
|
||||
.distinct().values('id', 'name'))
|
||||
CategorieSpectacle.objects
|
||||
.filter(spectacle__in=shows)
|
||||
.distinct()
|
||||
.values('id', 'name')
|
||||
)
|
||||
locations = list(
|
||||
Salle.objects.filter(
|
||||
spectacle__in=tirage.spectacle_set.all())
|
||||
.distinct().values('id', 'name'))
|
||||
Salle.objects
|
||||
.filter(spectacle__in=shows)
|
||||
.distinct()
|
||||
.values('id', 'name')
|
||||
)
|
||||
data_return = {'categories': categories, 'locations': locations}
|
||||
return JsonResponse(data_return, safe=False)
|
||||
if request_type == "descriptions":
|
||||
|
@ -687,33 +692,35 @@ def catalogue(request, request_type):
|
|||
# à la salle spécifiées
|
||||
|
||||
tirage_id = request.GET.get('id', '')
|
||||
categories = request.GET.get('category', '[0]')
|
||||
locations = request.GET.get('location', '[0]')
|
||||
categories = request.GET.get('category', '[]')
|
||||
locations = request.GET.get('location', '[]')
|
||||
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)
|
||||
tirage_id = int(tirage_id)
|
||||
categories_id = json.loads(categories)
|
||||
locations_id = json.loads(locations)
|
||||
# Integers expected
|
||||
if not all(isinstance(id, int) for id in categories_id):
|
||||
raise ValueError
|
||||
if not all(isinstance(id, int) for id in locations_id):
|
||||
raise ValueError
|
||||
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]'))
|
||||
"Parse error, please ensure the GET parameters have the "
|
||||
"following types:\n"
|
||||
"id: int, category: [int], location: [int]\n"
|
||||
"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
|
||||
# JSONifiable (il devrait y avoir un moyen plus efficace en
|
||||
|
|
20
kfet/migrations/0053_created_at.py
Normal file
20
kfet/migrations/0053_created_at.py
Normal 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),
|
||||
),
|
||||
]
|
|
@ -41,7 +41,7 @@ class Account(models.Model):
|
|||
max_digits = 6, decimal_places = 2,
|
||||
default = 0)
|
||||
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
|
||||
PROMO_CHOICES = [(r,r) for r in range(1980, date.today().year+1)]
|
||||
promo = models.IntegerField(
|
||||
|
|
|
@ -33,40 +33,42 @@
|
|||
<div class="content-right">
|
||||
<div class="content-right-block">
|
||||
<h2>Carte</h2>
|
||||
<div class="column-row">
|
||||
<div class="column-sm-1 column-md-2 column-lg-3">
|
||||
<div class="unbreakable carte-inverted">
|
||||
<h3>Pressions du moment</h3>
|
||||
<ul class="carte">
|
||||
{% for article in pressions %}
|
||||
<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>
|
||||
{% endfor %}
|
||||
</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 %}
|
||||
<div class="column-row">
|
||||
<div class="column-sm-1 column-md-2 column-lg-3">
|
||||
<div class="unbreakable carte-inverted">
|
||||
{% if pressions %}
|
||||
<h3>Pressions du moment</h3>
|
||||
<ul class="carte">
|
||||
{% for article in pressions %}
|
||||
<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>
|
||||
{% 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>
|
||||
|
|
|
@ -838,7 +838,7 @@ $(document).ready(function() {
|
|||
var reduc_divisor = 1;
|
||||
if (account_data['is_cof'])
|
||||
reduc_divisor = 1 + settings['subvention_cof'] / 100;
|
||||
return amount_euro / reduc_divisor;
|
||||
return (amount_euro / reduc_divisor).toFixed(2);
|
||||
}
|
||||
|
||||
function addPurchase(id, nb) {
|
||||
|
@ -852,7 +852,7 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
if (!existing) {
|
||||
var amount_euro = amountEuroPurchase(id, nb).toFixed(2);
|
||||
var amount_euro = amountEuroPurchase(id, nb);
|
||||
var index = addPurchaseToFormset(article_data[1], nb, amount_euro);
|
||||
article_basket_html = $(item_basket_default_html);
|
||||
article_basket_html
|
||||
|
|
Loading…
Reference in a new issue