forked from DGNum/gestioCOF
Merge branch 'Aufinal/inventaires' into 'master'
K-Fêt - Création d'inventaires - Amélioration de l'interface - Ajout de colonnes intermédiaires pour faciliter le calcul - Ajout d'indication de conflits possibles avec les opérations en cours - Résolution semi-automatique de ces conflits Closes #141 See merge request !200
This commit is contained in:
commit
0405eee7a7
7 changed files with 230 additions and 41 deletions
|
@ -463,7 +463,7 @@ class InventoryArticleForm(forms.Form):
|
||||||
queryset = Article.objects.all(),
|
queryset = Article.objects.all(),
|
||||||
widget = forms.HiddenInput(),
|
widget = forms.HiddenInput(),
|
||||||
)
|
)
|
||||||
stock_new = forms.IntegerField(required = False)
|
stock_new = forms.IntegerField(required=False)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(InventoryArticleForm, self).__init__(*args, **kwargs)
|
super(InventoryArticleForm, self).__init__(*args, **kwargs)
|
||||||
|
@ -472,6 +472,7 @@ class InventoryArticleForm(forms.Form):
|
||||||
self.stock_old = kwargs['initial']['stock_old']
|
self.stock_old = kwargs['initial']['stock_old']
|
||||||
self.category = kwargs['initial']['category']
|
self.category = kwargs['initial']['category']
|
||||||
self.category_name = kwargs['initial']['category__name']
|
self.category_name = kwargs['initial']['category__name']
|
||||||
|
self.box_capacity = kwargs['initial']['box_capacity']
|
||||||
|
|
||||||
# -----
|
# -----
|
||||||
# Order forms
|
# Order forms
|
||||||
|
|
|
@ -32,6 +32,7 @@ textarea {
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
margin-bottom:0;
|
margin-bottom:0;
|
||||||
|
border-bottom:1px solid #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
|
@ -230,6 +231,9 @@ textarea {
|
||||||
height:28px;
|
height:28px;
|
||||||
margin:3px 0px;
|
margin:3px 0px;
|
||||||
}
|
}
|
||||||
|
.content-center .auth-form {
|
||||||
|
margin:15px;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pages formulaires seuls
|
* Pages formulaires seuls
|
||||||
|
@ -549,3 +553,18 @@ thead .tooltip {
|
||||||
.help-block {
|
.help-block {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Inventaires */
|
||||||
|
|
||||||
|
.inventory_modified {
|
||||||
|
background:rgba(236,100,0,0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stock_diff {
|
||||||
|
padding-left: 5px;
|
||||||
|
color:#C8102E;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inventory_update {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
.jconfirm .jconfirm-box .content {
|
.jconfirm .jconfirm-box .content {
|
||||||
border-bottom:1px solid #ddd;
|
border-bottom:1px solid #ddd;
|
||||||
|
padding:5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jconfirm .jconfirm-box input {
|
.jconfirm .jconfirm-box input {
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
{% extends 'kfet/base.html' %}
|
{% extends 'kfet/base.html' %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load widget_tweaks %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
<script type="text/javascript" src="{% static 'kfet/js/reconnecting-websocket.js' %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static 'kfet/js/jquery-confirm.js' %}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block title %}Nouvel inventaire{% endblock %}
|
{% block title %}Nouvel inventaire{% endblock %}
|
||||||
{% block content-header-title %}Nouvel inventaire{% endblock %}
|
{% block content-header-title %}Nouvel inventaire{% endblock %}
|
||||||
|
@ -6,38 +13,194 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% include 'kfet/base_messages.html' %}
|
{% include 'kfet/base_messages.html' %}
|
||||||
|
<div class="content-center">
|
||||||
<form action="" method="post">
|
<div>
|
||||||
<table>
|
<form id='inventoryform' action="" method="post">
|
||||||
<thead>
|
<table class="table text-center">
|
||||||
<tr>
|
<thead>
|
||||||
<td>Article</td>
|
|
||||||
<td>Théo.</td>
|
|
||||||
<td>Réel</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for form in formset %}
|
|
||||||
{% ifchanged form.category %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">{{ form.category_name }}</td>
|
<td>Article</td>
|
||||||
|
<td>Quantité par caisse</td>
|
||||||
|
<td>Stock Théorique</td>
|
||||||
|
<td>Caisses en réserve</td>
|
||||||
|
<td>Caisses en arrière</td>
|
||||||
|
<td>Vrac</td>
|
||||||
|
<td>Stock total</td>
|
||||||
|
<td>Compte terminé</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endifchanged %}
|
</thead>
|
||||||
<tr>
|
<tbody>
|
||||||
{{ form.article }}
|
{% for form in formset %}
|
||||||
<td>{{ form.name }}</td>
|
{% ifchanged form.category %}
|
||||||
<td>{{ form.stock_old }}</td>
|
<tr class='section'>
|
||||||
<td>{{ form.stock_new }}</td>
|
<td>{{ form.category_name }}</td>
|
||||||
</tr>
|
<td colspan="7"></td>
|
||||||
{% endfor %}
|
</tr>
|
||||||
</tbody>
|
{% endifchanged %}
|
||||||
</table>
|
<tr>
|
||||||
{% if not perms.kfet.add_inventory %}
|
{{ form.article }}
|
||||||
<input type="password" name="KFETPASSWORD">
|
<td class='name'>{{ form.name }}</td>
|
||||||
{% endif %}
|
<td class='box_capacity'>{{ form.box_capacity }}</td>
|
||||||
{% csrf_token %}
|
<td><span class='current_stock'>{{ form.stock_old }}</span><span class='stock_diff'></span></td>
|
||||||
{{ formset.management_form }}
|
<td class='box_cellar'>
|
||||||
<input type="submit" value="Enregistrer" class="btn btn-primary btn-lg">
|
<div class='col-md-2'></div>
|
||||||
</form>
|
<div class='col-md-8'>
|
||||||
|
<input type='number' class='form-control' step='1'>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class='box_bar'>
|
||||||
|
<div class='col-md-offset-2 col-md-8'><input type='number' class='form-control' step='1'></div>
|
||||||
|
</td>
|
||||||
|
<td class='misc'>
|
||||||
|
<div class='col-md-offset-2 col-md-8'><input type='number' class='form-control' step='1'></div>
|
||||||
|
</td>
|
||||||
|
<td class='stock_new'>
|
||||||
|
<div class='col-md-offset-2 col-md-8'>{{ form.stock_new | attr:"readonly"| add_class:"form-control" }}</div>
|
||||||
|
<div class='col-md-2 inventory_update'><button type='button' class='btn-sm btn-primary'>MàJ</button></div>
|
||||||
|
</td>
|
||||||
|
<td class='finished'><input type='checkbox' class='form_control'></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{ formset.management_form }}
|
||||||
|
{% if not perms.kfet.add_inventory %}
|
||||||
|
<div class='auth-form form-horizontal'>
|
||||||
|
{% include "kfet/form_authentication_snippet.html" %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<input type="submit" value="Enregistrer" class="btn btn-primary btn-lg btn-block">
|
||||||
|
{% csrf_token %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var conflicts = new Set();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autofill new stock from other inputs
|
||||||
|
*/
|
||||||
|
|
||||||
|
$('input[type="number"]').on('input', function() {
|
||||||
|
var $line = $(this).closest('tr');
|
||||||
|
var box_capacity = +$line.find('.box_capacity').text();
|
||||||
|
var box_cellar = $line.find('.box_cellar input').val();
|
||||||
|
var box_bar = $line.find('.box_bar input').val();
|
||||||
|
var misc = $line.find('.misc input').val();
|
||||||
|
if (box_cellar || box_bar || misc)
|
||||||
|
$line.find('.stock_new input').val(
|
||||||
|
box_capacity*((+box_cellar) +(+box_bar))+(+misc));
|
||||||
|
else
|
||||||
|
$line.find('.stock_new input').val('');
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove warning and update stock
|
||||||
|
*/
|
||||||
|
|
||||||
|
function update_stock($line, update_count) {
|
||||||
|
$line.removeClass('inventory_modified');
|
||||||
|
$line.find('.inventory_update').hide();
|
||||||
|
|
||||||
|
var old_stock = +$line.find('.current_stock').text()
|
||||||
|
var stock_diff = +$line.find('.stock_diff').text();
|
||||||
|
$line.find('.current_stock').text(old_stock + stock_diff);
|
||||||
|
$line.find('.stock_diff').text('');
|
||||||
|
|
||||||
|
if ($line.find('.stock_new input').val() && update_count) {
|
||||||
|
var old_misc = +$line.find('.misc input').val();
|
||||||
|
$line.find('.misc input').val(old_misc + stock_diff)
|
||||||
|
.trigger('input');
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = $line.find('input[type="hidden"]').val();
|
||||||
|
conflicts.delete(parseInt(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.finished input').change(function() {
|
||||||
|
var $line = $(this).closest('tr');
|
||||||
|
update_stock($line, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.inventory_update button').click(function() {
|
||||||
|
var $line = $(this).closest('tr');
|
||||||
|
update_stock($line, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Websocket
|
||||||
|
*/
|
||||||
|
|
||||||
|
OperationWebSocket.add_handler(function(data) {
|
||||||
|
for (let article of data['articles']) {
|
||||||
|
var $line = $('input[value="'+article.id+'"]').parent();
|
||||||
|
if ($line.find('.finished input').is(":checked")) {
|
||||||
|
conflicts.add(article.id);
|
||||||
|
//Display warning
|
||||||
|
$line.addClass('inventory_modified');
|
||||||
|
|
||||||
|
//Realigning input and displaying update button
|
||||||
|
$line.find('.inventory_update').show();
|
||||||
|
|
||||||
|
//Displaying stock changes
|
||||||
|
var stock = $line.find('.current_stock').text();
|
||||||
|
$line.find('.stock_diff').text(article.stock - stock);
|
||||||
|
} else {
|
||||||
|
// If we haven't counted the article yet, we simply update the expected stock
|
||||||
|
$line.find('.current_stock').text(article.stock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('input[type="submit"]').on("click", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (conflicts.size) {
|
||||||
|
content = '';
|
||||||
|
content += "Conflits possibles :"
|
||||||
|
content += '<ul>';
|
||||||
|
for (let id of conflicts) {
|
||||||
|
var $line = $('input[value="'+id+'"]').closest('tr');
|
||||||
|
var name = $line.find('.name').text();
|
||||||
|
var stock_diff = $line.find('.stock_diff').text();
|
||||||
|
content += '<li>'+name+' ('+stock_diff+')</li>';
|
||||||
|
}
|
||||||
|
content += '</ul>'
|
||||||
|
} else {
|
||||||
|
// Prevent erroneous enter key confirmations
|
||||||
|
// Kinda complicated to filter if click or enter key...
|
||||||
|
content="Voulez-vous confirmer l'inventaire ?";
|
||||||
|
}
|
||||||
|
|
||||||
|
$.confirm({
|
||||||
|
title: "Confirmer l'inventaire",
|
||||||
|
content: content,
|
||||||
|
backgroundDismiss: true,
|
||||||
|
animation: 'top',
|
||||||
|
closeAnimation: 'bottom',
|
||||||
|
keyboardEnabled: true,
|
||||||
|
confirm: function() {
|
||||||
|
$('#inventoryform').submit();
|
||||||
|
},
|
||||||
|
onOpen: function() {
|
||||||
|
var that = this;
|
||||||
|
this.$content.find('input').on('keydown', function(e) {
|
||||||
|
if (e.keyCode == 13)
|
||||||
|
that.$confirmButton.click();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -66,11 +66,13 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% if not perms.kfet.add_order %}
|
|
||||||
<input type="password" name="KFETPASSWORD">
|
|
||||||
{% endif %}
|
|
||||||
{{ formset.management_form }}
|
{{ formset.management_form }}
|
||||||
<input type="submit" class="btn btn-primary btn-lg btn-block" value="Envoyer">
|
{% if not perms.kfet.add_inventory %}
|
||||||
|
<div class='auth-form form-horizontal'>
|
||||||
|
{% include "kfet/form_authentication_snippet.html" %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<input type="submit" value="Enregistrer" class="btn btn-primary btn-lg btn-block">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -42,11 +42,13 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% if not perms.kfet.order_to_inventory %}
|
|
||||||
<input type="password" name="KFETPASSWORD">
|
|
||||||
{% endif %}
|
|
||||||
{{ formset.management_form }}
|
{{ formset.management_form }}
|
||||||
<input type="submit" class="btn btn-primary btn-lg btn-block" value="Enregistrer">
|
{% if not perms.kfet.add_inventory %}
|
||||||
|
<div class='auth-form form-horizontal'>
|
||||||
|
{% include "kfet/form_authentication_snippet.html" %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<input type="submit" value="Enregistrer" class="btn btn-primary btn-lg btn-block">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1654,7 +1654,8 @@ def inventory_create(request):
|
||||||
'stock_old': article.stock,
|
'stock_old': article.stock,
|
||||||
'name' : article.name,
|
'name' : article.name,
|
||||||
'category' : article.category_id,
|
'category' : article.category_id,
|
||||||
'category__name': article.category.name
|
'category__name': article.category.name,
|
||||||
|
'box_capacity': article.box_capacity or 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
cls_formset = formset_factory(
|
cls_formset = formset_factory(
|
||||||
|
|
Loading…
Reference in a new issue