Commit 32241a99 by Damien Moulard

merge conflict

parents a15908ef 71fcc738
var suppliers_list = [], var suppliers_list = [],
products_list = [],
products_table = null, products_table = null,
products = [], products = [],
selected_suppliers = [], selected_suppliers = [],
...@@ -67,6 +68,67 @@ function dates_diff(date1, date2) { ...@@ -67,6 +68,67 @@ 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;
}
const product_exists = products.findIndex(p => p.name === user_input);
if (product_exists !== -1) {
alert("Cet article est déjà dans le tableau.");
$("#product_input").val('');
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.suppliersinfo = [];
data.default_code = ' ';
products.unshift(data);
update_main_screen({'sort_order_dir':'desc'});
update_cdb_order();
} 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 */
/** /**
...@@ -842,7 +904,7 @@ function prepare_datatable_columns() { ...@@ -842,7 +904,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();
$('#create_orders').hide(); $('#create_orders').hide();
...@@ -859,14 +921,17 @@ function display_products() { ...@@ -859,14 +921,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
...@@ -1027,7 +1092,7 @@ function unselect_all_rows() { ...@@ -1027,7 +1092,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');
...@@ -1037,7 +1102,7 @@ function update_main_screen() { ...@@ -1037,7 +1102,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) {
...@@ -1192,6 +1257,11 @@ $(document).ready(function() { ...@@ -1192,6 +1257,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();
}); });
...@@ -1304,7 +1374,7 @@ $(document).ready(function() { ...@@ -1304,7 +1374,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'};
...@@ -1317,4 +1387,62 @@ $(document).ready(function() { ...@@ -1317,4 +1387,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)
......
...@@ -61,7 +61,14 @@ ...@@ -61,7 +61,14 @@
</div> </div>
<div id="orders_creation_area"> <div id="orders_creation_area">
<div class="add_product_container"></div> <div class="add_product_container">
<div id="product_form_container">
<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>
<button type="button" class='btn--primary' id="create_orders" style="display:none;"> <button type="button" class='btn--primary' id="create_orders" style="display:none;">
Générer les commandes Générer les commandes
</button> </button>
......
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