Merge branch 'master' into qwann/k-fet/kfet_open
This commit is contained in:
commit
531a4611d3
|
@ -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)
|
||||||
|
|
||||||
|
|
89
bda/tests.py
89
bda/tests.py
|
@ -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)}
|
||||||
|
)
|
||||||
|
|
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.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
|
||||||
|
|
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,
|
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(
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
<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">
|
||||||
|
{% if pressions %}
|
||||||
<h3>Pressions du moment</h3>
|
<h3>Pressions du moment</h3>
|
||||||
<ul class="carte">
|
<ul class="carte">
|
||||||
{% for article in pressions %}
|
{% for article in pressions %}
|
||||||
|
@ -46,6 +47,7 @@
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
{% endif %}
|
||||||
</div><!-- endblock unbreakable -->
|
</div><!-- endblock unbreakable -->
|
||||||
{% for article in articles %}
|
{% for article in articles %}
|
||||||
{% ifchanged article.category %}
|
{% ifchanged article.category %}
|
||||||
|
@ -62,7 +64,7 @@
|
||||||
<span class="carte-label">{{ article.name }}</span>
|
<span class="carte-label">{{ article.name }}</span>
|
||||||
<span class="carte-ukf">{{ article.price | ukf:False}} UKF</span>
|
<span class="carte-ukf">{{ article.price | ukf:False}} UKF</span>
|
||||||
</li>
|
</li>
|
||||||
{% if foorloop.last %}
|
{% if forloop.last %}
|
||||||
</ul>
|
</ul>
|
||||||
</div><!-- endblock unbreakable -->
|
</div><!-- endblock unbreakable -->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -838,7 +838,7 @@ $(document).ready(function() {
|
||||||
var reduc_divisor = 1;
|
var reduc_divisor = 1;
|
||||||
if (account_data['is_cof'])
|
if (account_data['is_cof'])
|
||||||
reduc_divisor = 1 + settings['subvention_cof'] / 100;
|
reduc_divisor = 1 + settings['subvention_cof'] / 100;
|
||||||
return amount_euro / reduc_divisor;
|
return (amount_euro / reduc_divisor).toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPurchase(id, nb) {
|
function addPurchase(id, nb) {
|
||||||
|
@ -852,7 +852,7 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!existing) {
|
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);
|
var index = addPurchaseToFormset(article_data[1], nb, amount_euro);
|
||||||
article_basket_html = $(item_basket_default_html);
|
article_basket_html = $(item_basket_default_html);
|
||||||
article_basket_html
|
article_basket_html
|
||||||
|
|
Loading…
Reference in a new issue