Wednesday, February 4, 2026
19 changes · saas-18.4
Resolved issues and error corrections
Spanish Veri*Factu POS orders can no longer be combined into a single invoice. This avoids an error during invoicing and ensures each order is invoiced individually as required for reliable compliance handling.
Original PR description
Step to reproduce: - install `l10n_es_edi_verifactu_pos` and open POS - finalize 2 order with same customer (do not invoive it) - close session - go to pos orders, select both order and try to create…
Step to reproduce:
- install `l10n_es_edi_verifactu_pos` and open POS
- finalize 2 order with same customer (do not invoive it)
- close session
- go to pos orders, select both order and try to create consolidated invoice
Traceback:
```
File "/home/odoo/addons/l10n_es_edi_verifactu_pos/models/pos_order.py", line 293, in _prepare_invoice_vals
res['l10n_es_edi_verifactu_refund_reason'] = self.l10n_es_edi_verifactu_refund_reason
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/orm/fields.py", line 1365, in __get__
record.ensure_one()
```
Cause:
- `_prepare_invoice_vals` is written to accept only one order at time but it can contain multiple orders
Fix:
- we now do not allow invoice consolidation for Veri*Factu
- the consolidation flag has been made invisible so every order now has
to be invoiced individually.
opw-5379577
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#239391Odoo now uses the tenant-specific Microsoft token endpoint when renewing Outlook calendar access. This prevents calendar synchronization from stopping after the initial access token expires for businesses using single-tenant Azure applications.
Original PR description
Single-tenant Azure applications could synchronize calendar with Outlook, but refresh token renewal fail. Odoo was always using the default Microsoft token endpoint instead of the tenant-specific endpoint required for single-tenant apps. Steps to reproduce: - Create a single-tenant app in the Azure portal - Configure Odoo Microsoft Calendar with this app - Set `microsoft_account.auth_endpoint` and `microsoft_account.token_endpoint` system parameters with the specific endpoints using the tenant ID - Open the Calendar app and sync with Outlook - Wait for access token expiration - Refresh token request fails This commit fixes the issue by using the token endpoint stored in the microsoft_account.token_endpoint system parameter when requesting a refresh token. Forward-Port-Of: odoo/odoo#246829 Forward-Port-Of: odoo/odoo#244371
Employees using a work schedule that is not tied to a specific company will now see company public holidays correctly in Time Off. This prevents public holidays from being wrongly counted as leave days, improving accuracy in multi-company setups.
Original PR description
Revert of https://github.com/odoo/odoo/commit/a95af8b78a94a795e05a0adf299837adc0ef2117 and https://github.com/odoo/odoo/commit/f4f9ecb3e4801b3d382abc24c478fe5e533c9bf8 **Steps to reproduce** 1.…
Revert of https://github.com/odoo/odoo/commit/a95af8b78a94a795e05a0adf299837adc0ef2117 and
https://github.com/odoo/odoo/commit/f4f9ecb3e4801b3d382abc24c478fe5e533c9bf8
**Steps to reproduce**
1. Remove the company of the Working Schedule (needs to be done in
a multi-company environment from the UI) used by an employee.
2. Using the company of this employee, create a Public Holiday
(for the employee's schedule or all schedules).
Issues:
- the public holiday doesn't appear in the Time Off dashboard
- when taking a time off on that day, the public holiday is
included in the duration
**Cause**
After the fix in https://github.com/odoo/odoo/commit/a95af8b78a94a795e05a0adf299837adc0ef2117 , it will lead
to a search domain for public holidays of `('company_id', 'in', [False])`
when the working schedule has no company, ignoring any public
holidays with a company set. This is especially problematic since the
company of the public holiday is always forced.
https://github.com/odoo/odoo/blob/7bce5f3f95429a4d4ba034a66c350ee2a5868567/addons/resource/models/resource_calendar_leaves.py#L49-L51
**Solution**
Since the intent of the original fix https://github.com/odoo/odoo/commit/f4f9ecb3e4801b3d382abc24c478fe5e533c9bf8
was to correct an issue related to the computation of some `project.task`
fields calling a resource method (`get_work_duration_data`), we can revert
the fix and later fix the original issue directly in `project`, without
impacting `hr`/`resource` modules.
opw-5496999
opw-5401425
Forward-Port-Of: odoo/odoo#246779
Forward-Port-Of: odoo/odoo#244052Receipt printers with an open cover could previously stall indefinitely, preventing other printers from being detected or used. This change adds a timeout so delayed print jobs fail safely and the overall printer service remains responsive.
Original PR description
This PR https://github.com/odoo/odoo/pull/244031 added `self.printer._raw` method usage. Behind the scenes it uses "write" which in its turn uses the timeout defined when instantiating `self.escpos_device = printer.Usb()` Since we currently provide no timeout in some situations like when the printer cover is open the `_raw` method would block indefenitely and stop all the other printers detection. This PR fixes it by adding a timeout, ensuring that print jobs which take too long result in a timeout.
Fixed an issue where images added back into an email marketing template could disappear again after saving. This helps users reliably edit campaign emails without losing newly inserted images.
Original PR description
**Steps to reproduce:** - Install Email Marketing app - Create a new campaign with Subject and Recipients - Set plain text mail body - Add one image using /img or /image command - Save the template -…
**Steps to reproduce:**
- Install Email Marketing app
- Create a new campaign with Subject and Recipients
- Set plain text mail body
- Add one image using /img or /image command
- Save the template
- Remove the image
- Save the template
- Try to re-add an image, on save it will be deleted everytime
**Issue:**
During `commitChanges`, the history of the editor is in a wrong state which triggers a cleanup on
`this.wysiwyg.odooEditor.historyRevertCurrentStep();`.
This is caused by the `await saveCallback(element);` of `_onMediaDialogSave` which never resolve and never call its follow-up:
```js
this.odooEditor.historyUnpauseSteps();
this.odooEditor.historyStep();
```
The resolve is event-dependent and doesn't seem to be triggered in current versions:
`const event = $.Event("image_changed", {_complete: resolve});`
**Fix:**
Check that the current element is listening to the given event.
Might not be the proper fix as I wasn't able to reproduce the expected behavior with `image_changed` event.
related PR: https://github.com/odoo/odoo/pull/205594
opw-5245367
Forward-Port-Of: odoo/odoo#244396The editor now detects when the browser or device cannot support WebGL and disables image filter tools instead of showing an error. This improves reliability for users on affected Chrome/Linux setups or devices without WebGL support while keeping editing available.
Original PR description
*: html_editor This commit backports [3817cdd], which was properly adapted in 19.0. In 18.4 ([c943a88]), it was kept by mistake as in previous versions, prior to the html_builder refactoring. As a…
*: html_editor This commit backports [3817cdd], which was properly adapted in 19.0. In 18.4 ([c943a88]), it was kept by mistake as in previous versions, prior to the html_builder refactoring. As a result, the fix didn't work in this specific version. Original explanation: On recent versions of Chrome for Linux (v140+), the old SwiftShader software fallback for WebGL has been removed. As a result, new window.WebGLImageFilter() now throws if no GPU context is available, typically when WebGL is disabled or unsupported. Since the application cannot enable WebGL from JavaScript, this commit improves the user experience by detecting the absence of a WebGL context early and disabling image filters in edit mode. Instead of raising a traceback, the editor now skips the filter feature and can optionally display a friendly message explaining that WebGL is required to use image filters. This avoids runtime errors and ensures a more robust behavior on platforms where WebGL is unavailable. [3817cdd]: https://github.com/odoo/odoo/commit/3817cdd3bc096e62dbd017a85356a8032d5217bd [c943a88]: https://github.com/odoo/odoo/commit/c943a882624900743f02719560b70a0a683f095a task-5117584
Self-order restaurant tickets now avoid printing a duplicated “Order” label, making kitchen slips clearer. Orders sent from QR self-order are also synced correctly so staff no longer see an unnecessary “Send To Kitchen” button after the order is already in the kitchen.
Original PR description
Configuration: ------------------------- - Restaurant Mode - Self-Order Mode: “QR + Ordering” - Service At: Table (Online Payment)…
Configuration:
-------------------------
- Restaurant Mode
- Self-Order Mode: “QR + Ordering”
- Service At: Table (Online Payment)
--------------------------------------------------------------------------------
Issue 1: Extra Order word print in KOT
---------------------
Steps to Reproduce:
1. Make an order using Self Order (QR).
2. Configure and enable the Kitchen Printer.
3. Check the KOT print it shows “Order Self-Order T2”.
Cause:
- The QWeb template always prefixed “Order” regardless of order type.
Fix:
- Added a condition to skip the “Order” label for self-order references:
--------------------------------------------------------------------------------
Issue 2: “Send To Kitchen” Button Visible even order in kitchen
---------------
Steps to Reproduce:
1. Open the Restaurant
2. Place a order from mobile menu and select a table.
3. In the Restaurant UI:
- Open that table. The "Send To Kitchen" button is still visible even
though the order was already sent to the kitchen and printed.
Cause:
- In self-order mode the order is not automatically synced after being sent to
the kitchen and print.
- As a result, the system still treats it as unsent, leaving the Order button
visible.
Fix:
- Synced the order state after sending it to the kitchen.
----------------------------------------------------
Task-5106704
Forward-Port-Of: odoo/odoo#231005Fixes an editor issue where pasted text or image links could be inserted inside an existing empty or selected link instead of replacing it. This makes editing linked content more predictable and prevents accidental broken or unwanted links.
Original PR description
Problem: When pasting text or a image URL inside an empty link, or when the link is fully selected, the link is not removed and replaced by the pasted content. Instead, the text or URL is inserted…
Problem: When pasting text or a image URL inside an empty link, or when the link is fully selected, the link is not removed and replaced by the pasted content. Instead, the text or URL is inserted inside the link, which is not the intended behavior. Cause: When pasting text or a image URL, and a command is triggered from the powerbox via `openPowerboxOnUrlPaste`, we call `addStep` after the content insertion. This step not only inserts the content but also removes the link if it was fully selected (via `before_paste_handlers`). However, `onApplyCommand` then restores the state to before the content insertion and link removal. The command (e.g. “Embed Image”) is executed on that restored state, where the selection is collapsed inside the link. As a result, the inserted content ends up inside the link instead of replacing it. Solution: In this situation, fully select the link before inserting the content. This allows the `insert` logic to correctly replace the link with the pasted text or URL. task-5386862 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users mentioned in a discussion sub-channel are now automatically added to that sub-channel, so it appears in their sidebar. This helps ensure important pings are visible and reduces the chance of missed messages.
Original PR description
Before this commit, when a user was mentioned in a sub-channel they were not member of, the sub-channel would not appear in their sidebar. This could lead to some missed pings. This commit fixes the issue by automatically adding mentioned users to the sub-channel, ensuring it is pinned to their sidebar. task-5233958 Forward-Port-Of: odoo/odoo#246423 Forward-Port-Of: odoo/odoo#237538
Refunds made in Point of Sale with the “Ship Later” option now correctly reduce the delivered quantity on the related sales order. This prevents sales teams from seeing an incorrect delivered quantity of zero after a partial refund, improving order accuracy and follow-up.
Original PR description
The qty_delivered on sale.order.line was not correctly computed when the original order was refunded with a ship later. Steps to reproduce: ------------------- * Create a sale order for 5 quantities of any product * Confirm the sale order * Settle the order in the PoS * At this point the qty_delivered on the sale order line is 5 * Now go back to the PoS and refund partially the order for 3 quantities and use the "Ship Later" option > Observation: The qty_delivered is 0 instead of 2 Why the fix: ------------ We group the pos.order.line by procurement group and then check if all pickings related to these lines are done before adding the qty to the qty_delivered. We also make sure to include the refund lines in the computation opw-5059560 Forward-Port-Of: odoo/odoo#244640 Forward-Port-Of: odoo/odoo#240945
Malaysia POS consolidated e-invoices now calculate discounts using tax-excluded amounts, so tax included in product prices is no longer mistaken for a discount. This prevents incorrect MyInvois XML reporting and improves compliance with Malaysia e-invoicing rules.
Original PR description
The _add_consolidated_invoice_base_lines_vals method computed the gross subtotal using `price_unit * quantity`. When taxes are configured as "Included in Price", `price_unit` contains the…
The _add_consolidated_invoice_base_lines_vals method computed the gross subtotal using `price_unit * quantity`. When taxes are configured as "Included in Price", `price_unit` contains the tax-included amount, but `total_excluded` (used for the discounted amount) is tax-excluded.
This caused the tax amount to be incorrectly reported as an AllowanceCharge (discount) in the MyInvois XML, because:
discount_amount = price_unit * qty - total_excluded
= tax_included - tax_excluded
= TAX AMOUNT (not a discount!)
Example: Product priced at 110 MYR with 10% tax included:
- price_unit = 110 (tax-included)
- total_excluded = 100 (tax-excluded: 110 / 1.10)
- discount_amount = 110 - 100 = 10 ← incorrectly reported as discount
refs:
The cac:AllowanceCharge element in UBL is specifically for discounts and surcharges, NOT for taxes. According to the Peppol Malaysia e-Invoice specification:
https://docs.peppol.eu/poac/my/pint-my-sb/bis/#_allowances_and_charges
https://docs.peppol.eu/poacc/billing/3.0/codelist/UNCL5189/ (For this case we are interested in code 95)
Steps to Reproduce:
1. Configure a tax as "Included in Price" with Malaysia tax type
2. Create a product with that tax.
3. Create POS orders without any discount
4. Generate consolidated invoice and XML
5. XML incorrectly shows <cac:AllowanceCharge> with tax amount as discount
The fix uses `raw_total_excluded / discount_factor` (always tax-excluded) instead of `price_unit * quantity` (may be tax-included), consistent with the parent method:
https://github.com/odoo/odoo/blob/d645361a95037ac580d55e80bcb61d1eeb293efd/addons/account_edi_ubl_cii/models/account_edi_xml_ubl_20.py#L1846-L1876
Ticket [link](https://www.odoo.com/odoo/project.task/5476526)
opw-5476526
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#246490
Forward-Port-Of: odoo/odoo#245535This fix prevents invoice sending from failing when Belgian Peppol invoices include multiple fixed taxes such as emptying fees. The system now keeps those tax lines separate during calculation, avoiding an error and allowing affected invoices to be generated correctly.
Original PR description
Steps: - Belgian localisation - Activate peppol - Have two fixed sales taxes (T1 3.5 and T2 4.5) - Have 4 product: - P1: Any sale price, taxes 21% and T1 - P2: Any sale price, taxes 21% and T2 - P3: sale price 0, taxes 0% and T1 - Create an invoice, with following invoice lines: - P1, quantity 2 - P2, quantity 2 - P3, quantity -4 - Confirm and send it to peppol -> Traceback (ZeroDivisionError) The reason is that we try to extract emptying taxes like "Vidanges" and aggregate them into new base lines, but we treat all these taxes as they are the same but they are not always the same. Therefore we aggregate both price unit and quantity and we try to divide the aggregated price by the aggregated quantity. In our case we end up with a price unit of 2 (9 + 7 - 14) and a quantity of 0 (2 + 2 + -4) which leads to a zero division error. The fix adds a grouping function in order to group the extra lines by taxes before aggregating them. opw-5384928 Forward-Port-Of: odoo/odoo#244314
Website text highlights now appear in the correct position when visitors view content in right-to-left languages such as Arabic. This improves the visual quality and readability of multilingual websites, especially where highlighted text is used for emphasis.
Original PR description
Scenario: - add a RTL language to website (eg. arabic) - go to the website and add a highlight to part of a line - switch to RTL language Result: the highlight is not at the correct X position. This…
Scenario:
- add a RTL language to website (eg. arabic)
- go to the website and add a highlight to part of a line
- switch to RTL language
Result: the highlight is not at the correct X position.
This commit fixes the issue for most browser by changing in RTL that:
- the SVG is positionned from the right so the SVG right matches
the boundary rect right
- mirroring the SVG so when the 1x1 pixel is scaled, it is scaled toward
the left and it matches the left boundary rect
This is not always working (mostly for safari) because the positionning
of position:absolute SVG inside highlighted position:relative SPAN is
behavior differently in RTL (an even behave differently in case of mixed
RTL / LTR strings in dir:rtl blocks).
This is reproduced in this code:
https://gist.github.com/nle-odoo/21fea59d338b55b3e2a337cf360ef878
So to fix that issue, after inserting a SVG element in RTL in DOM, we
correct the X position by the current error from what we intended.
opw-5049432
opw-5344412
opw-5867908
## PR NOTE:
### 1) For the part:
```diff
- const firstRect = highlightEl.getClientRects()[0];
+ const rtl = window.getComputedStyle(highlightEl).direction === "rtl";
+ let firstRect;
+ if (rtl) { // Take the first top right element instead of top left
+ firstRect = [...highlightEl.getClientRects()].sort((a, b) => a.top - b.top || (b.left + b.width) - (a.left + a.width))[0];
+ } else {
+ firstRect = highlightEl.getClientRects()[0];
+ }
+
...
- const spanOffsetX = firstRect.x - containerRect.x;
const spanOffsetY = firstRect.y - containerRect.y;
- svg.style.left = `${(rects.x - containerRect.x - spanOffsetX) * scale}px`;
svg.style.top = `${(rects.y - containerRect.y - spanOffsetY) * scale}px`;
svg.style.bottom = `0px`;
- svg.style.right = `0px`;
+ if (rtl) { // Position from the right instead of left and mirror the SVG
+ const spanOffsetX = containerRect.x + containerRect.width - firstRect.x - firstRect.width;
+ svg.style.left = `0px`;
+ svg.style.right = `${(containerRect.x + containerRect.width - rects.x - rects.width - spanOffsetX) * scale}px`;
+ svg.style.transform = 'scale(-1, 1)';
+ } else {
+ const spanOffsetX = firstRect.x - containerRect.x;
+ svg.style.left = `${(rects.x - containerRect.x - spanOffsetX) * scale}px`;
+ svg.style.right = `0px`;
+ }
```
I don't understand why the other SVG are positioned relative to the first one(but the original code did that and making it but with the logic of RTL instead of LTR seems to be the only way to make it work).
Note that in saas-18.3 the logic seemed to be a lot more simple, but there was a "display: inline-block;" on the highlight item which simplified the logic a lot (you can just have 100% width to match the item highlighted), but would make (LTR in RTL content, or RTL in LTR content) "`<highlight>hello</highlight> world`" appear in RTL as "`world <highlight>hello</highlight>`".A recent error message appearing during payment processing with Avatax has been resolved. This was caused by an outdated method that no longer exists in the system. The fix removes this unused method, ensuring smooth payment processing for users utilizing Avatax.
Original PR description
Step to reproduce: - configure pos for Avatax from settings - open pos and settle a order - notice a error message on payment page Cause: - error is due to usage of `replaceDataByKey` which is removed in [1] [1] https://github.com/odoo/odoo/commit/3e94fe90ded58d498f0098cd9ed8679cbe500b8f Fix: - we removed the method as now we do not rely on it. opw-5089351 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#106135 Forward-Port-Of: odoo/enterprise#102101
A client reported that bankgiro payments were failing. This pull request corrects a typo and adjusts the order of data fields in the payment processing, ensuring bankgiro payments now function correctly. This resolves a critical issue impacting payment processing.
Original PR description
After PR: https://github.com/odoo/enterprise/pull/104777 The client reported that payment with bankgiro account doesn't works. Here are the problems found: - Typo : Should be `RfrdDocAmt` instead of `RfdDocAmt` - RfrdDocAmt should be inserted before CdtrRefInf - CdtNoteAmt should be before RmtdAmt opw-5427505 Forward-Port-Of: odoo/enterprise#106272
This update resolves an issue where subscriptions with zero-quantity lines resulted in invoices being incorrectly set to the subscription's start date. The fix ensures that invoice dates are accurately calculated, even when subscriptions include both positive and negative quantities, preventing delayed invoicing.
Original PR description
### Issue: When creating a subscription with several lines whose quantities add up to zero, the next invoice date is not updated and set to the start date. ### Steps to reproduce: - Install…
### Issue: When creating a subscription with several lines whose quantities add up to zero, the next invoice date is not updated and set to the start date. ### Steps to reproduce: - Install 'sale_subscription' - Create a new Subscription with two lines and a tart data several months in the past - One with a quantity of 1 and a higher price - The other with a quantity of -1 - It can be the same service product with invoicing based on ordered quantity - Confirm the Subscription - Click "Create Invoice" and confirm the invoice - Back to the Subscription, the next invoice date was not updated. ### Cause: In `_get_max_invoiced_date()` to compute the invoiced periods we check the quantity corresponding to this period. But if an invoice has two lines with opposite quantities, they will cancel each other out at this line: https://github.com/odoo/enterprise/blob/c2ac44f492ec53083864f07ff5bfbff9458ddf2a/sale_subscription/models/account_move_line.py#L131 So the method will return not return the date in `invoice_dates`. Later, if `_get_max_invoiced_date()` returns nothing for `last_invoice_end_date` then `next_invoice_date` is set to `start_date`: https://github.com/odoo/enterprise/blob/c2ac44f492ec53083864f07ff5bfbff9458ddf2a/sale_subscription/models/account_move.py#L66-L67 ### Solution: The goal was to not include invoices that were fully refunded for the `last_invoice_end_date`. This is why `_get_max_invoiced_date()` substract the quantities from refunds. To make this work we can take the absolute value of the quantity returned by the compute method before giving it the wanted sign based on if it's an invoice or a refund. opw-5360930 Forward-Port-Of: odoo/enterprise#106226 Forward-Port-Of: odoo/enterprise#103705
This update ensures that freight costs are now accurately included in the customs documents generated for international deliveries. Previously, the system incorrectly reported freight costs as zero. This change aligns with Sendcloud's API specifications and ensures accurate customs documentation for international shipments, improving compliance and transparency.
Original PR description
Issue ----- For international deliveries, the customs document does not include the freight costs. Steps to reproduce ----- - Create an international sale (eg BE -> US) - Validate delivery - Open the commercial invoice > Freight costs is set to 0 Change ----- The `freight_costs` should be included in the `customs_information` field of the request (along with all customs-related data, as other fields have been deprecated) https://api.sendcloud.dev/docs/sendcloud-public-api/branches/v2/parcels/operations/create-a-parcel#:~:text=object%2E-,customs%5Finformation ----- Ticket: opw-5486742 Forward-Port-Of: odoo/enterprise#105543
This update fixes a problem that prevented payslips from generating correctly when employees were linked to multiple commission plans using the same input. The change ensures accurate currency conversion for each commission, resolving a technical error that impacted payslip generation. This ensures consistent and reliable commission calculations for all employees.
Original PR description
Currently, an error occurs while generating a payslip for an employee who is linked to more than one commission plan using the same payslip input. **Steps to Reproduce:** 1. Install the…
Currently, an error occurs while generating a payslip for an employee who is linked to more than one commission plan using the same payslip input. **Steps to Reproduce:** 1. Install the hr_payroll_sale_commission module. 2. Create a user and link to an employee. Set a contract for the employee. 3. Create two commission plans for the same user: - Use the same Payslip Input in both plans. - Set the Target Frequency to "Monthly" for both. 4. Generate a payslip for the employee. Ref: [Video](https://drive.google.com/file/d/1HhtUL2xznS_Aoi9ePL0OJLdGaXU8ZFZR/view?usp=sharing) **Error:** `ValueError - Expected singleton: sale.commission.report(30026010100009, 40026010100009)` **Cause:** When multiple commission records belong to the same payslip input, it tries to convert the commission amount using `coms.commission`, where coms has multiple recordsets. This leads to a singleton error during currency conversion. **Fix:** This commit ensures the currency conversion is applied per commission and prevents the singleton error. sentry-7187854690 Forward-Port-Of: odoo/enterprise#104600 Forward-Port-Of: odoo/enterprise#104464
This update fixes an issue where subscription invoices were being generated prematurely when a note or section was added to the subscription. The fix ensures that invoices are now correctly calculated based on the end of the subscription period, regardless of whether a note is included. This improves invoice accuracy and prevents billing discrepancies.
Original PR description
**Steps to reproduce** - Have a subscription service product with invoicing policy set to "Based on delivered quantity (manual)". - Create a new monhtly subscription with this product and add a section or a note. - Confirm the subscription. Actual: next invoice date is today. Expected: same as without section/note, next invoice date should be at end of the period. **Cause** `_is_postpaid_line` should only be called on actual product lines. Related: https://github.com/odoo/enterprise/commit/d8a7f7cc2d9d11e42ed24db1b0f7a3c08c7fac1c opw-5478394 Forward-Port-Of: odoo/enterprise#104892