Commit 32fe6120 by Damien Moulard

Merge branch 'aide_a_la_commande' into dev_cooperatic

parents 2ea80edf 0c69109c
...@@ -14,13 +14,13 @@ ...@@ -14,13 +14,13 @@
.pill { .pill {
border-radius: 30px; border-radius: 30px;
min-width: 200px; min-width: 200px;
min-height: 35px; min-height: 40px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 8px 15px 8px 15px; padding: 5px 30px 5px 30px;
margin: 0 10px 5px 0; margin: 0 10px 5px 10px;
} }
.disabled { .disabled {
...@@ -84,6 +84,14 @@ ...@@ -84,6 +84,14 @@
/* -- Order data */ /* -- Order data */
#order_data_container { #order_data_container {
font-size: 1.8rem;
}
#order_data_separator {
margin: 0 10px 0 10px;
}
#order_forms_container {
margin-top: 30px; margin-top: 30px;
display: flex; display: flex;
justify-content: space-evenly; justify-content: space-evenly;
...@@ -157,14 +165,7 @@ ...@@ -157,14 +165,7 @@
/* -- Footer */ /* -- Footer */
#main_content_footer { #main_content_footer {
margin: 10px 0 35px 0; margin: 20px 0 40px 0;
}
#footer_orders_recap {
width: 100%;
display: flex;
justify-content: space-evenly;
margin-bottom: 15px;
} }
#footer_actions { #footer_actions {
...@@ -173,28 +174,26 @@ ...@@ -173,28 +174,26 @@
justify-content: space-between; justify-content: space-between;
} }
#suppliers_total_values {
display: flex;
}
.supplier_total_item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* -- Suppliers list */ /* -- Suppliers list */
#suppliers_container { #suppliers_container {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
margin: 20px 0 20px 0; margin: 30px 0 20px 0;
} }
.supplier_pill { .supplier_pill {
background-color: #e7e9ed; background-color: #e7e9edc5;
border: 1px solid black;
}
.pill_supplier_name {
font-weight: bold;
}
.supplier_total_value_container {
font-size: 1.5rem;
} }
.remove_supplier_icon { .remove_supplier_icon {
......
...@@ -214,8 +214,11 @@ function check_products_data() { ...@@ -214,8 +214,11 @@ function check_products_data() {
// Update suppliers info // Update suppliers info
for (let psi_index in products[p_index].suppliersinfo) { for (let psi_index in products[p_index].suppliersinfo) {
const updated_psi = updated_suppliersinfo.find(psi => psi.supplier_id == products[p_index].suppliersinfo[psi_index].supplier_id); const updated_psi = updated_suppliersinfo.find(psi => psi.supplier_id == products[p_index].suppliersinfo[psi_index].supplier_id);
products[p_index].suppliersinfo[psi_index].package_qty = updated_psi.package_qty; if (updated_psi !== undefined) {
products[p_index].suppliersinfo[psi_index].price = updated_psi.price; products[p_index].suppliersinfo[psi_index].package_qty = updated_psi.package_qty;
products[p_index].suppliersinfo[psi_index].price = updated_psi.price;
}
} }
} }
...@@ -482,7 +485,7 @@ function _compute_total_values_by_supplier() { ...@@ -482,7 +485,7 @@ function _compute_total_values_by_supplier() {
for (let supinfo of p.suppliersinfo) { for (let supinfo of p.suppliersinfo) {
let supplier_index = selected_suppliers.findIndex(s => s.id == supinfo.supplier_id); let supplier_index = selected_suppliers.findIndex(s => s.id == supinfo.supplier_id);
let product_supplier_value = ('qty' in supinfo) ? supinfo.qty * supinfo.price : 0; let product_supplier_value = ('qty' in supinfo) ? supinfo.qty * supinfo.package_qty * supinfo.price : 0;
selected_suppliers[supplier_index].total_value += product_supplier_value; selected_suppliers[supplier_index].total_value += product_supplier_value;
} }
} }
...@@ -586,42 +589,44 @@ function generate_inventory() { ...@@ -586,42 +589,44 @@ function generate_inventory() {
openModal( openModal(
modal_create_inventory.html(), modal_create_inventory.html(),
() => { () => {
$('#do_inventory').empty().append(`<i class="fas fa-spinner fa-spin"></i>`); if (is_time_to('validate_generate_inventory')) {
$.ajax({ $('#do_inventory').empty().append(`<i class="fas fa-spinner fa-spin"></i>`);
type: "POST", $.ajax({
url: "/inventory/generate_inventory_list", type: "POST",
dataType: "json", url: "/inventory/generate_inventory_list",
traditional: true, dataType: "json",
contentType: "application/json; charset=utf-8", traditional: true,
data: JSON.stringify(data), contentType: "application/json; charset=utf-8",
success: () => { data: JSON.stringify(data),
unselect_all_rows(); success: () => {
unselect_all_rows();
// Give time for modal to fade
setTimeout(function() { // Give time for modal to fade
setTimeout(function() {
$('#do_inventory').empty().append(`Faire un inventaire`);
$('#do_inventory').notify(
"Inventaire créé !",
{
globalPosition:"bottom center",
className: "success"
}
);
}, 200);
},
error: function(data) {
$('#do_inventory').empty().append(`Faire un inventaire`); $('#do_inventory').empty().append(`Faire un inventaire`);
$('#do_inventory').notify( let msg = "erreur serveur lors de la création de l'inventaire".
"Inventaire créé !", err = {msg: msg, ctx: 'generate_inventory'};
{
globalPosition:"bottom center", if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
className: "success" err.msg += ' : ' + data.responseJSON.error;
} }
); report_JS_error(err, 'orders');
}, 200);
}, alert("Erreur lors de la création de l'inventaire. Réessayez plus tard.");
error: function(data) {
$('#do_inventory').empty().append(`Faire un inventaire`);
let msg = "erreur serveur lors de la création de l'inventaire".
err = {msg: msg, ctx: 'generate_inventory'};
if (typeof data.responseJSON != 'undefined' && typeof data.responseJSON.error != 'undefined') {
err.msg += ' : ' + data.responseJSON.error;
} }
report_JS_error(err, 'orders'); });
}
alert("Erreur lors de la création de l'inventaire. Réessayez plus tard.");
}
});
}, },
'Valider' 'Valider'
); );
...@@ -635,7 +640,7 @@ function generate_inventory() { ...@@ -635,7 +640,7 @@ function generate_inventory() {
* Event fct: on click on an order button * Event fct: on click on an order button
*/ */
function order_pill_on_click() { function order_pill_on_click() {
if (is_time_to('order_pill_on_click')) { if (is_time_to('order_pill_on_click', 1000)) {
clicked_order_pill = $(this); clicked_order_pill = $(this);
let order_name_container = clicked_order_pill.find('.pill_order_name'); let order_name_container = clicked_order_pill.find('.pill_order_name');
let doc_id = $(order_name_container).text(); let doc_id = $(order_name_container).text();
...@@ -663,7 +668,9 @@ function order_pill_on_click() { ...@@ -663,7 +668,9 @@ function order_pill_on_click() {
openModal( openModal(
modal_order_access.html(), modal_order_access.html(),
() => { () => {
goto_main_screen(doc); if (is_time_to('validate_access_order')) {
goto_main_screen(doc);
}
}, },
'Valider' 'Valider'
); );
...@@ -790,7 +797,7 @@ function create_orders() { ...@@ -790,7 +797,7 @@ function create_orders() {
for (let p of products) { for (let p of products) {
for (let p_supplierinfo of p.suppliersinfo) { for (let p_supplierinfo of p.suppliersinfo) {
// If a qty is set for a supplier for a product // If a qty is set for a supplier for a product
if ('qty' in p_supplierinfo) { if ('qty' in p_supplierinfo && p_supplierinfo.qty != 0) {
const supplier_id = p_supplierinfo.supplier_id; const supplier_id = p_supplierinfo.supplier_id;
orders_data.suppliers_data[supplier_id].lines.push({ orders_data.suppliers_data[supplier_id].lines.push({
...@@ -958,6 +965,7 @@ function display_suppliers() { ...@@ -958,6 +965,7 @@ function display_suppliers() {
let template = $("#templates #supplier_pill_template"); let template = $("#templates #supplier_pill_template");
template.find(".pill_supplier_name").text(supplier.display_name); template.find(".pill_supplier_name").text(supplier.display_name);
template.find(".supplier_pill").attr('id', `pill_supplier_${supplier.id}`);
template.find(".remove_supplier_icon").attr('id', `remove_supplier_${supplier.id}`); template.find(".remove_supplier_icon").attr('id', `remove_supplier_${supplier.id}`);
supplier_container.append(template.html()); supplier_container.append(template.html());
...@@ -975,7 +983,9 @@ function display_suppliers() { ...@@ -975,7 +983,9 @@ function display_suppliers() {
openModal( openModal(
modal_remove_supplier.html(), modal_remove_supplier.html(),
() => { () => {
remove_supplier(supplier_id); if (is_time_to('validate_remove_supplier')) {
remove_supplier(supplier_id);
}
}, },
'Valider' 'Valider'
); );
...@@ -1023,18 +1033,23 @@ function _compute_product_data(product) { ...@@ -1023,18 +1033,23 @@ function _compute_product_data(product) {
/* Coverage related data */ /* Coverage related data */
if (order_doc.coverage_days !== null) { if (order_doc.coverage_days !== null) {
let days_not_covered = 0; let qty_not_covered = 0;
let days_covered = 0;
if (product.daily_conso !== 0) { if (product.daily_conso !== 0) {
let qty_not_covered = product.daily_conso * order_doc.coverage_days - product.qty_available - product.incoming_qty - purchase_qty; qty_not_covered = product.daily_conso * order_doc.coverage_days - product.qty_available - product.incoming_qty - purchase_qty;
days_not_covered = qty_not_covered / product.daily_conso; // get unmet needs in nb of days days_covered = qty_not_covered / product.daily_conso;
days_not_covered = -Math.ceil(days_not_covered); // round up, so if a day is not fully covered display it qty_not_covered = -Math.ceil(qty_not_covered); // round up, so if a value is not fully covered display it
days_not_covered = (days_not_covered > 0) ? 0 : days_not_covered; qty_not_covered = (qty_not_covered > 0) ? 0 : qty_not_covered; // only display qty not covered (neg value)
days_covered = -Math.ceil(days_covered);
} }
item.days_not_covered = days_not_covered; item.qty_not_covered = qty_not_covered;
item.days_covered = days_covered;
} else { } else {
item.days_not_covered = 'X'; item.qty_not_covered = 'X';
item.days_covered = 'X';
} }
return item; return item;
...@@ -1099,7 +1114,7 @@ function prepare_datatable_columns() { ...@@ -1099,7 +1114,7 @@ function prepare_datatable_columns() {
{ {
data: "default_code", data: "default_code",
title: "Ref", title: "Ref",
width: "8%", width: "6%",
render: function (data) { render: function (data) {
return (data === false) ? "" : data; return (data === false) ? "" : data;
} }
...@@ -1186,8 +1201,15 @@ function prepare_datatable_columns() { ...@@ -1186,8 +1201,15 @@ function prepare_datatable_columns() {
}); });
columns.push({ columns.push({
data: "days_not_covered", data: "qty_not_covered",
title: "Besoin non couvert (jours)", title: "Besoin non couvert (qté)",
className: "dt-body-center",
width: "4%"
});
columns.push({
data: "days_covered",
title: "Jours de couverture",
className: "dt-body-center", className: "dt-body-center",
width: "4%" width: "4%"
}); });
...@@ -1317,7 +1339,9 @@ function display_products(params) { ...@@ -1317,7 +1339,9 @@ function display_products(params) {
openModal( openModal(
modal_attach_product_to_supplier.html(), modal_attach_product_to_supplier.html(),
() => { () => {
save_supplier_product_association(product, supplier, this); if (is_time_to('validate_save_supplier_product_association')) {
save_supplier_product_association(product, supplier, this);
}
}, },
'Valider', 'Valider',
false false
...@@ -1404,7 +1428,9 @@ function display_products(params) { ...@@ -1404,7 +1428,9 @@ function display_products(params) {
openModal( openModal(
modal_product_npa.html(), modal_product_npa.html(),
() => { () => {
set_product_npa(p_id, npa); if (is_time_to('validate_set_product_npa')) {
set_product_npa(p_id, npa);
}
}, },
'Valider', 'Valider',
false, false,
...@@ -1441,17 +1467,14 @@ function unselect_all_rows() { ...@@ -1441,17 +1467,14 @@ function unselect_all_rows() {
function display_total_values() { function display_total_values() {
_compute_total_values_by_supplier(); _compute_total_values_by_supplier();
$('#suppliers_total_values_container').empty();
let total_values_content = '<ul>';
let order_total_value = 0; let order_total_value = 0;
for (let supplier of selected_suppliers) { for (let supplier of selected_suppliers) {
total_values_content += `<li>${supplier.display_name} : ${supplier.total_value}€</li>`; $(`#pill_supplier_${supplier.id}`).find('.supplier_total_value').text(supplier.total_value);
order_total_value += supplier.total_value; order_total_value += supplier.total_value;
} }
total_values_content += '</ul>';
$('#suppliers_total_values_container').append(total_values_content); order_total_value = parseFloat(order_total_value).toFixed(2);
$('#order_total_value').text(`${order_total_value}€`); $('#order_total_value').text(order_total_value);
} }
/** /**
...@@ -1624,7 +1647,7 @@ $(document).ready(function() { ...@@ -1624,7 +1647,7 @@ $(document).ready(function() {
// Main screen // Main screen
$("#coverage_form").on("submit", function(e) { $("#coverage_form").on("submit", function(e) {
e.preventDefault(); e.preventDefault();
if (is_time_to('submit_coverage_form')) { if (is_time_to('submit_coverage_form', 1000)) {
let val = $("#coverage_days_input").val(); let val = $("#coverage_days_input").val();
val = parseInt(val); val = parseInt(val);
...@@ -1644,32 +1667,32 @@ $(document).ready(function() { ...@@ -1644,32 +1667,32 @@ $(document).ready(function() {
$("#supplier_form").on("submit", function(e) { $("#supplier_form").on("submit", function(e) {
e.preventDefault(); e.preventDefault();
if (is_time_to('add_product')) { if (is_time_to('add_product', 1000)) {
add_supplier(); add_supplier();
} }
}); });
$("#product_form").on("submit", function(e) { $("#product_form").on("submit", function(e) {
e.preventDefault(); e.preventDefault();
if (is_time_to('add_product')) { if (is_time_to('add_product', 1000)) {
add_product(); add_product();
} }
}); });
$("#do_inventory").on("click", function() { $("#do_inventory").on("click", function() {
if (is_time_to('generate_inventory')) { if (is_time_to('generate_inventory', 1000)) {
generate_inventory(); generate_inventory();
} }
}); });
$('#back_to_order_selection_from_main').on('click', function() { $('#back_to_order_selection_from_main').on('click', function() {
if (is_time_to('back_to_order_selection_from_main')) { if (is_time_to('back_to_order_selection_from_main', 1000)) {
back(); back();
} }
}); });
$('#create_orders').on('click', function() { $('#create_orders').on('click', function() {
if (is_time_to('create_orders')) { if (is_time_to('create_orders', 1000)) {
let modal_create_order = $('#templates #modal_create_order'); let modal_create_order = $('#templates #modal_create_order');
modal_create_order.find('.suppliers_date_planned_area').empty(); modal_create_order.find('.suppliers_date_planned_area').empty();
...@@ -1686,7 +1709,9 @@ $(document).ready(function() { ...@@ -1686,7 +1709,9 @@ $(document).ready(function() {
openModal( openModal(
modal_create_order.html(), modal_create_order.html(),
() => { () => {
create_orders(); if (is_time_to('validate_create_orders')) {
create_orders();
}
}, },
'Valider', 'Valider',
false false
...@@ -1756,7 +1781,7 @@ $(document).ready(function() { ...@@ -1756,7 +1781,7 @@ $(document).ready(function() {
// Orders created screen // Orders created screen
$('#back_to_order_selection_from_orders_created').on('click', function() { $('#back_to_order_selection_from_orders_created').on('click', function() {
if (is_time_to('back_to_order_selection_from_orders_created')) { if (is_time_to('back_to_order_selection_from_orders_created', 1000)) {
switch_screen('order_selection', 'orders_created'); switch_screen('order_selection', 'orders_created');
} }
}); });
......
...@@ -468,7 +468,7 @@ class CagetteProducts(models.Model): ...@@ -468,7 +468,7 @@ class CagetteProducts(models.Model):
try: try:
today = datetime.date.today().strftime("%Y-%m-%d") today = datetime.date.today().strftime("%Y-%m-%d")
if len(supplier_ids) > 0: if supplier_ids is not None and len(supplier_ids) > 0:
# Get products/supplier relation # Get products/supplier relation
f = ["product_tmpl_id", 'date_start', 'date_end', 'package_qty', 'price', 'name'] f = ["product_tmpl_id", 'date_start', 'date_end', 'package_qty', 'price', 'name']
c = [['name', 'in', [ int(x) for x in supplier_ids]]] c = [['name', 'in', [ int(x) for x in supplier_ids]]]
...@@ -503,8 +503,8 @@ class CagetteProducts(models.Model): ...@@ -503,8 +503,8 @@ class CagetteProducts(models.Model):
sales_average_params = { sales_average_params = {
'ids': ptids, 'ids': ptids,
'from': '2019-04-10', # 'from': '2019-04-10',
'to': '2019-08-10', # 'to': '2019-08-10',
} }
sales = CagetteProducts.get_template_products_sales_average(sales_average_params) sales = CagetteProducts.get_template_products_sales_average(sales_average_params)
...@@ -515,7 +515,7 @@ class CagetteProducts(models.Model): ...@@ -515,7 +515,7 @@ class CagetteProducts(models.Model):
# Add supplier data to product data # Add supplier data to product data
for i, fp in enumerate(filtered_products_t): for i, fp in enumerate(filtered_products_t):
if len(supplier_ids) > 0: if supplier_ids is not None and len(supplier_ids) > 0:
psi_item = next(item for item in psi if item["product_tmpl_id"] is not False and item["product_tmpl_id"][0] == fp["id"]) psi_item = next(item for item in psi if item["product_tmpl_id"] is not False and item["product_tmpl_id"][0] == fp["id"])
filtered_products_t[i]['suppliersinfo'] = [{ filtered_products_t[i]['suppliersinfo'] = [{
'supplier_id': int(psi_item["name"][0]), 'supplier_id': int(psi_item["name"][0]),
......
...@@ -41,10 +41,14 @@ ...@@ -41,10 +41,14 @@
<div class="header txtcenter"> <div class="header txtcenter">
<h1>Aide à la commande</h1> <h1>Aide à la commande</h1>
<i>Commande : <span class="order_name_container"></span></i> <p id="order_data_container">
Commande : <span class="order_name_container"></span>
<span id="order_data_separator"> | </span>
Total HT : <span id="order_total_value">0</span>
</p>
</div> </div>
<div class="txtcenter" id="order_data_container"> <div class="txtcenter" id="order_forms_container">
<form action="javascript:;" id="coverage_form"> <form action="javascript:;" id="coverage_form">
<input type="number" name="coverage_days" id="coverage_days_input" placeholder="Nb jours de couverture" min="1"> <input type="number" name="coverage_days" id="coverage_days_input" placeholder="Nb jours de couverture" min="1">
<button type="submit" class='btn--primary'>Calculer les besoins</button> <button type="submit" class='btn--primary'>Calculer les besoins</button>
...@@ -55,7 +59,7 @@ ...@@ -55,7 +59,7 @@
</form> </form>
</div> </div>
<div class="txtcenter" id="suppliers_container"></div> <div id="suppliers_container"></div>
<div class="main" style="display:none;"> <div class="main" style="display:none;">
<div class="table_area"> <div class="table_area">
...@@ -64,14 +68,6 @@ ...@@ -64,14 +68,6 @@
</div> </div>
<div id="main_content_footer" style="display:none;"> <div id="main_content_footer" style="display:none;">
<div id="footer_orders_recap">
<div id="suppliers_total_values">
<h4>Total /fournisseur : </h4><div id="suppliers_total_values_container"></div>
</div>
<div id="order_total_value_container">
<h4>Total : <span id="order_total_value"></span></h4>
</div>
</div>
<div id="footer_actions"> <div id="footer_actions">
<div class="add_product_container"> <div class="add_product_container">
<div id="product_form_container"> <div id="product_form_container">
...@@ -121,6 +117,9 @@ ...@@ -121,6 +117,9 @@
<span class="pill_supplier_name"></span> <span class="pill_supplier_name"></span>
<i class="fas fa-times remove_supplier_icon"></i> <i class="fas fa-times remove_supplier_icon"></i>
</div> </div>
<div class="supplier_total_value_container">
Total: <span class="supplier_total_value">0</span>
</div>
</div> </div>
</div> </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