Commit 43d8ccfd by Damien Moulard

set product npa

parent e84f47f2
...@@ -99,6 +99,11 @@ ...@@ -99,6 +99,11 @@
flex-wrap: wrap; flex-wrap: wrap;
} }
.select_all_text {
margin-top: 5px;
margin-bottom: 5px;
}
#table_header_select_all input{ #table_header_select_all input{
margin-left: 5px; margin-left: 5px;
} }
...@@ -112,11 +117,11 @@ ...@@ -112,11 +117,11 @@
cursor: pointer; cursor: pointer;
} }
.product_name, .supplier_name { .product_name, .supplier_name, .product_npa {
font-weight: bold; font-weight: bold;
} }
.select_product_cb { .select_product_cb, .product_npa_cb {
cursor: pointer; cursor: pointer;
} }
......
...@@ -255,6 +255,55 @@ function is_product_related_to_supplier(product, supplier) { ...@@ -255,6 +255,55 @@ function is_product_related_to_supplier(product, supplier) {
return product.suppliers.find(s => s.id === supplier.id) !== undefined; return product.suppliers.find(s => s.id === supplier.id) !== undefined;
} }
/* - PRODUCT */
/**
* Update 'purchase_ok' of a product
*
* @param {int} p_id product id
* @param {Boolean} npa value to set purchase_ok to
*/
function set_product_npa(p_id, npa) {
openModal();
const data = {
product_tmpl_id: p_id,
purchase_ok: !npa
};
// Fetch supplier products
$.ajax({
type: "POST",
url: "/products/update_product_purchase_ok",
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
success: () => {
const index = products.findIndex(p => p.id == p_id);
products[index].purchase_ok = data["purchase_ok"];
update_order();
closeModal();
},
error: function(data) {
let msg = "erreur serveur lors de la sauvegarde du NPA".
msg += ` (product_tmpl_id: ${p_id})`;
err = {msg: msg, ctx: 'set_product_npa'};
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 sauvegarde de la donnée. Veuillez ré-essayer plus tard.');
update_main_screen();
}
});
}
/* - INVENTORY */ /* - INVENTORY */
/** /**
...@@ -331,13 +380,130 @@ function generate_inventory() { ...@@ -331,13 +380,130 @@ function generate_inventory() {
} }
} }
/* - ORDER */
function goto_main_screen(doc) {
order_doc = doc;
products = order_doc.products;
selected_suppliers = order_doc.selected_suppliers;
update_order();
update_main_screen();
switch_screen();
}
function back() {
reset_data();
update_order_selection_screen();
switch_screen('order_selection');
}
/**
* Event fct: on click on an order button
*/
function order_pill_on_click() {
let order_name_container = $(this).find('.pill_order_name');
let doc_id = $(order_name_container).text();
dbc.get(doc_id).then((doc) => {
if (doc.last_update.fingerprint !== fingerprint) {
time_diff = dates_diff(new Date(doc.last_update.timestamp), new Date());
diff_str = ``;
if (time_diff.days !== 0) {
diff_str += `${time_diff.days} jour(s), `;
}
if (time_diff.hours !== 0) {
diff_str += `${time_diff.hours} heure(s), `;
}
if (time_diff.min !== 0) {
diff_str += `${time_diff.min} min, `;
}
diff_str += `${time_diff.sec}s`;
let modal_order_access = $('#templates #modal_order_access');
modal_order_access.find(".order_last_update").text(diff_str);
openModal(
modal_order_access.html(),
() => {
goto_main_screen(doc);
},
'Valider'
);
} else {
goto_main_screen(doc);
}
})
.catch(function (err) {
if (err.status == 404) {
$.notify(
"Cette commande n'existe plus.",
{
globalPosition:"top right",
className: "error"
}
);
update_order_selection_screen()
} else {
alert('Erreur lors de la récupération de la commande. Si l\'erreur persiste, contactez un administrateur svp.');
}
console.log(err);
});
}
/**
* Create an order in couchdb if the name doesn't exist
*/
function create_order() {
const order_name = $("#new_order_name").val();
order_doc._id = order_name;
dbc.put(order_doc, function callback(err, result) {
if (!err) {
order_doc._rev = result.rev;
switch_screen();
} else {
if (err.status == 409) {
alert("Une commande porte déjà ce nom !");
}
console.log(err);
}
});
}
/**
* Update order data of an existing order in couchdb
*/
function update_order() {
order_doc.products = products;
order_doc.selected_suppliers = selected_suppliers;
// Save that current user last updated the order
order_doc.last_update = {
timestamp: Date.now(),
fingerprint: fingerprint
};
dbc.put(order_doc, function callback(err, result) {
if (!err && result !== undefined) {
order_doc._rev = result.rev;
} else {
alert("Erreur lors de la sauvegarde de la commande... Si l'erreur persiste contactez un administrateur svp.");
console.log(err);
}
});
}
/* - DISPLAY */ /* - DISPLAY */
/** /**
* Create a string to represent a supplier column in product data * Create a string to represent a supplier column in product data
* @returns String * @returns String
*/ */
function supplier_column_name(supplier) { function supplier_column_name(supplier) {
return `qty_supplier_${supplier.id}`; return `qty_supplier_${supplier.id}`;
} }
...@@ -397,8 +563,9 @@ function prepare_datatable_data(product_ids = []) { ...@@ -397,8 +563,9 @@ function prepare_datatable_data(product_ids = []) {
id: product.id, id: product.id,
name: product.name, name: product.name,
default_code: product.default_code, default_code: product.default_code,
incoming_qty: +parseFloat(product.incoming_qty).toFixed(3), // + sign removes unecessary zeroes at the end incoming_qty: +parseFloat(product.incoming_qty).toFixed(3), // '+' removes unecessary zeroes at the end
qty_available: +parseFloat(product.qty_available).toFixed(3), qty_available: +parseFloat(product.qty_available).toFixed(3),
purchase_ok: product.purchase_ok,
uom: product.uom_id[1] uom: product.uom_id[1]
}; };
...@@ -426,11 +593,12 @@ function prepare_datatable_columns() { ...@@ -426,11 +593,12 @@ function prepare_datatable_columns() {
columns = [ columns = [
{ {
data: "id", data: "id",
title:` <div id="table_header_select_all"> title: `<div id="table_header_select_all" class="txtcenter">
Tout <span class="select_all_text">Sélectionner</span>
<input type="checkbox" class="select_product_cb" id="select_all_products_cb" value="all"> <label for="select_all_products_cb">- Tout</label>
<input type="checkbox" class="select_product_cb" id="select_all_products_cb" name="select_all_products_cb" value="all">
</div>`, </div>`,
className:"dt-body-center", className: "dt-body-center",
orderable: false, orderable: false,
render: function (data) { render: function (data) {
return `<input type="checkbox" class="select_product_cb" id="select_product_${data}" value="${data}">`; return `<input type="checkbox" class="select_product_cb" id="select_product_${data}" value="${data}">`;
...@@ -450,6 +618,16 @@ function prepare_datatable_columns() { ...@@ -450,6 +618,16 @@ function prepare_datatable_columns() {
title: "Produit" title: "Produit"
}, },
{ {
data: "purchase_ok",
title: `NPA`,
className: "dt-body-center",
orderable: false,
render: function (data) {
return `<input type="checkbox" class="product_npa_cb" value="purchase_ok" ${data ? '' : 'checked'}>`;
},
width: "4%"
},
{
data: "qty_available", data: "qty_available",
title: "Stock", title: "Stock",
width: "4%" width: "4%"
...@@ -607,7 +785,7 @@ function display_products() { ...@@ -607,7 +785,7 @@ function display_products() {
.toggleClass('selected'); .toggleClass('selected');
// Save / unsave selected row // Save / unsave selected row
p_id = products_table.row($(this).closest('tr')).data().id; const p_id = products_table.row($(this).closest('tr')).data().id;
if (this.checked) { if (this.checked) {
selected_rows.push(p_id); selected_rows.push(p_id);
} else { } else {
...@@ -617,6 +795,33 @@ function display_products() { ...@@ -617,6 +795,33 @@ function display_products() {
} }
}); });
// Set product is NPA (Ne Pas Acheter)
$('#products_table').on('click', 'tbody td .product_npa_cb', function () {
// Save / unsave selected row
const p_id = products_table.row($(this).closest('tr')).data().id;
const npa = this.checked;
const product = products.find(p => p.id == p_id);
let modal_product_npa = $('#templates #modal_product_npa');
modal_product_npa.find(".product_name").text(product.name);
modal_product_npa.find(".product_npa").text(npa ? 'Ne Pas Acheter' : 'Peut Être Acheté');
openModal(
modal_product_npa.html(),
() => {
set_product_npa(p_id, npa);
},
'Valider',
false,
true,
() => {
this.checked = !this.checked;
}
);
});
return 0; return 0;
} }
...@@ -734,111 +939,6 @@ function switch_screen(direction = 'main_screen') { ...@@ -734,111 +939,6 @@ function switch_screen(direction = 'main_screen') {
newBox.animate({ "left": "", "right": "" }, 800); newBox.animate({ "left": "", "right": "" }, 800);
} }
/* - ORDER */
function goto_main_screen(doc) {
order_doc = doc;
products = order_doc.products;
selected_suppliers = order_doc.selected_suppliers;
update_order();
update_main_screen();
switch_screen();
}
function back() {
reset_data();
update_order_selection_screen();
switch_screen('order_selection');
}
/**
* Event fct: on click on an order button
*/
function order_pill_on_click() {
let order_name_container = $(this).find('.pill_order_name');
let doc_id = $(order_name_container).text();
dbc.get(doc_id).then((doc) => {
if (doc.last_update.fingerprint !== fingerprint) {
time_diff = dates_diff(new Date(doc.last_update.timestamp), new Date());
diff_str = ``;
if (time_diff.days !== 0) {
diff_str += `${time_diff.days} jour(s), `;
}
if (time_diff.hours !== 0) {
diff_str += `${time_diff.hours} heure(s), `;
}
if (time_diff.min !== 0) {
diff_str += `${time_diff.min} min, `;
}
diff_str += `${time_diff.sec}s`;
let modal_order_access = $('#templates #modal_order_access');
modal_order_access.find(".order_last_update").text(diff_str);
openModal(
modal_order_access.html(),
() => {
goto_main_screen(doc);
},
'Valider'
);
} else {
goto_main_screen(doc);
}
})
.catch(function (err) {
alert('Erreur lors de la récupération de la commande. Si l\'erreur persiste, contactez un administrateur svp.');
console.log(err);
});
}
/**
* Create an order in couchdb if the name doesn't exist
*/
function create_order() {
const order_name = $("#new_order_name").val();
order_doc._id = order_name;
dbc.put(order_doc, function callback(err, result) {
if (!err) {
order_doc._rev = result.rev;
switch_screen();
} else {
if (err.status == 409) {
alert("Une commande porte déjà ce nom !");
}
console.log(err);
}
});
}
/**
* Update order data of an existing order in couchdb
*/
function update_order() {
order_doc.products = products;
order_doc.selected_suppliers = selected_suppliers;
// Save that current user last updated the order
order_doc.last_update = {
timestamp: Date.now(),
fingerprint: fingerprint
};
dbc.put(order_doc, function callback(err, result) {
if (!err && result !== undefined) {
order_doc._rev = result.rev;
} else {
alert("Erreur lors de la sauvegarde de la commande... Si l'erreur persiste contactez un administrateur svp.");
console.log(err);
}
});
}
$(document).ready(function() { $(document).ready(function() {
fingerprint = new Fingerprint({canvas: true}).get(); fingerprint = new Fingerprint({canvas: true}).get();
......
...@@ -148,6 +148,23 @@ class CagetteProduct(models.Model): ...@@ -148,6 +148,23 @@ class CagetteProduct(models.Model):
return res return res
@staticmethod
def update_product_purchase_ok(product_tmpl_id, purchase_ok):
api = OdooAPI()
res = {}
f = {
'purchase_ok': purchase_ok
}
try:
res["update"] = api.update('product.template', product_tmpl_id, f)
except Exception as e:
res["error"] = str(e)
print(str(e))
return res
class CagetteProducts(models.Model): class CagetteProducts(models.Model):
"""Initially used to make massive barcode update.""" """Initially used to make massive barcode update."""
...@@ -432,7 +449,8 @@ class CagetteProducts(models.Model): ...@@ -432,7 +449,8 @@ class CagetteProducts(models.Model):
ptids.append(p["product_tmpl_id"][0]) ptids.append(p["product_tmpl_id"][0])
# Get products templates # Get products templates
f = ["id", "state", "name", "default_code", "qty_available", "incoming_qty", "uom_id"] f = ["id", "state", "name", "default_code", "qty_available", "incoming_qty", "uom_id", "purchase_ok"]
# TODO fetch only 'purchase_ok' products ?
c = [['id', 'in', ptids], ['purchase_ok', '=', True]] c = [['id', 'in', ptids], ['purchase_ok', '=', True]]
products_t = api.search_read('product.template', c, f) products_t = api.search_read('product.template', c, f)
filtered_products_t = [p for p in products_t if p["state"] != "end" and p["state"] != "obsolete"] filtered_products_t = [p for p in products_t if p["state"] != "end" and p["state"] != "obsolete"]
......
...@@ -7,6 +7,7 @@ urlpatterns = [ ...@@ -7,6 +7,7 @@ urlpatterns = [
url(r'^get_product_data$', views.get_product_data), url(r'^get_product_data$', views.get_product_data),
url(r'^get_products_stdprices$', views.get_products_stdprices), url(r'^get_products_stdprices$', views.get_products_stdprices),
url(r'^update_product_stock$', views.update_product_stock), url(r'^update_product_stock$', views.update_product_stock),
url(r'^update_product_purchase_ok$', views.update_product_purchase_ok),
url(r'^labels_appli_csv(\/?[a-z]*)$', views.labels_appli_csv, name='labels_appli_csv'), url(r'^labels_appli_csv(\/?[a-z]*)$', views.labels_appli_csv, name='labels_appli_csv'),
url(r'^label_print/([0-9]+)/?([0-9\.]*)/?([a-z]*)/?([0-9]*)$', views.label_print), url(r'^label_print/([0-9]+)/?([0-9\.]*)/?([a-z]*)/?([0-9]*)$', views.label_print),
url(r'^shelf_labels$', views.shelf_labels), # massive print url(r'^shelf_labels$', views.shelf_labels), # massive print
......
...@@ -75,6 +75,16 @@ def update_product_stock(request): ...@@ -75,6 +75,16 @@ def update_product_stock(request):
return JsonResponse({"res": res}) return JsonResponse({"res": res})
def update_product_purchase_ok(request):
res = {}
data = json.loads(request.body.decode())
res = CagetteProduct.update_product_purchase_ok(data["product_tmpl_id"], data["purchase_ok"])
if ('error' in res):
return JsonResponse(res, status=500)
else:
return JsonResponse({"res": res})
def labels_appli_csv(request, params): def labels_appli_csv(request, params):
"""Generate files to put in DAV directory to be retrieved by scales app.""" """Generate files to put in DAV directory to be retrieved by scales app."""
......
...@@ -116,6 +116,16 @@ ...@@ -116,6 +116,16 @@
<p>Êtez-vous sûr ?</p> <p>Êtez-vous sûr ?</p>
<hr/> <hr/>
</div> </div>
<div id="modal_product_npa">
<h3>Attention !</h3>
<p>
Vous vous apprêtez à passer le produit <span class="product_name"></span> en <span class="product_npa"></span>.<br/>
L'information sera enregistrée dès que vous aurez cliqué sur "Valider".
</p>
<p>Êtez-vous sûr ?</p>
<hr/>
</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