refactor: add default fallback order object to OrderDisplay to prevent errors when props are missing
This commit is contained in:
parent
0dcd17039f
commit
85aa55dda9
@ -24,6 +24,7 @@ Features
|
|||||||
'assets': {
|
'assets': {
|
||||||
'point_of_sale._assets_pos': [
|
'point_of_sale._assets_pos': [
|
||||||
# Incremental rendering patches (existing)
|
# Incremental rendering patches (existing)
|
||||||
|
'pos_ui_optimization/static/src/app/services/pos_store_patch.js',
|
||||||
'pos_ui_optimization/static/src/app/components/order_display/order_display_patch.js',
|
'pos_ui_optimization/static/src/app/components/order_display/order_display_patch.js',
|
||||||
'pos_ui_optimization/static/src/app/components/order_display/order_display_patch.xml',
|
'pos_ui_optimization/static/src/app/components/order_display/order_display_patch.xml',
|
||||||
'pos_ui_optimization/static/src/app/screens/product_screen/product_screen_patch.js',
|
'pos_ui_optimization/static/src/app/screens/product_screen/product_screen_patch.js',
|
||||||
|
|||||||
@ -4,7 +4,23 @@ import { OrderDisplay } from "@point_of_sale/app/components/order_display/order_
|
|||||||
import { patch } from "@web/core/utils/patch";
|
import { patch } from "@web/core/utils/patch";
|
||||||
import { useState, useEffect } from "@odoo/owl";
|
import { useState, useEffect } from "@odoo/owl";
|
||||||
|
|
||||||
|
OrderDisplay.props.order = { type: Object, optional: true };
|
||||||
|
|
||||||
patch(OrderDisplay.prototype, {
|
patch(OrderDisplay.prototype, {
|
||||||
|
get order() {
|
||||||
|
return this.props.order || {
|
||||||
|
lines: [],
|
||||||
|
prices: { taxDetails: { has_tax_groups: false } },
|
||||||
|
currencyDisplayPriceExcl: "",
|
||||||
|
currencyAmountTaxes: "",
|
||||||
|
currencyDisplayPriceIncl: "",
|
||||||
|
general_customer_note: "",
|
||||||
|
internal_note: "",
|
||||||
|
config_id: {},
|
||||||
|
currency: { id: null },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
super.setup();
|
super.setup();
|
||||||
// Use Object.assign to avoid overwriting state from other patches (e.g. pos_urban_piper)
|
// Use Object.assign to avoid overwriting state from other patches (e.g. pos_urban_piper)
|
||||||
|
|||||||
63
static/src/app/services/pos_store_patch.js
Normal file
63
static/src/app/services/pos_store_patch.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
import { PosStore } from "@point_of_sale/app/services/pos_store";
|
||||||
|
import { patch } from "@web/core/utils/patch";
|
||||||
|
|
||||||
|
patch(PosStore.prototype, {
|
||||||
|
get productToDisplayByCateg() {
|
||||||
|
// We override this getter to remove Odoo's hardcoded 100-product category limit.
|
||||||
|
// Because our custom UI optimization module uses progressive rendering (lazy loading)
|
||||||
|
// on scroll, we can safely return the entire category's product list without risking
|
||||||
|
// browser freeze or UI lockups.
|
||||||
|
const sortedProducts = this.productsToDisplay;
|
||||||
|
if (!this.config.iface_group_by_categ) {
|
||||||
|
return sortedProducts.length ? [["0", sortedProducts]] : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
const searchWord = this.searchProductWord.trim();
|
||||||
|
const byCateg = this.models["product.template"].toRaw().getAllBy("pos_categ_ids");
|
||||||
|
const selectedCategoryIds = !this.selectedCategory
|
||||||
|
? this.models["pos.category"].map((c) => c.id)
|
||||||
|
: this.selectedCategory.getAllChildren().map((c) => c.id);
|
||||||
|
|
||||||
|
// Sorting in place the categories according to their sequence in the database
|
||||||
|
selectedCategoryIds.sort((a, b) => {
|
||||||
|
const categA = this.models["pos.category"].get(a);
|
||||||
|
const categB = this.models["pos.category"].get(b);
|
||||||
|
|
||||||
|
// All category with a parent will be at the end
|
||||||
|
if (categA.parent_id && !categB.parent_id) {
|
||||||
|
return 1;
|
||||||
|
} else if (!categA.parent_id && categB.parent_id) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return categA.sequence - categB.sequence;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.selectedCategory) {
|
||||||
|
// In case of no category selected, we want to display products without category in
|
||||||
|
// a "Without category" category at the end of the list.
|
||||||
|
const productWithoutCategory = sortedProducts.filter((p) => !p.pos_categ_ids.length);
|
||||||
|
byCateg["0"] = productWithoutCategory;
|
||||||
|
selectedCategoryIds.push("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const catId of selectedCategoryIds) {
|
||||||
|
const products = byCateg[catId] || [];
|
||||||
|
const filtered = searchWord
|
||||||
|
? this.getProductsBySearchWord(searchWord, products)
|
||||||
|
: products;
|
||||||
|
|
||||||
|
if (filtered.length) {
|
||||||
|
const sorted = this.orderProductBySequenceAndFav(filtered);
|
||||||
|
// Return the complete list instead of splicing to 100 items.
|
||||||
|
// Our lazy loading mechanism will handle rendering chunk-by-chunk.
|
||||||
|
results.push([catId, sorted]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -99,6 +99,8 @@
|
|||||||
flex-grow: 1 !important;
|
flex-grow: 1 !important;
|
||||||
flex-shrink: 1 !important;
|
flex-shrink: 1 !important;
|
||||||
min-height: 0 !important;
|
min-height: 0 !important;
|
||||||
|
overflow-y: auto !important;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user