[FIX] point_of_sale: improve get_price performance
Test case: ~ 16 000 products and using a pricelist with a fixed price for all products (so ~16 000 pricelist_item). To reproduce: Open PoS and add an item to the order -> Very slow and not responsive: ~5 seconds to do the operation & around 2 minutes to fully load the PoS. Issue: `get_price` JS method is called several times and is a bit slow (~200ms). Mostly because of the linear search in the pricelist to check if the product does match. Note that the function is called once per ProductItem rendered. Each time a product is added to the order the rendering is refreshed for all ProductItem displayed. So the performance impact is significant if several of them are displayed. To solve: As the pricelist per Product.id is constant, we store the possible applied pricelist records on the product itself. After this commit: Order does take a few milliseconds to be added (2 ms VS 200ms) Other notes: A. With the current OWL version, it is not possible to force the render on only some of the ProductItem. A more appropriate fix could be done with "fine-grained reactivity" using a more recent OWL version B. It was thought to store/cache the price value on the ProductItem itself. It does have its share of disadvantages (no check if the pricelist time period did start/end, etc.). Either way, with that being implemented, the PoS was still a bit slow (because of the 200ms per `_get_price` call) OPW-2826122 closes odoo/odoo#90245 X-original-commit: 6f0bfb36a11e52e20b90ca85fc8847faadcdc95e Signed-off-by: Trinh Jacky (trj) <trj@odoo.com> Signed-off-by: Masereel Pierre <pim@odoo.com>
This commit is contained in:
@@ -222,11 +222,47 @@ class PosGlobalState extends PosModel {
|
||||
_loadResPartner() {
|
||||
this.db.add_partners(this.partners);
|
||||
}
|
||||
_assignApplicableItems(pricelist, correspondingProduct, pricelistItem) {
|
||||
if (!(pricelist.id in correspondingProduct.applicablePricelistItems)) {
|
||||
correspondingProduct.applicablePricelistItems[pricelist.id] = [];
|
||||
}
|
||||
correspondingProduct.applicablePricelistItems[pricelist.id].push(pricelistItem);
|
||||
}
|
||||
_loadProductProduct(products) {
|
||||
const productMap = {};
|
||||
const productTemplateMap = {};
|
||||
|
||||
const modelProducts = products.map(product => {
|
||||
product.pos = this;
|
||||
product.applicablePricelistItems = {};
|
||||
productMap[product.id] = product;
|
||||
productTemplateMap[product.product_tmpl_id[0]] = (productTemplateMap[product.product_tmpl_id[0]] || []).concat(product);
|
||||
return Product.create(product);
|
||||
});
|
||||
|
||||
for (let pricelist of this.pricelists) {
|
||||
for (const pricelistItem of pricelist.items) {
|
||||
if (pricelistItem.product_id) {
|
||||
let product_id = pricelistItem.product_id[0];
|
||||
let correspondingProduct = productMap[product_id];
|
||||
if (correspondingProduct) {
|
||||
this._assignApplicableItems(pricelist, correspondingProduct, pricelistItem);
|
||||
}
|
||||
}
|
||||
else if (pricelistItem.product_tmpl_id) {
|
||||
let product_tmpl_id = pricelistItem.product_tmpl_id[0];
|
||||
let correspondingProducts = productTemplateMap[product_tmpl_id];
|
||||
for (let correspondingProduct of (correspondingProducts || [])) {
|
||||
this._assignApplicableItems(pricelist, correspondingProduct, pricelistItem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const correspondingProduct of products) {
|
||||
this._assignApplicableItems(pricelist, correspondingProduct, pricelistItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.db.add_products(modelProducts)
|
||||
}
|
||||
_loadPosPaymentMethod() {
|
||||
@@ -1076,10 +1112,8 @@ class Product extends PosModel {
|
||||
category = category.parent;
|
||||
}
|
||||
|
||||
var pricelist_items = _.filter(pricelist.items, function (item) {
|
||||
return (! item.product_tmpl_id || item.product_tmpl_id[0] === self.product_tmpl_id) &&
|
||||
(! item.product_id || item.product_id[0] === self.id) &&
|
||||
(! item.categ_id || _.contains(category_ids, item.categ_id[0])) &&
|
||||
var pricelist_items = _.filter(self.applicablePricelistItems[pricelist.id], function (item) {
|
||||
return (! item.categ_id || _.contains(category_ids, item.categ_id[0])) &&
|
||||
(! item.date_start || moment.utc(item.date_start).isSameOrBefore(date)) &&
|
||||
(! item.date_end || moment.utc(item.date_end).isSameOrAfter(date));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user