In my Odoo 18 POS, I want to customize the receipt so that:
Only products of type “combo” are displayed.
The individual items included in the combo are not listed separately.
The displayed price is the total price of the combo, not the sum of the child products.
The receipt layout remains the default Odoo POS layout.
The order date should be displayed, not just the payment timestamp.
I have tried overriding OrderReceipt using a CustomOrderReceipt component, but I encounter errors such as OwlError or Cannot read properties of undefined when filtering lines or accessing paymentlines.
I am looking for an approach or working example to:
Filter order lines to show only combos.
Display the total price of the combo.
Show the order date.
Avoid Owl errors caused by missing data (e.g., payment_method undefined).
Any advice or working examples would be greatly appreciated.
My template
[text](
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!-- Surcharge du template OrderReceipt -->
<t t-name="pos_receipt_customisation.OrderReceipt" t-inherit="point_of_sale.OrderReceipt" t-inherit-mode="primary">
<xpath expr="//OrderWidget" position="replace">
<!-- Filtrer uniquement les lignes de type combo (exclure enfants) -->
<t t-set="combo_lines" t-value="props.data.orderlines.filter(line => line.is_combo)"/>
<div class="order-container d-flex flex-column flex-grow-1 overflow-y-auto text-start">
<t t-foreach="combo_lines" t-as="line" t-key="line.id">
<li class="orderline position-relative d-flex align-items-center p-2 lh-sm cursor-pointer px-0">
<div class="product-order"></div>
<div class="d-flex flex-column w-100 gap-1">
<div class="d-flex justify-content-between">
<div class="product-name d-inline-block flex-grow-1 fw-bolder pe-1 text-truncate">
<span class="text-wrap"><t t-esc="line.productName"/></span>
</div>
<div class="product-price price fw-bolder">
<t t-esc="line.price_total ? props.formatCurrency(line.price_total) : props.formatCurrency(line.price)"/>
</div>
</div>
<ul class="info-list d-flex flex-column">
<li class="price-per-unit">
<span class="qty px-1 border rounded text-bg-view fw-bolder me-1">
<t t-esc="line.qty"/> <t t-esc="line.unit || 'Unité(s)'"/>
</span>
x <t t-esc="line.price_total ? props.formatCurrency(line.price_total) : props.formatCurrency(line.price)"/> / <t t-esc="line.unit || 'Unité(s)'"/>
</li>
</ul>
</div>
</li>
</t>
</div>
<!-- Montant total -->
<div class="pos-receipt-amount receipt-total">
TOTAL
<span class="pos-receipt-right-align">
<t t-esc="props.formatCurrency(props.data.amount_total)"/>
</span>
</div>
<!-- Paiement -->
<div class="paymentlines text-start">
<t t-foreach="props.data.paymentlines" t-as="line" t-key="line.id">
<t t-if="line.payment_method">
<t t-esc="line.payment_method.name"/>
<span class="pos-receipt-right-align">
<t t-esc="props.formatCurrency(line.amount)"/>
</span>
</t>
<t t-else="">
<span>Autre</span>
<span class="pos-receipt-right-align">
<t t-esc="props.formatCurrency(line.amount)"/>
</span>
</t>
</t>
</div>
</xpath>
</t>
<!-- Surcharge ReceiptScreen -->
<t t-name="pos_receipt_customisation.ReceiptScreen" t-inherit="point_of_sale.ReceiptScreen" t-inherit-mode="extension" owl="1">
<xpath expr="//OrderReceipt" position="replace">
<CustomOrderReceipt data="pos.orderExportForPrinting(pos.get_order())" formatCurrency="env.utils.formatCurrency"/>
</xpath>
</t>
</templates>
this is the Js:
/** @odoo-module **/
import { patch } from "@web/core/utils/patch";
import { ReceiptScreen } from "@point_of_sale/app/screens/receipt_screen/receipt_screen";
import { OrderReceipt } from "@point_of_sale/app/screens/receipt_screen/receipt/order_receipt";
export class CustomOrderReceipt extends OrderReceipt {
static template = "pos_receipt_customisation.OrderReceipt";
}
patch(ReceiptScreen, {
components: { ...ReceiptScreen.components, CustomOrderReceipt },
});
)
What I tried:
I tried to customize the Odoo 18 POS receipt by:
Creating a custom XML template that inherits from point_of_sale.OrderReceipt.
Using an xpath to replace the OrderWidget section and filter only combo products (line.is_combo).
Displaying the combo product name, quantity, and total price, while excluding the products included in the combo.
Adding the total amount and payment lines using props.formatCurrency.
Creating a JavaScript class CustomOrderReceipt extending OrderReceipt and patching ReceiptScreen to include the custom component.
What I was expecting:
The receipt should only show combo products, not their child items.
Each combo should display its total price.
The receipt layout should remain the default Odoo POS style.
The total order amount and payment lines should display correctly.
Ideally, the receipt should also display the order date, not just the payment time.
Currently, instead of this expected behavior, I am getting Owl lifecycle errors and some combo prices or payment methods sometimes don’t display properly.