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(),
|
||||
widget = forms.HiddenInput(),
|
||||
)
|
||||
stock_new = forms.IntegerField(required = False)
|
||||
stock_new = forms.IntegerField(required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(InventoryArticleForm, self).__init__(*args, **kwargs)
|
||||
|
@ -472,6 +472,7 @@ class InventoryArticleForm(forms.Form):
|
|||
self.stock_old = kwargs['initial']['stock_old']
|
||||
self.category = kwargs['initial']['category']
|
||||
self.category_name = kwargs['initial']['category__name']
|
||||
self.box_capacity = kwargs['initial']['box_capacity']
|
||||
|
||||
# -----
|
||||
# Order forms
|
||||
|
|
|
@ -32,6 +32,7 @@ textarea {
|
|||
|
||||
.table {
|
||||
margin-bottom:0;
|
||||
border-bottom:1px solid #ddd;
|
||||
}
|
||||
|
||||
.table {
|
||||
|
@ -230,6 +231,9 @@ textarea {
|
|||
height:28px;
|
||||
margin:3px 0px;
|
||||
}
|
||||
.content-center .auth-form {
|
||||
margin:15px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pages formulaires seuls
|
||||
|
@ -549,3 +553,18 @@ thead .tooltip {
|
|||
.help-block {
|
||||
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 {
|
||||
border-bottom:1px solid #ddd;
|
||||
padding:5px 10px;
|
||||
}
|
||||
|
||||
.jconfirm .jconfirm-box input {
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
{% 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 content-header-title %}Nouvel inventaire{% endblock %}
|
||||
|
@ -6,38 +13,194 @@
|
|||
{% block content %}
|
||||
|
||||
{% include 'kfet/base_messages.html' %}
|
||||
|
||||
<form action="" method="post">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Article</td>
|
||||
<td>Théo.</td>
|
||||
<td>Réel</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for form in formset %}
|
||||
{% ifchanged form.category %}
|
||||
<div class="content-center">
|
||||
<div>
|
||||
<form id='inventoryform' action="" method="post">
|
||||
<table class="table text-center">
|
||||
<thead>
|
||||
<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>
|
||||
{% endifchanged %}
|
||||
<tr>
|
||||
{{ form.article }}
|
||||
<td>{{ form.name }}</td>
|
||||
<td>{{ form.stock_old }}</td>
|
||||
<td>{{ form.stock_new }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if not perms.kfet.add_inventory %}
|
||||
<input type="password" name="KFETPASSWORD">
|
||||
{% endif %}
|
||||
{% csrf_token %}
|
||||
{{ formset.management_form }}
|
||||
<input type="submit" value="Enregistrer" class="btn btn-primary btn-lg">
|
||||
</form>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for form in formset %}
|
||||
{% ifchanged form.category %}
|
||||
<tr class='section'>
|
||||
<td>{{ form.category_name }}</td>
|
||||
<td colspan="7"></td>
|
||||
</tr>
|
||||
{% endifchanged %}
|
||||
<tr>
|
||||
{{ form.article }}
|
||||
<td class='name'>{{ form.name }}</td>
|
||||
<td class='box_capacity'>{{ form.box_capacity }}</td>
|
||||
<td><span class='current_stock'>{{ form.stock_old }}</span><span class='stock_diff'></span></td>
|
||||
<td class='box_cellar'>
|
||||
<div class='col-md-2'></div>
|
||||
<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 %}
|
||||
|
|
|
@ -66,11 +66,13 @@
|
|||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if not perms.kfet.add_order %}
|
||||
<input type="password" name="KFETPASSWORD">
|
||||
{% endif %}
|
||||
{{ 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>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -42,11 +42,13 @@
|
|||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if not perms.kfet.order_to_inventory %}
|
||||
<input type="password" name="KFETPASSWORD">
|
||||
{% endif %}
|
||||
{{ 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>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1654,7 +1654,8 @@ def inventory_create(request):
|
|||
'stock_old': article.stock,
|
||||
'name' : article.name,
|
||||
'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(
|
||||
|
|
Loading…
Reference in a new issue