Commit f962b763 by François C.

Merge branch '2936-reception-add-products' into 'dev_cooperatic'

2936 reception add products

See merge request !185
parents 5916f6b2 3b618502
Pipeline #2270 passed with stage
in 1 minute 27 seconds
...@@ -55,6 +55,7 @@ EM_URL = '' ...@@ -55,6 +55,7 @@ EM_URL = ''
RECEPTION_MERGE_ORDERS_PSWD = 'jpsrcp' RECEPTION_MERGE_ORDERS_PSWD = 'jpsrcp'
RECEPTION_ADD_PRODUCTS_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
......
...@@ -352,6 +352,11 @@ ...@@ -352,6 +352,11 @@
Password to enter to validate merge orders processing Password to enter to validate merge orders processing
It has been set only to stop member action, considering the impact of the merge It has been set only to stop member action, considering the impact of the merge
- RECEPTION_ADD_PRODUCTS_PSWD = 'pass2makeApause'
Password to enter to add products to an order during reception
Same principle as previous pswd
- 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()'
......
...@@ -17,18 +17,22 @@ class CagetteReception(models.Model): ...@@ -17,18 +17,22 @@ class CagetteReception(models.Model):
self.id = int(id) self.id = int(id)
self.o_api = OdooAPI() self.o_api = OdooAPI()
def get_orders(): def get_orders(pids=[]):
"""Recupere la liste des BC en cours """ """
Recupere la liste des BC en cours.
pids: Id des purchase.order à récupérer. Limite la recherche si défini.
"""
orders = [] orders = []
try: try:
api = OdooAPI() api = OdooAPI()
f = ["purchase_id"] if len(pids) == 0:
c = [['picking_type_id', '=', 1], ["state", "in", ['assigned', 'partially_available']]] f = ["purchase_id"]
res = api.search_read('stock.picking', c, f) c = [['picking_type_id', '=', 1], ["state", "in", ['assigned', 'partially_available']]]
pids = [] res = api.search_read('stock.picking', c, f)
if res and len(res) > 0: pids = []
for r in res: if res and len(res) > 0:
pids.append(int(r['purchase_id'][0])) for r in res:
pids.append(int(r['purchase_id'][0]))
if len(pids): if len(pids):
f=["id","name","date_order", "partner_id", "date_planned", "amount_untaxed", "amount_total", "x_reception_status", 'create_uid'] f=["id","name","date_order", "partner_id", "date_planned", "amount_untaxed", "amount_total", "x_reception_status", 'create_uid']
......
...@@ -205,6 +205,76 @@ tr.odd td.row_product_no_qty { ...@@ -205,6 +205,76 @@ tr.odd td.row_product_no_qty {
background-color: rgb(236, 182, 106); /*#ec971f*/ background-color: rgb(236, 182, 106); /*#ec971f*/
} }
.add_products_button_container {
display: flex;
justify-content: center;
align-items: center;
}
#add_products_button {
display: none;
}
.search_products_to_add_area {
margin: 2rem 0;
display: flex;
align-items: center;
justify-content: center;
}
.search_product_input {
width: 60%;
}
.autocomplete_dropdown {
z-index: 10000001 !important;
}
.search_product_help {
margin-left: 10px;
}
.products_lines {
display: none;
}
.products_lines_title {
margin: 3rem 0 2rem 0;
}
.add_product_line {
display: flex;
align-items: center;
margin: 1rem 0;
}
.add_product_line_item {
width: 45%;
display: flex;
flex-direction: column;
align-items: center;
}
.product_qty_input_alert {
color: #d9534f;
font-size: 1.4rem;
display: none;
}
.remove_line {
width: 10%;
color: #d9534f;
cursor: pointer;
}
.remove_line:hover {
color: #c9302c;
}
.product_already_selected,
.product_already_selected:hover {
background-color: #acb3c2;
}
/* 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 */
......
...@@ -13,7 +13,6 @@ Sémantiquement, ici : ...@@ -13,7 +13,6 @@ Sémantiquement, ici :
* Associative array of current order(s) * Associative array of current order(s)
* If more than 1 element: group of orders * If more than 1 element: group of orders
* If 1 element: single order * If 1 element: single order
* -> check for Object.keys(orders).length to know if we're in a group case
*/ */
var orders = {}, var orders = {},
group_ids = []; group_ids = [];
...@@ -31,7 +30,9 @@ var reception_status = null, ...@@ -31,7 +30,9 @@ var reception_status = null,
validProducts = [], // Keep record of directly validated products validProducts = [], // Keep record of directly validated products
updateType = "", // step 1: qty_valid; step2: br_valid updateType = "", // step 1: qty_valid; step2: br_valid
barcodes = null, // Barcodes stored locally barcodes = null, // Barcodes stored locally
priceToWeightIsCorrect = true; priceToWeightIsCorrect = true,
suppliers_products = [], // All products of current order(s) supplier(s)
products_to_add = []; // Products to add to order
var dbc = null, var dbc = null,
sync = null, sync = null,
...@@ -43,6 +44,30 @@ function back() { ...@@ -43,6 +44,30 @@ function back() {
document.location.href = "/reception"; document.location.href = "/reception";
} }
/**
* Dingle order or grouped orders?
* @returns Boolean
*/
function is_grouped_order() {
return Object.keys(orders).length > 1;
}
/**
* Get distinct suppliers id of current orders
* @returns Boolean
*/
function get_suppliers_id() {
let suppliers_id = [];
for (var order_id in orders) {
if ('partner_id' in orders[order_id]) { // check for versions transition
suppliers_id.push(orders[order_id].partner_id);
}
}
return suppliers_id;
}
/** Search if the product being edited is already in the updated products. /** Search if the product being edited is already in the updated products.
* Returns its index or -1. * Returns its index or -1.
*/ */
...@@ -239,10 +264,15 @@ function resetPopUpButtons() { ...@@ -239,10 +264,15 @@ function resetPopUpButtons() {
document.querySelector('#modal_closebtn_bottom').style.backgroundColor = ""; document.querySelector('#modal_closebtn_bottom').style.backgroundColor = "";
} }
/* INIT */ /* FETCH SERVER DATA */
/**
* Get order(s) data from server
* @param {Array} po_ids if set, fetch data for these po only
*/
function fetch_data(po_ids = null) {
let po_to_fetch = (po_ids === null) ? group_ids : po_ids;
// Get order(s) data from server
function fetch_data() {
try { try {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
...@@ -250,7 +280,7 @@ function fetch_data() { ...@@ -250,7 +280,7 @@ function fetch_data() {
dataType:"json", dataType:"json",
traditional: true, traditional: true,
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
data: JSON.stringify({'po_ids' : group_ids}), data: JSON.stringify({'po_ids' : po_to_fetch}),
success: function(data) { success: function(data) {
// for each order // for each order
for (order_data of data.orders) { for (order_data of data.orders) {
...@@ -331,6 +361,74 @@ function fetch_data() { ...@@ -331,6 +361,74 @@ function fetch_data() {
} }
} }
// Load barcodes at page loading, then barcodes are stored locally
var get_barcodes = async function() {
if (barcodes == null) barcodes = await init_barcodes();
};
// Get labels to print for current orders from server
function get_pdf_labels() {
try {
if (is_time_to('print_pdf_labels', 10000)) {
// Concatenate orders id into a string, separated with comas, to retrieve
oids = group_ids.join(',');
// Send request & diret download pdf
var filename = "codebarres_" + group_ids[0] + ".pdf";
$.ajax({
url: "../../orders/get_pdf_labels?oids=" + oids,
success: download.bind(true, "pdf", filename)
});
} else {
alert("Vous avez cliqué il y a moins de 10s... Patience, la demande est en cours de traitement.");
}
} catch (e) {
err = {msg: e.name + ' : ' + e.message, ctx: 'get_pdf_labels'};
console.error(err);
report_JS_error(err, 'reception');
}
}
/**
* Get products of order(s) supplier(s) if not already fetched
*/
function fetch_suppliers_products() {
if (suppliers_products.length === 0) {
openModal();
let suppliers_id = get_suppliers_id();
// Fetch supplier products
$.ajax({
type: 'GET',
url: "/orders/get_supplier_products",
data: {
sids: suppliers_id
},
dataType:"json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function(data) {
suppliers_products = data.res.products;
closeModal();
set_add_products_modal();
},
error: function(data) {
err = {msg: "erreur serveur lors de la récupération des produits du fournisseur", ctx: 'get_supplier_products'};
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error;
}
report_JS_error(err, 'reception');
closeModal();
alert('Erreur lors de la récupération des produits, réessayer plus tard.');
}
});
} else {
set_add_products_modal();
}
}
/* LISTS HANDLING */ /* LISTS HANDLING */
...@@ -385,7 +483,7 @@ function initLists() { ...@@ -385,7 +483,7 @@ function initLists() {
let columns_processed = []; let columns_processed = [];
// In case of group orders, add "Order" as first column for ordering // In case of group orders, add "Order" as first column for ordering
if (Object.keys(orders).length > 1) { if (is_grouped_order()) {
columns_to_process.push({ columns_to_process.push({
data:"order_key", title: "n°", className: "dt-body-center", data:"order_key", title: "n°", className: "dt-body-center",
width: "20px" width: "20px"
...@@ -1223,30 +1321,6 @@ function setAllQties() { ...@@ -1223,30 +1321,6 @@ function setAllQties() {
/* ACTIONS */ /* ACTIONS */
// Get labels to print for current orders from server
function get_pdf_labels() {
try {
if (is_time_to('print_pdf_labels', 10000)) {
// Concatenate orders id into a string, separated with comas, to retrieve
oids = group_ids.join(',');
// Send request & diret download pdf
var filename = "codebarres_" + group_ids[0] + ".pdf";
$.ajax({
url: "../../orders/get_pdf_labels?oids=" + oids,
success: download.bind(true, "pdf", filename)
});
} else {
alert("Vous avez cliqué il y a moins de 10s... Patience, la demande est en cours de traitement.");
}
} catch (e) {
err = {msg: e.name + ' : ' + e.message, ctx: 'get_pdf_labels'};
console.error(err);
report_JS_error(err, 'reception');
}
}
function print_product_labels() { function print_product_labels() {
try { try {
if (is_time_to('print_pdt_labels', 10000)) { if (is_time_to('print_pdt_labels', 10000)) {
...@@ -1551,7 +1625,7 @@ function send() { ...@@ -1551,7 +1625,7 @@ function send() {
} }
// Set order(s) name in popup DOM // Set order(s) name in popup DOM
if (Object.keys(orders).length === 1) { // Single order if (is_grouped_order() === false) { // Single order
document.getElementById("order_ref").innerHTML = orders[Object.keys(orders)[0]].name; document.getElementById("order_ref").innerHTML = orders[Object.keys(orders)[0]].name;
} else { // group } else { // group
document.getElementById("success_order_name_container").hidden = true; document.getElementById("success_order_name_container").hidden = true;
...@@ -1633,7 +1707,7 @@ function send() { ...@@ -1633,7 +1707,7 @@ function send() {
let couchdb_update_data = Object.values(orders); let couchdb_update_data = Object.values(orders);
// We're in a group, remove it & update groups doc // We're in a group, remove it & update groups doc
if (Object.keys(orders).length > 1) { if (is_grouped_order()) {
let groups_doc = doc; let groups_doc = doc;
let first_order_id = parseInt(Object.keys(orders)[0]); let first_order_id = parseInt(Object.keys(orders)[0]);
...@@ -1709,6 +1783,233 @@ function confirm_all_left_is_good() { ...@@ -1709,6 +1783,233 @@ function confirm_all_left_is_good() {
closeModal(); closeModal();
} }
function saveErrorReport() {
user_comments = document.getElementById("error_report").value;
// Save comments in all orders
for (order_id of Object.keys(orders)) {
orders[order_id].user_comments = user_comments;
update_distant_order(order_id);
}
document.getElementById("search_input").focus();
}
/**
* Check if all qty inputs are set first.
* Adding products leads to creating a new order (for each supplier) that will be grouped with the current one(s)
*/
function add_products_action() {
let qty_inputs = $("#modal .products_lines").find(".product_qty_input");
let has_empty_qty_input = false;
for (let qty_input of qty_inputs) {
if ($(qty_input).val() === "") {
has_empty_qty_input = true;
$(qty_input).siblings(".product_qty_input_alert")
.show();
} else {
$(qty_input).siblings(".product_qty_input_alert")
.hide();
}
}
if (qty_inputs.length > 0 && has_empty_qty_input === false) {
create_orders();
}
}
/**
* Send request to create the new orders
*/
function create_orders() {
let orders_data = {
"suppliers_data": {}
};
// Mock order date_planned : today
let date_object = new Date();
formatted_date = date_object.toISOString().replace('T', ' ')
.split('.')[0]; // Get ISO format bare string
for (let supplier_id of get_suppliers_id()) {
orders_data.suppliers_data[supplier_id] = {
date_planned: formatted_date,
lines: []
};
}
// Prepare data: get products with their qty
for (let p of products_to_add) {
// Get product qty from input
let product_qty = 0;
let add_products_lines = $("#modal .add_product_line");
for (let i = 0; i < add_products_lines.length; i++) {
let line = add_products_lines[i];
if ($(line).find(".product_name")
.text() === p.name) {
product_qty = parseFloat($(line).find(".product_qty_input")
.val());
break;
}
}
let p_supplierinfo = p.suppliersinfo[0]; // product is ordered at its first supplier
const supplier_id = p_supplierinfo.supplier_id;
orders_data.suppliers_data[supplier_id].lines.push({
'package_qty': p_supplierinfo.package_qty,
'product_id': p.id,
'name': p.name,
'product_qty_package': (product_qty / p_supplierinfo.package_qty).toFixed(2),
'product_qty': product_qty,
'product_uom': p.uom_id[0],
'price_unit': p_supplierinfo.price,
'supplier_taxes_id': p.supplier_taxes_id,
'product_variant_ids': p.product_variant_ids,
'product_code': p_supplierinfo.product_code
});
}
// Remove supplier from order data if no lines
for (const supplier_id in orders_data.suppliers_data) {
if (orders_data.suppliers_data[supplier_id].lines.length === 0) {
delete(orders_data.suppliers_data[supplier_id]);
}
}
openModal();
$("#modal em:contains('Chargement en cours...')").append("<br/>L'opération peut prendre un certain temps...");
$.ajax({
type: "POST",
url: "/orders/create_orders",
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(orders_data),
success: (result) => {
po_ids = [];
for (let po of result.res.created) {
po_ids.push(po.id_po);
}
// Get orders data as needed by the module with order lines
$.ajax({
type: 'GET',
url: "/reception/get_list_orders",
dataType:"json",
traditional: true,
contentType: "application/json; charset=utf-8",
data: {
poids: po_ids,
get_order_lines: true
},
success: function(result2) {
let current_orders_key = group_ids.length;
for (let new_order of result2.data) {
// Add key (position in orders list) to new orders data
current_orders_key += 1;
new_order.key = current_orders_key;
// Consider new order lines as updated products
new_order.updated_products = new_order.po;
delete(new_order.po);
// Add necessary data to order updated products
for (let noup of new_order.updated_products) {
noup.order_key = current_orders_key;
noup.id_po = String(new_order.id);
noup.old_qty = 0; // products weren't originally ordered
}
// Create couchdb doc for the new order
create_order_doc(new_order);
}
dbc.get("grouped_orders").then((doc) => {
// Not a group (yet)
if (group_ids.length === 1) {
group_ids = group_ids.concat(po_ids);
doc.groups.push(group_ids);
} else {
for (let i in doc.groups) {
// If group found in saved distatnt groups
if (group_ids.findIndex(e => e == doc.groups[i][0]) !== -1) {
doc.groups[i] = doc.groups[i].concat(po_ids);
doc.groups[i].sort();
group_ids = doc.groups[i];
}
}
}
dbc.put(doc, () => {
// Update screen
// The easy way: reload page now all data is correctly set.
window.location.reload();
});
});
},
error: function(data) {
err = {msg: "erreur serveur lors de la récupération des commandes", ctx: 'get_list_orders'};
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error;
}
report_JS_error(err, 'orders');
closeModal();
alert('Erreur lors de la récupération des commandes, rechargez la page plus tard.');
}
});
},
error: function(data) {
let msg = "erreur serveur lors de la création des product orders";
err = {msg: msg, ctx: 'create_orders', data: orders_data};
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error;
}
report_JS_error(err, 'reception');
closeModal();
alert('Erreur lors de la création des commandes. Veuillez ré-essayer plus tard.');
}
});
}
/**
* Create a couchdb document for an order
*
* @param {Object} order_data
*/
function create_order_doc(order_data) {
const order_doc_id = 'order_' + order_data.id;
order_data._id = order_doc_id;
order_data.last_update = {
timestamp: Date.now(),
fingerprint: fingerprint
};
dbc.put(order_data).then(() => {})
.catch((err) => {
error = {
msg: 'Erreur dans la creation de la commande dans couchdb',
ctx: 'create_order_doc',
details: err
};
report_JS_error(error, 'reception');
console.log(error);
});
}
/* DOM */
function openFAQ() { function openFAQ() {
openModal($("div#modal_FAQ_content").html(), function() {}, 'Compris !', true, false); openModal($("div#modal_FAQ_content").html(), function() {}, 'Compris !', true, false);
} }
...@@ -1733,24 +2034,94 @@ function openErrorReport() { ...@@ -1733,24 +2034,94 @@ function openErrorReport() {
textarea.setSelectionRange(textarea.value.length, textarea.value.length); textarea.setSelectionRange(textarea.value.length, textarea.value.length);
} }
function saveErrorReport() { /**
user_comments = document.getElementById("error_report").value; * Set the autocomplete on add products modal, search product input.
* If extists, destroys instance and recreate it.
* Filter autocomplete data by removing products already selected.
*/
function set_products_autocomplete() {
// Filter autocomplete products on products already in orders
let autocomplete_products = suppliers_products.filter(p => list_to_process.findIndex(ptp => ptp.product_id[1] === p.name) === -1);
// Save comments in all orders autocomplete_products = autocomplete_products.filter(p => list_processed.findIndex(pp => pp.product_id[1] === p.name) === -1);
for (order_id of Object.keys(orders)) {
orders[order_id].user_comments = user_comments; console.log(products_to_add);
update_distant_order(order_id); // Filter autocomplete products on products already selected
autocomplete_products = autocomplete_products.filter(p => products_to_add.findIndex(pta => pta.name === p.name) === -1);
try {
$("#modal .search_product_input").autocomplete("destroy");
} catch (error) {
// autocomplete not set yet, do nothing
} }
document.getElementById("search_input").focus(); $("#modal .search_product_input").autocomplete({
source: autocomplete_products.map(p => p.name),
classes: {
"ui-autocomplete": "autocomplete_dropdown"
},
delay: 0,
select: function(event, ui) {
// Action called when an item is selected
event.preventDefault();
let product_name = ui.item.label;
// extra secutiry but shouldn't happen
if (products_to_add.findIndex(p => p.name === product_name) === -1) {
let product = suppliers_products.find(p => p.name === product_name);
products_to_add.push(product);
// Display
let add_product_template = $("#add_product_line_template");
add_product_template.find(".product_name").text(product_name);
$("#modal .products_lines").append(add_product_template.html());
if (products_to_add.length === 1) {
$("#modal .products_lines").show();
}
$(".remove_line_icon").off("click");
$(".remove_line_icon").on("click", remove_product_line);
// Reset search elements
$("#modal .search_product_input").val('');
set_products_autocomplete();
}
}
});
} }
// Load barcodes at page loading, then barcodes are stored locally /**
var get_barcodes = async function() { * Remove product from list of products to add & remove line from DOM
if (barcodes == null) barcodes = await init_barcodes(); * @param {Event} e
}; */
function remove_product_line(e) {
let product_line = $(e.target).closest(".add_product_line");
let product_name = product_line.find(".product_name").text();
let product_to_add_index = products_to_add.findIndex(p => p.name === product_name);
products_to_add.splice(product_to_add_index, 1);
product_line.remove();
set_products_autocomplete();
}
/**
* Set & display the modal to search products
*/
function set_add_products_modal() {
let add_products_modal = $("#modal_add_products");
openModal(
add_products_modal.html(),
add_products_action,
'Ajouter les produits',
false
);
set_products_autocomplete();
}
/** /**
* Init the page according to order(s) data (texts, colors, events...) * Init the page according to order(s) data (texts, colors, events...)
...@@ -1777,7 +2148,7 @@ function init_dom(partners_display_data) { ...@@ -1777,7 +2148,7 @@ function init_dom(partners_display_data) {
}); });
// Grouped orders // Grouped orders
if (Object.keys(orders).length > 1) { if (is_grouped_order()) {
$('#partner_name').html(Object.keys(orders).length + " commandes"); $('#partner_name').html(Object.keys(orders).length + " commandes");
// Display order data for each order // Display order data for each order
...@@ -1830,6 +2201,9 @@ function init_dom(partners_display_data) { ...@@ -1830,6 +2201,9 @@ function init_dom(partners_display_data) {
document.getElementById('edition_header').innerHTML = "Editer les quantités"; document.getElementById('edition_header').innerHTML = "Editer les quantités";
document.getElementById('edition_input_label').innerHTML = "Qté"; document.getElementById('edition_input_label').innerHTML = "Qté";
// Add products button
document.getElementById('add_products_button').style.display = "block";
document.getElementById("valid_all").innerHTML = "<button class='btn--danger full_width_button' id='valid_all_qties' onclick=\"openModal($('#templates #modal_no_qties').html(), setAllQties, 'Confirmer');\" disabled>Il n'y a plus de produits à compter</button>"; document.getElementById("valid_all").innerHTML = "<button class='btn--danger full_width_button' id='valid_all_qties' onclick=\"openModal($('#templates #modal_no_qties').html(), setAllQties, 'Confirmer');\" disabled>Il n'y a plus de produits à compter</button>";
document.getElementById("validation_button").innerHTML = "<button class='btn--primary full_width_button' id='valid_qty' onclick=\"pre_send('qty_valid')\" disabled>Valider le comptage des produits</button>"; document.getElementById("validation_button").innerHTML = "<button class='btn--primary full_width_button' id='valid_qty' onclick=\"pre_send('qty_valid')\" disabled>Valider le comptage des produits</button>";
...@@ -1922,6 +2296,21 @@ function init_dom(partners_display_data) { ...@@ -1922,6 +2296,21 @@ function init_dom(partners_display_data) {
} }
}); });
$("#add_products_button").on('click', () => {
if (reception_status == "False") {
let pswd = prompt('Merci de demander à un.e salarié.e le mot de passe pour ajouter des produits à la commande');
// Minimum security level
if (pswd == add_products_pswd) {
fetch_suppliers_products();
} else if (pswd == null) {
return;
} else {
alert('Mauvais mot de passe !');
}
}
});
// Barcode reader // Barcode reader
$(document).pos(); $(document).pos();
$(document).on('scan.pos.barcode', function(event) { $(document).on('scan.pos.barcode', function(event) {
...@@ -1984,8 +2373,7 @@ $(document).ready(function() { ...@@ -1984,8 +2373,7 @@ $(document).ready(function() {
alert("Une erreur de synchronisation s'est produite, la commande a sûrement été modifiée sur un autre navigateur. Vous allez être redirigé.e."); alert("Une erreur de synchronisation s'est produite, la commande a sûrement été modifiée sur un autre navigateur. Vous allez être redirigé.e.");
back(); back();
} }
console.log('erreur sync'); console.log('erreur sync', err);
console.log(err);
}); });
// Disable alert errors from datatables // Disable alert errors from datatables
...@@ -2066,7 +2454,7 @@ $(document).ready(function() { ...@@ -2066,7 +2454,7 @@ $(document).ready(function() {
// if not in group, add current order to group (1 order = group of 1) // if not in group, add current order to group (1 order = group of 1)
if (group_ids.length == 0) { if (group_ids.length == 0) {
group_ids.push(id); group_ids.push(parseInt(id));
} }
let partners_display_data = []; let partners_display_data = [];
......
...@@ -43,7 +43,11 @@ def home(request): ...@@ -43,7 +43,11 @@ def home(request):
def get_list_orders(request): def get_list_orders(request):
ordersOdoo = CagetteReception.get_orders() poids = [int(i) for i in request.GET.getlist('poids', [])]
get_order_lines = request.GET.get('get_order_lines', False)
get_order_lines = get_order_lines == "true"
ordersOdoo = CagetteReception.get_orders(poids)
orders = [] orders = []
for order in ordersOdoo: for order in ordersOdoo:
# Order with date at 'False' was found. # Order with date at 'False' was found.
...@@ -60,12 +64,18 @@ def get_list_orders(request): ...@@ -60,12 +64,18 @@ def get_list_orders(request):
"id" : order["id"], "id" : order["id"],
"name" : order["name"], "name" : order["name"],
"date_order" : order["date_order"], "date_order" : order["date_order"],
"partner_id" : order["partner_id"][0],
"partner" : order["partner_id"][1], "partner" : order["partner_id"][1],
"date_planned" : order["date_planned"], "date_planned" : order["date_planned"],
"amount_untaxed" : round(order["amount_untaxed"],2), "amount_untaxed" : round(order["amount_untaxed"],2),
"amount_total" : round(order["amount_total"],2), "amount_total" : round(order["amount_total"],2),
"reception_status" : str(order["x_reception_status"]) "reception_status" : str(order["x_reception_status"])
} }
if get_order_lines is True:
order_lines = CagetteReception.get_order_lines_by_po(int(order["id"]), nullQty = True)
ligne["po"] = order_lines
orders.append(ligne) orders.append(ligne)
return JsonResponse({"data": orders}, safe=False) return JsonResponse({"data": orders}, safe=False)
...@@ -82,6 +92,7 @@ def produits(request, id): ...@@ -82,6 +92,7 @@ def produits(request, id):
"DISPLAY_AUTRES": getattr(settings, 'DISPLAY_COL_AUTRES', True), "DISPLAY_AUTRES": getattr(settings, 'DISPLAY_COL_AUTRES', True),
"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'),
} }
fixed_barcode_prefix = '0490' fixed_barcode_prefix = '0490'
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
{% block additionnal_css %} {% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/reception_style.css' %}"> <link rel="stylesheet" href="{% static 'css/reception_style.css' %}">
<link rel="stylesheet" href="{% static 'jquery-ui-1.12.1/jquery-ui.min.css' %}">
{% endblock %} {% endblock %}
{% block additionnal_scripts %} {% block additionnal_scripts %}
...@@ -11,6 +12,7 @@ ...@@ -11,6 +12,7 @@
<script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script> <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.plugins.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery.pos.js' %}"></script> <script type="text/javascript" src="{% static 'js/jquery.pos.js' %}"></script>
<script type="text/javascript" src="{% static 'jquery-ui-1.12.1/jquery-ui.min.js' %}?v=1651853225"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
...@@ -103,7 +105,7 @@ ...@@ -103,7 +105,7 @@
</div> </div>
</div> </div>
<div class="row-2 container_products" id="container_left"> <div class="container_products" id="container_left">
<h4 id="header_container_left"></h4> <h4 id="header_container_left"></h4>
<table id="table_to_process" class="display" cellspacing="0" ></table> <table id="table_to_process" class="display" cellspacing="0" ></table>
</div> </div>
...@@ -111,6 +113,9 @@ ...@@ -111,6 +113,9 @@
<h4 id="header_container_right"></h4> <h4 id="header_container_right"></h4>
<table id="table_processed" class="display" cellspacing="0" ></table> <table id="table_processed" class="display" cellspacing="0" ></table>
</div> </div>
<div class="txtcenter add_products_button_container">
<button id="add_products_button" class="btn--inverse full_width_button">Ajouter des produits</button>
</div>
<div class="txtcenter"> <div class="txtcenter">
<span id="validation_button"></span> <span id="validation_button"></span>
</div> </div>
...@@ -185,6 +190,36 @@ ...@@ -185,6 +190,36 @@
est bien <b><span id="price_to_verify"></span></b> euros/Kg ?</p> est bien <b><span id="price_to_verify"></span></b> euros/Kg ?</p>
<input type="number" name="Prix au Kilo" id="new_price_to_weight"> <input type="number" name="Prix au Kilo" id="new_price_to_weight">
</div> </div>
<div id="modal_add_products">
<h3>Ajouter des produits à la commande</h3>
<div class="search_products_to_add_area">
<input type="text" class="search_product_input" name="search_product_input" placeholder="Rechercher un produit...">
<i
class='fa fa-info-circle search_product_help'
title='Vous ne trouvez pas un produit ? Les produits déjà dans la commande ou déjà sélectionnés ont été retirés de la liste.'
>
</i>
</div>
<div class="products_lines">
<p class="products_lines_title">
Liste des produits qui seront ajoutés à la commande.
<b>Vous devez renseigner une quantité pour chaque produit.</b>
</p>
</div>
<hr />
</div>
<div id="add_product_line_template">
<div class="add_product_line">
<div class="product_name add_product_line_item"></div>
<div class="product_qty add_product_line_item">
<input type="number" autocomplete="off" class="product_qty_input input_small" placeholder="Quantité">
<i class="product_qty_input_alert">Vous devez renseigner une quantité</i>
</div>
<div class="remove_line">
<i class="fas fa-times fa-lg remove_line_icon"></i>
</div>
</div>
</div>
</div> </div>
<br/> <br/>
</div> </div>
...@@ -198,6 +233,7 @@ ...@@ -198,6 +233,7 @@
var display_autres = "{{DISPLAY_AUTRES}}"; var display_autres = "{{DISPLAY_AUTRES}}";
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}}"
</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