Commit 129d2267 by Damien Moulard

merge dev_cooperatic

parents c0e7c9fc 707b2289
Pipeline #2290 passed with stage
in 1 minute 28 seconds
...@@ -331,7 +331,7 @@ ...@@ -331,7 +331,7 @@
margin: 15px 0; margin: 15px 0;
position: -webkit-sticky; position: -webkit-sticky;
position: sticky; position: sticky;
top: 140px; top: 120px;
z-index: 5; z-index: 5;
pointer-events: none; pointer-events: none;
} }
......
...@@ -298,9 +298,20 @@ function compute_and_affect_product_supplier_quantities(coeff, days) { ...@@ -298,9 +298,20 @@ function compute_and_affect_product_supplier_quantities(coeff, days) {
const daily_conso = product.daily_conso; const daily_conso = product.daily_conso;
let purchase_package_qty_for_coverage = compute_purchase_qty_for_coverage(product, coeff, stock, incoming_qty, daily_conso, days); let purchase_package_qty_for_coverage = compute_purchase_qty_for_coverage(product, coeff, stock, incoming_qty, daily_conso, days);
// Set qty to purchase for first supplier only
products[key].suppliersinfo[0].qty = purchase_package_qty_for_coverage; // Set qty to purchase for supplier with higher priority
let target_supplierinfo_index = 0;
let min_sequence = Number.POSITIVE_INFINITY; // min sequence = higher priority
for (let i in products[key].suppliersinfo) {
let suppliersinfo_sequence = products[key].suppliersinfo[i].sequence;
if (suppliersinfo_sequence < min_sequence) {
min_sequence = suppliersinfo_sequence;
target_supplierinfo_index = i;
}
}
products[key].suppliersinfo[target_supplierinfo_index].qty = purchase_package_qty_for_coverage;
} }
} }
} }
...@@ -1574,7 +1585,7 @@ function prepare_datatable_columns() { ...@@ -1574,7 +1585,7 @@ function prepare_datatable_columns() {
{ {
data: "default_code", data: "default_code",
title: "Ref", title: "Ref",
width: "8%", width: "5%",
render: function (data, type, full) { render: function (data, type, full) {
if (data === false) { if (data === false) {
return ""; return "";
...@@ -1613,7 +1624,7 @@ function prepare_datatable_columns() { ...@@ -1613,7 +1624,7 @@ function prepare_datatable_columns() {
return '<div class="help" title="' + full.stats+ '">' + data + '</div>'; return '<div class="help" title="' + full.stats+ '">' + data + '</div>';
}, },
className: "dt-body-center", className: "dt-body-center",
width: "6%" width: "4%"
} }
]; ];
...@@ -1692,7 +1703,7 @@ function prepare_datatable_columns() { ...@@ -1692,7 +1703,7 @@ function prepare_datatable_columns() {
width: "4%" width: "4%"
}); });
// Not in use for now // Not used for now
// columns.push({ // columns.push({
// data: "qty_not_covered", // data: "qty_not_covered",
// title: "Besoin non couvert (qté)", // title: "Besoin non couvert (qté)",
......
...@@ -455,6 +455,27 @@ function eanCheckDigit(s) { ...@@ -455,6 +455,27 @@ function eanCheckDigit(s) {
return (10 - (result % 10)) % 10; return (10 - (result % 10)) % 10;
} }
function isValidEAN8(ean) {
let answer = true;
let key = ean.substring(ean.length-1);
let digits = ean.substring(0, ean.length-1);
let checkSum = digits.split('').reduce(function(previousValue, currentValue, i) {
let temp_val = i % 2 == 0 ? parseInt(currentValue) * 3 : parseInt(currentValue);
return parseInt(previousValue) + temp_val;
}, 0);
let checkKey = 10 - checkSum % 10;
if (checkKey === 10) checkKey = 0;
if (checkKey != key) {
answer = false;
}
return answer;
}
function isValidEAN13(ean) { function isValidEAN13(ean) {
var answer = true; var answer = true;
var checkSum = ean.split('').reduce(function(p, v, i) { var checkSum = ean.split('').reduce(function(p, v, i) {
......
...@@ -56,7 +56,7 @@ class CagetteProduct(models.Model): ...@@ -56,7 +56,7 @@ class CagetteProduct(models.Model):
cond = [['product_tmpl_id.id', '=', template_id]] cond = [['product_tmpl_id.id', '=', template_id]]
fields = ['barcode', 'product_tmpl_id', 'pricetag_rackinfos', fields = ['barcode', 'product_tmpl_id', 'pricetag_rackinfos',
'price_weight_net', 'price_volume', 'list_price', 'price_weight_net', 'price_volume', 'list_price',
'weight_net', 'volume', 'to_weight'] 'weight_net', 'volume', 'to_weight', 'meal_voucher_ok']
additionnal_fields = getattr(settings, 'SHELF_LABELS_ADD_FIELDS', []) additionnal_fields = getattr(settings, 'SHELF_LABELS_ADD_FIELDS', [])
fields += additionnal_fields fields += additionnal_fields
product_data = api.search_read('product.product', cond, fields) product_data = api.search_read('product.product', cond, fields)
...@@ -607,7 +607,7 @@ class CagetteProducts(models.Model): ...@@ -607,7 +607,7 @@ class CagetteProducts(models.Model):
if supplier_ids is not None and len(supplier_ids) > 0: if supplier_ids is not None and len(supplier_ids) > 0:
# Get products/supplier relation # Get products/supplier relation
f = ["id", "product_tmpl_id", 'date_start', 'date_end', 'package_qty', 'price', 'name', 'product_code'] f = ["id", "product_tmpl_id", 'date_start', 'date_end', 'package_qty', 'price', 'name', 'product_code', 'sequence']
c = [['name', 'in', [ int(x) for x in supplier_ids]]] c = [['name', 'in', [ int(x) for x in supplier_ids]]]
psi = api.search_read('product.supplierinfo', c, f) psi = api.search_read('product.supplierinfo', c, f)
...@@ -669,7 +669,8 @@ class CagetteProducts(models.Model): ...@@ -669,7 +669,8 @@ class CagetteProducts(models.Model):
'supplier_id': int(psi_item["name"][0]), 'supplier_id': int(psi_item["name"][0]),
'package_qty': psi_item["package_qty"], 'package_qty': psi_item["package_qty"],
'price': psi_item["price"], 'price': psi_item["price"],
'product_code': psi_item["product_code"] 'product_code': psi_item["product_code"],
'sequence': psi_item["sequence"]
}) })
for s in sales: for s in sales:
......
...@@ -215,6 +215,11 @@ tr.odd td.row_product_no_qty { ...@@ -215,6 +215,11 @@ tr.odd td.row_product_no_qty {
display: none; display: none;
} }
.no_products_to_add_area {
margin: 2rem 0;
/* display: none; */
}
.search_products_to_add_area { .search_products_to_add_area {
margin: 2rem 0; margin: 2rem 0;
display: flex; display: flex;
......
...@@ -411,6 +411,11 @@ function fetch_suppliers_products() { ...@@ -411,6 +411,11 @@ function fetch_suppliers_products() {
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
success: function(data) { success: function(data) {
suppliers_products = data.res.products; suppliers_products = data.res.products;
// Filter supplier products on products already in orders
suppliers_products = suppliers_products.filter(p => list_to_process.findIndex(ptp => ptp.product_id[1] === p.name) === -1);
suppliers_products = suppliers_products.filter(p => list_processed.findIndex(pp => pp.product_id[1] === p.name) === -1);
closeModal(); closeModal();
set_add_products_modal(); set_add_products_modal();
}, },
...@@ -486,7 +491,7 @@ function initLists() { ...@@ -486,7 +491,7 @@ function initLists() {
if (is_grouped_order()) { 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: "15px"
}); });
} }
...@@ -499,11 +504,10 @@ function initLists() { ...@@ -499,11 +504,10 @@ function initLists() {
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"}, {data:"shelf_sortorder", title: "Rayon", className: "dt-body-center", width: "4%"},
{ {
data:"product_id.1", data:"product_id.1",
title:"Produit", title:"Produit",
width: "45%",
render: function (data, type, full) { render: function (data, type, full) {
// Add tooltip with barcode over product name // Add tooltip with barcode over product name
let display_barcode = "Aucun"; let display_barcode = "Aucun";
...@@ -521,6 +525,7 @@ function initLists() { ...@@ -521,6 +525,7 @@ function initLists() {
title: "Unité vente", title: "Unité vente",
className:"dt-body-center", className:"dt-body-center",
orderable: false, orderable: false,
width: "5%",
render: function (data) { render: function (data) {
if (display_autres === "True" && data.toLowerCase().indexOf('unit') === 0) { if (display_autres === "True" && data.toLowerCase().indexOf('unit') === 0) {
return "U"; return "U";
...@@ -533,6 +538,7 @@ function initLists() { ...@@ -533,6 +538,7 @@ function initLists() {
data:"product_qty", data:"product_qty",
title: (reception_status == "qty_valid") ? qty_title_tooltip : base_qty_title, title: (reception_status == "qty_valid") ? qty_title_tooltip : base_qty_title,
className: (reception_status == "qty_valid") ? "dt-body-center product_qty_cell" : "dt-body-center", className: (reception_status == "qty_valid") ? "dt-body-center product_qty_cell" : "dt-body-center",
width: "5%",
render: function (data, type, full) { render: function (data, type, full) {
if (reception_status == "False") { if (reception_status == "False") {
return data; return data;
...@@ -547,36 +553,40 @@ function initLists() { ...@@ -547,36 +553,40 @@ function initLists() {
data:"price_unit", data:"price_unit",
title:"Prix unit.", title:"Prix unit.",
className:"dt-body-center", className:"dt-body-center",
visible: (reception_status == "qty_valid") visible: (reception_status == "qty_valid"),
width: "5%"
}, },
{ {
title:"Editer", title:"Editer",
defaultContent: "<a class='btn toProcess_line_edit' href='#'><i class='far fa-edit'></i></a>", defaultContent: "<a class='btn toProcess_line_edit' href='#'><i class='far fa-edit'></i></a>",
className:"dt-body-center", className:"dt-body-center",
orderable: false orderable: false,
width: "5%"
}, },
{ {
title:"Valider", title:"Valider",
defaultContent: "<a class='btn toProcess_line_valid' href='#'><i class='far fa-check-square'></i></a>", defaultContent: "<a class='btn toProcess_line_valid' href='#'><i class='far fa-check-square'></i></a>",
className:"dt-body-center", className:"dt-body-center",
orderable: false orderable: false,
width: "5%"
}, },
{ {
title:"", title:"",
defaultContent: "<select class='select_product_action'><option value=''></option><option value='supplier_shortage'>Rupture fournisseur</option></select>", defaultContent: "<select class='select_product_action'><option value=''></option><option value='supplier_shortage'>Rupture fournisseur</option></select>",
className:"dt-body-center", className:"dt-body-center",
orderable: false, orderable: false,
visible: display_autres === "True" visible: display_autres === "True",
width: "5%"
} }
]); ]);
columns_processed = [ columns_processed = [
{data:"row_counter", title:"row_counter", visible: false}, // Hidden counter to display last row first {data:"row_counter", title:"row_counter", visible: false}, // Hidden counter to display last row first
{data:"shelf_sortorder", title: "Rayon", className:"dt-body-center"}, {data:"shelf_sortorder", title: "Rayon", className:"dt-body-center", width: "4%"},
{ {
data:"product_id.1", data:"product_id.1",
title:"Produit", title:"Produit",
width: "55%", // width: "55%",
render: function (data, type, full) { render: function (data, type, full) {
// Add tooltip with barcode over product name // Add tooltip with barcode over product name
let display_barcode = "Aucun"; let display_barcode = "Aucun";
...@@ -598,11 +608,12 @@ function initLists() { ...@@ -598,11 +608,12 @@ function initLists() {
return display; 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, width: "5%"},
{ {
data:"product_qty", data:"product_qty",
title: qty_title_tooltip, title: qty_title_tooltip,
className:"dt-head-center dt-body-center", className:"dt-head-center dt-body-center",
width: "5%",
// visible: (reception_status == "False"), // visible: (reception_status == "False"),
render: function (data, type, full) { render: function (data, type, full) {
let disp = [ let disp = [
...@@ -618,13 +629,15 @@ function initLists() { ...@@ -618,13 +629,15 @@ function initLists() {
data:"price_unit", data:"price_unit",
title:"Prix unit", title:"Prix unit",
className:"dt-body-center", className:"dt-body-center",
visible: (reception_status == "qty_valid") visible: (reception_status == "qty_valid"),
width: "5%",
}, },
{ {
title:"Editer", title:"Editer",
defaultContent: "<a class='btn' id='processed_line_edit' href='#'><i class='far fa-edit'></i></a>", defaultContent: "<a class='btn' id='processed_line_edit' href='#'><i class='far fa-edit'></i></a>",
className:"dt-body-center", className:"dt-body-center",
orderable: false orderable: false,
width: "5%",
}, },
{ {
title:"Autres", title:"Autres",
...@@ -1833,7 +1846,7 @@ function add_products_action() { ...@@ -1833,7 +1846,7 @@ function add_products_action() {
} }
} }
if (qty_inputs.length > 0 && has_empty_qty_input === false) { if (products_to_add.length > 0 && qty_inputs.length > 0 && has_empty_qty_input === false) {
create_orders(); create_orders();
} }
} }
...@@ -2059,14 +2072,8 @@ function openErrorReport() { ...@@ -2059,14 +2072,8 @@ function openErrorReport() {
* Filter autocomplete data by removing products already selected. * Filter autocomplete data by removing products already selected.
*/ */
function set_products_autocomplete() { 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);
autocomplete_products = autocomplete_products.filter(p => list_processed.findIndex(pp => pp.product_id[1] === p.name) === -1);
console.log(products_to_add);
// Filter autocomplete products on products already selected // Filter autocomplete products on products already selected
autocomplete_products = autocomplete_products.filter(p => products_to_add.findIndex(pta => pta.name === p.name) === -1); let autocomplete_products = suppliers_products.filter(p => products_to_add.findIndex(pta => pta.name === p.name) === -1);
try { try {
$("#modal .search_product_input").autocomplete("destroy"); $("#modal .search_product_input").autocomplete("destroy");
...@@ -2127,9 +2134,19 @@ function remove_product_line(e) { ...@@ -2127,9 +2134,19 @@ function remove_product_line(e) {
} }
/** /**
* Set & display the modal to search products * Set & display the modal to search products.
* If no products to add, display the according modal.
*/ */
function set_add_products_modal() { function set_add_products_modal() {
if (suppliers_products.length === 0) {
let modal_no_product_to_add = $("#modal_no_product_to_add");
openModal(
modal_no_product_to_add.html(),
() => {},
'OK'
);
} else {
let add_products_modal = $("#modal_add_products"); let add_products_modal = $("#modal_add_products");
openModal( openModal(
...@@ -2139,9 +2156,12 @@ function set_add_products_modal() { ...@@ -2139,9 +2156,12 @@ function set_add_products_modal() {
false false
); );
products_to_add = []; // Reset on modal opening
set_products_autocomplete(); 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...)
* *
...@@ -2341,6 +2361,9 @@ function init_dom(partners_display_data) { ...@@ -2341,6 +2361,9 @@ function init_dom(partners_display_data) {
} else if (barcode.length == 12 && barcode.indexOf('0') !== 0) { } else if (barcode.length == 12 && barcode.indexOf('0') !== 0) {
// User may use a scanner which remove leading 0 // User may use a scanner which remove leading 0
barcode = '0' + barcode; barcode = '0' + barcode;
} else if (barcode.length >= 8) {
// For EAN8
barcode = barcode.substring(barcode.length-8);
} else { } else {
//manually submitted after correction //manually submitted after correction
var barcode_input = $('#search_input'); var barcode_input = $('#search_input');
......
...@@ -96,10 +96,12 @@ function barcode_analyzer(chars) { ...@@ -96,10 +96,12 @@ function barcode_analyzer(chars) {
} else if (barcode && barcode.length == 12 && barcode.indexOf('0') !== 0) { } else if (barcode && barcode.length == 12 && barcode.indexOf('0') !== 0) {
// User may use a scanner which remove leading 0 // User may use a scanner which remove leading 0
barcode = '0' + barcode; barcode = '0' + barcode;
} else if (barcode && barcode.length >= 8) {
// For EAN8
barcode = barcode.substring(barcode.length-8);
} else { } else {
//manually submitted after correction //manually submitted after correction
var barcode_input = $('#search_input'); var barcode_input = $('#search_input');
barcode = barcode_input.val(); barcode = barcode_input.val();
} }
...@@ -142,10 +144,14 @@ function refresh() { ...@@ -142,10 +144,14 @@ function refresh() {
// Directly send a line to edition when barcode is read // Directly send a line to edition when barcode is read
function select_product_from_bc(barcode) { function select_product_from_bc(barcode) {
if (barcode === "" || barcode === null || barcode === undefined) {
return -1;
}
var found = null, var found = null,
qty = null; qty = null;
if (isValidEAN13(barcode)) { if (isValidEAN13(barcode) || isValidEAN8(barcode)) {
var scannedProduct = barcodes.get_corresponding_odoo_product(barcode); var scannedProduct = barcodes.get_corresponding_odoo_product(barcode);
if (scannedProduct === null) { if (scannedProduct === null) {
...@@ -159,7 +165,7 @@ function select_product_from_bc(barcode) { ...@@ -159,7 +165,7 @@ function select_product_from_bc(barcode) {
} }
} }
} else { } else {
alert("Le code-barre " + barcode + " n'est pas reconnu comme un EAN13 valide.'"); alert("Le code-barre " + barcode + " n'est pas reconnu comme un EAN13 ou EAN8 valide.");
return -1; return -1;
} }
...@@ -1108,6 +1114,16 @@ function init() { ...@@ -1108,6 +1114,16 @@ function init() {
list_to_process = products; list_to_process = products;
initLists(); initLists();
// Set processed_row_counter to current value
if ('list_processed' in shelf) {
for (let processed_item of shelf['list_processed']) {
if (processed_item.row_counter > processed_row_counter) {
processed_row_counter = processed_item.row_counter;
}
}
}
processed_row_counter++;
// Set DOM // Set DOM
if (originView == "shelf") { if (originView == "shelf") {
$('#shelf_name').text(shelf.name + ' (numéro ' + shelf.sort_order + ')'); $('#shelf_name').text(shelf.name + ' (numéro ' + shelf.sort_order + ')');
......
...@@ -600,6 +600,9 @@ $(document).ready(function() { ...@@ -600,6 +600,9 @@ $(document).ready(function() {
} else if (barcode.length == 12 && barcode.indexOf('0') !== 0) { } else if (barcode.length == 12 && barcode.indexOf('0') !== 0) {
// User may use a scanner which remove leading 0 // User may use a scanner which remove leading 0
barcode = '0' + barcode; barcode = '0' + barcode;
} else if (barcode.length >= 8) {
// For EAN8
barcode = barcode.substring(barcode.length-8);
} }
......
...@@ -778,6 +778,9 @@ $(document).ready(function() { ...@@ -778,6 +778,9 @@ $(document).ready(function() {
} else if (barcode.length == 12 && barcode.indexOf('0') !== 0) { } else if (barcode.length == 12 && barcode.indexOf('0') !== 0) {
// User may use a scanner which remove leading 0 // User may use a scanner which remove leading 0
barcode = '0' + barcode; barcode = '0' + barcode;
} else if (barcode.length >= 8) {
// For EAN8
barcode = barcode.substring(barcode.length-8);
} else { } else {
//manually submitted after correction //manually submitted after correction
barcode = barcode_input.val(); barcode = barcode_input.val();
......
...@@ -208,6 +208,13 @@ ...@@ -208,6 +208,13 @@
</div> </div>
<hr /> <hr />
</div> </div>
<div id="modal_no_product_to_add">
<h3>Ajouter des produits à la commande</h3>
<div class="no_products_to_add_area">
Aucun produit à ajouter : tous les produits de ce(s) fournisseur(s) sont déjà dans la commande.
</div>
<hr />
</div>
<div id="add_product_line_template"> <div id="add_product_line_template">
<div class="add_product_line"> <div class="add_product_line">
<div class="product_name add_product_line_item"></div> <div class="product_name add_product_line_item"></div>
......
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