Page Historique

- Reprise du JS d'historique dans `kfet/static/kfet/js/history.js`
- Adapatation de K-Psul pour l'utiliser
- Création page historique avec filtres (dates, caisses, comptes)
This commit is contained in:
Aurélien Delobelle 2016-08-24 19:52:07 +02:00
parent b380984a1e
commit 3b7c690f0b
9 changed files with 328 additions and 153 deletions

View file

@ -3,7 +3,6 @@ from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.contrib.auth.models import User, Group, Permission from django.contrib.auth.models import User, Group, Permission
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.forms import modelformset_factory from django.forms import modelformset_factory
from django.utils import timezone from django.utils import timezone
from kfet.models import (Account, Checkout, Article, OperationGroup, Operation, from kfet.models import (Account, Checkout, Article, OperationGroup, Operation,
@ -343,3 +342,7 @@ class SettingsForm(forms.ModelForm):
self.cleaned_data['value_account'] = None self.cleaned_data['value_account'] = None
cache.delete(name) cache.delete(name)
super(SettingsForm, self).clean() super(SettingsForm, self).clean()
class FilterHistoryForm(forms.Form):
checkouts = forms.ModelMultipleChoiceField(queryset = Checkout.objects.all())
accounts = forms.ModelMultipleChoiceField(queryset = Account.objects.all())

View file

@ -0,0 +1,108 @@
function KHistory(options={}) {
$.extend(this, KHistory.default_options, options);
this.$container = $(this.container);
this.reset = function() {
this.$container.html('');
};
this.addOpeGroup = function(opegroup) {
var $day = this._getOrCreateDay(opegroup['at']);
var $opegroup = this._opeGroupHtml(opegroup);
$day.after($opegroup);
var trigramme = opegroup['on_acc_trigramme'];
var is_cof = opegroup['is_cof'];
for (var i=0; i<opegroup['opes'].length; i++) {
var $ope = this._opeHtml(opegroup['opes'][i], is_cof, trigramme);
$ope.data('opegroup', opegroup['id']);
$opegroup.after($ope);
}
}
this._opeHtml = function(ope, is_cof, trigramme) {
var $ope_html = $(this.template_ope);
var parsed_amount = parseFloat(ope['amount']);
var amount = amountDisplay(parsed_amount, is_cof, trigramme);
var infos1 = '', infos2 = '';
if (ope['type'] == 'purchase') {
infos1 = ope['article_nb'];
infos2 = ope['article__name'];
} else {
infos1 = parsed_amount.toFixed(2)+'€';
infos2 = (ope['type'] == 'deposit') ? 'Charge' : 'Retrait';
}
$ope_html
.data('ope', ope['id'])
.find('.amount').text(amount).end()
.find('.infos1').text(infos1).end()
.find('.infos2').text(infos2).end();
var addcost_for = ope['addcost_for__trigramme'];
if (addcost_for) {
var addcost_amount = parseFloat(ope['addcost_amount']);
$ope_html.find('.addcost').text('('+amountDisplay(addcost_amount, is_cof)+'UKF pour '+addcost_for+')');
}
if (ope['canceled_at']) {
var canceled_at = dateUTCToParis(ope['canceled_at']);
var canceled_by = ope['canceled_by__trigramme'];
var cancel = 'Annulé';
if (canceled_by)
cancel += ' par '+canceled_by;
cancel += ' le '+canceled_at.format('DD/MM/YY à HH:mm:ss');
$ope_html.addClass('canceled').find('.canceled').text(cancel);
}
return $ope_html;
}
this._opeGroupHtml = function(opegroup) {
var $opegroup_html = $(this.template_opegroup);
var at = dateUTCToParis(opegroup['at']).format('HH:mm:ss');
var trigramme = opegroup['on_acc__trigramme'];
var amount = amountDisplay(
parseFloat(opegroup['amount']), opegroup['is_cof'], trigramme);
var comment = opegroup['comment'] || '';
$opegroup_html
.data('opegroup', opegroup['id'])
.find('.time').text(at).end()
.find('.amount').text(amount).end()
.find('.comment').text(comment).end();
if (this.display_trigramme)
$opegroup_html.find('.trigramme').text(trigramme);
if (opegroup['valid_by__trigramme'])
$opegroup_html.find('.valid_by').text('Par '+opegroup['valid_by__trigramme']);
return $opegroup_html;
}
this._getOrCreateDay = function(date) {
var at = dateUTCToParis(date);
var at_ser = at.format('YYYY-MM-DD');
var $day = this.$container.find('.day').filter(function() {
return $(this).data('date') == at_ser
});
if ($day.length == 1)
return $day;
var $day = $(this.template_day).prependTo(this.$container);
return $day.data('date', at_ser).text(at.format('D MMMM'));
}
}
KHistory.default_options = {
container: '#history',
template_day: '<div class="day"></div>',
template_opegroup: '<div class="opegroup"><span class="time"></span><span class="trigramme"></span><span class="amount"></span><span class="valid_by"></span><span class="comment"></span></div>',
template_ope: '<div class="ope"><span class="amount"></span><span class="infos1"></span><span class="infos2"></span><span class="addcost"></span><span class="canceled"></span></div>',
display_trigramme: true,
}

View file

@ -8,4 +8,35 @@ $(document).ready(function() {
$('.col-content-right').removeClass('col-sm-offset-4 col-md-offset-3'); $('.col-content-right').removeClass('col-sm-offset-4 col-md-offset-3');
} }
}); });
// Retrieving csrf token
var csrftoken = Cookies.get('csrftoken');
// Appending csrf token to ajax post requests
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
}); });
function dateUTCToParis(date) {
return moment.tz(date, 'UTC').tz('Europe/Paris');
}
function amountDisplay(amount, is_cof=false, tri='') {
if (tri == 'LIQ')
return (- amount).toFixed(2) +'€';
return amountToUKF(amount, is_cof);
}
function amountToUKF(amount, is_cof=false) {
var coef_cof = is_cof ? 1 + settings['subvention_cof'] / 100 : 1;
return Math.round(amount * coef_cof * 10);
}

View file

@ -8,7 +8,7 @@
<div class="row"> <div class="row">
<div class="col-sm-4 col-md-3 col-content-left"> <div class="col-sm-4 col-md-3 col-content-left">
<div class="content-left"> <div class="content-left">
<div class="content-left-top text-center"> <div class="content-left-top">
<div class="line line-big">{{ accounts|length|add:-1 }}</div> <div class="line line-big">{{ accounts|length|add:-1 }}</div>
<div class="line line-bigsub">compte{{ accounts|length|add:-1|pluralize }}</div> <div class="line line-bigsub">compte{{ accounts|length|add:-1|pluralize }}</div>
</div> </div>

View file

@ -34,6 +34,7 @@
<li><a href="{% url 'kfet.account' %}">Comptes</a></li> <li><a href="{% url 'kfet.account' %}">Comptes</a></li>
<li><a href="{% url 'kfet.checkout' %}">Caisses</a></li> <li><a href="{% url 'kfet.checkout' %}">Caisses</a></li>
<li><a href="{% url 'kfet.article' %}">Articles</a></li> <li><a href="{% url 'kfet.article' %}">Articles</a></li>
<li><a href="{% url 'kfet.history' %}">Historique</a></li>
{% if user.username != 'kfet_genericteam' %} {% if user.username != 'kfet_genericteam' %}
<li><a href="{% url 'kfet.login.genericteam' %}" target="_blank" id="genericteam">Connexion standard</a></li> <li><a href="{% url 'kfet.login.genericteam' %}" target="_blank" id="genericteam">Connexion standard</a></li>
{% endif %} {% endif %}

View file

@ -0,0 +1,140 @@
{% extends 'kfet/base.html' %}
{% load staticfiles %}
{% load l10n %}
{% block extra_head %}
<link rel="stylesheet" type="text/css" href="{% static 'bootstrap-datetimepicker.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'kfet/css/multiple-select.css' %}">
<script type="text/javascript" src="{% static 'kfet/js/js.cookie.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/jquery-confirm.js' %}"></script>
<script type="text/javascript" src="{% static 'moment.js' %}"></script>
<script type="text/javascript" src="{% static 'moment-fr.js' %}"></script>
<script type="text/javascript" src="{% static 'moment-timezone-with-data-2010-2020.js' %}"></script>
<script type="text/javascript" src="{% static 'bootstrap-datetimepicker.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/multiple-select.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/kfet.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/history.js' %}"></script>
{% endblock %}
{% block title %}Historique{% endblock %}
{% block content-header-title %}Historique{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-4 col-md-3 col-content-left">
<div class="content-left">
<div class="content-left-top">
<div class="line line-big" id="nb_opes"></div>
<div class="line line-bigsub">opérations</div>
<div class="block">
<h2>Filtres</h2>
<div class="line" style="position:relative"><b>De</b> <input type="text" id="from_date"></div>
<div class="line" style="position:relative"><b>à</b> <input type="text" id="to_date"></div>
<div class="line"><b>Caisses</b> {{ filter_form.checkouts }}</div>
<div class="line"><b>Comtpes</b> {{ filter_form.accounts }}</div>
</div>
</div>
</div>
</div>
<div class="col-sm-8 col-md-9 col-content-right">
{% include 'kfet/base_messages.html' %}
<div class="content-right">
<div class="content-right-block">
<h2>Général</h2>
<div>
</div>
</div>
<div class="content-right-block">
<h2>Opérations</h2>
<table id="history">
</table>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
settings = { 'subvention_cof': parseFloat({{ settings.subvention_cof|unlocalize }})}
khistory = new KHistory();
var $from_date = $('#from_date');
var $to_date = $('#to_date');
var $checkouts = $('#id_checkouts');
var $accounts = $('#id_accounts');
function getSelectedMultiple($el) {
var selected = [];
$el.find(':selected').each(function() {
selected.push($(this).val())
});
return selected;
}
function getHistory() {
var data = {};
if ($from_date.val())
data['from'] = moment($from_date.val()).format('YYYY-MM-DD HH:mm:ss');
if ($to_date.val())
data['to'] = moment($to_date.val()).format('YYYY-MM-DD HH:mm:ss');
var checkouts = getSelectedMultiple($checkouts);
if ($checkouts)
data['checkouts'] = checkouts;
var accounts = getSelectedMultiple($accounts);
data['accounts'] = accounts;
$.ajax({
dataType: "json",
url : "{% url 'kfet.history.json' %}",
method : "POST",
data : data,
})
.done(function(data) {
for (var i=0; i<data['opegroups'].length; i++) {
khistory.addOpeGroup(data['opegroups'][i]);
}
var nb_opes = khistory.$container.find('.ope:not(.canceled)').length;
$('#nb_opes').text(nb_opes);
});
}
$('#from_date').datetimepicker({
timeZone : 'Europe/Paris',
format : 'YYYY-MM-DD HH:mm',
stepping : 5,
locale : 'fr',
defaultDate: moment().subtract(24, 'hours'),
showTodayButton: true,
});
$('#to_date').datetimepicker({
timeZone : 'Europe/Paris',
format : 'YYYY-MM-DD HH:mm',
stepping : 5,
defaultDate: moment(),
locale : 'fr',
showTodayButton: true,
});
$("#from_date").on("dp.change", function (e) {
$('#to_date').data("DateTimePicker").minDate(e.date);
});
$("#to_date").on("dp.change", function (e) {
$('#from_date').data("DateTimePicker").maxDate(e.date);
});
$("select").multipleSelect({
width: 200,
filter: true,
});
$("input").on('dp.change change', function() {
khistory.reset();
getHistory();
});
getHistory();
});
</script>
{% endblock %}

View file

@ -11,6 +11,8 @@
<script type="text/javascript" src="{% static 'moment.js' %}"></script> <script type="text/javascript" src="{% static 'moment.js' %}"></script>
<script type="text/javascript" src="{% static 'moment-fr.js' %}"></script> <script type="text/javascript" src="{% static 'moment-fr.js' %}"></script>
<script type="text/javascript" src="{% static 'moment-timezone-with-data-2010-2020.js' %}"></script> <script type="text/javascript" src="{% static 'moment-timezone-with-data-2010-2020.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/kfet.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/history.js' %}"></script>
{% endblock %} {% endblock %}
{% block title %}K-Psul{% endblock %} {% block title %}K-Psul{% endblock %}
@ -19,8 +21,6 @@
{% block content %} {% block content %}
{% csrf_token %}
<div class="row kpsul_top"> <div class="row kpsul_top">
<div class="col-sm-8"> <div class="col-sm-8">
<div class="row" id="account"> <div class="row" id="account">
@ -98,6 +98,9 @@
</div> </div>
</div> </div>
<div id="history2">
</div>
<form id="operationgroup_form" style="display:none;">{{ operationgroup_form }}</form> <form id="operationgroup_form" style="display:none;">{{ operationgroup_form }}</form>
<form id="operation_formset" style="display:none;">{{ operation_formset }}</form> <form id="operation_formset" style="display:none;">{{ operation_formset }}</form>
@ -111,29 +114,9 @@ $(document).ready(function() {
// General // General
// ----- // -----
// Retrieving csrf token
var csrftoken = Cookies.get('csrftoken');
// Appending csrf token to ajax post requests
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
function amountToUKF(amount, is_cof=false) {
var coef_cof = is_cof ? 1 + settings['subvention_cof'] / 100 : 1;
return Math.round(amount * coef_cof * 10);
}
// Retrieve settings // Retrieve settings
var settings = {} settings = {}
function resetSettings() { function resetSettings() {
$.ajax({ $.ajax({
@ -979,114 +962,12 @@ $(document).ready(function() {
// History // History
// ----- // -----
var history_container = $('#history'); khistory = new KHistory();
var history_operationgroup_html = '<div class="opegroup"><span class="time"></span><span class="trigramme"></span><span class="amount"></span><span class="valid_by"></span><span class="comment"></span></div>';
var history_operation_html = '<div class="ope"><span class="amount"></span><span class="infos1"></span><span class="infos2"></span><span class="addcost"></span><span class="canceled"></span></div>';
function getOpeHtml(ope, is_cof=false, trigramme='') {
var ope_html = $(history_operation_html);
var amount = parseFloat(ope['amount']);
var amountUKF = amountToUKF(amount, is_cof);
var infos1 = '', infos2 = '';
if (ope['type'] == 'deposit') {
infos1 = amount.toFixed(2)+'€';
infos2 = 'Charge';
} else if (ope['type'] == 'withdraw') {
infos1 = amount.toFixed(2)+'€';
infos2 = 'Retrait';
} else {
infos1 = ope['article_nb'];
infos2 = ope['article__name'];
}
if (trigramme == 'LIQ')
amountUKF = (- amount).toFixed(2) +"€";
ope_html
.attr('data-ope', ope['id'])
.find('.amount').text(amountUKF).end()
.find('.infos1').text(infos1).end()
.find('.infos2').text(infos2).end();
if (ope['addcost_for__trigramme']) {
ope_html.find('.addcost').text('('+amountToUKF(ope['addcost_amount'],is_cof)+'UKF pour '+ope['addcost_for__trigramme']+')')
}
if (ope['canceled_at']) {
ope_html.addClass('canceled');
var cancel = 'Annulé';
if (ope['canceled_by__trigramme'])
cancel += ' par '+ope['canceled_by__trigramme'];
var canceled_at = moment.tz(ope['canceled_at'],'UTC');
cancel += ' le '+canceled_at.tz('Europe/Paris').format('DD/MM/YY à HH:mm:ss');
ope_html.find('.canceled').text(cancel);
}
return ope_html;
}
function getOpegroupHtml(opegroup) {
var opegroup_html = $(history_operationgroup_html);
var at = moment.tz(opegroup['at'], 'UTC');
var at_formated = at.tz('Europe/Paris').format('HH:mm:ss');
var amount = parseFloat(opegroup['amount']);
var trigramme = opegroup['on_acc__trigramme'];
if (opegroup['on_acc__trigramme'] == 'LIQ') {
var amount = (- amount).toFixed(2) +'€';
} else {
var amount = amountToUKF(amount, opegroup['is_cof']);
}
var valid_by = '';
if (opegroup['valid_by__trigramme'])
valid_by = 'Par '+opegroup['valid_by__trigramme'];
var comment = opegroup['comment'] || '';
opegroup_html
.attr('data-opegroup', opegroup['id'])
.find('.time').text(at_formated).end()
.find('.amount').text(amount).end()
.find('.trigramme').text(trigramme).end()
.find('.valid_by').text(valid_by).end()
.find('.comment').text(comment).end();
return opegroup_html;
}
function addOpeGroup(opegroup) {
checkOrCreateDay(opegroup['at']);
var $opegroup_html = getOpegroupHtml(opegroup);
history_container.find('.day').first().after($opegroup_html);
// Ajout des opérations de ce groupe
var $opegroup = history_container.find('[data-opegroup='+opegroup['id']+']');
for (var i=0; i < opegroup['opes'].length; i++) {
var $ope = getOpeHtml(opegroup['opes'][i], opegroup['is_cof'], opegroup['on_acc__trigramme']);
$ope.attr('data-opegroup', opegroup['id']);
$opegroup.after($ope);
}
}
var history_day_default_html = '<div class="day"></div>';
function checkOrCreateDay(at) {
var at = moment.tz(at, 'UTC').tz('Europe/Paris');
var mostRecentDay = history_container.find('.day').first();
if (mostRecentDay.length == 0 || at.month() != mostRecentDay.attr('data-month') || at.date() != mostRecentDay.attr('data-day')) {
var day_html = $(history_day_default_html);
day_html
.attr('data-month', at.month())
.attr('data-day', at.date())
.text(at.format('D MMMM'));
history_container.prepend(day_html);
}
}
function getHistory() { function getHistory() {
var data = { var data = {
from: moment().subtract(1, 'days').format('YYYY-MM-DD HH:mm:ss'), from: moment().subtract(1, 'days').format('YYYY-MM-DD HH:mm:ss'),
}; };
console.log(data);
$.ajax({ $.ajax({
dataType: "json", dataType: "json",
url : "{% url 'kfet.history.json' %}", url : "{% url 'kfet.history.json' %}",
@ -1095,15 +976,11 @@ $(document).ready(function() {
}) })
.done(function(data) { .done(function(data) {
for (var i=0; i<data['opegroups'].length; i++) { for (var i=0; i<data['opegroups'].length; i++) {
addOpeGroup(data['opegroups'][i]); khistory.addOpeGroup(data['opegroups'][i]);
} }
}); });
} }
function resetHistory() {
history_container.children().remove();
}
// ----- // -----
// Addcost // Addcost
// ----- // -----
@ -1182,13 +1059,15 @@ $(document).ready(function() {
// Cancel from history // Cancel from history
// ----- // -----
history_container.selectable({ khistory.$container.selectable({
filter: 'div.opegroup, div.ope', filter: 'div.opegroup, div.ope',
selected: function(e, ui) { selected: function(e, ui) {
$(ui.selected).each(function() { $(ui.selected).each(function() {
if ($(this).hasClass('opegroup')) if ($(this).hasClass('opegroup'))
var opegroup = $(this).attr('data-opegroup'); var opegroup = $(this).data('opegroup');
$(this).siblings('.ope[data-opegroup='+opegroup+']').addClass('ui-selected'); $(this).siblings('.ope').filter(function() {
return $(this).data('opegroup') == opegroup
}).addClass('ui-selected');
}); });
}, },
}); });
@ -1197,8 +1076,8 @@ $(document).ready(function() {
if (e.keyCode == 46) { if (e.keyCode == 46) {
// DEL (Suppr) // DEL (Suppr)
var opes_to_cancel = []; var opes_to_cancel = [];
history_container.find('.ope.ui-selected').each(function () { khistory.$container.find('.ope.ui-selected').each(function () {
opes_to_cancel.push($(this).attr('data-ope')); opes_to_cancel.push($(this).data('ope'));
}); });
if (opes_to_cancel.length > 0) if (opes_to_cancel.length > 0)
cancelOperations(opes_to_cancel); cancelOperations(opes_to_cancel);
@ -1206,24 +1085,25 @@ $(document).ready(function() {
}); });
function cancelOpeGroup(opegroup) { function cancelOpeGroup(opegroup) {
var opegroup_html = history_container.find('.opegroup[data-opegroup='+opegroup['id']+']'); var $opegroup = khistory.$container.find('.opegroup').filter(function() {
if (opegroup_html.find('.trigramme').text() == 'LIQ') { return $(this).data('opegroup') == opegroup['id']
var amount = (- parseFloat(opegroup['amount']).toFixed(2))+'€'; });
} else { var tri = $opegroup.find('.trigramme').text();
var amount = amountToUKF(opegroup['amount'], opegroup['on_acc__is_cof']); var amount = amountDisplay(
} parseFloat(opegroup['amount'], opegroup['is_cof'], tri))
opegroup_html.find('.amount').text(amount); $opegroup.find('.amount').text(amount);
} }
function cancelOpe(ope) { function cancelOpe(ope) {
var ope_html = history_container.find('[data-ope='+ope['id']+']'); var $ope = khistory.$container.find('.ope').filter(function() {
ope_html.addClass('canceled'); return $(this).data('ope') == ope['id']
});
var cancel = 'Annulé'; var cancel = 'Annulé';
var canceled_at = dateUTCToParis(ope['canceled_at']);
if (ope['canceled_by__trigramme']) if (ope['canceled_by__trigramme'])
cancel += ' par '+ope['canceled_by__trigramme']; cancel += ' par '+ope['canceled_by__trigramme'];
var canceled_at = moment.tz(ope['canceled_at'], 'UTC'); cancel += ' le '+canceled_at.format('DD/MM/YY à HH:mm:ss');
cancel += ' le '+canceled_at.tz('Europe/Paris').format('DD/MM/YY à HH:mm:ss'); $ope.addClass('canceled').find('.canceled').text(cancel);
ope_html.find('.canceled').text(cancel);
} }
// ----- // -----
@ -1285,7 +1165,7 @@ $(document).ready(function() {
coolReset(give_tri_focus); coolReset(give_tri_focus);
resetCheckout(); resetCheckout();
resetArticles(); resetArticles();
resetHistory(); khistory.reset();
resetSettings(); resetSettings();
getArticles(); getArticles();
getHistory(); getHistory();

View file

@ -8,6 +8,8 @@ urlpatterns = [
name = 'kfet.home'), name = 'kfet.home'),
url(r'^login/genericteam$', views.login_genericteam, url(r'^login/genericteam$', views.login_genericteam,
name = 'kfet.login.genericteam'), name = 'kfet.login.genericteam'),
url(r'^history$', views.history,
name = 'kfet.history'),
# ----- # -----
# Account urls # Account urls

View file

@ -975,13 +975,13 @@ def kpsul_cancel_operations(request):
# Need refresh from db cause we used update on querysets # Need refresh from db cause we used update on querysets
opegroups_pk = [ opegroup.pk for opegroup in to_groups_amounts ] opegroups_pk = [ opegroup.pk for opegroup in to_groups_amounts ]
opegroups = (OperationGroup.objects opegroups = (OperationGroup.objects
.values('id','amount','on_acc__cofprofile__is_cof').filter(pk__in=opegroups_pk)) .values('id','amount','is_cof').filter(pk__in=opegroups_pk))
for opegroup in opegroups: for opegroup in opegroups:
websocket_data['opegroups'].append({ websocket_data['opegroups'].append({
'cancellation': True, 'cancellation': True,
'id': opegroup['id'], 'id': opegroup['id'],
'amount': opegroup['amount'], 'amount': opegroup['amount'],
'on_acc__is_cof': opegroup['on_acc__cofprofile__is_cof'], 'is_cof': opegroup['is_cof'],
}) })
canceled_by__trigramme = canceled_by and canceled_by.trigramme or None canceled_by__trigramme = canceled_by and canceled_by.trigramme or None
for ope in opes: for ope in opes:
@ -1088,6 +1088,16 @@ def kpsul_articles_data(request):
.filter(is_sold=True)) .filter(is_sold=True))
return JsonResponse({ 'articles': list(articles) }) return JsonResponse({ 'articles': list(articles) })
@permission_required('kfet.is_team')
def history(request):
data = {
'filter_form': FilterHistoryForm(),
'settings': {
'subvention_cof': Settings.SUBVENTION_COF(),
}
}
return render(request, 'kfet/history.html', data)
# ----- # -----
# Settings views # Settings views
# ----- # -----