Commit aeba0458 by Damien Moulard

remove product-supplier association

parent 23c02513
...@@ -424,6 +424,58 @@ function save_supplier_product_association(product, supplier, cell) { ...@@ -424,6 +424,58 @@ function save_supplier_product_association(product, supplier, cell) {
} }
/** /**
* Send to server the deletion of association product-supplier
*
* @param {object} product
* @param {object} supplier
*/
function remove_supplier_product_association(product, supplier) {
openModal();
const data = {
product_tmpl_id: product.id,
supplier_id: supplier.id
};
// Send request to create association
$.ajax({
type: "POST",
url: "/orders/remove_supplier_product_association",
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
success: (res) => {
// Remove relation locally
let p_index = products.findIndex(p => p.id == product.id);
let psi_index = product.suppliersinfo.findIndex(psi => psi.supplier_id == supplier.id);
products[p_index].suppliersinfo.splice(psi_index, 1);
// Update table
display_products();
update_cdb_order();
closeModal();
},
error: function(data) {
let msg = "erreur serveur lors de la suppression de l'association product/supplier".
msg += ` (product_tmpl_id: ${product.id}; supplier_id: ${supplier.id})`;
err = {msg: msg, ctx: 'remove_supplier_product_association'};
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 suppression de l\'association. Veuillez ré-essayer plus tard.');
}
});
return 0;
}
/**
* When products are fetched, save them and the relation with the supplier. * When products are fetched, save them and the relation with the supplier.
* If product already saved, add the supplier to its suppliers list. * If product already saved, add the supplier to its suppliers list.
* Else, add product with supplier. * Else, add product with supplier.
...@@ -1179,7 +1231,7 @@ function prepare_datatable_columns() { ...@@ -1179,7 +1231,7 @@ function prepare_datatable_columns() {
return `<div id="${base_id}_cell_content" class="custom_cell_content">X</div>`; return `<div id="${base_id}_cell_content" class="custom_cell_content">X</div>`;
} else { } else {
let content = `<div id="${base_id}_cell_content" class="custom_cell_content"> let content = `<div id="${base_id}_cell_content" class="custom_cell_content">
<input type="number" class="product_qty_input" id="${base_id}_qty_input" min="0" value=${data}>`; <input type="number" class="product_qty_input" id="${base_id}_qty_input" min="-1" value=${data}>`;
if (full.package_qty === 'X') { if (full.package_qty === 'X') {
let product_data = products.find(p => p.id == full.id); let product_data = products.find(p => p.id == full.id);
...@@ -1327,15 +1379,41 @@ function display_products(params) { ...@@ -1327,15 +1379,41 @@ function display_products(params) {
$('#products_table').on('blur', 'tbody td .product_qty_input', function () { $('#products_table').on('blur', 'tbody td .product_qty_input', function () {
let val = ($(this).val() == '') ? 0 : $(this).val(); let val = ($(this).val() == '') ? 0 : $(this).val();
val = parseFloat(val);
// If value is a number
if (!isNaN(val)) {
const id_split = $(this).attr('id') const id_split = $(this).attr('id')
.split('_'); .split('_');
const prod_id = id_split[1]; const prod_id = id_split[1];
const supplier_id = id_split[3]; const supplier_id = id_split[3];
console.log(val);
if (val == -1) {
let modal_remove_supplier_product_association = $('#templates #modal_remove_supplier_product_association');
const product = products.find(p => p.id == prod_id);
modal_remove_supplier_product_association.find(".product_name").text(product.name);
const supplier = selected_suppliers.find(s => s.id == supplier_id);
modal_remove_supplier_product_association.find(".supplier_name").text(supplier.display_name);
openModal(
modal_remove_supplier_product_association.html(),
() => {
if (is_time_to('validate_remove_supplier_product_association')) {
remove_supplier_product_association(product, supplier);
}
},
'Valider',
false,
true,
() => {
// Reset value in input on cancel
const psi = product.suppliersinfo.find(psi_item => psi_item.supplier_id == supplier_id);
$(this).val(psi.qty);
}
);
} else {
val = parseFloat(val);
// If value is a number
if (!isNaN(val)) {
// Save value // Save value
save_product_supplier_qty(prod_id, supplier_id, val); save_product_supplier_qty(prod_id, supplier_id, val);
...@@ -1351,7 +1429,18 @@ function display_products(params) { ...@@ -1351,7 +1429,18 @@ function display_products(params) {
} else { } else {
$(this).val(''); $(this).val('');
} }
}); }
})
.on('change', 'tbody td .product_qty_input', function () {
// Since data change is saved on blur, set focus on change in case of arrows pressed
$(this).focus();
})
.on('keypress', 'tbody td .product_qty_input', function(e) {
if (e.which == 13) {
// Validate on Enter pressed
$(this).blur();
}
});;
// Associate product to supplier on click on 'X' in the table // Associate product to supplier on click on 'X' in the table
$('#products_table').on('click', 'tbody .product_not_from_supplier', function () { $('#products_table').on('click', 'tbody .product_not_from_supplier', function () {
......
...@@ -13,6 +13,7 @@ urlpatterns = [ ...@@ -13,6 +13,7 @@ urlpatterns = [
url(r'^get_suppliers$', views.get_suppliers), url(r'^get_suppliers$', views.get_suppliers),
url(r'^get_supplier_products$', views.get_supplier_products), url(r'^get_supplier_products$', views.get_supplier_products),
url(r'^associate_supplier_to_product$', views.associate_supplier_to_product), url(r'^associate_supplier_to_product$', views.associate_supplier_to_product),
url(r'^remove_supplier_product_association$', views.remove_supplier_product_association),
url(r'^create_orders$', views.create_orders), url(r'^create_orders$', views.create_orders),
url(r'^get_orders_attachment$', views.get_orders_attachment), url(r'^get_orders_attachment$', views.get_orders_attachment),
] ]
...@@ -61,6 +61,18 @@ def associate_supplier_to_product(request): ...@@ -61,6 +61,18 @@ def associate_supplier_to_product(request):
return JsonResponse({'res': res}) return JsonResponse({'res': res})
def remove_supplier_product_association(request):
""" This product is now unavailable from this supplier """
res = {}
try:
data = json.loads(request.body.decode())
res = CagetteProduct.remove_supplier_product_association(data)
except Exception as e:
res["error"] = str(e)
return JsonResponse(res, status=500)
return JsonResponse({'res': res})
def create_orders(request): def create_orders(request):
""" Create products orders """ """ Create products orders """
res = { "created": [] } res = { "created": [] }
......
...@@ -156,6 +156,22 @@ class CagetteProduct(models.Model): ...@@ -156,6 +156,22 @@ class CagetteProduct(models.Model):
return res return res
@staticmethod @staticmethod
def remove_supplier_product_association(data):
api = OdooAPI()
product_tmpl_id = data["product_tmpl_id"]
partner_id = data["supplier_id"]
f = ["id"]
c = [['product_tmpl_id', '=', product_tmpl_id], ['name', '=', partner_id]]
res_supplierinfo = api.search_read('product.supplierinfo', c, f)
psi_id = res_supplierinfo[0]['id']
res = api.execute('product.supplierinfo', 'unlink', [psi_id])
return res
@staticmethod
def update_product_purchase_ok(product_tmpl_id, purchase_ok): def update_product_purchase_ok(product_tmpl_id, purchase_ok):
api = OdooAPI() api = OdooAPI()
res = {} res = {}
......
...@@ -202,6 +202,19 @@ ...@@ -202,6 +202,19 @@
<hr/> <hr/>
</div> </div>
<div id="modal_remove_supplier_product_association">
<h3>Attention !</h3>
<p>
Vous vous apprêtez à rendre le produit <span class="product_name"></span>
indisponible chez le fournisseur <span class="supplier_name"></span>.
</p>
<p>
L'association sera supprimée dès que vous aurez cliqué sur "Valider".<br/>
</p>
<p>Êtez-vous sûr ?</p>
<hr/>
</div>
<div id="modal_create_inventory"> <div id="modal_create_inventory">
<p> <p>
Vous vous apprêtez à créer un inventaire de <span class="inventory_products_count"></span> produits. Vous vous apprêtez à créer un inventaire de <span class="inventory_products_count"></span> produits.
......
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