Friday, September 18, 2026
21 changes · saas-19.4
Enhancements to existing features
The Belgian payroll module now uses the latest official indexed rate for the economic unemployment bonus. This helps keep payroll calculations aligned with current Belgian requirements and reduces the risk of outdated employee compensation amounts.
Original PR description
Update the economic_unemployment_bonus parameter values to reflect the official rate indexation. task-6541797
Resolved issues and error corrections
This fixes how Odoo determines the flag image shown for a language, allowing custom modules to choose a different flag when needed. It matters for businesses that serve specific regions or want more accurate localization without extra workaround development.
Original PR description
Which flag stands for a language is a presentation choice, not a property of its code. `_compute_field_flag_image_url` derives the URL from the country part of the locale, and a site that wants a…
Which flag stands for a language is a presentation choice, not a property of its code. `_compute_field_flag_image_url` derives the URL from the country part of the locale, and a site that wants a different flag for a language it offers, a regional one or the flag of the country it actually serves rather than the one the code names, has to compute that URL its own way.
That is not possible today. The field passes the compute as the function object:
flag_image_url = fields.Char(compute=_compute_field_flag_image_url)
`determine()` takes the `callable` branch and calls that object with the recordset. A plain function is not bound, so the implementation of `base` runs whatever class the record has: a module that inherits res.lang and defines `_compute_field_flag_image_url` changes nothing, and nothing says so. No error, no warning, and the field keeps answering the same URL. Getting around it means redeclaring the field only to replace its compute, which is more than the situation calls for.
Passing the method name puts the computation back on the MRO and costs nothing else: `Field.get_depends` resolves a string with `resolve_mro` and collects `_depends` from every implementation it finds, so the `@api.depends('code', 'flag_image')` declared here keeps applying, to this implementation and to an override alike.
This is the same kind of fix as #185419, which made the `domain` of a field reachable by an override for the same reason. Two field declarations in the codebase still pass a function object this way; the other is `website.menu.is_mega_menu`, which passes `inverse` the same way and is left alone here.
Forward-Port-Of: odoo/odoo#288686This fixes cases where product quantity precision was still using an old setting name, causing the system to default to only two decimal places. It helps keep point-of-sale, stock packaging, and Jordanian POS e-invoicing calculations accurate when products require more precise unit quantities.
Original PR description
…al.precision The `decimal.precision` "Product Unit of Measure" was renamed "Product Unit" in 18.1. Some occurences called the old name still exist in the code. This is silently fallbacking on the default 2 decimals from the `precision_get`. See: https://github.com/odoo/odoo/pull/193490 task-none Forward-Port-Of: odoo/odoo#288964 Forward-Port-Of: odoo/odoo#288508
This fixes a crash that could occur when users discarded changes while editing a mass mailing. The update ensures the email campaign editor recognizes the correct close-and-discard action, improving reliability without changing the user workflow.
Original PR description
Commit [1] introduced usage of a `discardAndClose` props, but declared it as `discardChanges`. This did not cause any issue because `owl3_compatibility_layer` uses `useProps()` which accepts any props without validation. However, after commit [2] in Odoo 20.0, usage of `useProps` in the `MassMailingBuilder` means that `useProps()` is overwritten, and the component will only accept props that are declared in the schema. This commit fixes the invalid props schema. [1]: https://github.com/odoo/odoo/commit/c6fbfb69c2a59041fc360bb4ddf3b09a1eeaf012 [2]: https://github.com/odoo/odoo/commit/5df880f7ba851abf4151fca2f2af50b1c18afb2c task-6584680
When users duplicate a section, the related product now carries over even if that field is locked. This prevents copied lines from losing product information, reducing manual correction and potential billing mistakes.
Original PR description
**Version: saas-19.4+** **Description of the issue/feature this PR addresses:** Duplicating a section doesn't copy the product when it's readonly. **Current behavior before PR:** Duplicated lines keep qty/description but product is empty. **Desired behavior after PR is merged:** Product is always copied when duplicating a section.
A navigation issue in the API documentation was fixed so opening a related field in a new tab now leads to the intended related model instead of the original model. This makes model exploration more reliable and avoids confusion for users consulting technical documentation.
Original PR description
Steps to reproduce: * open api_doc * select a model (eg: project.task) * middle click on a many2one field (eg: stage_id) Observed behavior: The new tab is opened on the base model (project.task) instead of the comodel (project.task.type). This commit fixes the issue by using `t-att-href` to point to the correct model and `preventDefault` to avoid a full reload when clicking on a m2o. Forward-Port-Of: odoo/odoo#288558
The PEPPOL invoice sending option is now disabled when an invoice has already been sent through PEPPOL. This prevents users from accidentally trying to resend an invoice and makes the screen behavior clearer.
Original PR description
If the invoice is already sent through PEPPOL, the checkbox for sending the invoice should then be readonly and unchecked. Currently is correctly unchecked but not readonly. We fix it by copying what French localization (`l10n_fr_pdp`) does already, giving a reason for disabling. <img width="1359" height="948" alt="immagine" src="https://github.com/user-attachments/assets/6f91ab34-8989-487e-8cd9-96dafee7bcb5" /> . Pad: https://pad.odoo.com/p/accountingv20 pad-accountingv20 Forward-Port-Of: odoo/odoo#288898
The manufacturing order Kanban progress bar now shows draft orders with a more visible color. This helps users quickly spot draft manufacturing orders instead of missing them because they blended into the background.
Original PR description
Issue before this commit: ========================= The draft progress segment in the manufacturing order Kanban view is barely visible against the background. <img width="442" height="145"…
Issue before this commit: ========================= The draft progress segment in the manufacturing order Kanban view is barely visible against the background. <img width="442" height="145" alt="image" src="https://github.com/user-attachments/assets/9ba3e4ef-7b91-4c82-86ee-1fe0e47f472f" /> Steps to reproduce: =================== - Install MRP. - Create a draft manufacturing order. - Open the manufacturing orders in the Kanban view. - Observe the progress bar and notice that the segment representing the draft state is barely visible Cause of the issue: =================== In this [commit](https://github.com/odoo/odoo/pull/251475/changes#diff-3bad372563263ef117de6ed9e222008e2a27b2ea212df89f72f269066a8eacacR603) the manufacturing order Kanban progress bar was changed to represent order states. Draft orders were assigned the `light` color, which blends into the Kanban background and makes their segment barely visible. After this commit: ================== The progress segment for the draft state is clearly visible, allowing users to easily distinguish draft orders in the Kanban view. <img width="343" height="123" alt="image" src="https://github.com/user-attachments/assets/6646143f-a299-4544-b8b5-115e13ebf8c5" /> Forward-Port-Of: odoo/odoo#288462
This change corrects an internal error message format used when validating exported records. It ensures the system reports the intended validation error instead of an unrelated technical failure, making troubleshooting more reliable.
Original PR description
The format was broken. `'{}:{}' % it` → `TypeError` instead of `AssertionError`.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#288836
Forward-Port-Of: odoo/odoo#288610Users can now click, select, or copy the extra informational text shown under a many2one field without accidentally opening the selection dropdown. This removes a small but frustrating interaction issue and makes forms easier to use.
Original PR description
Clicking on the informative extra text of a many2one field would focus the field and open the dropdown, making it inconvenient for the user to simply select or copy the text. This commit prevents the many2one dropdown from opening when the user clicks on the extra lines. Task-6538439 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288019
This change adds a test to ensure Avalara tax recalculation stays consistent when only exemption-related tax details are updated. It helps prevent mismatches between invoice product lines and tax lines after an exemption certificate is uploaded and taxes are recalculated.
Original PR description
We removed the explicit tax clearing [1]. It ends up triggering a situation where extra_tax_data on the product lines diverges from the tax lines. This happens when the tax integration writes only extra_tax_data without modifying anything else on the lines (if e.g. you first calculate tax, upload the exemption certificate to Avalara, and then recalculate tax). This tests that exact scenario. opw-6547387 [1] https://github.com/odoo/enterprise/pull/107863 Forward-Port-Of: odoo/enterprise#131815
Merging helpdesk tickets now updates related timesheets so they use the same sales order item as the merged destination ticket. This prevents inconsistent billing or service tracking information after tickets are combined.
Original PR description
Currently when you merge helpdesk tickets with differing sale order items, the sales order item listed on the timesheets of the source ticket is not updated to match the destination ticket's sales order item. This PR ensures uniformity bugfix-6473396 Forward-Port-Of: odoo/enterprise#131155 Forward-Port-Of: odoo/enterprise#129060
This fix updates the planning field service sales timesheet code to use the renamed Product Unit precision setting. It helps ensure quantities are rounded with the intended accuracy instead of silently falling back to a generic two-decimal default.
Original PR description
The `decimal.precision` "Product Unit of Measure" was renamed "Product Unit" in 18.1. Some occurences called the old name still exist in the code. This is silently fallbacking on the default 2 decimals from the `precision_get`. See: https://github.com/odoo/odoo/pull/193490 task-none Forward-Port-Of: odoo/enterprise#132006 Forward-Port-Of: odoo/enterprise#131709
This fix ensures the Belgian payroll calculation uses the correct employer contribution code 261 instead of 260. It helps keep payroll contributions accurate for affected Belgian payroll scenarios.
Original PR description
One-line fix to use the correct contribution task-6526911
Fixed an error that appeared when users clicked away from the notes field while creating an appointment booking in Point of Sale. This prevents interruptions during booking entry and helps staff complete appointment workflows smoothly.
Original PR description
Steps: - Open a store with appointments enabled. - Go to the Bookings tab. - Open a new booking form. - Click on the note input, enter some text, and click away. Issue: - A traceback appears when focusing out of the note editor. Fix: - Add `MediaPlugin` to the `htmlField` editor configuration, as the plugin is used by the field when committing local changes via `_commitChanges`. [here](https://github.com/odoo/odoo/blob/saas-19.4/addons/html_editor/static/src/fields/html_field.js#L253) Task-6580877
Return attachments are now generated only once during the appropriate review or submission step. This prevents duplicate files from being created, reducing confusion and keeping tax return submissions cleaner.
Original PR description
We now call _generate_locking_attachments at review and submit so it was generating two times the attachments. The fix is to always call at submit. And for the review stage we only call it when there is no submit step.
Creating an appointment event from the calendar now respects the time slot the user draws instead of replacing it with the appointment type's default duration. This prevents unintended event lengths and makes scheduling more predictable for staff using appointment calendars.
Original PR description
When creating an event from the calendar view of an appointment type, the duration of the event was set to the duration of the appointment, therefore bypassing the slot we drew. This commit fixes this behavior by giving the priority to the end date of the drawed slot. Task-6412432 Forward-Port-Of: odoo/enterprise#130171
Regular users could hit an access error when an AI chat without its own name was shown in places like Documents. The change lets the system safely display the linked AI agent name for users who already have access to the chat, preventing this interruption.
Original PR description
AI chat channels can have an empty name, in which case their display name is computed from the linked ai_agent_id. That field is restricted with fields. NO_ACCESS, so flows that read the channel display name, such as adding an AI chat attachment to Documents, could raise an access error for regular users. Compute the AI chat display name through sudo() when reading ai_agent_id, since users who can access the AI chat may safely see the agent name. task-6547727
This fix ensures AI-generated pivot reports handle grouped column data in the format the report view expects. It prevents display or loading issues when reports group columns by date intervals or similar categories.
Original PR description
The AI backend returns column groupbys as a list containing both strings and dictionaries with interval information. While this format is used to preserve the interval metadata, the pivot model expects `colGroupBys` to be a flat list of strings. This commit updates the view patch to flatten dictionary entries into their corresponding `<field>:<interval>` strings before assigning them to the pivot model metadata, ensuring the format matches the pivot model's expectations. task-6377810 Forward-Port-Of: odoo/enterprise#129515
The Canadian Balance Sheet report now displays correctly when using the split horizontally option. This ensures assets, equity, and liabilities appear in the intended columns, making the report easier to read and preventing confusion for Canadian accounting users.
Original PR description
The Canadian Balance Sheet "split horizontally" feature was broken during the refactor [1]. This commit - fixes the correct split between the Assets on the right and the Equity and Liabilities on the left, - remove the redundant split=right on child of aforementioned category. [1]: https://github.com/odoo/enterprise/pull/114127 task-none (DSH finding) **before** <img width="1903" height="861" alt="image" src="https://github.com/user-attachments/assets/58ee1ab8-5ca4-4d80-9567-5588d70b3f64" /> **after** <img width="1916" height="881" alt="image" src="https://github.com/user-attachments/assets/894358cd-d18a-4039-a468-65c7cabb20cf" /> Forward-Port-Of: odoo/enterprise#131933
This fixes an issue in Odoo Studio where deleting text next to an element in a customized view could leave the text behind. The correction ensures the intended content is fully removed, reducing confusion and keeping customized views consistent with user edits.
Original PR description
Have an arch like ``` <div> <br /> TEXT <span /> </div> ``` Now remove the block `TEXT <span />` Before this commit, the resulting inheriting arch was just `<xpath expr="//span" position="replace" />` So the `TEXT` was not removed After this commit, the `TEXT` is removed along with the following span opw-6524957 Forward-Port-Of: odoo/enterprise#131812 Forward-Port-Of: odoo/enterprise#131717