Commit 71fcc738 by François

Adding product to order which is not in suppliers list (need 'Add products…

Adding product to order which is not in suppliers list (need 'Add products simple list, to fit with product search in autocomplete list' Odoo update)
parent 6a661024
var suppliers_list = [], var suppliers_list = [],
products_list = [],
products_table = null, products_table = null,
products = [], products = [],
selected_suppliers = [], selected_suppliers = [],
...@@ -63,6 +64,56 @@ function dates_diff(date1, date2) { ...@@ -63,6 +64,56 @@ function dates_diff(date1, date2) {
return diff; return diff;
} }
/* - PRODUCTS */
/**
* Add a product.
*
* @returns -1 if validation failed, 0 otherwise
*/
function add_product() {
const user_input = $("#product_input").val();
// Check if user input is a valid article
const product = products_list.find(s => s.display_name === user_input);
if (product === undefined) {
alert("L'article renseigné n'est pas valide.\n"
+ "Veuillez sélectionner un article dans la liste déroulante.");
return -1;
}
$.ajax({
type: 'GET',
url: '/products/get_product_for_help_order_line/' + product.tpl_id,
dataType:"json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function(data) {
if (typeof data.id != "undefined") {
data.suppliers = [];
data.default_code = ' ';
products.unshift(data);
update_main_screen({'sort_order_dir':'desc'});
} else {
alert("L'article n'a pas toutes les caractéristiques pour être ajouté.")
}
$("#product_input").val('');
},
error: function(data) {
err = {msg: "erreur serveur lors de la récupération des données liées à l'article", ctx: 'get_product_for_help_order_line'};
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 récupération des informations, réessayer plus tard.');
}
});
return 0;
}
/* - SUPPLIERS */ /* - SUPPLIERS */
/** /**
...@@ -692,7 +743,7 @@ function prepare_datatable_columns() { ...@@ -692,7 +743,7 @@ function prepare_datatable_columns() {
/** /**
* Display the Datatable containing the products * Display the Datatable containing the products
*/ */
function display_products() { function display_products(params) {
if (products.length == 0) { if (products.length == 0) {
$('.main').hide(); $('.main').hide();
...@@ -707,14 +758,17 @@ function display_products() { ...@@ -707,14 +758,17 @@ function display_products() {
const data = prepare_datatable_data(); const data = prepare_datatable_data();
const columns = prepare_datatable_columns(); const columns = prepare_datatable_columns();
let sort_order_dir = "asc";
if (params != undefined && typeof params.sort_order_dir != "undefined") {
sort_order_dir = params.sort_order_dir;
}
products_table = $('#products_table').DataTable({ products_table = $('#products_table').DataTable({
data: data, data: data,
columns: columns, columns: columns,
order: [ order: [
[ [
5, // Order by default by first supplier 6, // Order by default by first supplier
"asc" sort_order_dir
] ]
], ],
stripeClasses: [], // Remove datatable cells coloring stripeClasses: [], // Remove datatable cells coloring
...@@ -873,7 +927,7 @@ function unselect_all_rows() { ...@@ -873,7 +927,7 @@ function unselect_all_rows() {
/** /**
* Update DOM display on main screen * Update DOM display on main screen
*/ */
function update_main_screen() { function update_main_screen(params) {
// Remove listener before recreating them // Remove listener before recreating them
$('#products_table').off('input', 'tbody td .product_qty_input'); $('#products_table').off('input', 'tbody td .product_qty_input');
$('#products_table').off('click', 'tbody .product_not_from_supplier'); $('#products_table').off('click', 'tbody .product_not_from_supplier');
...@@ -883,7 +937,7 @@ function update_main_screen() { ...@@ -883,7 +937,7 @@ function update_main_screen() {
$(".order_name_container").text(order_doc._id); $(".order_name_container").text(order_doc._id);
display_suppliers(); display_suppliers();
display_products(); display_products(params);
// Re-select previously selected rows // Re-select previously selected rows
if (selected_rows.length > 0) { if (selected_rows.length > 0) {
...@@ -1014,6 +1068,11 @@ $(document).ready(function() { ...@@ -1014,6 +1068,11 @@ $(document).ready(function() {
add_supplier(); add_supplier();
}); });
$("#product_form").on("submit", function(e) {
e.preventDefault();
add_product();
});
$("#do_inventory").on("click", function() { $("#do_inventory").on("click", function() {
generate_inventory(); generate_inventory();
}); });
...@@ -1045,7 +1104,7 @@ $(document).ready(function() { ...@@ -1045,7 +1104,7 @@ $(document).ready(function() {
source: suppliers_list.map(a => a.display_name) source: suppliers_list.map(a => a.display_name)
}); });
closeModal();
}, },
error: function(data) { error: function(data) {
err = {msg: "erreur serveur lors de la récupération des fournisseurs", ctx: 'get_suppliers'}; err = {msg: "erreur serveur lors de la récupération des fournisseurs", ctx: 'get_suppliers'};
...@@ -1058,4 +1117,62 @@ $(document).ready(function() { ...@@ -1058,4 +1117,62 @@ $(document).ready(function() {
alert('Erreur lors de la récupération des fournisseurs, rechargez la page plus tard'); alert('Erreur lors de la récupération des fournisseurs, rechargez la page plus tard');
} }
}); });
//Get products
var accentMap = {
"á": "a",
"à": "a",
"â": "a",
"é": "e",
"è": "e",
"ê": "e",
"ë": "e",
"ç": "c",
"ù": "u",
"ü": "u",
"ö": "o"
};
var normalize = function( term ) {
var ret = "";
for ( var i = 0; i < term.length; i++ ) {
ret += accentMap[ term.charAt(i) ] || term.charAt(i);
}
return ret;
};
$.ajax({
type: 'GET',
url: "/products/simple_list",
dataType:"json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function(data) {
products_list = data.list;
// Set up autocomplete on product input
$("#product_input").autocomplete({
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
response( $.grep( products_list.map(a => a.display_name), function( value ) {
value = value.label || value.value || value;
return matcher.test( value ) || matcher.test( normalize( value ) );
}) );
},
position: {collision: "flip" }
});
closeModal();
},
error: function(data) {
err = {msg: "erreur serveur lors de la récupération des articles", ctx: 'get_products'};
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 articles, rechargez la page plus tard');
}
});
}); });
...@@ -165,10 +165,34 @@ class CagetteProduct(models.Model): ...@@ -165,10 +165,34 @@ class CagetteProduct(models.Model):
return res return res
@staticmethod
def get_product_for_help_order_line(product_tmpl_id):
api = OdooAPI()
res = []
try:
f = ["id", "state", "name", "default_code", "qty_available", "incoming_qty", "uom_id", "purchase_ok"]
# TODO fetch only 'purchase_ok' products ?
c = [['id', '=', product_tmpl_id], ['purchase_ok', '=', True]]
products_t = api.search_read('product.template', c, f)
res = [p for p in products_t if p["state"] != "end" and p["state"] != "obsolete"]
except Exception as e:
coop_logger.error("Odoo API get_product_for_help_order_line (tpl_id = %s) : %s", str(product_tmpl_id), 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."""
@staticmethod @staticmethod
def get_simple_list():
res = []
api = OdooAPI()
try:
res = api.execute('lacagette.products', 'get_simple_list', {'only_purchase_ok': True})
except Exception as e:
coop_logger.error("Odoo api products simple list : %s", str(e))
return res
@staticmethod
def __unique_product_list(plist): def __unique_product_list(plist):
# 276 # 276
upl = {} upl = {}
......
...@@ -4,6 +4,8 @@ from . import views ...@@ -4,6 +4,8 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.home), url(r'^$', views.home),
url(r'^simple_list$', views.get_simple_list),
url(r'^get_product_for_help_order_line/([0-9]+)$', views.get_product_for_help_order_line),
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),
......
...@@ -26,6 +26,33 @@ def home(request): ...@@ -26,6 +26,33 @@ def home(request):
return HttpResponse(template.render(context, request)) return HttpResponse(template.render(context, request))
def get_simple_list(request):
res = {}
try:
res = CagetteProducts.get_simple_list()
except Exception as e:
coop_logger.error("Get products simple list : %s", str(e))
res['error'] = str(e)
if ('error' in res):
return JsonResponse(res, status=500)
else:
return JsonResponse(res, safe=False)
def get_product_for_help_order_line(request, tpl_id):
res = {}
try:
result = CagetteProduct.get_product_for_help_order_line(tpl_id)
if len(result) == 1:
res = result[0]
except Exception as e:
coop_logger.error("get_product_for_help_order_line : %s", str(e))
res['error'] = str(e)
if ('error' in res):
return JsonResponse(res, status=500)
else:
return JsonResponse(res, safe=False)
def get_product_data(request): def get_product_data(request):
barcode = request.GET['barcode'] barcode = request.GET['barcode']
res = CagetteProduct.get_product_from_barcode(barcode) res = CagetteProduct.get_product_from_barcode(barcode)
......
...@@ -56,6 +56,12 @@ ...@@ -56,6 +56,12 @@
<table id="products_table" class="display" cellspacing="0" width="100%"></table> <table id="products_table" class="display" cellspacing="0" width="100%"></table>
</div> </div>
</div> </div>
<div id="product_form_container" style="margin-bottom: 50px;">
<form action="javascript:;" id="product_form">
<input type="text" name="article" id="product_input" placeholder="Rechercher un article">
<button type="submit" class='btn--primary'>Ajouter l'article</button>
</form>
</div>
</div> </div>
<div id="templates" style="display:none;"> <div id="templates" style="display:none;">
......
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