From 468098ae7b12c2f9640cc1c551f86af2b8dbccb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Mon, 5 Sep 2016 20:07:08 +0200 Subject: [PATCH 01/41] =?UTF-8?q?S=C3=A9lection=20par=20d=C3=A9faut=20de?= =?UTF-8?q?=20la=20caisse=20lorsqu'il=20n'y=20en=20a=20qu'une=20seule=20di?= =?UTF-8?q?sponible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kfet/templates/kfet/kpsul.html | 2 +- kfet/views.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 1694d57f..95dbd208 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -1139,7 +1139,7 @@ $(document).ready(function() { function hardReset(give_tri_focus=true) { coolReset(give_tri_focus); - resetCheckout(); + checkoutInput.trigger('change'); resetArticles(); khistory.reset(); resetSettings(); diff --git a/kfet/views.py b/kfet/views.py index 736dbe8a..787ff102 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -796,7 +796,15 @@ def kpsul(request): data = {} data['operationgroup_form'] = KPsulOperationGroupForm() data['trigramme_form'] = KPsulAccountForm() - data['checkout_form'] = KPsulCheckoutForm() + initial = {} + try: + checkout = Checkout.objects.filter( + is_protected=False, valid_from__lte=timezone.now(), + valid_to__gte=timezone.now()).get() + initial['checkout'] = checkout + except Checkout.DoesNotExist, Checkout.MultipleObjectsReturned: + pass + data['checkout_form'] = KPsulCheckoutForm(initial=initial) operation_formset = KPsulOperationFormSet(queryset=Operation.objects.none()) data['operation_formset'] = operation_formset return render(request, 'kfet/kpsul.html', data) From 5e6645ab84be805441dface7210cc29e5495d684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Mon, 5 Sep 2016 20:19:46 +0200 Subject: [PATCH 02/41] Fix JS K-Psul --- kfet/static/kfet/js/kfet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kfet/static/kfet/js/kfet.js b/kfet/static/kfet/js/kfet.js index 7aa1d963..6ed1b2c0 100644 --- a/kfet/static/kfet/js/kfet.js +++ b/kfet/static/kfet/js/kfet.js @@ -67,7 +67,7 @@ function getErrorsHtml(data) { } if ('negative' in data['errors']) { var url_base = "{% url 'kfet.account.update' LIQ}"; - url_base = base_url(0, url_base.length-8); + url_base = url_base(0, url_base.length-8); for (var i=0; iAutorisation de négatif requise pour '+data['errors']['negative'][i]+''; } From 985dd2e82da384a96c028fffe723a2f096065ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Mon, 5 Sep 2016 20:35:45 +0200 Subject: [PATCH 03/41] =?UTF-8?q?Fix=20autocompl=C3=A9tion=20article=20K-P?= =?UTF-8?q?sul?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kfet/templates/kfet/kpsul.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 95dbd208..eaaad49a 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -635,7 +635,9 @@ $(document).ready(function() { return false; } - articleSelect.on('keypress', function(e) { + articleSelect.on('keydown', function(e) { + console.log('trolo'); + console.log(e.charCode); var text = articleSelect.val(); // Comportement normal pour ces touches if (normalKeys.test(e.keyCode) || e.ctrlKey) { @@ -648,12 +650,10 @@ $(document).ready(function() { articleSelect.val(''); } return true; - } else if (e.charCode !== 0) { - if (updateMatchedArticles(text+e.key)) { - articleNb.val('1'); - articleNb.focus().select(); - } - return false; + } + if (updateMatchedArticles(text+e.key)) { + articleNb.val('1'); + articleNb.focus().select(); } return false; }); From a5b19b4328093f4a7ca3524f45ed2d66675ab8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Mon, 5 Sep 2016 20:38:15 +0200 Subject: [PATCH 04/41] fix js k-psul --- kfet/static/kfet/js/kfet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kfet/static/kfet/js/kfet.js b/kfet/static/kfet/js/kfet.js index 6ed1b2c0..a82ca29f 100644 --- a/kfet/static/kfet/js/kfet.js +++ b/kfet/static/kfet/js/kfet.js @@ -67,7 +67,7 @@ function getErrorsHtml(data) { } if ('negative' in data['errors']) { var url_base = "{% url 'kfet.account.update' LIQ}"; - url_base = url_base(0, url_base.length-8); + url_base = url_base.substr(0, url_base.length - 8); for (var i=0; iAutorisation de négatif requise pour '+data['errors']['negative'][i]+''; } From 58cb6015fc85601e7fff5013fb66412672eef17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Mon, 5 Sep 2016 22:12:58 +0200 Subject: [PATCH 05/41] fix transfers --- kfet/templates/kfet/kpsul.html | 2 -- kfet/views.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index eaaad49a..daa402b2 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -636,8 +636,6 @@ $(document).ready(function() { } articleSelect.on('keydown', function(e) { - console.log('trolo'); - console.log(e.charCode); var text = articleSelect.val(); // Comportement normal pour ces touches if (normalKeys.test(e.keyCode) || e.ctrlKey) { diff --git a/kfet/views.py b/kfet/views.py index 787ff102..77bed012 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -1410,7 +1410,7 @@ def perform_transfers(request): transfers = transfer_formset.save(commit = False) # Initializing vars - required_perms = set('kfet.add_transfer') # Required perms to perform all transfers + required_perms = set(['kfet.add_transfer']) # Required perms to perform all transfers to_accounts_balances = defaultdict(lambda:0) # For balances of accounts for transfer in transfers: From 5569b7d154c1b324713dc8d210bd293addd3bce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Tue, 6 Sep 2016 15:30:51 +0200 Subject: [PATCH 06/41] Fix encodage password --- kfet/backends.py | 2 +- kfet/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kfet/backends.py b/kfet/backends.py index 62b2d820..3729f1bd 100644 --- a/kfet/backends.py +++ b/kfet/backends.py @@ -18,7 +18,7 @@ class KFetBackend(object): return None try: - password_sha256 = hashlib.sha256(password.encode()).hexdigest() + password_sha256 = hashlib.sha256(password.encode('utf-8')).hexdigest() account = Account.objects.get(password=password_sha256) user = account.cofprofile.user except Account.DoesNotExist: diff --git a/kfet/views.py b/kfet/views.py index 77bed012..6bd260a3 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -399,7 +399,7 @@ def account_update(request, trigramme): if (request.user.has_perm('kfet.change_account_password') and pwd_form.is_valid()): pwd = pwd_form.cleaned_data['pwd1'] - pwd_sha256 = hashlib.sha256(pwd.encode()).hexdigest() + pwd_sha256 = hashlib.sha256(pwd.encode('utf-8')).hexdigest() Account.objects.filter(pk=account.pk).update( password = pwd_sha256) messages.success(request, 'Mot de passe mis à jour') From e154316eae3bd613722cccca43c4b1ad84a45522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Tue, 6 Sep 2016 16:33:04 +0200 Subject: [PATCH 07/41] =?UTF-8?q?Optimisation=20JS=20K-Psul=20s=C3=A9lecti?= =?UTF-8?q?on=20articles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kfet/templates/kfet/kpsul.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index daa402b2..aab04abe 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -504,17 +504,17 @@ $(document).ready(function() { function addArticle(article) { var article_html = $(article_default_html); - article_html.attr('data-article', article['id']); - article_html.attr('data-category', article['category_id']); + article_html.attr('id', 'data-article-'+article['id']); + article_html.addClass('data-category-'+article['category_id']); for (var elem in article) { article_html.find('.'+elem).text(article[elem]) } article_html.find('.price').text(amountToUKF(article['price'], false)); var category_html = articles_container - .find('.category[data-category='+article['category_id']+']'); + .find('#data-category-'+article['category_id']); if (category_html.length == 0) { category_html = $(article_category_default_html); - category_html.attr('data-category', article['category_id']); + category_html.attr('id', 'data-category-'+article['category_id']); category_html.find('td').text(article['category__name']); var added = false; articles_container.find('.category').each(function() { @@ -528,14 +528,14 @@ $(document).ready(function() { } var added = false; articles_container - .find('.article[data-category='+article['category_id']+']').each(function() { + .find('.article.data-category-'+article['category_id']).each(function() { if (article['name'].toLowerCase < $('.name', this).text().toLowerCase()) { $(this).before(article_html); added = true; return false; } }); - if (!added) articles_container.find('.category[data-category='+article['category_id']+']').after(article_html); + if (!added) articles_container.find('#data-category-'+article['category_id']).after(article_html); // Pour l'autocomplétion articlesList.push([article['name'],article['id'],article['category_id'],article['price']]); } @@ -597,17 +597,17 @@ $(document).ready(function() { var categories_to_display = []; for (var i=0; i -1) { - articles_container.find('[data-article='+articlesList[i][1]+']').show(); + articles_container.find('#data-article-'+articlesList[i][1]).show(); if (categories_to_display.indexOf(articlesList[i][2]) == -1) categories_to_display.push(articlesList[i][2]); } else { - articles_container.find('[data-article='+articlesList[i][1]+']').hide(); + articles_container.find('#data-article-'+articlesList[i][1]).hide(); } } articles_container.find('.category').hide(); for (var i=0; i Date: Tue, 6 Sep 2016 16:38:48 +0200 Subject: [PATCH 08/41] Clean JS ajout article et ordre des articles --- kfet/templates/kfet/kpsul.html | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index aab04abe..86bb48fa 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -526,16 +526,14 @@ $(document).ready(function() { }); if (!added) articles_container.append(category_html); } - var added = false; + var $after = articles_container.find('#data-category-'+article['category_id']); articles_container .find('.article.data-category-'+article['category_id']).each(function() { - if (article['name'].toLowerCase < $('.name', this).text().toLowerCase()) { - $(this).before(article_html); - added = true; + if (article['name'].toLowerCase < $('.name', this).text().toLowerCase()) return false; - } + $after = $(this); }); - if (!added) articles_container.find('#data-category-'+article['category_id']).after(article_html); + $after.after(article_html); // Pour l'autocomplétion articlesList.push([article['name'],article['id'],article['category_id'],article['price']]); } From f6fa13fa95725d4f33374f3d86ce1b2c4d5fde17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Tue, 6 Sep 2016 17:37:18 +0200 Subject: [PATCH 09/41] =?UTF-8?q?Fix=20url=20cr=C3=A9ation=20compte=20depu?= =?UTF-8?q?is=20K-Psul?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kfet/static/kfet/js/kfet.js | 1 - kfet/templates/kfet/kpsul.html | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kfet/static/kfet/js/kfet.js b/kfet/static/kfet/js/kfet.js index a82ca29f..28ca7de8 100644 --- a/kfet/static/kfet/js/kfet.js +++ b/kfet/static/kfet/js/kfet.js @@ -110,4 +110,3 @@ function requestAuth(data, callback, focus_next = null) { } }); } - diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 86bb48fa..34af13b3 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -198,8 +198,9 @@ $(document).ready(function() { } if (account_data['id'] == 0) { var trigramme = triInput.val().toUpperCase(); + var url_base = '{% url 'kfet.account.create' %}' if (isValidTrigramme(trigramme)) { - buttons += ''; + buttons += ''; } } account_container.find('.buttons').html(buttons); From 6ba8c9e7416f431c953744a0468a7679a2b8f3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Tue, 6 Sep 2016 17:50:05 +0200 Subject: [PATCH 10/41] URL Websocket K-Psul --- kfet/templates/kfet/kpsul.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 34af13b3..c065f3de 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -1085,7 +1085,9 @@ $(document).ready(function() { websocket_msg_default = {'opegroups':[],'opes':[],'checkouts':[],'articles':[]} var websocket_protocol = window.location.protocol == 'https:' ? 'wss' : 'ws'; - socket = new ReconnectingWebSocket(websocket_protocol+"://" + window.location.host + "/ws/k-fet/k-psul/"); + var location_host = window.location.host; + var location_url = window.location.pathname.startsWith('/gestion/') ? location_host + '/gestion' : location_host; + socket = new ReconnectingWebSocket(websocket_protocol+"://" + location_url + "/ws/k-fet/k-psul/"); socket.onmessage = function(e) { data = $.extend({}, websocket_msg_default, JSON.parse(e.data)); From ad661cab096175a730d5793d8423a9ecddbf8b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Tue, 6 Sep 2016 18:50:57 +0200 Subject: [PATCH 11/41] fix url account neg K-Psul --- kfet/static/kfet/js/kfet.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/kfet/static/kfet/js/kfet.js b/kfet/static/kfet/js/kfet.js index 28ca7de8..dbfba0b2 100644 --- a/kfet/static/kfet/js/kfet.js +++ b/kfet/static/kfet/js/kfet.js @@ -66,8 +66,11 @@ function getErrorsHtml(data) { content += ''; } if ('negative' in data['errors']) { - var url_base = "{% url 'kfet.account.update' LIQ}"; - url_base = url_base.substr(0, url_base.length - 8); + if (window.location.pathname.startsWith('/gestion/')) { + var url_base = '/gestion/k-fet/accounts/'; + } else { + var url_base = '/k-fet/accounts/'; + } for (var i=0; iAutorisation de négatif requise pour '+data['errors']['negative'][i]+''; } From 120ffd574a733899e3bdcde9d94a127c4256173e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Tue, 6 Sep 2016 19:44:40 +0200 Subject: [PATCH 12/41] =?UTF-8?q?Fix=20liste=20utilisateurs=20cr=C3=A9atio?= =?UTF-8?q?n=20de=20compte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kfet/templates/kfet/account_create_autocomplete.html | 1 + 1 file changed, 1 insertion(+) diff --git a/kfet/templates/kfet/account_create_autocomplete.html b/kfet/templates/kfet/account_create_autocomplete.html index b99abecf..1185c3a8 100644 --- a/kfet/templates/kfet/account_create_autocomplete.html +++ b/kfet/templates/kfet/account_create_autocomplete.html @@ -38,6 +38,7 @@
  • {{ clipper|highlight_clipper:q }} +
  • {% endfor %} {% endif %} From f614051365c0dbb225668271ff7d14a8967f421b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Tue, 6 Sep 2016 19:49:28 +0200 Subject: [PATCH 13/41] =?UTF-8?q?Fix=20cr=C3=A9ation=20compte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kfet/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kfet/views.py b/kfet/views.py index 6bd260a3..a08be40b 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -219,7 +219,8 @@ def account_form_set_readonly_fields(user_form, cof_form): def get_account_create_forms(request=None, username=None, login_clipper=None): user = None clipper = None - if login_clipper and not username: + if login_clipper and (login_clipper == username or not username): + print('trololo') # à partir d'un clipper # le user associé à ce clipper ne devrait pas encore exister clipper = get_object_or_404(Clipper, username = login_clipper) From fe7f84ffadd097b98676bd14684868d9a3a0b605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sat, 10 Sep 2016 22:49:07 +0200 Subject: [PATCH 14/41] Ajout message pour proposer connexion standard --- kfet/__init__.py | 1 + kfet/apps.py | 14 +++++++++++ kfet/signals.py | 16 ++++++++++++ kfet/static/kfet/css/index.css | 34 ++++++++++++++++++++++++++ kfet/templates/kfet/base_messages.html | 19 ++++++++++---- 5 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 kfet/apps.py create mode 100644 kfet/signals.py diff --git a/kfet/__init__.py b/kfet/__init__.py index e69de29b..5d6c8f97 100644 --- a/kfet/__init__.py +++ b/kfet/__init__.py @@ -0,0 +1 @@ +default_app_config = 'kfet.apps.KFetConfig' diff --git a/kfet/apps.py b/kfet/apps.py new file mode 100644 index 00000000..29f9f98e --- /dev/null +++ b/kfet/apps.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- + +from __future__ import (absolute_import, division, + print_function, unicode_literals) +from builtins import * + +from django.apps import AppConfig + +class KFetConfig(AppConfig): + name = 'kfet' + verbose_name = "Application K-Fêt" + + def ready(self): + import kfet.signals diff --git a/kfet/signals.py b/kfet/signals.py new file mode 100644 index 00000000..3dd4d677 --- /dev/null +++ b/kfet/signals.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +from __future__ import (absolute_import, division, + print_function, unicode_literals) +from builtins import * + +from django.contrib import messages +from django.contrib.auth.signals import user_logged_in +from django.core.urlresolvers import reverse +from django.dispatch import receiver + +@receiver(user_logged_in) +def messages_on_login(sender, request, user, **kwargs): + if (not user.username == 'kfet_genericteam' + and user.has_perm('kfet.is_team')): + messages.info(request, 'Connexion en utilisateur partagé ?' % reverse('kfet.login.genericteam'), extra_tags='safe') diff --git a/kfet/static/kfet/css/index.css b/kfet/static/kfet/css/index.css index c6ee9ff6..dc229b5d 100644 --- a/kfet/static/kfet/css/index.css +++ b/kfet/static/kfet/css/index.css @@ -263,3 +263,37 @@ textarea { display:block; padding:5px 20px; } + +/* + * Messages + */ + +.messages .alert { + padding:10px 15px; + margin:0; + border:0; + border-radius:0; +} + +.messages .alert-dismissible { + padding-right:35px; +} + +.messages .alert .close { + top:0; + right:0; +} + +.messages .alert-info { + color:inherit; + background-color:#ccc; +} + +.messages .alert-error { + color:inherit; + background-color:rgba(200,16,46,0.2); +} + +.messages .alert-success { + color:#333; +} diff --git a/kfet/templates/kfet/base_messages.html b/kfet/templates/kfet/base_messages.html index d2bb5061..440b8c10 100644 --- a/kfet/templates/kfet/base_messages.html +++ b/kfet/templates/kfet/base_messages.html @@ -1,7 +1,16 @@ {% if messages %} -
      - {% for message in messages %} - {{ message }} - {% endfor %} -
    +
    + {% for message in messages %} +
    +
    + + {% if 'safe' in message.tags %} + {{ message|safe }} + {% else %} + {{ message }} + {% endif %} +
    +
    + {% endfor %} +
    {% endif %} From 8d20dbfe244d4f5dfc19757cb8dfd030a3995aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sat, 10 Sep 2016 22:54:23 +0200 Subject: [PATCH 15/41] Ajout affichage messages sur K-Psul --- kfet/templates/kfet/kpsul.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index c065f3de..b09830fc 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -21,6 +21,8 @@ {% block content %} +{% include 'kfet/base_messages.html' %} +
    From dc4f0473fe9b43bf3500fa722d64cb3329baf484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sun, 11 Sep 2016 22:55:46 +0200 Subject: [PATCH 16/41] Ajout affichage raccourcis K-Psul avec ctrl+Hw --- kfet/static/kfet/css/index.css | 44 +++++++++++++++++++++++++ kfet/templates/kfet/base.html | 8 +++++ kfet/templates/kfet/kpsul.html | 59 ++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) diff --git a/kfet/static/kfet/css/index.css b/kfet/static/kfet/css/index.css index dc229b5d..f3e9bf8c 100644 --- a/kfet/static/kfet/css/index.css +++ b/kfet/static/kfet/css/index.css @@ -297,3 +297,47 @@ textarea { .messages .alert-success { color:#333; } + +/* + * Help + */ + +.help { + display:none; + position:fixed; + top:50px; + left:0; + right:0; + bottom:0; + overflow:auto; + background:rgba(51,51,51,0.3); + z-index:500; +} + +.help-box { + margin-top:30px; + padding-top:1px; + padding-bottom:15px; + background:rgba(51,51,51,0.7); + color:#fff; +} + +@media (max-width:768px) { + .help-box { + margin:20px 15px; + } +} + +.help h2 { + padding:0 15px 20px; + border-bottom:1px solid #999; + text-align:center; +} + +.help .row > div { + padding-right:0; +} + +.help h4 { + margin:15px 0; +} diff --git a/kfet/templates/kfet/base.html b/kfet/templates/kfet/base.html index c1db0c26..173a5fb7 100644 --- a/kfet/templates/kfet/base.html +++ b/kfet/templates/kfet/base.html @@ -40,5 +40,13 @@ {% block content %}{% endblock %} {% include "kfet/base_footer.html" %}
    +
    +
    +
    +

    Aide

    + {% block help %}{% endblock %} +
    +
    +
    diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index b09830fc..d4a1b1b8 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -19,6 +19,55 @@ {% block content-header %}{% endblock %} +{% block help %} + +
    +
    +
    +

    Opérations

    +
    +
    F3
    +
    Charge
    +
    +
    +
    Shift + F3
    +
    Retrait
    +
    +
    +
    F8
    +
    Edition
    +
    +
    +
    +
    +
    +

    Général

    +
    +
    F1
    +
    Reset
    +
    +
    +
    F2
    +
    Reset compte
    +
    +
    +
    Shift + F2
    +
    Reset panier
    +
    +
    +
    F9
    +
    Majoration
    +
    +
    +
    F10
    +
    Hard reset
    +
    +
    +
    +
    + +{% endblock %} + {% block content %} {% include 'kfet/base_messages.html' %} @@ -1164,6 +1213,16 @@ $(document).ready(function() { $(document).on('keydown', function(e) { switch (e.keyCode) { + case 27: + // Escape - Hide help + $('.help').hide('fast'); + return false; + case 72: + if (e.ctrlKey) { + // Ctrl+H - Display help + $('.help').show('fast'); + } + return false; case 112: // F1 - Cool reset coolReset(); From f37bdd90b701bcbaa454737e097d0704827794fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 12 Sep 2016 16:49:37 +0200 Subject: [PATCH 17/41] =?UTF-8?q?Cr=C3=A9e=20un=20setup=20proche=20de=20ce?= =?UTF-8?q?lui=20en=20production?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On fait tourner GestioCOF avec daphne derrière un reverse-proxy Apache sur la VM Vagrant tout comme sur le serveur de production. On peut tester en local GestioCOF en “conditions réelles”. Le serveur lancé avec `python manage.py runserver 0.0.0.0:8000` est toujours accessible à la même url `localhost:8000`. Le (nouveau) serveur apache est accessible à `localhost:8080`. Pour appliquer les changements dans le code au serveur type prod, il faut relancer le worker : `sudo supervisorctl restart worker`. Alors que le serveur de dev se relance tout seul. NB important : ce patch supprime le mot de passe sur le serveur redis en dev, pour faire marcher ce nouveau setup avec un version précédente de la VM, il faut lancer `sudo redis-cli config set requirepass ""` --- README.md | 43 +++++++++++++++++++++++++++------- {apache => cof}/asgi.py | 2 +- cof/settings_dev.py | 5 ++-- provisioning/apache.conf | 29 +++++++++++++++++++++++ provisioning/bootstrap.sh | 20 ++++++++++++---- provisioning/prepare_django.sh | 1 + provisioning/supervisor.conf | 20 ++++++++++++++++ 7 files changed, 104 insertions(+), 16 deletions(-) rename {apache => cof}/asgi.py (57%) create mode 100644 provisioning/apache.conf create mode 100644 provisioning/supervisor.conf diff --git a/README.md b/README.md index 15f0ec0d..80d87e87 100644 --- a/README.md +++ b/README.md @@ -47,28 +47,47 @@ gérer la machine virtuelle : - `vagrant ssh` vous connecte en SSH à la machine virtuelle, dans le dossier où est installé GestioCOF. Vous pouvez utiliser les commandes Django - habituelles (`manage.py runserver` etc.); toutefois pour lancer le serveur il faut faire - - python manage.py runserver 0.0.0.0:8000 - - car par défaut Django n'écoute que sur l'adresse locale de la machine - virtuelle - or vous voudrez accéder à GestioCOF depuis votre machine - physique. + habituelles (`manage.py runserver` etc.) **Le dossier avec le code de GestioCOF est partagé entre la machine virtuelle et votre machine physique : vous pouvez donc utiliser votre éditeur favori pour coder depuis l'extérieur de la machine virtuelle, et les changements seront répercutés dans la machine virtuelle.** +#### Lancer le serveur de développement standard + +Pour lancer le serveur de développement, il faut faire + + python manage.py runserver 0.0.0.0:8000 + +car par défaut Django n'écoute que sur l'adresse locale de la machine virtuelle +or vous voudrez accéder à GestioCOF depuis votre machine physique. L'url à +entrer dans le navigateur est `localhost:8000`. + +#### Serveur de développement type production + +Sur la VM Vagrant, un serveur apache est configuré pour servir GestioCOF de +façon similaire à la version en production : on utilise +[Daphne](https://github.com/django/daphne/) et `python manage.py runworker` +derrière un reverse-proxy apache. Le tout est monitoré par +[supervisor](http://supervisord.org/). + +Ce serveur se lance tout seul et est accessible en dehors de la VM à l'url +`localhost:8080`. Toutefois il ne se recharge pas tout seul lorsque le code +change, il faut relancer le worker avec `sudo supervisorctl restart worker` pour +visualiser la dernière version du code. + ### Installation manuelle Si vous optez pour une installation manuelle plutôt que d'utiliser Vagrant, il est fortement conseillé d'utiliser un environnement virtuel pour Python. Il vous faudra installer mercurial, pip, les librairies de développement de -python, ainsi qu'un client et un serveur MySQL ; sous Debian et dérivées (Ubuntu, ...) : +python, un client et un serveur MySQL ainsi qu'un serveur redis ; sous Debian et +dérivées (Ubuntu, ...) : sudo apt-get install mercurial python-pip python-dev libmysqlclient-dev + redis-server Si vous décidez d'utiliser un environnement virtuel Python (virtualenv; fortement conseillé), déplacez-vous dans le dossier où est installé GestioCOF @@ -87,7 +106,13 @@ Vous pouvez maintenant installer les dépendances Python depuis les fichiers pip install -r requirements.txt -r requirements-devel.txt -Enfin, copiez le fichier `cof/settings_dev.py` dans `cof/settings.py`. +Copiez le fichier `cof/settings_dev.py` dans `cof/settings.py`. + +Enfin, configurez le mot de passe redis le plus simple et de ne pas en utiliser +(pas de risque en local) en remplaçant la ligne `hosts` dans +`settings.CHANNEL_LAYER` par + + "hosts": [("localhost", 6379)] #### Installation avec MySQL diff --git a/apache/asgi.py b/cof/asgi.py similarity index 57% rename from apache/asgi.py rename to cof/asgi.py index eb18c7b2..bb1b3b83 100644 --- a/apache/asgi.py +++ b/cof/asgi.py @@ -1,6 +1,6 @@ import os from channels.asgi import get_channel_layer -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings_dev") channel_layer = get_channel_layer() diff --git a/cof/settings_dev.py b/cof/settings_dev.py index c63437a5..f9adb2cf 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -29,7 +29,7 @@ SECRET_KEY = 'q()(zn4m63i%5cp4)f+ww4-28_w+ly3q9=6imw2ciu&_(5_4ah' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ['127.0.0.1'] # Application definition @@ -123,6 +123,7 @@ USE_TZ = True # https://docs.djangoproject.com/en/1.8/howto/static-files/ STATIC_URL = '/static/' +STATIC_ROOT = '/var/www/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static/'), @@ -175,7 +176,7 @@ CHANNEL_LAYERS = { "default": { "BACKEND": "asgi_redis.RedisChannelLayer", "CONFIG": { - "hosts": [("redis://:redis_password@127.0.0.1:6379/0")], + "hosts": [("localhost", 6379)], }, "ROUTING": "cof.routing.channel_routing", } diff --git a/provisioning/apache.conf b/provisioning/apache.conf new file mode 100644 index 00000000..6bc1cd28 --- /dev/null +++ b/provisioning/apache.conf @@ -0,0 +1,29 @@ + + ServerName default + DocumentRoot /var/www/html + + ProxyPreserveHost On + ProxyRequests Off + ProxyPass /static/ ! + ProxyPass /media/ ! + ProxyPass /ws/ ws://127.0.0.1:8000/ws/ + ProxyPass / http://127.0.0.1:8000/ + ProxyPassReverse / http://127.0.0.1:8000/ + + Alias /media /vagrant/media + Alias /static /var/www/static + + Order deny,allow + Allow from all + + + Order deny,allow + Allow from all + + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index b6df6caa..d3d0f4cb 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -9,7 +9,7 @@ DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" # Installation de paquets utiles apt-get update && apt-get install -y mercurial python-pip python-dev \ - libmysqlclient-dev libjpeg-dev git + libmysqlclient-dev libjpeg-dev git redis-server # Configuration et installation de mysql. Le mot de passe root est le même que # le mot de passe pour l'utilisateur local - pour rappel, ceci est une instance @@ -21,9 +21,15 @@ apt-get install -y mysql-server mysql -uroot -p$DBPASSWD -e "CREATE DATABASE $DBNAME; GRANT ALL PRIVILEGES ON $DBNAME.* TO '$DBUSER'@'localhost' IDENTIFIED BY '$DBPASSWD'" -# Installation de redis-server. Todo: lui mettre un mot de passe -apt-get install -y redis-server -redis-cli config set requirepass redis_password +# Installation et configuration d'Apache +apt-get install -y apache2 +a2enmod proxy proxy_http +cp /vagrant/provisioning/apache.conf /etc/apache2/sites-available/gestiocof.conf +a2ensite gestiocof +a2dissite 000-default +service apache2 restart +mkdir /var/www/static +chown -R vagrant:www-data /var/www/static # Mise en place du .bash_profile pour tout configurer lors du `vagrant ssh` cat > ~vagrant/.bash_profile < Date: Mon, 12 Sep 2016 17:04:50 +0200 Subject: [PATCH 18/41] Correction de port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le port 8000 est réservé au serveur de dev --- provisioning/apache.conf | 6 +++--- provisioning/supervisor.conf | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/provisioning/apache.conf b/provisioning/apache.conf index 6bc1cd28..001c6ec9 100644 --- a/provisioning/apache.conf +++ b/provisioning/apache.conf @@ -6,9 +6,9 @@ ProxyRequests Off ProxyPass /static/ ! ProxyPass /media/ ! - ProxyPass /ws/ ws://127.0.0.1:8000/ws/ - ProxyPass / http://127.0.0.1:8000/ - ProxyPassReverse / http://127.0.0.1:8000/ + ProxyPass /ws/ ws://127.0.0.1:8001/ws/ + ProxyPass / http://127.0.0.1:8001/ + ProxyPassReverse / http://127.0.0.1:8001/ Alias /media /vagrant/media Alias /static /var/www/static diff --git a/provisioning/supervisor.conf b/provisioning/supervisor.conf index 814b8c35..487defe3 100644 --- a/provisioning/supervisor.conf +++ b/provisioning/supervisor.conf @@ -10,7 +10,7 @@ stopasgroup=true redirect_stderr=true [program:interface] -command=/usr/local/bin/daphne -b 127.0.0.1 -p 8000 cof.asgi:channel_layer +command=/usr/local/bin/daphne -b 127.0.0.1 -p 8001 cof.asgi:channel_layer environment=DBUSER="cof_gestion",DBNAME="cof_gestion",DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" directory=/vagrant/ redirect_stderr=true From 14733c07a0b4356f15380e5e6df60c5a60586b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 12 Sep 2016 19:33:39 +0200 Subject: [PATCH 19/41] Petits changements Clarification du README Utilisation de sed pour construire les fichiers de config --- README.md | 10 +++------- provisioning/bootstrap.sh | 3 +++ provisioning/supervisor.conf | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 80d87e87..db2cc93b 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,9 @@ gérer la machine virtuelle : - `vagrant ssh` vous connecte en SSH à la machine virtuelle, dans le dossier où est installé GestioCOF. Vous pouvez utiliser les commandes Django - habituelles (`manage.py runserver` etc.) + habituelles (`manage.py runserver` etc.) pour lancer + [le serveur en dev](#lancer-le-serveur-de-développement-standard) par + exemple **Le dossier avec le code de GestioCOF est partagé entre la machine virtuelle et votre machine physique : vous pouvez donc utiliser votre éditeur favori pour @@ -108,12 +110,6 @@ Vous pouvez maintenant installer les dépendances Python depuis les fichiers Copiez le fichier `cof/settings_dev.py` dans `cof/settings.py`. -Enfin, configurez le mot de passe redis le plus simple et de ne pas en utiliser -(pas de risque en local) en remplaçant la ligne `hosts` dans -`settings.CHANNEL_LAYER` par - - "hosts": [("localhost", 6379)] - #### Installation avec MySQL Il faut maintenant installer MySQL. Si vous n'avez pas déjà MySQL installé sur diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index d3d0f4cb..f072e6fc 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -65,4 +65,7 @@ sudo -H -u vagrant crontab provisioning/cron.dev pip install daphne apt-get install -y supervisor cp /vagrant/provisioning/supervisor.conf /etc/supervisor/conf.d/gestiocof.conf +sed "s/{DBUSER}/$DBUSER/" -i /etc/supervisor/conf.d/gestiocof.conf +sed "s/{DBNAME}/$DBNAME/" -i /etc/supervisor/conf.d/gestiocof.conf +sed "s/{DBPASSWD}/$DBPASSWD/" -i /etc/supervisor/conf.d/gestiocof.conf service supervisor restart diff --git a/provisioning/supervisor.conf b/provisioning/supervisor.conf index 487defe3..4c46b952 100644 --- a/provisioning/supervisor.conf +++ b/provisioning/supervisor.conf @@ -2,7 +2,7 @@ command=/usr/bin/python /vagrant/manage.py runworker directory=/vagrant/ user=vagrant -environment=DBUSER="cof_gestion",DBNAME="cof_gestion",DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4",DJANGO_SETTINGS_MODULE="cof.settings_dev" +environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" autostart=true autorestart=true redirect_stderr=true @@ -11,7 +11,7 @@ redirect_stderr=true [program:interface] command=/usr/local/bin/daphne -b 127.0.0.1 -p 8001 cof.asgi:channel_layer -environment=DBUSER="cof_gestion",DBNAME="cof_gestion",DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" +environment=DBUSER={DBUSER},DBNAME={DBNAME},DBPASSWD={DBPASSWD},DJANGO_SETTINGS_MODULE="cof.settings_dev" directory=/vagrant/ redirect_stderr=true autostart=true From c79456e95803f3fe53fde125cc8a275b0fe2bf8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 12 Sep 2016 23:24:18 +0200 Subject: [PATCH 20/41] Syntaxe py3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `except e1, e2:` n'est pas valide en python3, il faut des parenthèses. --- kfet/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kfet/views.py b/kfet/views.py index a08be40b..98c4760a 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -803,7 +803,7 @@ def kpsul(request): is_protected=False, valid_from__lte=timezone.now(), valid_to__gte=timezone.now()).get() initial['checkout'] = checkout - except Checkout.DoesNotExist, Checkout.MultipleObjectsReturned: + except (Checkout.DoesNotExist, Checkout.MultipleObjectsReturned): pass data['checkout_form'] = KPsulCheckoutForm(initial=initial) operation_formset = KPsulOperationFormSet(queryset=Operation.objects.none()) From 2bae32a10558d761f1c1e5ff291441d4942a9a86 Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Wed, 14 Sep 2016 16:22:30 +0200 Subject: [PATCH 21/41] Ajouts et corrections --- bda/templates/descriptions.html | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bda/templates/descriptions.html b/bda/templates/descriptions.html index a993848a..a229757b 100644 --- a/bda/templates/descriptions.html +++ b/bda/templates/descriptions.html @@ -3,6 +3,7 @@ + @@ -75,7 +79,7 @@ From ac3c79daca1937ec4cc642d3763bf952f8023d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Thu, 22 Sep 2016 14:01:01 +0200 Subject: [PATCH 24/41] Fix petits cours --- gestioncof/petits_cours_views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gestioncof/petits_cours_views.py b/gestioncof/petits_cours_views.py index b7b9cd36..1a31115d 100644 --- a/gestioncof/petits_cours_views.py +++ b/gestioncof/petits_cours_views.py @@ -135,7 +135,7 @@ def _finalize_traitement(request, demande, proposals, proposed_for, unsatisfied, attribdata, redo=False, errors=None): proposals = proposals.items() proposed_for = proposed_for.items() - # attribdata = attribdata.items() + attribdata = list(attribdata.items()) proposed_mails = _generate_eleve_email(demande, proposed_for) mainmail = render_template("petits-cours-mail-demandeur.txt", {"proposals": proposals, @@ -153,7 +153,8 @@ def _finalize_traitement(request, demande, proposals, proposed_for, "proposed_mails": proposed_mails, "mainmail": mainmail, "attribdata": - base64.b64encode(simplejson.dumps(attribdata).encode('utf_8')), + base64.b64encode(simplejson.dumps(attribdata) + .encode('utf_8')), "redo": redo, "errors": errors, }) From 0b618fa0452389ff1fc56f9a0e4170531826cf8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Thu, 22 Sep 2016 17:59:51 +0200 Subject: [PATCH 25/41] =?UTF-8?q?K-Psul=20-=20S=C3=A9lection=20des=20artic?= =?UTF-8?q?les?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout de la sélection au clic (souris/tactile) --- kfet/static/kfet/css/kpsul.css | 5 +++++ kfet/templates/kfet/kpsul.html | 29 +++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/kfet/static/kfet/css/kpsul.css b/kfet/static/kfet/css/kpsul.css index b15f6de8..9fd53604 100644 --- a/kfet/static/kfet/css/kpsul.css +++ b/kfet/static/kfet/css/kpsul.css @@ -319,6 +319,11 @@ input[type=number]::-webkit-outer-spin-button { padding-left:20px; } +#articles_data .article:hover { + background:rgba(200,16,46,0.3); + cursor:pointer; +} + /* Second part - Left - bottom */ .kpsul_middle_left_bottom { diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index d4a1b1b8..2278a6f7 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -685,6 +685,12 @@ $(document).ready(function() { return false; } + // A utiliser après la sélection d'un article + function goToArticleNb() { + articleNb.val('1'); + articleNb.focus().select(); + } + articleSelect.on('keydown', function(e) { var text = articleSelect.val(); // Comportement normal pour ces touches @@ -699,13 +705,28 @@ $(document).ready(function() { } return true; } - if (updateMatchedArticles(text+e.key)) { - articleNb.val('1'); - articleNb.focus().select(); - } + if (updateMatchedArticles(text+e.key)) + goToArticleNb(); return false; }); + function getArticleId($article) { + return $article.attr('id').split('-')[2]; + } + + function getArticleName($article) { + return $article.find('.name').text(); + } + + // Sélection des articles à la souris/tactile + articles_container.on('click', '.article', function() { + console.log('1'); + articleId.val(getArticleId($(this))); + articleSelect.val(getArticleName($(this))); + displayMatchedArticles(articlesList); + goToArticleNb(); + }); + function is_nb_ok(nb) { return /^[0-9]+$/.test(nb) && nb > 0 && nb <= 24; } From 1553b9d9ffd3767383464084bed6acb562d2cffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Thu, 22 Sep 2016 21:06:04 +0200 Subject: [PATCH 26/41] =?UTF-8?q?Fix=20affichage=20balance=20r=C3=A9elle?= =?UTF-8?q?=20gestion=20n=C3=A9gatifs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kfet/templates/kfet/account_negative.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kfet/templates/kfet/account_negative.html b/kfet/templates/kfet/account_negative.html index 77fdf118..5f77b8f0 100644 --- a/kfet/templates/kfet/account_negative.html +++ b/kfet/templates/kfet/account_negative.html @@ -59,7 +59,7 @@ {{ neg.account.name }} {{ neg.account.balance|floatformat:2 }}€ - {% if neg.account.balance_offset %} + {% if neg.balance_offset %} {{ neg.account.real_balance|floatformat:2 }}€ {% endif %} From 4e2ae1cb5450e5cd2e58b2c84234d9bd7bc153d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Fri, 23 Sep 2016 01:44:36 +0200 Subject: [PATCH 27/41] =?UTF-8?q?Fix=20(th=C3=A9orique)=20autocompl=C3=A9t?= =?UTF-8?q?ion=20sur=20mobile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit D'après https://groups.google.com/a/chromium.org/d/msg/chromium-bugs/08KdqaHAhsY/DD8uqKDz01AJ --- kfet/templates/kfet/kpsul.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 2278a6f7..ca401ccb 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -120,7 +120,7 @@
    - +
    @@ -720,7 +720,6 @@ $(document).ready(function() { // Sélection des articles à la souris/tactile articles_container.on('click', '.article', function() { - console.log('1'); articleId.val(getArticleId($(this))); articleSelect.val(getArticleName($(this))); displayMatchedArticles(articlesList); From 1ce16f48f6f8a60116c21c5f5a45010898a49a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sat, 24 Sep 2016 14:18:26 +0200 Subject: [PATCH 28/41] Annulation transferts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Possibilité d'annuler un (ou plusieurs) transferts depuis la page "Transferts" --- kfet/templates/kfet/transfers.html | 102 ++++++++++++++++++++++++++++- kfet/urls.py | 2 + kfet/views.py | 99 ++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+), 2 deletions(-) diff --git a/kfet/templates/kfet/transfers.html b/kfet/templates/kfet/transfers.html index 1875a21e..cbdf0fe3 100644 --- a/kfet/templates/kfet/transfers.html +++ b/kfet/templates/kfet/transfers.html @@ -1,4 +1,13 @@ {% extends 'kfet/base.html' %} +{% load staticfiles %} + +{% block extra_head %} + + + + + +{% endblock %} {% block title %}Transferts{% endblock %} {% block content-header-title %}Transferts{% endblock %} @@ -24,13 +33,13 @@

    Liste des transferts

    {% for transfergroup in transfergroups %} -
    +
    {{ transfergroup.at }} {{ transfergroup.valid_by.trigramme }} {{ transfergroup.comment }}
    {% for transfer in transfergroup.transfers.all %} -
    +
    {{ transfer.amount }} € {{ transfer.from_acc.trigramme }} @@ -44,4 +53,93 @@
    + + {% endblock %} diff --git a/kfet/urls.py b/kfet/urls.py index e0bacf9a..9b9ebf21 100644 --- a/kfet/urls.py +++ b/kfet/urls.py @@ -170,6 +170,8 @@ urlpatterns = [ name = 'kfet.transfers.create'), url(r'^transfers/perform$', views.perform_transfers, name = 'kfet.transfers.perform'), + url(r'^transfers/cancel$', views.cancel_transfers, + name = 'kfet.transfers.cancel'), # ----- # Inventories urls diff --git a/kfet/views.py b/kfet/views.py index 98c4760a..4b115942 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -1477,6 +1477,105 @@ def perform_transfers(request): return JsonResponse(data) +@teamkfet_required +def cancel_transfers(request): + # Pour la réponse + data = { 'canceled': [], 'warnings': {}, 'errors': {}} + + # Checking if BAD REQUEST (transfers_pk not int or not existing) + try: + # Set pour virer les doublons + transfers_post = set(map(int, filter(None, request.POST.getlist('transfers[]', [])))) + except ValueError: + return JsonResponse(data, status=400) + transfers_all = ( + Transfer.objects + .select_related('group', 'from_acc', 'from_acc__negative', + 'to_acc', 'to_acc__negative') + .filter(pk__in=transfers_post)) + transfers_pk = [ transfer.pk for transfer in transfers_all ] + transfers_notexisting = [ transfer for transfer in transfers_post + if transfer not in transfers_pk ] + if transfers_notexisting: + data['errors']['transfers_notexisting'] = transfers_notexisting + return JsonResponse(data, status=400) + + transfers_already_canceled = [] # Déjà annulée + transfers = [] # Pas déjà annulée + required_perms = set() + stop_all = False + cancel_duration = Settings.CANCEL_DURATION() + to_accounts_balances = defaultdict(lambda:0) # Modifs à faire sur les balances des comptes + for transfer in transfers_all: + if transfer.canceled_at: + # Transfert déjà annulé, va pour un warning en Response + transfers_already_canceled.append(transfer.pk) + else: + transfers.append(transfer.pk) + # Si transfer il y a plus de CANCEL_DURATION, permission requise + if transfer.group.at + cancel_duration < timezone.now(): + required_perms.add('kfet.cancel_old_operations') + + # Calcul de toutes modifs à faire en cas de validation + + # Pour les balances de comptes + to_accounts_balances[transfer.from_acc] += transfer.amount + to_accounts_balances[transfer.to_acc] += -transfer.amount + + if not transfers: + data['warnings']['already_canceled'] = transfers_already_canceled + return JsonResponse(data) + + negative_accounts = [] + # Checking permissions or stop + for account in to_accounts_balances: + (perms, stop) = account.perms_to_perform_operation( + amount = to_accounts_balances[account]) + required_perms |= perms + stop_all = stop_all or stop + if stop: + negative_accounts.append(account.trigramme) + + print(required_perms) + print(request.user.get_all_permissions()) + + if stop_all or not request.user.has_perms(required_perms): + missing_perms = get_missing_perms(required_perms, request.user) + if missing_perms: + data['errors']['missing_perms'] = missing_perms + if stop_all: + data['errors']['negative'] = negative_accounts + return JsonResponse(data, status=403) + + canceled_by = required_perms and request.user.profile.account_kfet or None + canceled_at = timezone.now() + + with transaction.atomic(): + (Transfer.objects.filter(pk__in=transfers) + .update(canceled_by=canceled_by, canceled_at=canceled_at)) + + for account in to_accounts_balances: + Account.objects.filter(pk=account.pk).update( + balance = F('balance') + to_accounts_balances[account]) + account.refresh_from_db() + if account.balance < 0: + if hasattr(account, 'negative'): + if not account.negative.start: + account.negative.start = timezone.now() + account.negative.save() + else: + negative = AccountNegative( + account = account, start = timezone.now()) + negative.save() + elif (hasattr(account, 'negative') + and not account.negative.balance_offset): + account.negative.delete() + + data['canceled'] = transfers + if transfers_already_canceled: + data['warnings']['already_canceled'] = transfers_already_canceled + return JsonResponse(data) + class InventoryList(ListView): queryset = (Inventory.objects .select_related('by', 'order') From d89493856f5457e424349a68de39bf71c760d807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 24 Sep 2016 17:34:15 +0200 Subject: [PATCH 29/41] Fix: inscriptions bda MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problèmes d'encodage sur la fonction `_hash_queryset` --- bda/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/views.py b/bda/views.py index 4ea0df32..4cf3dd03 100644 --- a/bda/views.py +++ b/bda/views.py @@ -66,7 +66,7 @@ def etat_places(request, tirage_id): def _hash_queryset(queryset): - data = serializers.serialize("json", queryset).encode() + data = serializers.serialize("json", queryset).encode('utf-8') hasher = hashlib.sha256() hasher.update(data) return hasher.hexdigest() From 3ead35e171a13a407e774debba6d21b4683758fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sat, 24 Sep 2016 18:27:40 +0200 Subject: [PATCH 30/41] clean --- kfet/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/kfet/views.py b/kfet/views.py index 98c4760a..f64e209c 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -220,7 +220,6 @@ def get_account_create_forms(request=None, username=None, login_clipper=None): user = None clipper = None if login_clipper and (login_clipper == username or not username): - print('trololo') # à partir d'un clipper # le user associé à ce clipper ne devrait pas encore exister clipper = get_object_or_404(Clipper, username = login_clipper) From 7f8c825c2a2fb9ee527476515b6044d1bec1deaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sat, 24 Sep 2016 18:44:01 +0200 Subject: [PATCH 31/41] Pour la prod! --- kfet/routing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kfet/routing.py b/kfet/routing.py index e7bcca55..9c816c92 100644 --- a/kfet/routing.py +++ b/kfet/routing.py @@ -8,7 +8,7 @@ from channels.routing import route, route_class from kfet import consumers channel_routing = [ - route_class(consumers.KPsul, path=r"^/ws/k-fet/k-psul/$"), + route_class(consumers.KPsul, path=r"^/gestion/ws/k-fet/k-psul/$"), #route("websocket.connect", ws_kpsul_history_connect), #route('websocket.receive', ws_message) ] From 05e48386a1f53ea10bf088af54f8a24d793f30e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 24 Sep 2016 18:44:35 +0200 Subject: [PATCH 32/41] Ajustements, fix --- gestioncof/views.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gestioncof/views.py b/gestioncof/views.py index 3148308a..80f528f7 100644 --- a/gestioncof/views.py +++ b/gestioncof/views.py @@ -346,7 +346,7 @@ def registration_form2(request, login_clipper=None, username=None): registration_set_ro_fields(user_form, profile_form) # events & clubs event_formset = EventFormset(events=events, prefix='events') - clubs_form = ClubsForm(initial={'clubs': member.clubs.all()}) + clubs_form = ClubsForm() if username: member = get_object_or_404(User, username=username) (profile, _) = CofProfile.objects.get_or_create(user=member) diff --git a/requirements.txt b/requirements.txt index d7cada42..2d1109eb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ configparser==3.5.0 Django==1.8 django-autocomplete-light==2.3.3 django-autoslug==1.9.3 -django-cas-ng==3.5.4 +git+https://github.com/xapantu/django-cas-ng.git#egg=django-cas-ng django-grappelli==2.8.1 django-recaptcha==1.0.5 mysqlclient==1.3.7 From 59dcb72542f2b26ef9a20f2b0875af787521e035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sat, 24 Sep 2016 18:49:40 +0200 Subject: [PATCH 33/41] K-Psul - Fix erreur 500 caisse inexistante --- kfet/views.py | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/kfet/views.py b/kfet/views.py index f64e209c..a0719a80 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -835,28 +835,27 @@ def kpsul_checkout_data(request): pk = request.POST.get('pk', 0) if not pk: pk = 0 - try: - data = (Checkout.objects - .annotate( - last_statement_by_first_name=F('statements__by__cofprofile__user__first_name'), - last_statement_by_last_name=F('statements__by__cofprofile__user__last_name'), - last_statement_by_trigramme=F('statements__by__trigramme'), - last_statement_balance=F('statements__balance_new'), - last_statement_at=F('statements__at')) - .values( - 'id', 'name', 'balance', 'valid_from', 'valid_to', - 'last_statement_balance', 'last_statement_at', - 'last_statement_by_trigramme', 'last_statement_by_last_name', - 'last_statement_by_first_name') - .select_related( - 'statements' - 'statements__by', - 'statements__by__cofprofile__user') - .filter(pk=pk) - .order_by('statements__at') - .last()) - except Checkout.DoesNotExist: - raise http404 + data = (Checkout.objects + .annotate( + last_statement_by_first_name=F('statements__by__cofprofile__user__first_name'), + last_statement_by_last_name=F('statements__by__cofprofile__user__last_name'), + last_statement_by_trigramme=F('statements__by__trigramme'), + last_statement_balance=F('statements__balance_new'), + last_statement_at=F('statements__at')) + .values( + 'id', 'name', 'balance', 'valid_from', 'valid_to', + 'last_statement_balance', 'last_statement_at', + 'last_statement_by_trigramme', 'last_statement_by_last_name', + 'last_statement_by_first_name') + .select_related( + 'statements' + 'statements__by', + 'statements__by__cofprofile__user') + .filter(pk=pk) + .order_by('statements__at') + .last()) + if data is None: + raise Http404 return JsonResponse(data) @teamkfet_required From 38bb59b004c51298386e554b908718d1f97c880b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Mon, 12 Sep 2016 22:08:39 +0200 Subject: [PATCH 34/41] =?UTF-8?q?Permet=20l'ajout=20d'un=20pr=C3=A9fixe=20?= =?UTF-8?q?dans=20les=20urls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cof/urls.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cof/urls.py b/cof/urls.py index ca7ea247..263fc3a0 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -24,7 +24,7 @@ from gestioncof.autocomplete import autocomplete autocomplete_light.autodiscover() admin.autodiscover() -urlpatterns = [ +my_urlpatterns = [ # Page d'accueil url(r'^$', gestioncof_views.home, name='home'), # Le BdA @@ -88,3 +88,7 @@ urlpatterns = [ else []) # Si on est en production, MEDIA_ROOT est servi par Apache. # Il faut dire à Django de servir MEDIA_ROOT lui-même en développement. + +urlpatterns = [ + url(r'^gestion/', include(my_urlpatterns)) +] From efd92e996766df717c260e4891022a58510ef89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sat, 24 Sep 2016 19:31:50 +0200 Subject: [PATCH 35/41] Fix protection autocomplete --- kfet/autocomplete.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kfet/autocomplete.py b/kfet/autocomplete.py index e4203bd1..2a24a51e 100644 --- a/kfet/autocomplete.py +++ b/kfet/autocomplete.py @@ -8,8 +8,10 @@ from django.shortcuts import render from django.http import Http404 from django.db.models import Q from gestioncof.models import User, Clipper +from kfet.decorators import teamkfet_required from kfet.models import Account +@teamkfet_required def account_create(request): if "q" not in request.GET: raise Http404 From 54409fb85f458c9220554c51305a99c9521a712e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 24 Sep 2016 19:34:36 +0200 Subject: [PATCH 36/41] Modif pour la production --- apache/__init__.py | 0 apache/django.wsgi | 7 ------- apache/wsgi.py | 18 ------------------ cof/asgi.py | 3 ++- 4 files changed, 2 insertions(+), 26 deletions(-) delete mode 100644 apache/__init__.py delete mode 100644 apache/django.wsgi delete mode 100644 apache/wsgi.py diff --git a/apache/__init__.py b/apache/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/apache/django.wsgi b/apache/django.wsgi deleted file mode 100644 index 7b9c271d..00000000 --- a/apache/django.wsgi +++ /dev/null @@ -1,7 +0,0 @@ -import os, sys -sys.path.append (os.path.expanduser ('~gestion/www')) -os.environ['DJANGO_SETTINGS_MODULE'] = 'cof.settings' - -import django.core.handlers.wsgi - -application = django.core.handlers.wsgi.WSGIHandler() diff --git a/apache/wsgi.py b/apache/wsgi.py deleted file mode 100644 index 177542a8..00000000 --- a/apache/wsgi.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -WSGI config for myproject project. -It exposes the WSGI callable as a module-level variable named ``application``. -For more information on this file, see -https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ -""" - -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -import os -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings") -application = get_wsgi_application() diff --git a/cof/asgi.py b/cof/asgi.py index bb1b3b83..a34621c7 100644 --- a/cof/asgi.py +++ b/cof/asgi.py @@ -1,6 +1,7 @@ import os from channels.asgi import get_channel_layer -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings_dev") +if "DJANGO_SETTINGS_MODULE" not in os.environ: + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings") channel_layer = get_channel_layer() From 68153652d03988fa07fa2dc88604a74106ff2dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 24 Sep 2016 19:40:16 +0200 Subject: [PATCH 37/41] Protection de la vue autocomplete --- gestioncof/autocomplete.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gestioncof/autocomplete.py b/gestioncof/autocomplete.py index 5b4616be..ed0a1e5a 100644 --- a/gestioncof/autocomplete.py +++ b/gestioncof/autocomplete.py @@ -10,8 +10,10 @@ from django.db.models import Q from django.contrib.auth.models import User from gestioncof.models import CofProfile, Clipper +from gestioncof.decorators import buro_required +@buro_required def autocomplete(request): if "q" not in request.GET: raise Http404 From 3bf4e6ae06caf9a352f0d0dfd99d4539fff22f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 24 Sep 2016 19:34:36 +0200 Subject: [PATCH 38/41] Modif pour la production MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Suppression du dossier `apache` devenu inutile. - On utilise `cof.settings` dans le fichier `asgi.py` par défaut - Correction dans les urls du fichier de settings en lien avec les nouvelles urls en `/gestion/...` --- apache/__init__.py | 0 apache/django.wsgi | 7 ------- apache/wsgi.py | 18 ------------------ cof/asgi.py | 3 ++- cof/settings_dev.py | 6 +++--- 5 files changed, 5 insertions(+), 29 deletions(-) delete mode 100644 apache/__init__.py delete mode 100644 apache/django.wsgi delete mode 100644 apache/wsgi.py diff --git a/apache/__init__.py b/apache/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/apache/django.wsgi b/apache/django.wsgi deleted file mode 100644 index 7b9c271d..00000000 --- a/apache/django.wsgi +++ /dev/null @@ -1,7 +0,0 @@ -import os, sys -sys.path.append (os.path.expanduser ('~gestion/www')) -os.environ['DJANGO_SETTINGS_MODULE'] = 'cof.settings' - -import django.core.handlers.wsgi - -application = django.core.handlers.wsgi.WSGIHandler() diff --git a/apache/wsgi.py b/apache/wsgi.py deleted file mode 100644 index 177542a8..00000000 --- a/apache/wsgi.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -WSGI config for myproject project. -It exposes the WSGI callable as a module-level variable named ``application``. -For more information on this file, see -https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ -""" - -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - -import os -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings") -application = get_wsgi_application() diff --git a/cof/asgi.py b/cof/asgi.py index bb1b3b83..a34621c7 100644 --- a/cof/asgi.py +++ b/cof/asgi.py @@ -1,6 +1,7 @@ import os from channels.asgi import get_channel_layer -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings_dev") +if "DJANGO_SETTINGS_MODULE" not in os.environ: + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cof.settings") channel_layer = get_channel_layer() diff --git a/cof/settings_dev.py b/cof/settings_dev.py index f9adb2cf..38d36390 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -152,12 +152,12 @@ PETITS_COURS_REPLYTO = "cof@ens.fr" RAPPEL_FROM = 'Le BdA ' RAPPEL_REPLY_TO = RAPPEL_FROM -LOGIN_URL = "/login" -LOGIN_REDIRECT_URL = "/" +LOGIN_URL = "/gestion/login" +LOGIN_REDIRECT_URL = "/gestion/" CAS_SERVER_URL = 'https://cas.eleves.ens.fr/' CAS_IGNORE_REFERER = True -CAS_REDIRECT_URL = '/' +CAS_REDIRECT_URL = '/gestion/' CAS_EMAIL_FORMAT = "%s@clipper.ens.fr" AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', From 5d05b220fd865d0bad483c2ae7ca5bca5bebf3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?= Date: Sun, 25 Sep 2016 23:35:29 +0200 Subject: [PATCH 39/41] Fix touche H sur K-Psul --- kfet/templates/kfet/kpsul.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index ca401ccb..0eceebd2 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -1240,9 +1240,10 @@ $(document).ready(function() { case 72: if (e.ctrlKey) { // Ctrl+H - Display help + e.preventDefault(); $('.help').show('fast'); } - return false; + return true; case 112: // F1 - Cool reset coolReset(); From 15e755334dde6a1ca56ee70ea1af1fba2d480c56 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 26 Sep 2016 15:31:09 +0200 Subject: [PATCH 40/41] cron --- bda/management/commands/manage_reventes.py | 4 ++++ provisioning/cron.dev | 1 + provisioning/cron.md | 11 +++++++++++ 3 files changed, 16 insertions(+) diff --git a/bda/management/commands/manage_reventes.py b/bda/management/commands/manage_reventes.py index 9fea3f6a..f45357b1 100644 --- a/bda/management/commands/manage_reventes.py +++ b/bda/management/commands/manage_reventes.py @@ -14,6 +14,7 @@ class Command(BaseCommand): def handle(self, *args, **options): now = timezone.now() + self.stdout.write(now) reventes = SpectacleRevente.objects.all() for revente in reventes: # Check si < 24h @@ -22,11 +23,14 @@ class Command(BaseCommand): now >= revente.date + timedelta(minutes=15) and \ not revente.notif_sent: revente.mail_shotgun() + self.stdout.write("Mail de disponibilité immédiate envoyé") # Check si délai de retrait dépassé elif (now >= revente.date + timedelta(hours=1) and not revente.notif_sent): revente.send_notif() + self.stdout.write("Mail d'inscription à une revente envoyé") # Check si tirage à faire elif (now >= revente.expiration_time and not revente.tirage_done): revente.tirage() + self.stdout.write("Tirage effectué, mails envoyés") diff --git a/provisioning/cron.dev b/provisioning/cron.dev index d249d547..6cd2ca81 100644 --- a/provisioning/cron.dev +++ b/provisioning/cron.dev @@ -7,3 +7,4 @@ DBNAME="cof_gestion" DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" 19 */12 * * * date >> /vagrant/rappels.log ; python /vagrant/manage.py sendrappels >> /vagrant/rappels.log 2>&1 +*/5 * * * * python /vagrant/manage.py manage_revente >> /vagrant/reventes.log 2>&1 diff --git a/provisioning/cron.md b/provisioning/cron.md index 8b3f608e..840a8716 100644 --- a/provisioning/cron.md +++ b/provisioning/cron.md @@ -14,3 +14,14 @@ envoyés). - Garde les logs peut être une bonne idée. Exemple : voir le fichier `provisioning/cron.dev`. + +## Gestion des mails de revente + +Il faut effectuer très régulièrement la commande `manage_reventes` de GestioCOF, +qui gère toutes les actions associées à BdA-Revente : envoi des mails de notification, +tirages. + +- Pour l'instant un délai de 5 min est hardcodé +- Garde des logs ; ils vont finir par être assez lourds si on a beaucoup de reventes. + +Exemple : provisioning/cron.dev From 59b8f406b652ffb1ddd9a20a726d3e5461264cf7 Mon Sep 17 00:00:00 2001 From: Ludovic Stephan Date: Mon, 26 Sep 2016 15:53:58 +0200 Subject: [PATCH 41/41] fix bug shotgun --- bda/views.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bda/views.py b/bda/views.py index bac7415d..12c57d49 100644 --- a/bda/views.py +++ b/bda/views.py @@ -406,7 +406,7 @@ def list_revente(request, tirage_id): if qset.exists(): # On l'inscrit à l'un des tirages au sort for revente in qset.all(): - if revente.shotgun: + if revente.shotgun and not revente.soldTo: deja_revente = True else: revente.interested.add(participant) @@ -435,12 +435,16 @@ def buy_revente(request, spectacle_id): revente.delete() return HttpResponseRedirect(reverse("bda-liste-revente", args=[tirage.id])) + reventes_shotgun = [] + for revente in reventes.all(): + if revente.shotgun: + reventes_shotgun.append(revente) - if not reventes.exists(): + if reventes_shotgun.empty(): return render(request, "bda-no-revente.html", {}) if request.POST: - revente = random.choice(reventes.all()) + revente = random.choice(reventes_shotgun) revente.soldTo = participant revente.save() mail = """Bonjour !