Ajout historique d'un compte

- Création d'un style général pour les historiques
- Reprise de l'affichage historique K-Psul
This commit is contained in:
Aurélien Delobelle 2016-08-20 17:18:41 +02:00
parent 50ed08dd72
commit ee583c3cfb
9 changed files with 239 additions and 100 deletions

View file

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('kfet', '0027_auto_20160811_0648'),
]
operations = [
migrations.AlterField(
model_name='operation',
name='group',
field=models.ForeignKey(to='kfet.OperationGroup', on_delete=django.db.models.deletion.PROTECT, related_name='opes'),
),
migrations.AlterField(
model_name='operationgroup',
name='checkout',
field=models.ForeignKey(to='kfet.Checkout', on_delete=django.db.models.deletion.PROTECT, related_name='opesgroup'),
),
migrations.AlterField(
model_name='operationgroup',
name='on_acc',
field=models.ForeignKey(to='kfet.Account', on_delete=django.db.models.deletion.PROTECT, related_name='opesgroup'),
),
]

View file

@ -7,6 +7,7 @@ from gestioncof.models import CofProfile
from django.utils.six.moves import reduce from django.utils.six.moves import reduce
from django.utils import timezone from django.utils import timezone
from django.db import transaction from django.db import transaction
from django.core.cache import cache
from datetime import date, timedelta from datetime import date, timedelta
import re import re
@ -415,10 +416,10 @@ class Transfer(models.Model):
class OperationGroup(models.Model): class OperationGroup(models.Model):
on_acc = models.ForeignKey( on_acc = models.ForeignKey(
Account, on_delete = models.PROTECT, Account, on_delete = models.PROTECT,
related_name = "operations") related_name = "opesgroup")
checkout = models.ForeignKey( checkout = models.ForeignKey(
Checkout, on_delete = models.PROTECT, Checkout, on_delete = models.PROTECT,
related_name = "operations") related_name = "opesgroup")
at = models.DateTimeField(auto_now_add = True) at = models.DateTimeField(auto_now_add = True)
amount = models.DecimalField( amount = models.DecimalField(
max_digits = 6, decimal_places = 2, max_digits = 6, decimal_places = 2,
@ -446,7 +447,7 @@ class Operation(models.Model):
group = models.ForeignKey( group = models.ForeignKey(
OperationGroup, on_delete = models.PROTECT, OperationGroup, on_delete = models.PROTECT,
related_name = "+") related_name = "opes")
type = models.CharField( type = models.CharField(
choices = TYPE_ORDER_CHOICES, choices = TYPE_ORDER_CHOICES,
max_length = choices_length(TYPE_ORDER_CHOICES)) max_length = choices_length(TYPE_ORDER_CHOICES))
@ -507,10 +508,15 @@ class Settings(models.Model):
@staticmethod @staticmethod
def SUBVENTION_COF(): def SUBVENTION_COF():
subvention_cof = cache.get('SUBVENTION_COF')
if subvention_cof:
return subvention_cof
try: try:
return Settings.setting_inst("SUBVENTION_COF").value_decimal subvention_cof = Settings.setting_inst("SUBVENTION_COF").value_decimal
except Settings.DoesNotExist: except Settings.DoesNotExist:
return 0 subvention_cof = 0
cache.set('SUBVENTION_COF', subvention_cof)
return subvention_cof
@staticmethod @staticmethod
def ADDCOST_AMOUNT(): def ADDCOST_AMOUNT():

View file

@ -0,0 +1,82 @@
#history {
font-family:'Roboto Mono';
}
#history span {
display:inline-block;
height:100%;
}
#history .day {
height:40px;
line-height:40px;
background-color:#c8102e;
color:#fff;
padding-left:20px;
font-size:16px;
font-weight:bold;
}
#history .opegroup {
height:30px;
line-height:30px;
background-color:rgba(200,16,46,0.85);
color:#fff;
font-weight:bold;
padding-left:20px;
}
#history .opegroup .time {
width:70px;
}
#history .opegroup .trigramme {
width:55px;
text-align:right;
}
#history .opegroup .amount {
text-align:right;
width:90px;
}
#history .ope {
position:relative;
height:25px;
line-height:24px;
font-size:12px;
padding-left:15px;
}
#history .ope .amount {
width:50px;
text-align:right;
}
#history .ope .infos1 {
width:80px;
text-align:right;
}
#history .ope .infos2 {
padding-left:15px;
}
#history div.general.ui-selected, #history div.general.ui-selecting,
#history div.ope.ui-selected, #history div.ope.ui-selecting {
background-color:rgba(200,16,46,0.6);
color:#FFF;
}
#history .ope.canceled {
color:#444;
}
#history .ope.canceled::before {
position: absolute;
content: ' ';
width:100%;
left:0;
top: 12px;
border-top: 1px solid rgba(200,16,46,0.5);
}

View file

@ -1,6 +1,7 @@
@import url("nav.css"); @import url("nav.css");
@import url("kpsul.css"); @import url("kpsul.css");
@import url("jconfirm-kfet.css"); @import url("jconfirm-kfet.css");
@import url("history.css");
body { body {
margin-top:50px; margin-top:50px;
@ -54,6 +55,10 @@ a:focus, a:hover {
padding:0; padding:0;
} }
/*.col-content-left {
position:fixed;
}*/
.content-left-top { .content-left-top {
background:#fff; background:#fff;
padding:10px 30px; padding:10px 30px;
@ -92,3 +97,18 @@ a:focus, a:hover {
font-size:45px; font-size:45px;
text-align:center; text-align:center;
} }
.content-right {
margin:0 15px;
}
.content-right-block h2 {
margin:20px 20px 15px;
padding-bottom:5px;
border-bottom:3px solid #c8102e;
font-size:40px;
}
.content-right-block table {
width:100%;
}

View file

@ -318,6 +318,10 @@ input[type=number]::-webkit-outer-spin-button {
height:100%; height:100%;
} }
#basket_rel {
border-top:1px solid #C8102E;
}
#basket { #basket {
overflow:auto; overflow:auto;
} }
@ -327,6 +331,7 @@ input[type=number]::-webkit-outer-spin-button {
margin-right:7px; margin-right:7px;
} }
#basket_rel { #basket_rel {
border-top:0;
margin-left:7px; margin-left:7px;
} }
} }
@ -362,74 +367,3 @@ input[type=number]::-webkit-outer-spin-button {
.kpsul_middle_right_col { .kpsul_middle_right_col {
overflow:auto; overflow:auto;
} }
#history .day {
height:40px;
line-height:40px;
background-color:#c8102e;
color:#fff;
padding-left:20px;
font-size:16px;
font-weight:bold;
}
#history .opegroup .general {
height:30px;
line-height:30px;
background-color:#c8102e;
color:#fff;
font-weight:bold;
padding-left:10px;
}
#history .opegroup .general .trigramme {
padding-left:15px;
}
#history .opegroup .general .amount {
padding-left:15px;
}
#history .opegroup .ope {
position:relative;
height:25px;
line-height:24px;
font-size:12px;
}
#history .opegroup .ope .amountukf {
padding-left:15px;
}
#history .opegroup .ope span {
display:inline-block;
padding-right:10px;
}
#history .opegroup .ope .amountukf {
width:75px;
text-align:right;
}
#history .opegroup .ope .infos1 {
width:60px;
text-align:right;
}
#history div.general.ui-selected, #history div.general.ui-selecting,
#history div.ope.ui-selected, #history div.ope.ui-selecting {
background-color:rgba(200,16,46,0.6);
color:#FFF;
}
#history .ope.canceled {
color:#444;
}
#history .ope.canceled::before {
position: absolute;
content: ' ';
width:100%;
top: 12px;
border-top: 1px solid rgba(200,16,46,0.5);
}

View file

@ -69,7 +69,66 @@
</div> </div>
<div class="col-sm-8 col-md-9 col-content-right"> <div class="col-sm-8 col-md-9 col-content-right">
{% include "kfet/base_messages.html" %} {% include "kfet/base_messages.html" %}
<div class="content-right">
<div class="content-right-block">
<h2>Historique</h2>
<div id="history">
{% spaceless %}
{% for ope in history %}
{% ifchanged ope.group.at|date:'dmY' %}
<div class="day">
{{ ope.group.at|date:'l j F' }}
</div>
{% endifchanged %}
{% ifchanged ope.group.pk %}
<div class="opegroup" data-opegroup="{{ ope.group.pk }}">
<span class="time">{{ ope.group.at|date:'H:i:s' }}</span>
<span class="amount">
{% if ope.group.on_acc.trigramme == 'LIQ' %}
{{ ope.group.amount|floatformat:2 }}
{% else %}
{{ ope.group.amount|ukf:ope.group.is_cof }}
{% endif %}
</span>
</div>
{% endifchanged %}
<div class="ope {% if ope.canceled_at %}canceled{% endif %}" data-ope="{{ ope.pk }}" data-opegroup="{{ ope.group.pk }}">
{% if ope.group.on_acc.trigramme == 'LIQ' %}
<span class="amount">{{ ope.amount|floatformat:2 }}€</span>
{% else %}
<span class="amount">{{ ope.amount|ukf:ope.group.is_cof }}</span>
{% endif %}
{% if ope.type == "purchase" %}
<span class="infos1">{{ ope.article_nb }}</span>
<span class="infos2">{{ ope.article.name }}</span>
{% else %}
<span class="infos1">{{ ope.amount|floatformat:2 }}€</span>
<span class="infos2">
{% if ope.type == "deposit" %}Charge{% else %}Retrait{% endif %}
</span>
{% endif %}
</div>
{% endfor %}
{% endspaceless %}
</div>
</div>
</div>
</div> </div>
</div> </div>
<script type="text/javascript">
$(document).ready(function() {
$(window).scroll(function() {
console.log($(this).scrollTop());
if ($(window).width() >= 768 && $(this).scrollTop() > 72.6) {
$('.col-content-left').css({'position':'fixed', 'top':'50px'});
$('.col-content-right').addClass('col-sm-offset-4 col-md-offset-3');
} else {
$('.col-content-left').css({'position':'relative', 'top':'0'});
$('.col-content-right').removeClass('col-sm-offset-4 col-md-offset-3');
}
});
});
</script>
{% endblock %} {% endblock %}

View file

@ -867,9 +867,8 @@ $(document).ready(function() {
// ----- // -----
var history_container = $('#history'); var history_container = $('#history');
var history_operationgroup_html = '<div class="opegroup"></div>'; var history_operationgroup_html = '<div class="opegroup"><span class="time"></span><span class="trigramme"></span><span class="amount"></span></div>';
var history_operationgroupgeneral_html = '<div class="general"><span class="at"></span><span class="trigramme"></span><span class="amount"></span></div>'; var history_operation_html = '<div class="ope"><span class="amount"></span><span class="infos1"></span><span class="infos2"></span></div>';
var history_operation_html = '<div class="ope"><span class="amountukf"></span><span class="infos1"></span><span class="infos2"></span></div>';
function getOpeHtml(ope, is_cof=false, trigramme='') { function getOpeHtml(ope, is_cof=false, trigramme='') {
var ope_html = $(history_operation_html); var ope_html = $(history_operation_html);
@ -893,7 +892,7 @@ $(document).ready(function() {
ope_html ope_html
.attr('data-ope', ope['id']) .attr('data-ope', ope['id'])
.find('.amountukf').text(amountUKF).end() .find('.amount').text(amountUKF).end()
.find('.infos1').text(infos1).end() .find('.infos1').text(infos1).end()
.find('.infos2').text(infos2).end(); .find('.infos2').text(infos2).end();
@ -903,8 +902,8 @@ $(document).ready(function() {
return ope_html; return ope_html;
} }
function getOpegroupGeneralHtml(opegroup) { function getOpegroupHtml(opegroup) {
var opegroupgeneral_html = $(history_operationgroupgeneral_html); var opegroup_html = $(history_operationgroup_html);
var at = new Date(opegroup['at']); var at = new Date(opegroup['at']);
var at_hours = (at.getHours() < 10 ? '0' : '') + at.getHours(); var at_hours = (at.getHours() < 10 ? '0' : '') + at.getHours();
var at_minutes = (at.getMinutes() < 10 ? '0' : '') + at.getMinutes(); var at_minutes = (at.getMinutes() < 10 ? '0' : '') + at.getMinutes();
@ -918,27 +917,27 @@ $(document).ready(function() {
var amount = amountToUKF(amount, opegroup['is_cof']); var amount = amountToUKF(amount, opegroup['is_cof']);
} }
opegroupgeneral_html opegroup_html
.find('.at').text(at_formated).end() .attr('data-opegroup', opegroup['id'])
.find('.time').text(at_formated).end()
.find('.amount').text(amount).end() .find('.amount').text(amount).end()
.find('.trigramme').text(trigramme).end(); .find('.trigramme').text(trigramme).end();
return opegroupgeneral_html; return opegroup_html;
} }
function addOpeGroup(opegroup) { function addOpeGroup(opegroup) {
checkOrCreateDay(opegroup['at']); checkOrCreateDay(opegroup['at']);
var opegroup_html = $(history_operationgroup_html); var $opegroup_html = getOpegroupHtml(opegroup);
opegroup_html.attr('data-opegroup', opegroup['id']); history_container.find('.day').first().after($opegroup_html);
// Ajout des infos générales sur le groupe d'opés
opegroup_html.append(getOpegroupGeneralHtml(opegroup));
// Ajout des opérations de ce groupe // 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++) { for (var i=0; i < opegroup['opes'].length; i++) {
opegroup_html.append(getOpeHtml(opegroup['opes'][i], opegroup['is_cof'], opegroup['on_acc__trigramme'])); var $ope = getOpeHtml(opegroup['opes'][i], opegroup['is_cof'], opegroup['on_acc__trigramme']);
$ope.attr('data-opegroup', opegroup['id']);
$opegroup.after($ope);
} }
// Ajout du groupe
history_container.find('.day').first().after(opegroup_html);
} }
var history_day_default_html = '<div class="day"></div>'; var history_day_default_html = '<div class="day"></div>';
@ -979,16 +978,16 @@ $(document).ready(function() {
// ----- // -----
history_container.selectable({ history_container.selectable({
filter: 'div.opegroup div.general, 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('general')) if ($(this).hasClass('opegroup'))
$(this).siblings('.ope').addClass('ui-selected'); $(this).siblings('.ope').addClass('ui-selected');
}); });
}, },
unselected: function(e, ui) { unselected: function(e, ui) {
$(ui.unselected).each(function() { $(ui.unselected).each(function() {
if ($(this).hasClass('general')) if ($(this).hasClass('opegroup'))
$(this).siblings('.ope').removeClass('ui-selected'); $(this).siblings('.ope').removeClass('ui-selected');
}); });
} }

View file

@ -1,6 +1,7 @@
from django import template from django import template
from django.utils.html import escape from django.utils.html import escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.core.cache import cache
from kfet.models import Settings from kfet.models import Settings
import re import re

View file

@ -187,7 +187,15 @@ def account_read(request, trigramme):
and request.user != account.user: and request.user != account.user:
raise PermissionDenied raise PermissionDenied
return render(request, "kfet/account_read.html", { 'account' : account }) history = (Operation.objects
.select_related('group', 'group__valid_by', 'addcost_for', 'article')
.filter(group__on_acc=account)
.order_by('-group__at'))
return render(request, "kfet/account_read.html", {
'account' : account,
'history' : history,
})
# Account - Update # Account - Update
@ -553,9 +561,9 @@ def kpsul_perform_operations(request):
negative = AccountNegative( negative = AccountNegative(
account = operationgroup.on_acc, start = timezone.now()) account = operationgroup.on_acc, start = timezone.now())
negative.save() negative.save()
elif (hasattr(on_acc, 'negative') elif (hasattr(operationgroup.on_acc, 'negative')
and not on_acc.negative.balance_offset): and not operationgroup.on_acc.negative.balance_offset):
on_acc.negative.delete() operationgroup.on_acc.negative.delete()
# Updating checkout's balance # Updating checkout's balance
if to_checkout_balance: if to_checkout_balance:
@ -745,7 +753,7 @@ def kpsul_cancel_operations(request):
websocket_data['opes'].append({ websocket_data['opes'].append({
'cancellation': True, 'cancellation': True,
'id': ope, 'id': ope,
'canceled_by__trigramme': canceled_by, 'canceled_by__trigramme': canceled_by__trigramme,
'canceled_at': canceled_at, 'canceled_at': canceled_at,
}) })
# Need refresh from db cause we used update on querysets # Need refresh from db cause we used update on querysets