feat: implement order pagination and reduce duration update frequency to optimize KDS performance

This commit is contained in:
Suherdy Yacob 2026-06-07 19:40:16 +07:00
parent 5e196ab48a
commit f097db007e
5 changed files with 103 additions and 0 deletions

View File

@ -87,6 +87,15 @@ Installation
3. Search for "POS KDS Stage Reset Fix" and install it. 3. Search for "POS KDS Stage Reset Fix" and install it.
4. No additional configuration is required. 4. No additional configuration is required.
Performance Optimization
------------------------
This module also optimizes the Preparation Display's rendering and idle CPU usage for low RAM devices:
- Order Pagination: Limits rendering to 16 order cards per page, significantly reducing DOM nodes.
- Pagination Controls: Adds Page Navigation buttons at the bottom of the main orders area.
- Timer Refresh Rate: Reduces the order age/duration update frequency from 1 second to 15 seconds.
Compatibility Compatibility
------------- -------------

View File

@ -21,6 +21,8 @@ and todo status of previously processed prep order lines.
'pos_preparation_display.assets': [ 'pos_preparation_display.assets': [
'pos_kds_fix/static/src/app/components/orderline/orderline_patch.js', 'pos_kds_fix/static/src/app/components/orderline/orderline_patch.js',
'pos_kds_fix/static/src/app/components/order/order_patch.js', 'pos_kds_fix/static/src/app/components/order/order_patch.js',
'pos_kds_fix/static/src/app/components/preparation_display/preparation_display_patch.js',
'pos_kds_fix/static/src/app/components/preparation_display/preparation_display_patch.xml',
], ],
}, },
'installable': True, 'installable': True,

View File

@ -4,6 +4,19 @@ import { Order } from "@pos_enterprise/app/components/order/order";
import { patch } from "@web/core/utils/patch"; import { patch } from "@web/core/utils/patch";
patch(Order.prototype, { patch(Order.prototype, {
setup() {
super.setup();
if (this.interval) {
clearInterval(this.interval);
this.interval = setInterval(() => {
if (this.order && this.order.pos_order_id) {
this._updateDuration();
} else {
clearInterval(this.interval);
}
}, 15000); // Update every 15 seconds instead of 1 second
}
},
get pdisNotes() { get pdisNotes() {
try { try {
return JSON.parse(this.order.pos_order_id.internal_note || "[]"); return JSON.parse(this.order.pos_order_id.internal_note || "[]");

View File

@ -0,0 +1,40 @@
/** @odoo-module **/
import { PrepDisplay } from "@pos_enterprise/app/components/preparation_display/preparation_display";
import { patch } from "@web/core/utils/patch";
patch(PrepDisplay.prototype, {
setup() {
super.setup();
this.state.currentPage = 1;
this.state.pageSize = 16; // 16 orders per page
this.lastFilterState = "";
},
get totalPages() {
const orders = this.prepDisplay.filteredOrders || [];
return Math.max(1, Math.ceil(orders.length / this.state.pageSize));
},
get paginatedOrders() {
const orders = this.prepDisplay.filteredOrders || [];
const currentStageId = this.prepDisplay.selectedStageId;
const filterState = `${currentStageId}-${Array.from(this.prepDisplay.selectedCategoryIds).join(',')}-${Array.from(this.prepDisplay.selectedProductIds).join(',')}-${Array.from(this.prepDisplay.selectedTimeIds).join(',')}-${Array.from(this.prepDisplay.selectedPresetIds).join(',')}`;
if (this.lastFilterState !== filterState) {
this.lastFilterState = filterState;
this.state.currentPage = 1;
}
const totalPages = this.totalPages;
if (this.state.currentPage > totalPages) {
this.state.currentPage = totalPages;
}
const start = (this.state.currentPage - 1) * this.state.pageSize;
return orders.slice(start, start + this.state.pageSize);
},
changePage(offset) {
const targetPage = this.state.currentPage + offset;
if (targetPage >= 1 && targetPage <= this.totalPages) {
this.state.currentPage = targetPage;
}
}
});

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-inherit="pos_enterprise.PrepDisplay" t-inherit-mode="extension" owl="1">
<!-- Replace filteredOrders loop with paginatedOrders -->
<xpath expr="//t[@t-foreach='this.prepDisplay.filteredOrders']" position="attributes">
<attribute name="t-foreach">this.paginatedOrders</attribute>
</xpath>
<!-- Add d-flex flex-column to o_pdis_main_area to support pagination at the bottom -->
<xpath expr="//div[hasclass('o_pdis_main_area')]" position="attributes">
<attribute name="class">o_pdis_main_area w-100 h-100 overflow-hidden d-flex flex-column</attribute>
</xpath>
<!-- Remove h-100 from o_pdis_orders so it auto-shrinks to make space for pagination controls -->
<xpath expr="//div[hasclass('o_pdis_orders')]" position="attributes">
<attribute name="class">o_pdis_orders position-relative d-grid flex-grow-1 gap-3 text-reset p-3 overflow-auto</attribute>
</xpath>
<!-- Append pagination controls to main area -->
<xpath expr="//div[hasclass('o_pdis_main_area')]" position="inside">
<div t-if="this.totalPages > 1" class="o_pdis_pagination d-flex justify-content-between align-items-center bg-white border-top p-3 text-dark fs-4 fw-semibold shadow-sm">
<button class="btn btn-secondary btn-lg px-4"
t-att-disabled="this.state.currentPage === 1"
t-on-click="() => this.changePage(-1)">
<i class="fa fa-chevron-left me-2"/> Previous
</button>
<span class="align-self-center">
Page <t t-esc="this.state.currentPage"/> of <t t-esc="this.totalPages"/>
<span class="text-muted ms-2 fs-6">(Total <t t-esc="this.prepDisplay.filteredOrders.length"/> orders)</span>
</span>
<button class="btn btn-secondary btn-lg px-4"
t-att-disabled="this.state.currentPage === this.totalPages"
t-on-click="() => this.changePage(1)">
Next <i class="fa fa-chevron-right ms-2"/>
</button>
</div>
</xpath>
</t>
</templates>