Merge branch 'master' into aureplop/cof-tests_calendar

This commit is contained in:
Martin Pépin 2018-04-07 10:24:41 +02:00
commit 60d8e76fee
26 changed files with 2228 additions and 51 deletions

View file

@ -14,7 +14,7 @@
</tr></thead> </tr></thead>
<tbody class="bda_formset_content"> <tbody class="bda_formset_content">
{% endif %} {% endif %}
<tr class="{% cycle row1,row2 %} dynamic-form {% if form.instance.pk %}has_original{% endif %}"> <tr class="{% cycle 'row1' 'row2' %} dynamic-form {% if form.instance.pk %}has_original{% endif %}">
{% for field in form.visible_fields %} {% for field in form.visible_fields %}
{% if field.name != "DELETE" and field.name != "priority" %} {% if field.name != "DELETE" and field.name != "priority" %}
<td class="bda-field-{{ field.name }}"> <td class="bda-field-{{ field.name }}">

View file

@ -27,6 +27,14 @@ var django = {
var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-'); var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
$(this).attr('for', newFor); $(this).attr('for', newFor);
}); });
// Cloning <select> element doesn't properly propagate the default
// selected <option>, so we set it manually.
newElement.find('select').each(function (index, select) {
var defaultValue = $(select).find('option[selected]').val();
if (typeof defaultValue !== 'undefined') {
$(select).val(defaultValue);
}
});
total++; total++;
$('#id_' + type + '-TOTAL_FORMS').val(total); $('#id_' + type + '-TOTAL_FORMS').val(total);
$(selector).after(newElement); $(selector).after(newElement);

View file

@ -16,7 +16,7 @@
<h4 class="bda-prix">Total à payer : {{ total|floatformat }}€</h4> <h4 class="bda-prix">Total à payer : {{ total|floatformat }}€</h4>
<br/> <br/>
<p>Ne manque pas un spectacle avec le <p>Ne manque pas un spectacle avec le
<a href="{% url "gestioncof.views.calendar" %}">calendrier <a href="{% url "calendar" %}">calendrier
automatique&#8239;!</a></p> automatique&#8239;!</a></p>
{% else %} {% else %}
<h3>Vous n'avez aucune place :(</h3> <h3>Vous n'avez aucune place :(</h3>

View file

@ -7,6 +7,7 @@ the local development server should be here.
""" """
import os import os
import sys
try: try:
from . import secret from . import secret
@ -53,9 +54,13 @@ BASE_DIR = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))) os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
) )
TESTING = sys.argv[1] == 'test'
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
'shared',
'gestioncof', 'gestioncof',
# Must be before 'django.contrib.admin'. # Must be before 'django.contrib.admin'.

View file

@ -4,13 +4,18 @@ The settings that are not listed here are imported from .common
""" """
from .common import * # NOQA from .common import * # NOQA
from .common import INSTALLED_APPS, MIDDLEWARE from .common import INSTALLED_APPS, MIDDLEWARE, TESTING
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
DEBUG = True DEBUG = True
if TESTING:
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.MD5PasswordHasher',
]
# --- # ---
# Apache static/media config # Apache static/media config
@ -36,6 +41,7 @@ def show_toolbar(request):
""" """
return DEBUG return DEBUG
if not TESTING:
INSTALLED_APPS += ["debug_toolbar", "debug_panel"] INSTALLED_APPS += ["debug_toolbar", "debug_panel"]
MIDDLEWARE = [ MIDDLEWARE = [

View file

@ -11,7 +11,7 @@
{% endif %} {% endif %}
{% include "tristate_js.html" %} {% include "tristate_js.html" %}
<h3>Filtres</h3> <h3>Filtres</h3>
<form method="post" action="{% url 'gestioncof.views.event_status' event.id %}"> <form method="post" action="{% url 'event.details.status' event.id %}">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<input style="margin-top:10px;" type="submit" class="btn btn-primary" value="Filtrer" /> <input style="margin-top:10px;" type="submit" class="btn btn-primary" value="Filtrer" />

View file

@ -8,7 +8,7 @@
{% if survey.details %} {% if survey.details %}
<p>{{ survey.details }}</p> <p>{{ survey.details }}</p>
{% endif %} {% endif %}
<form class="form-horizontal" method="post" action="{% url 'gestioncof.views.survey' survey.id %}"> <form class="form-horizontal" method="post" action="{% url 'survey.details' survey.id %}">
{% csrf_token %} {% csrf_token %}
{{ form | bootstrap}} {{ form | bootstrap}}

View file

@ -16,7 +16,7 @@
</tr></thead> </tr></thead>
<tbody class="bda_formset_content"> <tbody class="bda_formset_content">
{% endif %} {% endif %}
<tr class="{% cycle row1,row2 %} dynamic-form {% if form.instance.pk %}has_original{% endif %}"> <tr class="{% cycle 'row1' 'row2' %} dynamic-form {% if form.instance.pk %}has_original{% endif %}">
{% for field in form.visible_fields %} {% for field in form.visible_fields %}
{% if field.name != "DELETE" and field.name != "priority" %} {% if field.name != "DELETE" and field.name != "priority" %}
<td class="bda-field-{{ field.name }}"> <td class="bda-field-{{ field.name }}">

View file

@ -4,7 +4,7 @@
{% block page_size %}col-sm-8{% endblock %} {% block page_size %}col-sm-8{% endblock %}
{% block extra_head %} {% block extra_head %}
<script src="{% static "autocomplete_light/autocomplete.js" %}" type="text/javascript"></script> <script src="{% static "vendor/jquery.autocomplete-light/3.5.0/dist/jquery.autocomplete-light.min.js" %}" type="text/javascript"></script>
{% endblock %} {% endblock %}
{% block realcontent %} {% block realcontent %}

View file

@ -11,7 +11,7 @@
{% endif %} {% endif %}
<h3>Filtres</h3> <h3>Filtres</h3>
{% include "tristate_js.html" %} {% include "tristate_js.html" %}
<form method="post" action="{% url 'gestioncof.views.survey_status' survey.id %}"> <form method="post" action="{% url 'survey.details.status' survey.id %}">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<input style="margin-top:10px;" type="submit" class="btn btn-primary" value="Filtrer" /> <input style="margin-top:10px;" type="submit" class="btn btn-primary" value="Filtrer" />

View file

@ -7,7 +7,7 @@ from django.contrib.messages.storage.base import Message
from django.test import TestCase from django.test import TestCase
from bda.models import Salle, Tirage from bda.models import Salle, Tirage
from gestioncof.models import CalendarSubscription from gestioncof.models import CalendarSubscription, Event, Survey, SurveyAnswer
from gestioncof.tests.testcases import ViewTestCaseMixin from gestioncof.tests.testcases import ViewTestCaseMixin
@ -149,3 +149,328 @@ class CalendarICSViewTests(ViewTestCaseMixin, TestCase):
'uid': 'show-{}-{}@example.com'.format(self.s2.pk, self.t.pk), 'uid': 'show-{}-{}@example.com'.format(self.s2.pk, self.t.pk),
}, },
]) ])
class EventViewTests(ViewTestCaseMixin, TestCase):
url_name = 'event.details'
http_methods = ['GET', 'POST']
auth_user = 'user'
auth_forbidden = [None]
post_expected_message = Message(messages.SUCCESS, (
"Votre inscription a bien été enregistrée ! Vous pouvez cependant la "
"modifier jusqu'à la fin des inscriptions."
))
@property
def url_kwargs(self):
return {'event_id': self.e.pk}
@property
def url_expected(self):
return '/event/{}'.format(self.e.pk)
def setUp(self):
super().setUp()
self.e = Event.objects.create()
self.ecf1 = self.e.commentfields.create(name='Comment Field 1')
self.ecf2 = self.e.commentfields.create(
name='Comment Field 2', fieldtype='char',
)
self.o1 = self.e.options.create(name='Option 1')
self.o2 = self.e.options.create(name='Option 2', multi_choices=True)
self.oc1 = self.o1.choices.create(value='O1 - Choice 1')
self.oc2 = self.o1.choices.create(value='O1 - Choice 2')
self.oc3 = self.o2.choices.create(value='O2 - Choice 1')
self.oc4 = self.o2.choices.create(value='O2 - Choice 2')
def test_get(self):
r = self.client.get(self.url)
self.assertEqual(r.status_code, 200)
def test_post_new(self):
r = self.client.post(self.url, {
'option_{}'.format(self.o1.pk): [str(self.oc1.pk)],
'option_{}'.format(self.o2.pk): [
str(self.oc3.pk), str(self.oc4.pk),
],
})
self.assertEqual(r.status_code, 200)
self.assertIn(self.post_expected_message, get_messages(r.wsgi_request))
er = self.e.eventregistration_set.get(user=self.users['user'])
self.assertQuerysetEqual(
er.options.all(), map(repr, [self.oc1, self.oc3, self.oc4]),
ordered=False,
)
# TODO: Make the view care about comments.
# self.assertQuerysetEqual(
# er.comments.all(), map(repr, []),
# ordered=False,
# )
def test_post_edit(self):
er = self.e.eventregistration_set.create(user=self.users['user'])
er.options.add(self.oc1, self.oc3, self.oc4)
er.comments.create(
commentfield=self.ecf1, content='Comment 1',
)
r = self.client.post(self.url, {
'option_{}'.format(self.o1.pk): [],
'option_{}'.format(self.o2.pk): [str(self.oc3.pk)],
})
self.assertEqual(r.status_code, 200)
self.assertIn(self.post_expected_message, get_messages(r.wsgi_request))
er.refresh_from_db()
self.assertQuerysetEqual(
er.options.all(), map(repr, [self.oc3]),
ordered=False,
)
# TODO: Make the view care about comments.
# self.assertQuerysetEqual(
# er.comments.all(), map(repr, []),
# ordered=False,
# )
class EventStatusViewTests(ViewTestCaseMixin, TestCase):
url_name = 'event.details.status'
http_methods = ['GET', 'POST']
auth_user = 'staff'
auth_forbidden = [None, 'user', 'member']
@property
def url_kwargs(self):
return {'event_id': self.e.pk}
@property
def url_expected(self):
return '/event/{}/status'.format(self.e.pk)
def setUp(self):
super().setUp()
self.e = Event.objects.create()
self.cf1 = self.e.commentfields.create(name='Comment Field 1')
self.cf2 = self.e.commentfields.create(
name='Comment Field 2', fieldtype='char',
)
self.o1 = self.e.options.create(name='Option 1')
self.o2 = self.e.options.create(name='Option 2', multi_choices=True)
self.oc1 = self.o1.choices.create(value='O1 - Choice 1')
self.oc2 = self.o1.choices.create(value='O1 - Choice 2')
self.oc3 = self.o2.choices.create(value='O2 - Choice 1')
self.oc4 = self.o2.choices.create(value='O2 - Choice 2')
self.er1 = self.e.eventregistration_set.create(user=self.users['user'])
self.er1.options.add(self.oc1)
self.er2 = self.e.eventregistration_set.create(
user=self.users['member'],
)
def _get_oc_filter_name(self, oc):
return 'option_{}_choice_{}'.format(oc.event_option.pk, oc.pk)
def _test_filters(self, filters, expected):
r = self.client.post(self.url, {
self._get_oc_filter_name(oc): v for oc, v in filters
})
self.assertEqual(r.status_code, 200)
self.assertQuerysetEqual(
r.context['user_choices'], map(repr, expected),
ordered=False,
)
def test_filter_none(self):
self._test_filters([(self.oc1, 'none')], [self.er1, self.er2])
def test_filter_yes(self):
self._test_filters([(self.oc1, 'yes')], [self.er1])
def test_filter_no(self):
self._test_filters([(self.oc1, 'no')], [self.er2])
class SurveyViewTests(ViewTestCaseMixin, TestCase):
url_name = 'survey.details'
http_methods = ['GET', 'POST']
auth_user = 'user'
auth_forbidden = [None]
post_expected_message = Message(messages.SUCCESS, (
"Votre réponse a bien été enregistrée ! Vous pouvez cependant la "
"modifier jusqu'à la fin du sondage."
))
@property
def url_kwargs(self):
return {'survey_id': self.s.pk}
@property
def url_expected(self):
return '/survey/{}'.format(self.s.pk)
def setUp(self):
super().setUp()
self.s = Survey.objects.create(title='Title')
self.q1 = self.s.questions.create(question='Question 1 ?')
self.q2 = self.s.questions.create(
question='Question 2 ?',
multi_answers=True,
)
self.qa1 = self.q1.answers.create(answer='Q1 - Answer 1')
self.qa2 = self.q1.answers.create(answer='Q1 - Answer 2')
self.qa3 = self.q2.answers.create(answer='Q2 - Answer 1')
self.qa4 = self.q2.answers.create(answer='Q2 - Answer 2')
def test_get(self):
r = self.client.get(self.url)
self.assertEqual(r.status_code, 200)
def test_post_new(self):
r = self.client.post(self.url, {
'question_{}'.format(self.q1.pk): [str(self.qa1.pk)],
'question_{}'.format(self.q2.pk): [
str(self.qa3.pk), str(self.qa4.pk),
],
})
self.assertEqual(r.status_code, 200)
self.assertIn(self.post_expected_message, get_messages(r.wsgi_request))
a = self.s.surveyanswer_set.get(user=self.users['user'])
self.assertQuerysetEqual(
a.answers.all(), map(repr, [self.qa1, self.qa3, self.qa4]),
ordered=False,
)
def test_post_edit(self):
a = self.s.surveyanswer_set.create(user=self.users['user'])
a.answers.add(self.qa1, self.qa1, self.qa4)
r = self.client.post(self.url, {
'question_{}'.format(self.q1.pk): [],
'question_{}'.format(self.q2.pk): [str(self.qa3.pk)],
})
self.assertEqual(r.status_code, 200)
self.assertIn(self.post_expected_message, get_messages(r.wsgi_request))
a.refresh_from_db()
self.assertQuerysetEqual(
a.answers.all(), map(repr, [self.qa3]),
ordered=False,
)
def test_post_delete(self):
a = self.s.surveyanswer_set.create(user=self.users['user'])
a.answers.add(self.qa1, self.qa4)
r = self.client.post(self.url, {'delete': '1'})
self.assertEqual(r.status_code, 200)
expected_message = Message(
messages.SUCCESS, "Votre réponse a bien été supprimée")
self.assertIn(expected_message, get_messages(r.wsgi_request))
with self.assertRaises(SurveyAnswer.DoesNotExist):
a.refresh_from_db()
def test_forbidden_closed(self):
self.s.survey_open = False
self.s.save()
r = self.client.get(self.url)
self.assertNotEqual(r.status_code, 200)
def test_forbidden_old(self):
self.s.old = True
self.s.save()
r = self.client.get(self.url)
self.assertNotEqual(r.status_code, 200)
class SurveyStatusViewTests(ViewTestCaseMixin, TestCase):
url_name = 'survey.details.status'
http_methods = ['GET', 'POST']
auth_user = 'staff'
auth_forbidden = [None, 'user', 'member']
@property
def url_kwargs(self):
return {'survey_id': self.s.pk}
@property
def url_expected(self):
return '/survey/{}/status'.format(self.s.pk)
def setUp(self):
super().setUp()
self.s = Survey.objects.create(title='Title')
self.q1 = self.s.questions.create(question='Question 1 ?')
self.q2 = self.s.questions.create(
question='Question 2 ?',
multi_answers=True,
)
self.qa1 = self.q1.answers.create(answer='Q1 - Answer 1')
self.qa2 = self.q1.answers.create(answer='Q1 - Answer 2')
self.qa3 = self.q2.answers.create(answer='Q2 - Answer 1')
self.qa4 = self.q2.answers.create(answer='Q2 - Answer 2')
self.a1 = self.s.surveyanswer_set.create(user=self.users['user'])
self.a1.answers.add(self.qa1)
self.a2 = self.s.surveyanswer_set.create(user=self.users['member'])
def test_get(self):
r = self.client.get(self.url)
self.assertEqual(r.status_code, 200)
def _get_qa_filter_name(self, qa):
return 'question_{}_answer_{}'.format(qa.survey_question.pk, qa.pk)
def _test_filters(self, filters, expected):
r = self.client.post(self.url, {
self._get_qa_filter_name(qa): v for qa, v in filters
})
self.assertEqual(r.status_code, 200)
self.assertQuerysetEqual(
r.context['user_answers'], map(repr, expected),
ordered=False,
)
def test_filter_none(self):
self._test_filters([(self.qa1, 'none')], [self.a1, self.a2])
def test_filter_yes(self):
self._test_filters([(self.qa1, 'yes')], [self.a1])
def test_filter_no(self):
self._test_filters([(self.qa1, 'no')], [self.a2])

View file

@ -20,6 +20,7 @@ class TriStateCheckbox(Widget):
def render(self, name, value, attrs=None, choices=()): def render(self, name, value, attrs=None, choices=()):
if value is None: if value is None:
value = 'none' value = 'none'
final_attrs = self.build_attrs(attrs, value=value) attrs['value'] = value
final_attrs = self.build_attrs(self.attrs, attrs)
output = ["<span class=\"tristate\"%s></span>" % flatatt(final_attrs)] output = ["<span class=\"tristate\"%s></span>" % flatatt(final_attrs)]
return mark_safe('\n'.join(output)) return mark_safe('\n'.join(output))

View file

@ -296,17 +296,17 @@ class KPsulAccountForm(forms.ModelForm):
class KPsulCheckoutForm(forms.Form): class KPsulCheckoutForm(forms.Form):
checkout = forms.ModelChoiceField( checkout = forms.ModelChoiceField(
queryset=( queryset=None,
Checkout.objects
.filter(
is_protected=False,
valid_from__lte=timezone.now(),
valid_to__gte=timezone.now(),
)
),
widget=forms.Select(attrs={'id': 'id_checkout_select'}), widget=forms.Select(attrs={'id': 'id_checkout_select'}),
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Create the queryset on form instanciation to use the current time.
self.fields['checkout'].queryset = (
Checkout.objects.is_valid().filter(is_protected=False))
class KPsulOperationForm(forms.ModelForm): class KPsulOperationForm(forms.ModelForm):
article = forms.ModelChoiceField( article = forms.ModelChoiceField(

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.12 on 2018-04-05 21:47
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('kfet', '0062_delete_globalpermissions'),
]
operations = [
migrations.AlterField(
model_name='account',
name='promo',
field=models.IntegerField(blank=True, choices=[(1980, 1980), (1981, 1981), (1982, 1982), (1983, 1983), (1984, 1984), (1985, 1985), (1986, 1986), (1987, 1987), (1988, 1988), (1989, 1989), (1990, 1990), (1991, 1991), (1992, 1992), (1993, 1993), (1994, 1994), (1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018)], default=2017, null=True),
),
]

View file

@ -341,6 +341,13 @@ class AccountNegative(models.Model):
return self.start + kfet_config.overdraft_duration return self.start + kfet_config.overdraft_duration
class CheckoutQuerySet(models.QuerySet):
def is_valid(self):
now = timezone.now()
return self.filter(valid_from__lte=now, valid_to__gte=now)
class Checkout(models.Model): class Checkout(models.Model):
created_by = models.ForeignKey( created_by = models.ForeignKey(
Account, on_delete = models.PROTECT, Account, on_delete = models.PROTECT,
@ -353,6 +360,8 @@ class Checkout(models.Model):
default = 0) default = 0)
is_protected = models.BooleanField(default = False) is_protected = models.BooleanField(default = False)
objects = CheckoutQuerySet.as_manager()
def get_absolute_url(self): def get_absolute_url(self):
return reverse('kfet.checkout.read', kwargs={'pk': self.pk}) return reverse('kfet.checkout.read', kwargs={'pk': self.pk})
@ -362,6 +371,22 @@ class Checkout(models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
def save(self, *args, **kwargs):
created = self.pk is None
ret = super().save(*args, **kwargs)
if created:
self.statements.create(
amount_taken=0,
balance_old=self.balance,
balance_new=self.balance,
by=self.created_by,
)
return ret
class CheckoutTransfer(models.Model): class CheckoutTransfer(models.Model):
from_checkout = models.ForeignKey( from_checkout = models.ForeignKey(
Checkout, on_delete = models.PROTECT, Checkout, on_delete = models.PROTECT,

View file

@ -5,7 +5,7 @@
{% block header-title %}Création d'un compte{% endblock %} {% block header-title %}Création d'un compte{% endblock %}
{% block extra_head %} {% block extra_head %}
<script src="{% static "autocomplete_light/autocomplete.js" %}" type="text/javascript"></script> <script src="{% static "vendor/jquery.autocomplete-light/3.5.0/dist/jquery.autocomplete-light.min.js" %}" type="text/javascript"></script>
{% endblock %} {% endblock %}
{% block main %} {% block main %}

48
kfet/tests/test_forms.py Normal file
View file

@ -0,0 +1,48 @@
import datetime
from unittest import mock
from django.test import TestCase
from django.utils import timezone
from kfet.forms import KPsulCheckoutForm
from kfet.models import Checkout
from .utils import create_user
class KPsulCheckoutFormTests(TestCase):
def setUp(self):
self.now = timezone.now()
user = create_user()
self.c1 = Checkout.objects.create(
name='C1', balance=10,
created_by=user.profile.account_kfet,
valid_from=self.now,
valid_to=self.now + datetime.timedelta(days=1),
)
self.form = KPsulCheckoutForm()
def test_checkout(self):
checkout_f = self.form.fields['checkout']
self.assertListEqual(list(checkout_f.choices), [
('', '---------'),
(self.c1.pk, 'C1'),
])
@mock.patch('django.utils.timezone.now')
def test_checkout_valid(self, mock_now):
"""
Checkout are filtered using the current datetime.
Regression test for #184.
"""
self.now += datetime.timedelta(days=2)
mock_now.return_value = self.now
form = KPsulCheckoutForm()
checkout_f = form.fields['checkout']
self.assertListEqual(list(checkout_f.choices), [('', '---------')])

View file

@ -1,7 +1,12 @@
import datetime
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.test import TestCase from django.test import TestCase
from django.utils import timezone
from kfet.models import Account from kfet.models import Account, Checkout
from .utils import create_user
User = get_user_model() User = get_user_model()
@ -23,3 +28,33 @@ class AccountTests(TestCase):
with self.assertRaises(Account.DoesNotExist): with self.assertRaises(Account.DoesNotExist):
Account.objects.get_by_password('bernard') Account.objects.get_by_password('bernard')
class CheckoutTests(TestCase):
def setUp(self):
self.now = timezone.now()
self.u = create_user()
self.u_acc = self.u.profile.account_kfet
self.c = Checkout(
created_by=self.u_acc,
valid_from=self.now,
valid_to=self.now + datetime.timedelta(days=1),
)
def test_initial_statement(self):
"""A statement is added with initial balance on creation."""
self.c.balance = 10
self.c.save()
st = self.c.statements.get()
self.assertEqual(st.balance_new, 10)
self.assertEqual(st.amount_taken, 0)
self.assertEqual(st.amount_error, 0)
# Saving again doesn't create a new statement.
self.c.save()
self.assertEqual(self.c.statements.count(), 1)

View file

@ -746,11 +746,15 @@ class CheckoutReadViewTests(ViewTestCaseMixin, TestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
with mock.patch('django.utils.timezone.now') as mock_now:
mock_now.return_value = self.now
self.checkout = Checkout.objects.create( self.checkout = Checkout.objects.create(
name='Checkout', name='Checkout', balance=Decimal('10'),
created_by=self.accounts['team'], created_by=self.accounts['team'],
valid_from=self.now, valid_from=self.now,
valid_to=self.now + timedelta(days=5), valid_to=self.now + timedelta(days=1),
) )
def test_ok(self): def test_ok(self):
@ -794,7 +798,7 @@ class CheckoutUpdateViewTests(ViewTestCaseMixin, TestCase):
name='Checkout', name='Checkout',
valid_from=self.now, valid_from=self.now,
valid_to=self.now + timedelta(days=5), valid_to=self.now + timedelta(days=5),
balance='3.14', balance=Decimal('3.14'),
is_protected=False, is_protected=False,
created_by=self.accounts['team'], created_by=self.accounts['team'],
) )
@ -864,6 +868,7 @@ class CheckoutStatementListViewTests(ViewTestCaseMixin, TestCase):
self.assertQuerysetEqual( self.assertQuerysetEqual(
r.context['checkoutstatements'], r.context['checkoutstatements'],
map(repr, expected_statements), map(repr, expected_statements),
ordered=False,
) )

View file

@ -245,13 +245,7 @@ class ViewTestCaseMixin(TestCaseMixin):
self.register_user(label, user) self.register_user(label, user)
if self.auth_user: if self.auth_user:
# The wrapper is a sanity check. self.client.force_login(self.users[self.auth_user])
self.assertTrue(
self.client.login(
username=self.auth_user,
password=self.auth_user,
)
)
def tearDown(self): def tearDown(self):
del self.users_base del self.users_base

View file

@ -528,15 +528,7 @@ class CheckoutCreate(SuccessMessageMixin, CreateView):
# Creating # Creating
form.instance.created_by = self.request.user.profile.account_kfet form.instance.created_by = self.request.user.profile.account_kfet
checkout = form.save() form.save()
# Création d'un relevé avec balance initiale
CheckoutStatement.objects.create(
checkout = checkout,
by = self.request.user.profile.account_kfet,
balance_old = checkout.balance,
balance_new = checkout.balance,
amount_taken = 0)
return super(CheckoutCreate, self).form_valid(form) return super(CheckoutCreate, self).form_valid(form)

View file

@ -1,5 +1,8 @@
#!/bin/sh #!/bin/sh
# Stop if an error is encountered
set -e
# Configuration de la base de données. Le mot de passe est constant car c'est # Configuration de la base de données. Le mot de passe est constant car c'est
# pour une installation de dév locale qui ne sera accessible que depuis la # pour une installation de dév locale qui ne sera accessible que depuis la
# machine virtuelle. # machine virtuelle.

View file

@ -1,5 +1,8 @@
#!/bin/bash #!/bin/bash
# Stop if an error is encountered.
set -e
python manage.py migrate python manage.py migrate
python manage.py loaddata gestion sites articles python manage.py loaddata gestion sites articles
python manage.py loaddevdata python manage.py loaddevdata

View file

@ -11,7 +11,7 @@ psycopg2
Pillow Pillow
six six
unicodecsv unicodecsv
django-bootstrap-form==3.2.1 django-bootstrap-form==3.3
asgiref==1.1.1 asgiref==1.1.1
daphne==1.3.0 daphne==1.3.0
asgi-redis==1.3.0 asgi-redis==1.3.0

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long