Commit af4b178b by François C.

Ajout module Saisie Mouvement de Stock (repas salariés, pertes, autoconso)

parent b36613dc
...@@ -165,3 +165,26 @@ footer { position: fixed; ...@@ -165,3 +165,26 @@ footer { position: fixed;
} }
.mac-msg {background: red; color: #fff; padding: 3px;} .mac-msg {background: red; color: #fff; padding: 3px;}
.notifyjs-cancelable-base {
font-weight: bold;
padding: 8px 15px 8px 14px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
background-color: #fcf8e3;
border: 1px solid #fbeed5;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
white-space: nowrap;
padding-left: 25px;
background-repeat: no-repeat;
background-position: 3px 7px;
}
.notifyjs-cancelable-info {
color: #3A87AD;
background-color: #D9EDF7;
border-color: #BCE8F1;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QYFAhkSsdes/QAAA8dJREFUOMvVlGtMW2UYx//POaWHXg6lLaW0ypAtw1UCgbniNOLcVOLmAjHZolOYlxmTGXVZdAnRfXQm+7SoU4mXaOaiZsEpC9FkiQs6Z6bdCnNYruM6KNBw6YWewzl9z+sHImEWv+vz7XmT95f/+3/+7wP814v+efDOV3/SoX3lHAA+6ODeUFfMfjOWMADgdk+eEKz0pF7aQdMAcOKLLjrcVMVX3xdWN29/GhYP7SvnP0cWfS8caSkfHZsPE9Fgnt02JNutQ0QYHB2dDz9/pKX8QjjuO9xUxd/66HdxTeCHZ3rojQObGQBcuNjfplkD3b19Y/6MrimSaKgSMmpGU5WevmE/swa6Oy73tQHA0Rdr2Mmv/6A1n9w9suQ7097Z9lM4FlTgTDrzZTu4StXVfpiI48rVcUDM5cmEksrFnHxfpTtU/3BFQzCQF/2bYVoNbH7zmItbSoMj40JSzmMyX5qDvriA7QdrIIpA+3cdsMpu0nXI8cV0MtKXCPZev+gCEM1S2NHPvWfP/hL+7FSr3+0p5RBEyhEN5JCKYr8XnASMT0xBNyzQGQeI8fjsGD39RMPk7se2bd5ZtTyoFYXftF6y37gx7NeUtJJOTFlAHDZLDuILU3j3+H5oOrD3yWbIztugaAzgnBKJuBLpGfQrS8wO4FZgV+c1IxaLgWVU0tMLEETCos4xMzEIv9cJXQcyagIwigDGwJgOAtHAwAhisQUjy0ORGERiELgG4iakkzo4MYAxcM5hAMi1WWG1yYCJIcMUaBkVRLdGeSU2995TLWzcUAzONJ7J6FBVBYIggMzmFbvdBV44Corg8vjhzC+EJEl8U1kJtgYrhCzgc/vvTwXKSib1paRFVRVORDAJAsw5FuTaJEhWM2SHB3mOAlhkNxwuLzeJsGwqWzf5TFNdKgtY5qHp6ZFf67Y/sAVadCaVY5YACDDb3Oi4NIjLnWMw2QthCBIsVhsUTU9tvXsjeq9+X1d75/KEs4LNOfcdf/+HthMnvwxOD0wmHaXr7ZItn2wuH2SnBzbZAbPJwpPx+VQuzcm7dgRCB57a1uBzUDRL4bfnI0RE0eaXd9W89mpjqHZnUI5Hh2l2dkZZUhOqpi2qSmpOmZ64Tuu9qlz/SEXo6MEHa3wOip46F1n7633eekV8ds8Wxjn37Wl63VVa+ej5oeEZ/82ZBETJjpJ1Rbij2D3Z/1trXUvLsblCK0XfOx0SX2kMsn9dX+d+7Kf6h8o4AIykuffjT8L20LU+w4AZd5VvEPY+XpWqLV327HR7DzXuDnD8r+ovkBehJ8i+y8YAAAAASUVORK5CYII=);
}
.notifyjs-cancelable-base .buttons {width: 190px; margin: 5px auto;}
.notifyjs-cancelable-base button {width: 90px;text-align: center; margin: 3px;}
\ No newline at end of file
...@@ -231,4 +231,8 @@ hr { ...@@ -231,4 +231,8 @@ hr {
white-space: pre-wrap; white-space: pre-wrap;
} }
#main_content {width: 100%;} #main_content {width: 100%;}
\ No newline at end of file
.select_product_action {
max-width: 20px;
}
...@@ -220,7 +220,7 @@ function initLists() { ...@@ -220,7 +220,7 @@ function initLists() {
{ {
data:"product_id.1", data:"product_id.1",
title:"Produit", title:"Produit",
width: "50%", width: "40%",
render: function (data, type, full, meta) { render: function (data, type, full, meta) {
// Add tooltip with barcode over product name // Add tooltip with barcode over product name
let display_barcode = "Aucun"; let display_barcode = "Aucun";
...@@ -258,6 +258,12 @@ function initLists() { ...@@ -258,6 +258,12 @@ function initLists() {
defaultContent: "<a class='btn' id='toProcess_line_valid' href='#'><i class='far fa-check-square'></i></a>", defaultContent: "<a class='btn' id='toProcess_line_valid' href='#'><i class='far fa-check-square'></i></a>",
className:"dt-body-center", className:"dt-body-center",
orderable: false orderable: false
},
{
title:"Autres",
defaultContent: "<select class='select_product_action'><option value=''></option><option value='supplier_shortage'>Rupture fournisseur</option></select>",
className:"dt-body-center",
orderable: false
} }
], ],
rowId : "product_id.0", rowId : "product_id.0",
...@@ -292,9 +298,17 @@ function initLists() { ...@@ -292,9 +298,17 @@ function initLists() {
display_barcode = full.barcode; display_barcode = full.barcode;
} }
return '<div class="tooltip">' + data let display = '<div class="tooltip">' + data
+ ' <span class="tooltiptext tt_twolines">Code barre : ' + ' <span class="tooltiptext tt_twolines">Code barre : '
+ display_barcode + '</span> </div>'; + display_barcode + '</span> </div>';
if (full.supplier_shortage) {
display += ' <div class="tooltip"><i class="fas fa-info-circle"></i>'
+ ' <span class="tooltiptext tt_twolines">Rupture fournisseur'
+ '</span> </div>';
}
return display;
} }
}, },
{data:"product_uom.1", title: "Unité vente", className:"dt-body-center", orderable: false}, {data:"product_uom.1", title: "Unité vente", className:"dt-body-center", orderable: false},
...@@ -395,6 +409,38 @@ function initLists() { ...@@ -395,6 +409,38 @@ function initLists() {
} }
}); });
$('#table_to_process tbody').on('change', '.select_product_action', function () {
try {
if ($(this).val() == 'supplier_shortage') {
var row = table_to_process.row($(this).parents('tr'));
var data = row.data();
var modal_shortage = $('#modal_set_supplier_shortage');
modal_shortage.find(".supplier_shortage_product").text(' ' + data.product_id[1]);
modal_shortage.find(".supplier_shortage_supplier").text(' ' + data.partner_id[1]);
openModal(
modal_shortage.html(),
function() {
set_supplier_shortage(row, data);
},
'Valider',
true,
true,
function() {
$(".select_product_action").val('');
}
);
}
} catch (e) {
err = {msg: e.name + ' : ' + e.message, ctx: 'initLists : listener set supplier shortage'};
console.error(err);
report_JS_error(err, 'reception');
}
});
// Edit processed line // Edit processed line
$('#table_processed tbody').on('click', 'a#processed_line_edit', function () { $('#table_processed tbody').on('click', 'a#processed_line_edit', function () {
try { try {
...@@ -550,6 +596,49 @@ function remove_from_processed(row, product) { ...@@ -550,6 +596,49 @@ function remove_from_processed(row, product) {
} }
} }
// Indicate the product is on supplier shortage.
// Direct validation from to_process & set qty to 0
function set_supplier_shortage(row, product) {
try {
product.supplier_shortage = true;
// Step 1: set qty to 0
if (reception_status == 'False') {
product.old_qty = product.product_qty;
product.product_qty = 0;
} else {
// Step 2: for consistency purposes, updated products need these fields to be set
product.old_price_unit = product.price_unit;
product.new_shelf_price = null;
}
updatedProducts.push(product);
add_to_processed(product);
remove_from_toProcess(row, product);
// Update local storage of product's order
if (!orders[product.id_po]['updated_products'])
orders[product.id_po]['updated_products'] = [];
orders[product.id_po]['updated_products'].push(product);
localStorage.setItem("order_" + product.id_po, JSON.stringify(orders[product.id_po]));
// Reset search
document.getElementById('search_input').value = '';
$('table.dataTable').DataTable()
.search('')
.draw();
search_chars = [];
document.getElementById('search_input').focus();
} catch (e) {
err = {msg: e.name + ' : ' + e.message, ctx: 'set_supplier_shortage'};
console.error(err);
report_JS_error(err, 'reception');
}
}
/* EDITION */ /* EDITION */
...@@ -635,9 +724,9 @@ function editProductInfo (productToEdit, value = null) { ...@@ -635,9 +724,9 @@ function editProductInfo (productToEdit, value = null) {
// Edit product info // Edit product info
productToEdit.product_qty = newValue; productToEdit.product_qty = newValue;
/* /*
If qty has changed, we choose to set detailed values as follow: If qty has changed, we choose to set detailed values as follow:
1 package (product_qty_package) of X products (package_qty) 1 package (product_qty_package) of X products (package_qty)
*/ */
productToEdit.product_qty_package = 1; productToEdit.product_qty_package = 1;
productToEdit.package_qty = productToEdit.product_qty; productToEdit.package_qty = productToEdit.product_qty;
} }
...@@ -862,7 +951,7 @@ function data_validation() { ...@@ -862,7 +951,7 @@ function data_validation() {
// Send the request to the server // Send the request to the server
function send() { function send() {
try { try {
// Loading on // Loading on
openModal(); openModal();
// Only send to server the updated lines // Only send to server the updated lines
...@@ -940,8 +1029,6 @@ function send() { ...@@ -940,8 +1029,6 @@ function send() {
prod_order_id = updatedProducts[i].id_po; prod_order_id = updatedProducts[i].id_po;
update_data.orders[prod_order_id]['po'].push(updatedProducts[i]); update_data.orders[prod_order_id]['po'].push(updatedProducts[i]);
} }
// console.log(update_data)
// return -1
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } }); $.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
$.ajax({ $.ajax({
......
...@@ -8,6 +8,31 @@ from datetime import datetime ...@@ -8,6 +8,31 @@ from datetime import datetime
class CagetteStock(models.Model): class CagetteStock(models.Model):
@staticmethod @staticmethod
def get_movements(movement_type, date_from, date_to):
o_api = OdooAPI()
errors = []
if movement_type == 'losses':
location_dest_id = settings.LOSSES_LOC_ID
elif movement_type == 'meals':
location_dest_id = settings.MEALS_LOC_ID
elif movement_type == 'autoconso':
location_dest_id = settings.AUTOCONSO_LOC_ID
else:
errors.append('Type de mouvement incorrect')
return {'errors': errors}
f = ['name', 'date_done', 'inventory_value']
c = [['location_dest_id', "=", location_dest_id],
['date_done', ">=", date_from],
['date_done', "<=", date_to],
['state', "=", 'done']]
res = o_api.search_read('stock.picking', c, f)
return res
@staticmethod
def do_stock_movement(stock_movement_data): def do_stock_movement(stock_movement_data):
"""Do a stock movement : """ """Do a stock movement : """
......
.main, .barcode_search_area {
margin-top: 40px;
}
#sm_barcode_selector {
border: 1px solid #555;
border-radius:10px;
}
.stock_edit_input {
max-width: 60px;
}
#movement_validation_button {
margin-top: 20px;
}
.notifyjs-test1-base {
background: #5CB85C !important;
}
.confirmation_checking_msgs {
padding-bottom: 10px;
}
.remove_row_icon {
font-size: 1.4em;
color: #d9534f;
cursor: pointer;
}
.blink_me {
animation: blinker 1s ease-in-out;
}
@keyframes blinker {
15% { background-color: #218D9B ; } /* F0AD4E*/
}
#back_to_movement_selection {
position:absolute;
left:0;
margin: 5px;
}
.movement_type_buttons {
margin-top: 60px;
}
.movement_type_button {
height: 2.2em;
width: 30%;
border-radius: 3px;
margin: 10px;
font-size: 1.3em;
}
.movement_type_button_icons {
float: right;
margin: 2px;
}
.page_body {
position: relative;
}
.page_content {
position: absolute;
top: 0;
left: 0;
right: 0;
}
.select_movement_area {
margin-top: 25px;
}
.select_movement_element {
display: inline-block;
margin-right: 10px;
}
.main {
margin-top: 25px;
}
.table_area {
margin: auto;
width: 50%;
padding: 10px;
}
.select_movement_input {
border-radius:5px;
}
.btn_export_movements {
margin-top: 10px;
}
/*
* Extract and display a stock movement type between two dates
*
*/
// var dateFormat = "mm/dd/yy",
var dateFormat = "yy-mm-dd",
from_datepicker = null,
to_datepicker = null,
movements_table = null;
// Return a date from a string if valid, else return null
function getDate(element) {
var date;
try {
date = $.datepicker.parseDate(dateFormat, element);
} catch (error) {
date = null;
}
return date;
}
// Enable validation button if all fields are valid
function enable_validation() {
if ($('#movement_type_selector').val() != '' &&
getDate(from_datepicker.val()) &&
getDate(to_datepicker.val())) {
$('#movement_selection_button').prop('disabled', false);
} else {
$('#movement_selection_button').prop('disabled', true);
}
}
function display_movements(movements) {
total_value = 0;
for (move of movements) {
total_value += move.inventory_value;
}
$('#count_movements').text(movements.length);
$('#total_value_movements').text(parseFloat(total_value).toFixed(2));
// Empty datatable if already exists
if (movements_table) {
movements_table.destroy();
}
movements_table = $('#movements_table').DataTable({
data: movements,
columns:[
{
data:"name",
title:"Mouvement",
width: "70%"
},
{
data:"inventory_value",
title: "Valeur",
className:"dt-body-center",
render: function (data, type, full) {
return parseFloat(data).toFixed(2) + ' €';
}
},
{
data:"date_done",
title:"Trier par Date",
className:"dt-body-center",
render: function (data, type, full) {
return '<i>' + data + '</i>';
}
}
],
order: [
[
2,
"desc"
]
],
buttons: [{ extend: 'csvHtml5', text: 'Export en CSV', className: 'btn--primary btn_export_movements' }],
dom: '<lr<t>ip><"clear"><B>',
iDisplayLength: 10,
language: {url : '/static/js/datatables/french.json'}
});
$('.main').show();
}
function get_movements() {
openModal();
var url = "/stock/get_movements";
url += '?movement_type=' + encodeURIComponent($('#movement_type_selector').val());
url += '&from=' + encodeURIComponent(from_datepicker.val());
url += '&to=' + encodeURIComponent(to_datepicker.val());
$.ajax({
type: 'GET',
url: url,
dataType:"json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function(data) {
display_movements(data.res);
closeModal();
},
error: function(data) {
err = {msg: "erreur serveur lors de la sélection des mouvements de stock", ctx: 'get_movements'};
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error;
}
report_JS_error(err, 'stock');
closeModal();
alert('Erreur lors de la récupération, réessayez plus tard');
}
});
}
$(document).ready(function() {
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
// Set datepicker
$.datepicker.regional['fr'] = {
monthNames: [
'Janvier',
'Fevrier',
'Mars',
'Avril',
'Mai',
'Juin',
'Juillet',
'Aout',
'Septembre',
'Octobre',
'Novembre',
'Decembre'
],
dayNamesMin: [
'Di',
'Lu',
'Ma',
'Me',
'Je',
'Ve',
'Sa'
],
dateFormat: dateFormat,
firstDay: 1,
minDate: 1,
maxDate: '+12M +0D'
};
$.datepicker.setDefaults($.datepicker.regional['fr']);
from_datepicker = $("#from")
.datepicker({
defaultDate: "-1d",
changeMonth: true,
changeYear: true,
yearRange: "-03:+00",
minDate: new Date(2007, 1 - 1, 1),
maxDate: new Date()
})
.on("change", function() {
to_datepicker.datepicker("option", "minDate", getDate(this.value));
});
to_datepicker = $("#to")
.datepicker({
defaultDate: "-1d",
changeMonth: true,
changeYear: true,
yearRange: "-03:+00",
minDate: new Date(2007, 1 - 1, 1),
maxDate: new Date()
})
.on("change", function() {
from_datepicker.datepicker("option", "maxDate", getDate(this.value));
});
$('.select_movement_element').change(function() {
enable_validation();
});
$('#movement_selection_button').click(function() {
get_movements();
});
});
...@@ -4,8 +4,10 @@ from django.conf.urls import url ...@@ -4,8 +4,10 @@ from django.conf.urls import url
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^movements', views.movements_page), url(r'^movements$', views.movements_page),
url(r'^do_movement', views.do_movement), url(r'^do_movement', views.do_movement),
url(r'^movements_view$', views.movements_view),
url(r'^get_movements$', views.get_movements),
### NOT IN USE: ### ### NOT IN USE: ###
......
...@@ -18,6 +18,15 @@ def movements_page(request): ...@@ -18,6 +18,15 @@ def movements_page(request):
return HttpResponse(template.render(context, request)) return HttpResponse(template.render(context, request))
def movements_view(request):
"""Page d'extraction des mouvements de stocks"""
context = {
'title': 'Mouvements de stock'
}
template = loader.get_template('stock/stock_movements_view.html')
return HttpResponse(template.render(context, request))
def do_movement(request): def do_movement(request):
"""Do the stock movement: losses, self conso or stock correction""" """Do the stock movement: losses, self conso or stock correction"""
res = {} res = {}
...@@ -46,6 +55,20 @@ def do_movement(request): ...@@ -46,6 +55,20 @@ def do_movement(request):
else: else:
return JsonResponse({'res': res}) return JsonResponse({'res': res})
def get_movements(request):
res = {}
movement_type = request.GET.get('movement_type', '')
date_from = request.GET.get('from', '')
date_to = request.GET.get('to', '')
res = CagetteStock.get_movements(movement_type, date_from, date_to)
if 'errors' in res and res['errors']:
return JsonResponse(res, status=500)
else:
return JsonResponse({'res': res})
### NOT IN USE ### ### NOT IN USE ###
# ??? a voir si on garde les heur d'ouverture de la cagette ici # ??? a voir si on garde les heur d'ouverture de la cagette ici
......
...@@ -92,7 +92,6 @@ ...@@ -92,7 +92,6 @@
<span id="valid_all"></span> <span id="valid_all"></span>
<span id="all_left_is_good"> <span id="all_left_is_good">
<button class='btn--danger half_width_button' onclick="openModal($('#templates #modal_all_left_is_good').html(), confirm_all_left_is_good, 'Confirmer', false);">Tout le reste est bon</button> <button class='btn--danger half_width_button' onclick="openModal($('#templates #modal_all_left_is_good').html(), confirm_all_left_is_good, 'Confirmer', false);">Tout le reste est bon</button>
</span> </span>
</div> </div>
{% else %} {% else %}
...@@ -153,6 +152,14 @@ ...@@ -153,6 +152,14 @@
<p>Êtez-vous sûr ?</p> <p>Êtez-vous sûr ?</p>
<hr /> <hr />
</div> </div>
<div id="modal_set_supplier_shortage">
<h3>Attention !</h3>
<p>Vous vous apprêtez indiquer que le produit<b><span class="supplier_shortage_product"></span></b>
est en rupture chez le fournisseur<b><span class="supplier_shortage_supplier"></span></b>.</p>
<p>La quantité du produit sera mise à 0 si vous en êtes à l'étape du comptage de produits.</p>
<p>Êtez-vous sûr ?</p>
<hr />
</div>
<div id="modal_unprocessable_porducts"> <div id="modal_unprocessable_porducts">
<h3>Traitement impossible</h3> <h3>Traitement impossible</h3>
<p> <p>
......
{% extends "base.html" %}
{% load static %}
{% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/stock_movements.css' %}">
{% endblock %}
{% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/datatables/dataTables.plugins.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery.pos.js' %}"></script>
<script type="text/javascript" src="{% static 'js/stock_movements.js' %}?v="></script>
<script type="text/javascript" src="{% static 'js/notify.min.js' %}?v="></script>
{% endblock %}
{% block content %}
<div class="page_body">
<div id="content_movement_type_selection" class="page_content">
<div class="header txtcenter">
<h1>Saisie de mouvements de stock</h1>
<p><i>Choisissez le type de mouvement de stock que vous voulez enregistrer</i></p>
</div>
<div class="movement_type_buttons txtcenter">
<button type="button" class="btn--primary movement_type_button" id="losses_type_button">
Pertes
<span class="movement_type_button_icons"><i class="fas fa-arrow-right"></i></span>
</button><br>
<button type="button" class="btn--primary movement_type_button" id="autoconso_type_button">
Autoconsommation
<span class="movement_type_button_icons"><i class="fas fa-arrow-right"></i></span>
</button><br>
<button type="button" class="btn--primary movement_type_button" id="meals_type_button">
Repas salariés
<span class="movement_type_button_icons"><i class="fas fa-arrow-right"></i></span>
</button>
</div>
</div>
<div id="content_main" class="page_content" style="display:none;">
<div class="header txtcenter">
<div id="back_to_movement_selection">
<button type="button" class="btn--danger"><i class="fas fa-arrow-left"></i>&nbsp; Retour</button>
</div>
<h1 id="title_movement_type"></h1>
<p style="margin-bottom:0;"><i>Passez un produit sous la douchette ! Si rien ne se passe, cliquez sur le champ ci-dessous puis ré-essayez.</i></p>
<p><i>Vous pouvez également taper le codebarre, puis appuyer sur la touche Entrée.</i></p>
</div>
<div class="barcode_search_area txtcenter">
<input type="text" id="sm_barcode_selector" placeholder="Codebarre">
<div id="icon_product_not_found" class="tooltip" style="display:none;">
<span class="tooltiptext tooltip-lg tt_twolines">Aucun produit trouvé avec ce code-barre.</span>
<span style="color: #d9534f;"> <i class="fas fa-ban"></i>
</div>
</div>
<div class="main">
<table id="products_table" class="display" cellspacing="0" ></table>
</div>
<div class="footer txtcenter" style="display:none">
<h4>Total (H.T.) : <span class="total_value">0</span></h4>
<button type="button" class="btn--primary" id="movement_validation_button" name="button">Validation du total des produits saisis</button>
</div>
<input type="hidden" name="barcode"/>
</div>
<div id="templates" style="display:none;">
<div id="modal_confirm_movement">
<h4 id="confirm_message_movtype"></h4>
<br>
<div class="confirmation_modal_content">
<div class="confirmation_checking_msgs">
<p id="confirmation_checking_price_msg"><i class="fas fa-spinner fa-spin"></i> Vérification des prix...</p>
<p id="confirmation_price_changed" style="display:none;"><i class="fas fa-exclamation-triangle"></i> Des prix ont changé, veuillez recharger la page après cette opération.</p>
</div>
<table id="confirmation_table" class="display" cellspacing="0" width="100%"></table>
</div>
<br>
<h5>Total (H.T.) : <span class="total_value">0</span></h5>
<hr />
</div>
<div id="modal_confirm_delete_line">
<p>Vous vous apprêtez à suprimer une ligne du tableau, <b>êtes-vous sûr ?</b></p>
</div>
</div>
</div>
<script src="{% static "js/all_common.js" %}?v="></script>
<script src='{% static "js/barcodes.js" %}?v='></script>
{% endblock %}
{% extends "base.html" %}
{% load static %}
{% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/stock_movements_view.css' %}">
<link rel="stylesheet" href="{% static 'jquery-ui-1.12.1/jquery-ui.min.css' %}">
{% endblock %}
{% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/datatables/dataTables.plugins.js' %}"></script>
<script type="text/javascript" src="{% static 'js/datatables/datatables.buttons.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/datatables/buttons.html5.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/stock_movements_view.js' %}?v="></script>
<script type="text/javascript" src="{% static 'jquery-ui-1.12.1/jquery-ui.min.js' %}?v="></script>
{% endblock %}
{% block content %}
<div class="page_body">
<div id="content_main" class="page_content">
<div class="header txtcenter">
<h1>Extraction de mouvements de stock</h1>
</div>
<div class="select_movement_area txtcenter">
<select class="select_movement_element select_movement_input" id="movement_type_selector" name="">
<option value="">-- Choisissez un type de mouvement --</option>
<option value="losses">Pertes</option>
<option value="meals">Repas salariés</option>
<option value="autoconso">Autoconsomation</option>
</select>
<p class="select_movement_element">De : <input type="text" id="from" class="select_movement_input"></p>
<p class="select_movement_element">À : <input type="text" id="to" class="select_movement_input"></p>
<button type="button" class="btn--primary" id="movement_selection_button" disabled>C'est parti !</button>
</div>
<div class="main" style="display:none;">
<div class="txtcenter">
<h3>Total de <span id="count_movements"></span> mouvements d'une valeur de <span id="total_value_movements"></span></h3>
</div>
<div class="table_area">
<table id="movements_table" class="display" cellspacing="0" width="100%"></table>
</div>
</div>
</div>
<div id="templates" style="display:none;">
</div>
</div>
<script src="{% static "js/all_common.js" %}?v="></script>
{% endblock %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment