Commit f53fd634 by Damien Moulard

Merge branch 'aide_a_la_commande' into dev_cooperatic

parents 313c7e0f 2d254598
......@@ -292,7 +292,9 @@ class Order(models.Model):
res = {
'id_po': id_po,
'confirm_po': True
'confirm_po': True,
'supplier_id': supplier_id,
'date_planned': date_planned
}
return res
......
......@@ -91,11 +91,11 @@
#supplier_input {
width: 350px;
border-radius: 8px;
border-radius: 3px;
}
#date_planned_input, #coverage_days_input {
border-radius: 8px;
border-radius: 3px;
}
/* -- Table */
......@@ -106,7 +106,7 @@
#products_table_filter input{
height: 35px;
width: 300px;
border-radius: 10px;
border-radius: 3px;
}
#products_table .help {cursor: help;}
#table_header_select_all{
......@@ -154,12 +154,34 @@
cursor: pointer;
}
/* -- Bottom action button */
/* -- Footer */
#main_content_footer {
margin: 10px 0 35px 0;
}
#footer_orders_recap {
width: 100%;
display: flex;
justify-content: space-evenly;
margin-bottom: 15px;
}
#footer_actions {
width: 100%;
display: flex;
justify-content: space-between;
margin: 15px 0 35px 0;
}
#suppliers_total_values {
display: flex;
}
.supplier_total_item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
/* -- Suppliers list */
......@@ -182,27 +204,32 @@
}
/* -- Attach product to supplier modal */
.new_product_supplier_input_area {
.modal_input_area {
margin-bottom: 15px;
width: 100%;
display: flex;
justify-content: center;
}
.new_product_supplier_input, .new_product_supplier_label {
.modal_input_container, .modal_input_label {
width:50%;
margin: 0 15px 0 15px;
}
.new_product_supplier_label {
.modal_input_label {
display: flex;
justify-content: flex-end;
align-items: center;
}
.modal_input {
width: 90%;
}
/* - Orders created screen */
.order_created_header {
margin-top: 5px;
margin-bottom: 40px;
}
......@@ -227,6 +254,14 @@
text-decoration: none;
color: white;
}
.download_order_file_button:active {
text-decoration: none;
color: white;
}
.download_order_file_button:focus {
text-decoration: none;
color: white;
}
#recap_delivery_date {
font-weight: bold;
......
......@@ -15,7 +15,6 @@ var dbc = null,
sync = null,
order_doc = {
_id: null,
date_planned: null,
coverage_days: null,
last_update: {
timestamp: null,
......@@ -42,7 +41,6 @@ function reset_data() {
product_orders = [];
order_doc = {
_id: null,
date_planned: null,
coverage_days: null,
last_update : {
timestamp: null,
......@@ -112,19 +110,6 @@ function add_product() {
return -1;
}
/*
onst product_ids = products.map(p => p.id);
if (product_ids.length > 0) {
clicked_order_pill.find('.pill_order_name').empty().append(`<i class="fas fa-spinner fa-spin"></i>`);
$.ajax({
type: 'POST',
url: '/products/get_product_for_order_helper',
data: JSON.stringify(product_ids),
dataType:"json",
*/
$.ajax({
type: 'POST',
url: '/products/get_product_for_order_helper',
......@@ -167,6 +152,7 @@ function compute_products_coverage_qties() {
key,
product
] of Object.entries(products)) {
if ('suppliersinfo' in product && product.suppliersinfo.length > 0) {
let purchase_qty_for_coverage = null;
// Durée couverture produit = (stock + qté entrante + qté commandée ) / conso quotidienne
......@@ -180,43 +166,60 @@ function compute_products_coverage_qties() {
// Reduce to nb of packages to purchase
purchase_package_qty_for_coverage = purchase_qty_for_coverage / product.suppliersinfo[0].package_qty;
// Round according to uom
if (product.uom_id[0] == 1 || product.uom_id[0] == 20) {
purchase_package_qty_for_coverage = parseFloat(purchase_package_qty_for_coverage).toFixed(0);
} else {
purchase_package_qty_for_coverage = parseFloat(purchase_package_qty_for_coverage).toFixed(2);
}
// Round up to unit for all products
purchase_package_qty_for_coverage = Math.ceil(purchase_package_qty_for_coverage);
// Set qty to purchase for first supplier only
products[key].suppliersinfo[0].qty = purchase_package_qty_for_coverage;
}
}
}
/**
* Update order products data in case they have changed.
*/
function check_products_data() {
return new Promise((resolve, reject) => {
const product_ids = products.map(p => p.id);
return new Promise((resolve) => {
const suppliers_id = selected_suppliers.map(s => s.id);
if (suppliers_id.length > 0) {
$.notify(
"Vérfication des informations produits...",
{
globalPosition:"top left",
className: "warning"
}
);
if (product_ids.length > 0) {
clicked_order_pill.find('.pill_order_name').empty().append(`<i class="fas fa-spinner fa-spin"></i>`);
$.ajax({
type: 'POST',
url: '/products/get_product_for_order_helper',
data: JSON.stringify(product_ids),
type: 'GET',
url: '/orders/get_supplier_products',
data: {
sids: suppliers_id
},
dataType:"json",
traditional: true,
contentType: "application/json; charset=utf-8",
success: function(data) {
for (let product of data.products) {
for (let product of data.res.products) {
const p_index = products.findIndex(p => p.id == product.id);
// Override products data with new data
// Override products data with new data (without suppliersinfo so we don't override qty)
const updated_suppliersinfo = product.suppliersinfo;
delete product.suppliersinfo;
products[p_index] = { ...products[p_index], ...product };
// Update suppliers info
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);
products[p_index].suppliersinfo[psi_index].package_qty = updated_psi.package_qty;
products[p_index].suppliersinfo[psi_index].price = updated_psi.price;
}
}
$('.notifyjs-wrapper').trigger('notify-hide');
resolve();
},
error: function(data) {
......@@ -227,6 +230,7 @@ function check_products_data() {
report_JS_error(err, 'orders');
alert(`Erreur lors de la vérification des données des articles. Certaines données peuvent être erronées`);
$('.notifyjs-wrapper').trigger('notify-hide');
// Don't block process if this call fails
resolve();
}
......@@ -249,7 +253,7 @@ function add_supplier() {
const user_input = $("#supplier_input").val();
// Check if user input is a valid supplier
const supplier = suppliers_list.find(s => s.display_name === user_input);
let supplier = suppliers_list.find(s => s.display_name === user_input);
if (supplier === undefined) {
alert("Le fournisseur renseigné n'est pas valide.\n"
......@@ -268,11 +272,11 @@ function add_supplier() {
openModal();
supplier.total_value = 0;
selected_suppliers.push(supplier);
let url = "/orders/get_supplier_products";
url += "?sid=" + encodeURIComponent(supplier.id);
url += "?sids=" + encodeURIComponent(supplier.id);
// Fetch supplier products
$.ajax({
......@@ -465,6 +469,25 @@ function is_product_related_to_supplier(product, supplier) {
return product.suppliersinfo.find(s => s.supplier_id === supplier.id) !== undefined;
}
/**
* Calculate the total value purchased for all supplier
*/
function _compute_total_values_by_supplier() {
// Reinit
for (let s of selected_suppliers) {
s.total_value = 0;
}
for (let p of products) {
for (let supinfo of p.suppliersinfo) {
let supplier_index = selected_suppliers.findIndex(s => s.id == supinfo.supplier_id);
let product_supplier_value = ('qty' in supinfo) ? supinfo.qty * supinfo.price : 0;
selected_suppliers[supplier_index].total_value += product_supplier_value;
}
}
}
/* - PRODUCT */
/**
......@@ -492,7 +515,20 @@ function set_product_npa(p_id, npa) {
success: () => {
const index = products.findIndex(p => p.id == p_id);
products[index].purchase_ok = data["purchase_ok"];
// Give time for modal to fade
setTimeout(function() {
$.notify(
"Produit passé en NPA !",
{
globalPosition:"top right",
className: "success"
}
);
}, 500);
// Remove NPA products
products.splice(index, 1);
update_main_screen();
update_cdb_order();
closeModal();
......@@ -550,6 +586,7 @@ function generate_inventory() {
openModal(
modal_create_inventory.html(),
() => {
$('#do_inventory').empty().append(`<i class="fas fa-spinner fa-spin"></i>`);
$.ajax({
type: "POST",
url: "/inventory/generate_inventory_list",
......@@ -562,6 +599,7 @@ function generate_inventory() {
// Give time for modal to fade
setTimeout(function() {
$('#do_inventory').empty().append(`Faire un inventaire`);
$('#do_inventory').notify(
"Inventaire créé !",
{
......@@ -569,9 +607,10 @@ function generate_inventory() {
className: "success"
}
);
}, 500);
}, 200);
},
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'};
......@@ -686,27 +725,64 @@ function update_cdb_order() {
fingerprint: fingerprint
};
return new Promise((resolve) => {
dbc.put(order_doc, function callback(err, result) {
if (!err && result !== undefined) {
order_doc._rev = result.rev;
resolve();
} else {
alert("Erreur lors de la sauvegarde de la commande... Si l'erreur persiste contactez un administrateur svp.");
console.log(err);
resolve();
}
});
});
}
/**
* Create the Product Orders in Odoo
*/
function create_orders() {
openModal();
let orders_data = {
"date_planned": order_doc.date_planned,
"suppliers_data": {}
};
// Get planned delivery date for each supplier before hiding the modal
for (let supplier of selected_suppliers) {
// Get planned date from modal
let supplier_date_planned = $(`#date_planned_supplier_${supplier.id}`).val();
let formatted_date = null;
if (supplier_date_planned !== '') {
if (date_format === "dd/mm/yy") {
// Change format [dd/mm/yy] to ISO [yy-mm-dd]
formatted_date = supplier_date_planned
.split('/')
.reverse()
.join('-') + ' 00:00:00';
} else {
formatted_date = supplier_date_planned + ' 00:00:00';
}
} else {
// Default date : tomorrow
let date_object = new Date();
date_object.setDate(date_object.getDate() + 1);
// Get ISO format bare string
formatted_date = date_object.toISOString().replace('T', ' ').split('.')[0];
}
// Create an entry for this supplier
orders_data.suppliers_data[supplier.id] = {
date_planned: formatted_date,
lines: []
}
}
openModal();
// Prepare data: get products where a qty is set
for (let p of products) {
for (let p_supplierinfo of p.suppliersinfo) {
......@@ -714,12 +790,7 @@ function create_orders() {
if ('qty' in p_supplierinfo) {
const supplier_id = p_supplierinfo.supplier_id;
// Create entry for this supplier in data object if doesn't exist
if (orders_data.suppliers_data[supplier_id] === undefined) {
orders_data.suppliers_data[supplier_id] = [];
}
orders_data.suppliers_data[supplier_id].push({
orders_data.suppliers_data[supplier_id].lines.push({
'package_qty': p_supplierinfo.package_qty,
'product_id': p.id,
'name': p.name,
......@@ -734,13 +805,6 @@ function create_orders() {
}
}
if (Object.keys(orders_data.suppliers_data).length === 0) {
closeModal();
alert("Commande non créée : vous n'avez rentré aucune quantité !");
return -1;
}
$.ajax({
type: "POST",
url: "/orders/create_orders",
......@@ -749,12 +813,16 @@ function create_orders() {
contentType: "application/json; charset=utf-8",
data: JSON.stringify(orders_data),
success: (result) => {
$('#recap_delivery_date').text($('#date_planned_input').val());
// Display new orders
for (let new_order of result.res.created) {
const supplier_name = suppliers_list.find(s => s.id == new_order.supplier_id).display_name;
const date_planned = new_order.date_planned
.split(' ')[0]
.split('-')
.reverse()
.join('/');
product_orders.push({
'id': new_order.id_po,
'supplier_id': new_order.supplier_id,
......@@ -765,6 +833,7 @@ function create_orders() {
new_order_template.find(".new_order_supplier_name").text(supplier_name);
new_order_template.find(".new_order_po").text(`PO${new_order.id_po}`);
new_order_template.find(".new_order_date_planned").text(`Date de livraison prévue: ${date_planned}`);
new_order_template.find(".download_order_file_button").attr('id', `download_attachment_${new_order.id_po}`);
$('#created_orders_area').append(new_order_template.html());
......@@ -775,10 +844,10 @@ function create_orders() {
// Clear data
order_doc._deleted = true;
update_cdb_order();
reset_data();
update_cdb_order().then(() => {
update_order_selection_screen();
})
reset_data();
switch_screen('orders_created');
closeModal();
},
......@@ -992,7 +1061,7 @@ function prepare_datatable_data(product_ids = []) {
daily_conso: product.daily_conso,
purchase_ok: product.purchase_ok,
uom: product.uom_id[1],
stats: "Ecart type: " + product.sigma + ", % jours sans vente = " + (product.vpc) * 100
stats: `Ecart type: ${product.sigma} / Jours sans vente: ${Math.round((product.vpc) * 100)}%`
};
const computed_data = _compute_product_data(product);
......@@ -1026,7 +1095,7 @@ function prepare_datatable_columns() {
},
{
data: "default_code",
title: "Référence Produit",
title: "Ref",
width: "8%",
render: function (data) {
return (data === false) ? "" : data;
......@@ -1115,7 +1184,7 @@ function prepare_datatable_columns() {
columns.push({
data: "days_not_covered",
title: "Besoin non couvert",
title: "Besoin non couvert (jours)",
className: "dt-body-center",
width: "4%"
});
......@@ -1218,6 +1287,7 @@ function display_products(params) {
.draw();
update_cdb_order();
display_total_values();
} else {
$(this).val('');
}
......@@ -1363,6 +1433,25 @@ function unselect_all_rows() {
}
/**
* Display the total values for each supplier & the global total value
*/
function display_total_values() {
_compute_total_values_by_supplier();
$('#suppliers_total_values_container').empty();
let total_values_content = '<ul>';
let order_total_value = 0;
for (let supplier of selected_suppliers) {
total_values_content += `<li>${supplier.display_name} : ${supplier.total_value}€</li>`;
order_total_value += supplier.total_value;
}
total_values_content += '</ul>';
$('#suppliers_total_values_container').append(total_values_content);
$('#order_total_value').text(`${order_total_value}€`);
}
/**
* Update DOM display on main screen
*/
function update_main_screen(params) {
......@@ -1376,6 +1465,7 @@ function update_main_screen(params) {
$(".order_name_container").text(order_doc._id);
display_suppliers();
display_products(params);
display_total_values();
// Re-select previously selected rows
if (selected_rows.length > 0) {
......@@ -1391,17 +1481,7 @@ function update_main_screen(params) {
return 0;
});
}
if (order_doc.date_planned !== null) {
// Switch format from yy-mm-dd hh:mm:ss to readable dd/mm/yy
let date_to_format = order_doc.date_planned.split(' ')[0];
let readable_date = date_to_format.split('-').reverse()
.join('/');
$("#date_planned_input").val(readable_date);
} else {
$("#date_planned_input").val('');
}
$("#select_all_products_cb").prop("checked", false);
if (order_doc.coverage_days !== null) {
$("#coverage_days_input").val(order_doc.coverage_days);
......@@ -1429,7 +1509,6 @@ function update_order_selection_screen() {
} else {
for (let row of result.rows) {
let template = $("#templates #order_pill_template");
template.find(".pill_order_name").text(row.id);
existing_orders_container.append(template.html());
......@@ -1489,13 +1568,10 @@ function switch_screen(direction = 'main_screen', from = 'main_screen') {
}
$(document).ready(function() {
fingerprint = new Fingerprint({canvas: true}).get();
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
openModal();
// Init CouchDB
/**
* Init the PouchDB local database & sync
*/
function init_pouchdb_sync() {
dbc = new PouchDB(couchdb_dbname);
sync = PouchDB.sync(couchdb_dbname, couchdb_server, {
live: true,
......@@ -1515,13 +1591,12 @@ $(document).ready(function() {
className: "error"
}
);
update_order_selection_screen();
back();
break;
} else if (doc._deleted === true) {
update_order_selection_screen();
}
}
update_order_selection_screen();
}
}).on('error', function (err) {
if (err.status === 409) {
......@@ -1531,6 +1606,16 @@ $(document).ready(function() {
console.log('erreur sync');
console.log(err);
});
}
$(document).ready(function() {
fingerprint = new Fingerprint({canvas: true}).get();
$.ajaxSetup({ headers: { "X-CSRFToken": getCookie('csrftoken') } });
openModal();
init_pouchdb_sync();
// Main screen
$("#coverage_form").on("submit", function(e) {
......@@ -1569,13 +1654,18 @@ $(document).ready(function() {
});
$('#create_orders').on('click', function() {
if (order_doc.date_planned === null) {
alert("Veuillez rentrer une date de livraison prévue.");
let modal_create_order = $('#templates #modal_create_order');
modal_create_order.find('.suppliers_date_planned_area').empty();
return -1;
for (let supplier of selected_suppliers) {
let supplier_date_planned_template = $('#templates #modal_create_order__supplier_date_planned');
supplier_date_planned_template.find(".supplier_name").text(supplier.display_name);
supplier_date_planned_template.find(".modal_input_container").attr('id', `container_date_planned_supplier_${supplier.id}`);
modal_create_order.find('.suppliers_date_planned_area').append(supplier_date_planned_template.html());
}
let modal_create_order = $('#templates #modal_create_order');
openModal(
modal_create_order.html(),
......@@ -1586,6 +1676,26 @@ $(document).ready(function() {
false
);
// Add id to input once modal is displayed
for (let supplier of selected_suppliers) {
$(`#modal #container_date_planned_supplier_${supplier.id}`).find(".supplier_date_planned").attr('id', `date_planned_supplier_${supplier.id}`);
}
$("#modal .supplier_date_planned")
.datepicker({
defaultDate: "+1d",
minDate: new Date()
})
.on('change', function() {
try {
// When date input changes, try to read date
$.datepicker.parseDate(date_format, $(this).val());
} catch {
alert('Date invalide');
$(this).val('');
}
});
return 0;
});
......@@ -1617,40 +1727,6 @@ $(document).ready(function() {
};
$.datepicker.setDefaults($.datepicker.regional['fr']);
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
$("#date_planned_input")
.datepicker({
defaultDate: "+1d",
minDate: tomorrow
})
.on('change', function() {
try {
// When date input changes, try to read date
$.datepicker.parseDate(date_format, $(this).val());
// No exception raised: date is valid.
// Change format from readable (dd/mm/yy) to ISO (yy-mm-dd)
let formatted_date = $(this).val()
.split('/')
.reverse()
.join('-') + ' 00:00:00';
// Update doc if changed
if (formatted_date !== order_doc.date_planned) {
order_doc.date_planned = formatted_date;
update_cdb_order();
}
} catch (error) {
alert('Date invalide');
$(this).val('');
order_doc.date_planned = null;
update_cdb_order();
}
});
// Order selection screen
update_order_selection_screen();
......
......@@ -41,8 +41,8 @@ def get_suppliers(request):
def get_supplier_products(request):
""" Get supplier products """
sid = request.GET.get('sid', '')
res = CagetteProducts.get_products_for_order_helper(sid)
suppliers_id = request.GET.getlist('sids', '')
res = CagetteProducts.get_products_for_order_helper(suppliers_id)
if 'error' in res:
return JsonResponse(res, status=500)
......@@ -69,8 +69,13 @@ def create_orders(request):
# suppliers id are keys in request data
for supplier_id in data["suppliers_data"].keys():
res_created = Order.create(supplier_id, data["date_planned"], data["suppliers_data"][supplier_id])
res_created["supplier_id"] = supplier_id
supplier_data = data["suppliers_data"][supplier_id]
res_created = Order.create(
supplier_id,
supplier_data["date_planned"],
supplier_data["lines"]
)
res["created"].append(res_created)
except Exception as e:
......
......@@ -455,11 +455,11 @@ class CagetteProducts(models.Model):
return res
@staticmethod
def get_products_for_order_helper(supplier_id, pids = []):
def get_products_for_order_helper(supplier_ids, pids = []):
"""
One of the two parameters must be set.
Get products by supplier if a supplier_id is set.
If supplier_id is None, get products specified in pids.
One of the two parameters must be not empty.
Get products by supplier if one or more supplier_id is set.
If supplier_ids is empty, get products specified in pids. In this case, suppliers info won't be fetched.
"""
api = OdooAPI()
res = {}
......@@ -468,10 +468,10 @@ class CagetteProducts(models.Model):
try:
today = datetime.date.today().strftime("%Y-%m-%d")
if supplier_id is not None:
if len(supplier_ids) > 0:
# Get products/supplier relation
f = ["product_tmpl_id", 'date_start', 'date_end', 'package_qty', 'price']
c = [['name', '=', int(supplier_id)]]
f = ["product_tmpl_id", 'date_start', 'date_end', 'package_qty', 'price', 'name']
c = [['name', 'in', [ int(x) for x in supplier_ids]]]
psi = api.search_read('product.supplierinfo', c, f)
# Filter valid data
......@@ -503,8 +503,8 @@ class CagetteProducts(models.Model):
sales_average_params = {
'ids': ptids,
# 'from': '2019-06-10',
# 'to': '2019-08-10',
'from': '2019-04-10',
'to': '2019-08-10',
}
sales = CagetteProducts.get_template_products_sales_average(sales_average_params)
......@@ -515,10 +515,10 @@ class CagetteProducts(models.Model):
# Add supplier data to product data
for i, fp in enumerate(filtered_products_t):
if supplier_id is not None:
if 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"])
filtered_products_t[i]['suppliersinfo'] = [{
'supplier_id': int(supplier_id),
'supplier_id': int(psi_item["name"][0]),
'package_qty': psi_item["package_qty"],
'price': psi_item["price"]
}]
......@@ -531,7 +531,7 @@ class CagetteProducts(models.Model):
res["products"] = filtered_products_t
except Exception as e:
coop_logger.error('get_products_for_order_helper %s (%s)', str(e), str(supplier_id))
coop_logger.error('get_products_for_order_helper %s (%s)', str(e))
res["error"] = str(e)
return res
......
......@@ -53,7 +53,6 @@
<input type="text" name="supplier" id="supplier_input" placeholder="Rechercher un fournisseur par son nom">
<button type="submit" class='btn--primary'>Ajouter le fournisseur</button>
</form>
<input type="text" name="date_planned" id="date_planned_input" placeholder="Date de livraison souhaitée">
</div>
<div class="txtcenter" id="suppliers_container"></div>
......@@ -65,6 +64,15 @@
</div>
<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 class="add_product_container">
<div id="product_form_container">
<form action="javascript:;" id="product_form">
......@@ -78,6 +86,7 @@
</button>
</div>
</div>
</div>
<div id="orders_created" class="page_content" style="display:none;">
<div class="actions_buttons_area">
......@@ -88,9 +97,6 @@
<div class="order_created_header txtcenter">
<h2>Commandes créées !</h2>
</div>
<div class="txtcenter">
Livraison prévue le : <span id="recap_delivery_date">XX/XX/XX</span>
</div>
<div id="created_orders_area"></div>
<br/><br/><hr/><br/>
<div class="mail_example_container">
......@@ -128,6 +134,7 @@
<div class="new_order_item">
<h3 class="new_order_supplier_name"></h3>
<h3 class="new_order_po"></h3>
<h4 class="new_order_date_planned"></h4>
<div class='download_order_file'>
<i class="fas fa-spinner fa-spin download_order_file_loading"></i>
<a class='btn--success download_order_file_button' style="display:none;" href="#">
......@@ -168,13 +175,17 @@
Vous vous apprêtez à associer le produit <span class="product_name"></span> au fournisseur <span class="supplier_name"></span>.<br/>
</p>
<br/>
<div class="new_product_supplier_input_area">
<span class="new_product_supplier_label">Prix du produit chez ce fournisseur: </span>
<input type="number" class="new_product_supplier_input new_product_supplier_price" >
<div class="modal_input_area">
<span class="modal_input_label">Prix du produit chez ce fournisseur: </span>
<div class="modal_input_container">
<input type="number" class="modal_input new_product_supplier_price" >
</div>
</div>
<div class="modal_input_area">
<span class="modal_input_label">Colisage chez ce fournisseur: </span>
<div class="modal_input_container">
<input type="number" class="modal_input new_product_supplier_package_pty">
</div>
<div class="new_product_supplier_input_area">
<span class="new_product_supplier_label">Colisage chez ce fournisseur: </span>
<input type="number" class="new_product_supplier_input new_product_supplier_package_pty">
</div>
<br/>
<p>
......@@ -196,20 +207,35 @@
<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".
Dès que vous aurez cliqué sur "Valider", le produit sera retiré du tableau et l'information sera enregistrée dans Odoo.
</p>
<p>Êtez-vous sûr ?</p>
<hr/>
</div>
<div id="modal_create_order">
<h3>Attention !</h3>
<h3>Dernière étape...</h3>
<br/>
<p>
Vous vous apprêtez à générer les commandes à partir des données rentrées dans le tableau.
</p>
<p>Êtez-vous sûr ?</p>
<p>
Vous pouvez rentrer une date de livraison prévue pour chaque fournisseur (optionnel, la date par défaut sera celle de demain).
</p>
<br/>
<div class="suppliers_date_planned_area"></div>
<br/>
<hr/>
</div>
<div id="modal_create_order__supplier_date_planned">
<div class="modal_input_area">
<span class="modal_input_label supplier_name"></span>
<div class="modal_input_container">
<input type="text" class="modal_input supplier_date_planned" placeholder="Date de livraison prévue">
</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