Commit b174700f by François C.

Merge branch '2937-REC-update-qty-in-2nd-step' into 'dev_cooperatic'

2937 rec update qty in 2nd step

See merge request !189
parents 707b2289 bf02619f
Pipeline #2295 passed with stage
in 1 minute 26 seconds
...@@ -56,6 +56,7 @@ EM_URL = '' ...@@ -56,6 +56,7 @@ EM_URL = ''
RECEPTION_MERGE_ORDERS_PSWD = 'jpsrcp' RECEPTION_MERGE_ORDERS_PSWD = 'jpsrcp'
RECEPTION_ADD_PRODUCTS_PSWD = 'jpsrcp' RECEPTION_ADD_PRODUCTS_PSWD = 'jpsrcp'
RECEPTION_UPDATE_QTY_PSWD = 'jpsrcp'
RECEPTION_PB = "Ici, vous pouvez signaler toute anomalie lors d'une réception, les produits non commandés, cassés ou pourris. \ RECEPTION_PB = "Ici, vous pouvez signaler toute anomalie lors d'une réception, les produits non commandés, cassés ou pourris. \
Merci d'indiquer un maximum d'informations, le nom du produit et son code barre." Merci d'indiquer un maximum d'informations, le nom du produit et son code barre."
DISPLAY_COL_AUTRES = False DISPLAY_COL_AUTRES = False
......
...@@ -357,6 +357,10 @@ ...@@ -357,6 +357,10 @@
Password to enter to add products to an order during reception Password to enter to add products to an order during reception
Same principle as previous pswd Same principle as previous pswd
- RECEPTION_UPDATE_QTY_PSWD = 'pass2makeApause'
Password to update a product qty during prices update.
- RECEPTION_PDT_LABELS_BTN_TEXT = 'Lancer l\'impression' - RECEPTION_PDT_LABELS_BTN_TEXT = 'Lancer l\'impression'
- RECEPTION_PDT_LABELS_FN = 'print_product_labels()' - RECEPTION_PDT_LABELS_FN = 'print_product_labels()'
......
...@@ -280,6 +280,35 @@ tr.odd td.row_product_no_qty { ...@@ -280,6 +280,35 @@ tr.odd td.row_product_no_qty {
background-color: #acb3c2; background-color: #acb3c2;
} }
#error_report {
width: 100%;
height: 200px;
border: 2px solid #555;
border-radius: 10px;
white-space: pre-wrap;
}
#main_content {width: 100%;}
.select_product_action {
max-width: 5px;
}
.toProcess_line_edit, .toProcess_line_valid {
min-width: 11px;
}
.product_qty_cell {
cursor: pointer;
}
.product_qty_cell:hover {
background-color: #e7e9ed;
}
td.row_product_no_qty.product_qty_cell:hover {
background-color: #db9129;
}
/* Accordion style */ /* Accordion style */
/* Style the buttons that are used to open and close the accordion panel */ /* Style the buttons that are used to open and close the accordion panel */
...@@ -327,21 +356,3 @@ hr { ...@@ -327,21 +356,3 @@ hr {
.panel.active:after { .panel.active:after {
margin-bottom: 30px; margin-bottom: 30px;
} }
#error_report {
width: 100%;
height: 200px;
border: 2px solid #555;
border-radius: 10px;
white-space: pre-wrap;
}
#main_content {width: 100%;}
.select_product_action {
max-width: 5px;
}
.toProcess_line_edit, .toProcess_line_valid {
min-width: 11px;
}
\ No newline at end of file
...@@ -32,7 +32,8 @@ var reception_status = null, ...@@ -32,7 +32,8 @@ var reception_status = null,
barcodes = null, // Barcodes stored locally barcodes = null, // Barcodes stored locally
priceToWeightIsCorrect = true, priceToWeightIsCorrect = true,
suppliers_products = [], // All products of current order(s) supplier(s) suppliers_products = [], // All products of current order(s) supplier(s)
products_to_add = []; // Products to add to order products_to_add = [], // Products to add to order
re_editing_qty = false; // During prices edition, edit qty mode enabled
var dbc = null, var dbc = null,
sync = null, sync = null,
...@@ -495,6 +496,13 @@ function initLists() { ...@@ -495,6 +496,13 @@ function initLists() {
}); });
} }
// Titles for Qty column
const base_qty_title = "Qté";
const qty_title_tooltip = `<div class="tooltip tt_twolines">
Qté
<span class="tooltiptext">Qté comptée / Qté commandée</span>
</div>`;
columns_to_process = columns_to_process.concat([ columns_to_process = columns_to_process.concat([
{data:"product_id.0", title: "id", visible: false}, {data:"product_id.0", title: "id", visible: false},
{data:"shelf_sortorder", title: "Rayon", className: "dt-body-center", width: "4%"}, {data:"shelf_sortorder", title: "Rayon", className: "dt-body-center", width: "4%"},
...@@ -529,8 +537,8 @@ function initLists() { ...@@ -529,8 +537,8 @@ function initLists() {
}, },
{ {
data:"product_qty", data:"product_qty",
title: "Qté", title: (reception_status == "qty_valid") ? qty_title_tooltip : base_qty_title,
className:"dt-body-center", className: (reception_status == "qty_valid") ? "dt-body-center product_qty_cell" : "dt-body-center",
width: "5%", width: "5%",
render: function (data, type, full) { render: function (data, type, full) {
if (reception_status == "False") { if (reception_status == "False") {
...@@ -604,8 +612,8 @@ function initLists() { ...@@ -604,8 +612,8 @@ function initLists() {
{data:"product_uom.1", title: "Unité vente", className:"dt-body-center", orderable: false, width: "5%"}, {data:"product_uom.1", title: "Unité vente", className:"dt-body-center", orderable: false, width: "5%"},
{ {
data:"product_qty", data:"product_qty",
title:"Qté", title: qty_title_tooltip,
className:"dt-head-center dt-body-center", className: (reception_status == "qty_valid") ? "dt-head-center dt-body-center product_qty_cell" : "dt-head-center dt-body-center",
width: "5%", width: "5%",
// visible: (reception_status == "False"), // visible: (reception_status == "False"),
render: function (data, type, full) { render: function (data, type, full) {
...@@ -648,17 +656,30 @@ function initLists() { ...@@ -648,17 +656,30 @@ function initLists() {
} }
]; ];
table_to_process_ordering = [
[
0,
"asc"
]
];
// For grouped orders, order first by number of order, then by product id
if (is_grouped_order()) {
table_to_process_ordering.push(
[
1,
"asc"
]
)
}
// Init table for to_process content // Init table for to_process content
table_to_process = $('#table_to_process').DataTable({ table_to_process = $('#table_to_process').DataTable({
data: list_to_process, data: list_to_process,
columns: columns_to_process, columns: columns_to_process,
rowId : "product_id.0", rowId : "product_id.0",
order: [ order: table_to_process_ordering,
[
0,
"asc"
]
],
scrollY: "33vh", scrollY: "33vh",
scrollCollapse: true, scrollCollapse: true,
paging: false, paging: false,
...@@ -895,6 +916,68 @@ function initLists() { ...@@ -895,6 +916,68 @@ function initLists() {
clearLineEdition(); clearLineEdition();
} }
}); });
$('#table_to_process tbody').on('click', '.product_qty_cell', function () {
// Prevent editing mutiple lines at a time
if (editing_product == null) {
let pswd = prompt('Mot de passe requis pour éditer la quantité de ce produit');
if (pswd == update_qty_pswd) {
// Password ok, edit product qty
let row = table_to_process.row($(this).parents('tr'));
let data = row.data();
// Product goes to editing
editing_origin = "to_process";
re_editing_qty = true;
setLineEdition(data);
remove_from_toProcess(row, data);
document.getElementById('search_input').value = '';
$('table.dataTable').DataTable()
.search('')
.draw();
} else if (pswd == null) {
return;
} else {
alert('Mauvais mot de passe !');
}
} else {
alert("Il y a déjà un produit dans la zone d'édition. Terminez d'abord d'éditer ce produit.")
}
});
$('#table_processed tbody').on('click', '.product_qty_cell', function () {
// Prevent editing mutiple lines at a time
if (editing_product == null) {
let pswd = prompt('Mot de passe requis pour éditer la quantité de ce produit');
if (pswd == update_qty_pswd) {
// Password ok, edit product qty
let row = table_processed.row($(this).parents('tr'));
let data = row.data();
// Product goes to editing
editing_origin = "processed";
re_editing_qty = true;
setLineEdition(data);
remove_from_processed(row, data);
document.getElementById('search_input').value = '';
$('table.dataTable').DataTable()
.search('')
.draw();
} else if (pswd == null) {
return;
} else {
alert('Mauvais mot de passe !');
}
} else {
alert("Il y a déjà un produit dans la zone d'édition. Terminez d'abord d'éditer ce produit.")
}
});
} }
// Add a line to to_process // Add a line to to_process
...@@ -1076,23 +1159,23 @@ function set_supplier_shortage(row, product, from_processed = false) { ...@@ -1076,23 +1159,23 @@ function set_supplier_shortage(row, product, from_processed = false) {
/* EDITION */ /* EDITION */
// Set edition // Set edition area
function setLineEdition(product) { function setLineEdition(product) {
editing_product = product; editing_product = product;
// name // name
document.getElementById('product_name').innerHTML = editing_product.product_id[1]; document.getElementById('product_name').innerHTML = editing_product.product_id[1];
// intput // intput
if (reception_status == "qty_valid") if (reception_status == 'False' || re_editing_qty === true)
document.getElementById('edition_input').value = editing_product.price_unit;
else
document.getElementById('edition_input').value = editing_product.product_qty; document.getElementById('edition_input').value = editing_product.product_qty;
else
document.getElementById('edition_input').value = editing_product.price_unit;
document.getElementById("edition_input").focus(); document.getElementById("edition_input").focus();
// uom // uom
if (editing_product.product_uom[0] == 1) { // Unit if (editing_product.product_uom[0] == 1) { // Unit
if (reception_status == 'False') { if (reception_status == 'False' || re_editing_qty === true) {
document.getElementById('product_uom').innerHTML = ' unité(s)'; document.getElementById('product_uom').innerHTML = ' unité(s)';
$('#edition_input').attr('type', 'number') $('#edition_input').attr('type', 'number')
.attr('step', 1) .attr('step', 1)
...@@ -1104,7 +1187,7 @@ function setLineEdition(product) { ...@@ -1104,7 +1187,7 @@ function setLineEdition(product) {
.attr('max', 9999); .attr('max', 9999);
} }
} else if (editing_product.product_uom[0] == 21) { // kg } else if (editing_product.product_uom[0] == 21) { // kg
if (reception_status == 'False') { if (reception_status == 'False' || re_editing_qty === true) {
document.getElementById('product_uom').innerHTML = ' kg'; document.getElementById('product_uom').innerHTML = ' kg';
$('#edition_input').attr('type', 'number') $('#edition_input').attr('type', 'number')
.attr('step', 0.001) .attr('step', 0.001)
...@@ -1117,6 +1200,12 @@ function setLineEdition(product) { ...@@ -1117,6 +1200,12 @@ function setLineEdition(product) {
} }
} }
// If editing qty during prices edition
if (re_editing_qty === true) {
document.getElementById('edition_header').innerHTML = "Ré-éditer la quantité";
document.getElementById('edition_input_label').innerHTML = "Qté";
}
// Make edition area blink when edition button clicked // Make edition area blink when edition button clicked
container_edition.classList.add('blink_me'); container_edition.classList.add('blink_me');
} }
...@@ -1130,6 +1219,13 @@ function clearLineEdition() { ...@@ -1130,6 +1219,13 @@ function clearLineEdition() {
document.getElementById('edition_input').value = null; document.getElementById('edition_input').value = null;
document.getElementById('search_input').focus(); document.getElementById('search_input').focus();
document.getElementById('product_uom').innerHTML = ''; document.getElementById('product_uom').innerHTML = '';
if (re_editing_qty === true) {
document.getElementById('edition_header').innerHTML = "Editer les prix";
document.getElementById('edition_input_label').innerHTML = "Prix unit.";
re_editing_qty = false;
}
} }
/** /**
...@@ -1154,6 +1250,57 @@ function editProductInfo (productToEdit, value = null, batch = false) { ...@@ -1154,6 +1250,57 @@ function editProductInfo (productToEdit, value = null, batch = false) {
newValue = isFinite(newValue) ? newValue : 0; newValue = isFinite(newValue) ? newValue : 0;
} }
// Particular process in case of qty reedition during prices update
if (re_editing_qty === true) {
// Look for product in product's order first step data
let previous_step_index = -1;
for (let i = 0; i < orders[productToEdit.id_po]["previous_steps_data"]["False"]["updated_products"].length; i++) {
if (
orders[productToEdit.id_po]["previous_steps_data"]["False"]["updated_products"][i].id
===
productToEdit.id
) {
previous_step_index = i;
break;
}
}
if (previous_step_index === -1) {
// Product qty hasn't been updated yet: add to first step data
productToEdit.old_qty = productToEdit.product_qty;
productToEdit.product_qty = newValue;
productToEdit.product_qty_package = 1;
productToEdit.package_qty = productToEdit.product_qty;
orders[productToEdit.id_po]["previous_steps_data"]["False"]["updated_products"].push(productToEdit)
} else {
productToEdit.product_qty = newValue;
productToEdit.package_qty = productToEdit.product_qty;
// Product qty has been updated before, update first step data
orders[productToEdit.id_po]["previous_steps_data"]["False"]["updated_products"][previous_step_index].product_qty = newValue;
orders[productToEdit.id_po]["previous_steps_data"]["False"]["updated_products"][previous_step_index].package_qty = newValue;
}
/* Send request to server to update a single product */
updateType = "qty_valid";
send([productToEdit]);
// Update temp couchdb order
update_distant_order(productToEdit.id_po);
// Put back product in its original list
if (editing_origin === "to_process") {
add_to_toProcess(productToEdit);
} else if (editing_origin === "processed") {
add_to_processed(productToEdit);
}
return true;
}
// addition mode = weight is directly added from scanned product // addition mode = weight is directly added from scanned product
$.each(list_processed, function(i, e) { $.each(list_processed, function(i, e) {
if ( if (
...@@ -1433,8 +1580,14 @@ function data_validation() { ...@@ -1433,8 +1580,14 @@ function data_validation() {
}); });
} }
// Send the request to the server /**
function send() { * Send the request to update order(s) data
*
* @param {Array} given_products If set, only update these products.
* If no given products, we're in the regular process, ie the end of a reception.
* Else, we're in the middle of a reception, so we'll skip some parts.
*/
function send(given_products = []) {
try { try {
// Loading on // Loading on
openModal(); openModal();
...@@ -1451,15 +1604,19 @@ function send() { ...@@ -1451,15 +1604,19 @@ function send() {
update_data.orders[order_id] = {'po' : []}; update_data.orders[order_id] = {'po' : []};
} }
has_given_products = given_products.length > 0;
// If given products, update these only, else update global updatedProducts list
products_to_update = has_given_products === true ? given_products : updatedProducts;
// for each updated product, add it to its order list // for each updated product, add it to its order list
for (i in updatedProducts) { for (i in products_to_update) {
/* ---> The following part concerns products found in different orders */ /* ---> The following part concerns products found in different orders */
if ('other_orders_data' in updatedProducts[i]) { if ('other_orders_data' in products_to_update[i]) {
// for each other order of product // for each other order of product
for (other_order_data of updatedProducts[i].other_orders_data) { for (other_order_data of products_to_update[i].other_orders_data) {
// Make a clone (deep copy) of the product object // Make a clone (deep copy) of the product object
let product_copy = $.extend(true, {}, updatedProducts[i]); let product_copy = $.extend(true, {}, products_to_update[i]);
// Set correct order line id for this product // Set correct order line id for this product
product_copy.id = other_order_data.id_product; product_copy.id = other_order_data.id_product;
...@@ -1468,30 +1625,30 @@ function send() { ...@@ -1468,30 +1625,30 @@ function send() {
if (reception_status == 'False') { if (reception_status == 'False') {
// Reset initial qties in respective orders // Reset initial qties in respective orders
product_copy.old_qty = other_order_data.initial_qty; product_copy.old_qty = other_order_data.initial_qty;
for (j in orders[updatedProducts[i].id_po]['updated_products']) { for (j in orders[products_to_update[i].id_po]['updated_products']) {
if (orders[updatedProducts[i].id_po]['updated_products'][j].product_id[0] if (orders[products_to_update[i].id_po]['updated_products'][j].product_id[0]
== product_copy.product_id[0]) { == product_copy.product_id[0]) {
orders[updatedProducts[i].id_po]['updated_products'][j].old_qty -= other_order_data.initial_qty; orders[products_to_update[i].id_po]['updated_products'][j].old_qty -= other_order_data.initial_qty;
break; break;
} }
} }
if (product_copy.product_uom[0] == 21 && updatedProducts[i].product_qty > 0.1) { // kg if (product_copy.product_uom[0] == 21 && products_to_update[i].product_qty > 0.1) { // kg
// Add minimum qty in other orders // Add minimum qty in other orders
product_copy.product_qty_package = 1; product_copy.product_qty_package = 1;
product_copy.package_qty = 0.1; product_copy.package_qty = 0.1;
product_copy.product_qty = 0.1; product_copy.product_qty = 0.1;
// Remove this qty from first order // Remove this qty from first order
updatedProducts[i].package_qty -= 0.1; products_to_update[i].package_qty -= 0.1;
updatedProducts[i].product_qty -= 0.1; products_to_update[i].product_qty -= 0.1;
} else if (product_copy.product_uom[0] == 1 && updatedProducts[i].product_qty > 1) { // Unit } else if (product_copy.product_uom[0] == 1 && products_to_update[i].product_qty > 1) { // Unit
product_copy.product_qty_package = 1; product_copy.product_qty_package = 1;
product_copy.package_qty = 1; product_copy.package_qty = 1;
product_copy.product_qty = 1; product_copy.product_qty = 1;
updatedProducts[i].package_qty -= 1; products_to_update[i].package_qty -= 1;
updatedProducts[i].product_qty -= 1; products_to_update[i].product_qty -= 1;
} else { // Not handled, all qty in one order } else { // Not handled, all qty in one order
product_copy.product_qty_package = 0; product_copy.product_qty_package = 0;
product_copy.package_qty = 0; product_copy.package_qty = 0;
...@@ -1514,16 +1671,18 @@ function send() { ...@@ -1514,16 +1671,18 @@ function send() {
/* <--- */ /* <--- */
// Add product to order's prod list // Add product to order's prod list
prod_order_id = updatedProducts[i].id_po; prod_order_id = products_to_update[i].id_po;
update_data.orders[prod_order_id]['po'].push(updatedProducts[i]); update_data.orders[prod_order_id]['po'].push(products_to_update[i]);
} }
// Only send error report & no barcode list when no given products (ie normal process, end of reception)
if (has_given_products === false) {
/* Create the error report */ /* Create the error report */
// Send changes between items to process and processed items // Send changes between items to process and processed items
var error_report_data = { var error_report_data = {
'group_amount_total' : 0, 'group_amount_total' : 0,
'update_type' : updateType, 'update_type' : updateType,
'updated_products' : updatedProducts, 'updated_products' : products_to_update,
'user_comments': user_comments, 'user_comments': user_comments,
'orders' : [] 'orders' : []
}; };
...@@ -1580,6 +1739,7 @@ function send() { ...@@ -1580,6 +1739,7 @@ function send() {
alert('Erreur dans l\'envoi du rapport.'); alert('Erreur dans l\'envoi du rapport.');
} }
}); });
}
/* Update orders */ /* Update orders */
$.ajax({ $.ajax({
...@@ -1592,6 +1752,7 @@ function send() { ...@@ -1592,6 +1752,7 @@ function send() {
success: function() { success: function() {
closeModal(); closeModal();
if (has_given_products === false) {
try { try {
// If step 1 (counting) // If step 1 (counting)
if (reception_status == "False") { if (reception_status == "False") {
...@@ -1750,6 +1911,7 @@ function send() { ...@@ -1750,6 +1911,7 @@ function send() {
console.error(err); console.error(err);
report_JS_error(err, 'reception'); report_JS_error(err, 'reception');
} }
}
}, },
error: function() { error: function() {
closeModal(); closeModal();
......
...@@ -93,6 +93,7 @@ def produits(request, id): ...@@ -93,6 +93,7 @@ def produits(request, id):
"ADD_ALL_LEFT_IS_GOOD_QTIES": False, "ADD_ALL_LEFT_IS_GOOD_QTIES": False,
"ADD_ALL_LEFT_IS_GOOD_PRICES": False, "ADD_ALL_LEFT_IS_GOOD_PRICES": False,
'add_products_pswd': getattr(settings, 'RECEPTION_ADD_PRODUCTS_PSWD', 'makeastop'), 'add_products_pswd': getattr(settings, 'RECEPTION_ADD_PRODUCTS_PSWD', 'makeastop'),
'update_qty_pswd': getattr(settings, 'RECEPTION_UPDATE_QTY_PSWD', 'makeastop')
} }
fixed_barcode_prefix = '0490' fixed_barcode_prefix = '0490'
......
...@@ -241,6 +241,7 @@ ...@@ -241,6 +241,7 @@
var add_all_left_is_good_qties = "{{ADD_ALL_LEFT_IS_GOOD_QTIES}}" var add_all_left_is_good_qties = "{{ADD_ALL_LEFT_IS_GOOD_QTIES}}"
var add_all_left_is_good_prices = "{{ADD_ALL_LEFT_IS_GOOD_PRICES}}" var add_all_left_is_good_prices = "{{ADD_ALL_LEFT_IS_GOOD_PRICES}}"
var add_products_pswd = "{{add_products_pswd}}" var add_products_pswd = "{{add_products_pswd}}"
var update_qty_pswd = "{{update_qty_pswd}}"
</script> </script>
<script src="{% static "js/all_common.js" %}?v=1651853225"></script> <script src="{% static "js/all_common.js" %}?v=1651853225"></script>
<script src='{% static "js/barcodes.js" %}?v=1651853225'></script> <script src='{% static "js/barcodes.js" %}?v=1651853225'></script>
......
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