Friday, September 4, 2026
28 changes · saas-19.4
Resolved issues and error corrections
This fix makes employee records with the same name appear in a consistent order when partner time off information is prepared. It prevents intermittent test and build failures and helps ensure the correct return date is associated with the main user.
Original PR description
Before this commit, TestPartner.test_res_partner_to_store fails on the all-modules and per-country builds: AssertionError: '2024-06-06' != '2024-06-07' : Return date is the return date of the main…
Before this commit, TestPartner.test_res_partner_to_store fails on the all-modules and per-country builds: AssertionError: '2024-06-06' != '2024-06-07' : Return date is the return date of the main user of the partner This happens because the test reads the first entry of the hr.employee list, which holds one employee per user of the partner: back on the 7th for the main user, on the 6th for the other. This comes from "[FIX] hr*: load out-of-office dates from all user employees", which added the employees of the partner to the payload, where it held those of the main user only. The problem is that the list keeps the order of employee_ids, which is 'name' with no tiebreaker, and both employees are named test1, as an employee takes the name of its user and creating the second user renames the partner. Postgres is then free to return either one first, and the failing builds get the second one. This commit fixes the issue by ordering the employees on 'name, id', so that employees sharing a name keep a stable order instead of the one the database picks. The test asserts the whole hr.employee list, one entry per user of the partner, rather than its first entry alone, and that assertion pins the order. https://runbot.odoo.com/odoo/error/945994 Forward-Port-Of: odoo/odoo#286750 Forward-Port-Of: odoo/odoo#286236
An older Point of Sale data cleanup workaround was removed because a newer fix handles the issue more precisely. This reduces the risk of removing more checkout data than intended while keeping stale loyalty reward lines cleaned up.
Original PR description
This fix is no longer required(https://github.com/odoo/odoo/pull/202752) as this one (https://github.com/odoo/odoo/pull/257043) is cleaner and less aggressive (it will only delete stale reward lines). This is the relevant part of the new fix to delete the previous one: https://github.com/odoo/odoo/pull/257043/changes#diff-18cef42f8c39513a82387e9cb81bc732b252304cd15b5b2f7b0b4623ac20cb41R100-R104 opw-6447092 Forward-Port-Of: odoo/odoo#286072 Forward-Port-Of: odoo/odoo#285376
This update fixes outdated internal documentation about how temporary records are accessed. It clarifies that standard access rights and record rules apply, helping developers and administrators avoid misunderstandings when configuring permissions.
Original PR description
Since 6d8688bb124d, TransientModel records use the regular access rights mechanisms instead of being implicitly restricted to their creator. The docstring was not updated with that change and has therefore incorrectly documented creator-only access since 14.0. Forward-Port-Of: odoo/odoo#286374 Forward-Port-Of: odoo/odoo#286251
This update adds test coverage to ensure spreadsheets exported to Excel keep embedded images working correctly. It helps prevent regressions when users share or export spreadsheet documents that include visual content.
Original PR description
Counterpart of https://github.com/odoo/odoo/pull/279788 Task-6432724 Forward-Port-Of: odoo/enterprise#130172 Forward-Port-Of: odoo/enterprise#126384
Changing Peppol reception to receive documents no longer triggers an error for Belgian companies using Peppol. This helps users complete Peppol setup smoothly and avoids disruption when configuring incoming electronic invoices.
Original PR description
Steps to reproduce: - Install `documents_account_peppol` and `l10n_be` module - Switch to BE Company > `Activate Peppol` - Change `Peppol Reception Mode` -> `Receive as Documents` Traceback: `AttributeError: 'res.company' object has no attribute '_peppol_allows_document_reception'` Problem: Changing the `Peppol Reception Mode` to `Receive as Documents` causes an `AttributeError` because `_compute_peppol_purchase_journal_required()` calls `_peppol_allows_document_reception()` on `config.company_id`, but the method is defined on `res.config.settings`. Cause: The method is available on the `res.config.settings`, not on the `res.company`. Solution: Add `_peppol_allows_document_reception()` method in `res.company` and call company's method from the `res.config.settings` method. opw-6470552 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where some applied website editor options were not recognized when their priority value was below zero. It helps ensure the correct option remains selected in composite editing actions, improving reliability for users editing web pages.
Original PR description
The function `useSelectableComponent` looked for the selected option by searching for the option with the highest priority among the options that are applied. The search for highest priority implicitely excluded options with negative priority. This case happens with `composite` action when the inner actions have no definition of `getPriority`. This commit initialize the "highest priority found so far" as `-Infinity` instead of 0. task-5245362 Forward-Port-Of: odoo/odoo#286652 Forward-Port-Of: odoo/odoo#286503
Automated accounting-related processes can now generate required reports even when they run on behalf of users without accounting permissions. This prevents setup or localization workflows, such as tax or trade reporting, from failing unnecessarily.
Original PR description
This was spotted in a dev branch for master, where we set a default account_opening_date on every company, hence trying to directly create the returns for it. Some modules need to call reports for that (like intrastat l10n), and do it in sudo(). However, even in sudo, a user without the accounting rights still doesn't have the proper group, and it raises an exception. We hence adapt the condition. Forward-Port-Of: odoo/enterprise#130448
The demo payment provider now handles refunds correctly after a manually captured payment. This prevents demo transactions from getting stuck in an authorized refund state with negative amounts, making payment testing more reliable.
Original PR description
Issue: --- When using manual capture, you can refund the transaction but it will be only authorized, and you'll then be blocked with a negative authorized amount and the impossibility to refund it. This seems to be specific to demo payment provider. Steps: 1- Enable manual capture on demo provider. 2- Buy a product from shop and checkout and pay. 3- Capture the payment in backend. Then click on post process. 4- Try refund. opw-6413515 Forward-Port-Of: odoo/odoo#286625 Forward-Port-Of: odoo/odoo#282315
Reference fields now show a placeholder in the record selector, making it clearer that users must choose both a model and a specific record. This helps prevent incomplete links from being saved and later disappearing after the page is refreshed.
Original PR description
Steps to reproduce: 1. Install Sign. 2. Open the form view of a document. 3. Select a model in the "Link to" (Reference) field, but leave the record empty. 4. Save and refresh the page. Issue: -…
Steps to reproduce:
1. Install Sign.
2. Open the form view of a document.
3. Select a model in the "Link to" (Reference) field, but leave the record empty.
4. Save and refresh the page.
Issue:
- After refreshing, the selected model is cleared because the reference value is invalid.
Cause:
- A reference field is only valid when it contains both a model and a record ID. However, the record selector has no placeholder, making it easy to overlook and save an incomplete value.
Solution:
- Add a default placeholder to the record selector of reference fields to make it more visible.
<table>
<tr>
<th>Before</th>
</tr>
<tr>
<td>
<img src="https://github.com/user-attachments/assets/3ba34b77-f901-4d3e-9768-5acaf2e673b8" alt="Before" width="100%">
</td>
</tr>
<tr>
<th>After</th>
</tr>
<tr>
<td>
<img src="https://github.com/user-attachments/assets/1fe54b89-221f-4d28-bd2b-0a3c706d5746" alt="After" width="100%">
</td>
</tr>
</table>
opw-6426339
Forward-Port-Of: odoo/odoo#280266This fixes a spelling mistake in the Instagram video embed option shown while editing a page. Users will now see the provider name spelled correctly, improving polish and avoiding confusion in the editor.
Original PR description
Steps to reproduce: - Edit existing page. - Paste any Instagram reel. - In powerbox Instagram entry is listed as "Embed Intagram Video". Introduced by https://github.com/odoo/odoo/commit/2bae2abd4db704451234b115eb4942dcae7d8afa This commit fixes typo.
This fixes a crash that could occur when generating electronic invoice data in Odoo Community Edition without the enterprise accounting add-on installed. The system now checks whether optional deferred billing date fields are available before using them, helping invoices process reliably across editions.
Original PR description
The fields `deferred_start_date` and `deferred_end_date` are created by the enterprise addon `account_accountant`, so not having it installed, this crashes with:
```
File "/opt/odoo/auto/addons/account_edi_ubl_cii/models/account_edi_cii.py", line 684, in <listcomp>
billing_start_dates += [move_line.deferred_start_date for move_line in invoice.invoice_line_ids if move_line.deferred_start_date]
AttributeError: 'account.move.line' object has no attribute 'deferred_start_date'
```
This PR protects the access to these fields checking first if they exist.
Bug introduced in the refactoring in #261572.
@Tecnativa TT64359
Forward-Port-Of: odoo/odoo#286245The HTML editor now properly clears file-related event handlers when an editor instance is closed. This prevents small memory leaks that could build up over repeated editing sessions, helping keep the editor stable and responsive.
Original PR description
FilePlugin registered its click, keydown and pointerdown handlers with raw `addEventListener`, so they were never removed when the plugin was destroyed. The pointerdown one is bound to the document, which outlives the editable, leaking a handler per editor instance. Use `addDomListener` so Plugin.destroy() removes them. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286144
Custom website snippets with very large responsive text now display correctly in the snippets dialog. This makes previews more reliable for website editors without affecting how snippets appear when placed on a page.
Original PR description
Steps to reproduce: - Go to the website editor. - Add a snippet with editable text to the page. - Select the text and set its font size to 144. - Save the edited block as a custom snippet. - Open the…
Steps to reproduce: - Go to the website editor. - Add a snippet with editable text to the page. - Select the text and set its font size to 144. - Save the edited block as a custom snippet. - Open the snippets dialog. - Go to the Custom category. => The custom snippet preview shows the text too large. Before this commit, responsive font sizes using `clamp()` with a `vw` term were rendered too large in the block dialog. The `vw` value was based on the full preview iframe width, while snippets were displayed inside columns. After this commit, the block dialog adjusts `vw` values on cloned `.o_rfs` preview content only, so the preview matches its column width without changing the snippet dropped on the page. task-6303725 | BEFORE (font size -> 144) | AFTER (font size -> 144) | | ------------- | ------------- | | <img width="416" height="409" alt="image" src="https://github.com/user-attachments/assets/e0eb0a4e-eb7b-4ee6-b080-536ea2a75c68" /> | <img width="421" height="272" alt="image" src="https://github.com/user-attachments/assets/6468a234-0966-45c9-9435-e97d9752b794" /> | Forward-Port-Of: odoo/odoo#273257
Changing Peppol Reception Mode to Receive as Documents no longer triggers an error for Belgian companies using document-based Peppol reception. This keeps the Peppol activation and configuration flow working as expected, avoiding disruption when users update reception settings.
Original PR description
Steps to reproduce: - Install `documents_account_peppol` and `l10n_be` module - Switch to `BE` Company > `Activate Peppol` - Change `Peppol Reception Mode` -> `Receive as Documents` Traceback: `AttributeError: 'res.company' object has no attribute '_peppol_allows_document_reception'` Problem: Changing the `Peppol Reception Mode` to `Receive as Documents` causes an `AttributeError` because `_compute_peppol_purchase_journal_required()` calls `_peppol_allows_document_reception()` on `config.company_id`, but the method is defined on `res.config.settings`. Cause: The method is available on the `res.config.settings`, not on the `res.company`. Solution: Call `_peppol_allows_document_reception()` directly on the `res.config.settings`. opw-6470552
This change removes sample scheduling data that could fail to load when an optional planning feature was not installed. It helps ensure the helpdesk field service module can be installed reliably without requiring unrelated optional modules.
Original PR description
…ct on helpdesk intervention Before this commit, `project_id` field in `planning.slot` only exists if `project_forecast` module is installed. However, when `helpdesk_planning_field_service_sale_timesheet` is installed, we cannot guarranty `project_forecast` module is also installed since it is not in the dependencies of `helpdesk_planning_field_service_sale_timesheet` module. This commit just removes the demo data inside `helpdesk_planning_field_service_sale_timesheet` module.
This fixes a broken layout in the inventory report by removing extra table columns that no longer matched the report header. Users should see inventory report tables display correctly again, improving readability and reducing confusion.
Original PR description
This reverts commit 43add3f72f29c35280869010b897c3c5656f5120. It was adding too many columns in table body after columns were removed from the header in 19.0. opw-6307728 Forward-Port-Of: odoo/odoo#286294
The certificate setup screen no longer shows an error as soon as a key file is added without a password. Users now only see the warning when they actually entered an incorrect password, reducing confusion during certificate configuration.
Original PR description
When adding a key file without entering a password, an error banner is immediately displayed, incorrectly suggesting that the password may be invalid. Only show the error banner when a password was provided and is incorrect. Also refactored the compute function to avoid repeated try-except blocks. task-6299175 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286307 Forward-Port-Of: odoo/odoo#283589
This update corrects Belgian payroll certificate handling when an employee contract has no end date. It helps prevent errors or incorrect occupation attestations for ongoing contracts.
Original PR description
A check was missing if the contract end date was false Forward-Port-Of: odoo/enterprise#130346
This fix prevents installation errors when the Restaurant point of sale app is installed alongside an older Point of Sale version. It makes the receipt template update rely on a stable element, reducing manual upgrade steps and avoiding disruptions for customized setups.
Original PR description
The template for the preparation tickets was using an xpath targeting a newly added div element. This raised an error when installing the `pos_restaurant` module while an old version of `point_of_sale` was still in place, since the customer would need to manually upgrade `point_of_sale` first to have that new div element available. We now use receipt-header as the xpath target, which was always present in the template. We also refill `pos_self_order.pos_order_change_receipt` to prevent breaks with custo. --- Report: https://github.com/odoo/odoo/pull/267161#discussion_r3758115362 Forward-Port-Of: odoo/odoo#281768
This fix ensures that when an employee has multiple contracts and payslips in the same month, the canteen cost is applied to the first payslip that includes a paid amount. This helps Belgian payroll remain accurate and avoids assigning the cost to an unpaid or inappropriate payslip.
Original PR description
In case of multiple contracts for a single month (and then multiple payslips), the canteen cost must appear in the first payslip that have a paid amount. Forward-Port-Of: odoo/enterprise#130109
This update adds test coverage to ensure timesheet assistant suggestions are correctly matched with helpdesk tickets and calendar entries. It helps reduce the risk of incorrect timesheet suggestions reaching users in future updates.
Original PR description
task: 6475133 Forward-Port-Of: odoo/enterprise#130157
Product image thumbnails now remain consistently sized and centered when auto-cropping is disabled. This improves the product page presentation and keeps thumbnail click areas predictable, especially for products with mixed portrait and landscape images.
Original PR description
Steps to reproduce: =================== 1. Add several images to a product, one of them much wider than tall. 2. On the product page, set the image ratio to "Disabled". 3. Move the thumbnails below…
Steps to reproduce: =================== 1. Add several images to a product, one of them much wider than tall. 2. On the product page, set the image ratio to "Disabled". 3. Move the thumbnails below the image. => The wide thumbnail sits at the top of its slot, with blank space under it. Root cause: =========== Thumbnails are given a fixed width of 64px and take their height from `aspect-ratio: var(--o-wsale-product-image-ratio)` [1]. With cropping disabled that variable is `auto`, so each thumbnail keeps the shape of its own image and they no longer share a height. They sit in a flex row, which stretches every slot to the height of the tallest one. The image inside keeps its own height and stays at the top of the slot, so a wide image leaves the rest of its slot empty. The slots are only stretched when the images differ in height, which is why the problem needs cropping to be disabled, and why it does not appear when every image is a landscape one. - [1] sized the thumbnails from the image ratio. Fix: ==== Center the thumbnails in the row so each one keeps the height of its own image instead of being stretched to the tallest. Their width stays at 64px, so a row of wide images still takes the same space as before and none of them is pushed out of the container. [1]: 670b1daa2254 opw-6472484 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283246
French PDP invoice exports now automatically include the due date when an invoice is marked as paid. This helps businesses comply with France's latest e-invoicing validation rules and avoids rejected invoice files.
Original PR description
According the schematron v1.4, the cbc:DueDate is required when the move is PAID. "[BR-FR-CO-09/BT-23] : Si le cadre de facturation (BT-23) est B2, S2 ou M2, alors la date d’échéance (BT-9) doit être renseignée et correspondre à la date de paiement." no-task --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286263
This fixes when remaining hours are recalculated on sales order lines for timesheet-based services. It helps keep service delivery and project hour information accurate when units of measure or availability values change.
Original PR description
The dependencies of _compute_remaining_hours do not match the fields actually used for the computation: it lists analytic_line_ids, which it never uses, and omits both remaining_hours_available, and product_uom. _compute_remaining_hours_available has the same issue: it uses product_uom but only depends on product_id.service_policy. analytic_line_ids, on the other hand, can be dropped: qty_delivered already depends on it, along with its so_line, unit_amount, product_uom_id and project_id, so the timesheet flow keeps triggering the recomputation. This PR fixes the dependencies for both aforementioned compute methods. Task-4748521 Forward-Port-Of: odoo/odoo#285685 Forward-Port-Of: odoo/odoo#284750
This fix makes Odoo's internal sequence tests use the same timezone setting as the application itself. It prevents false test failures around midnight in Belgium, improving release reliability without changing user-facing behavior.
Original PR description
## Issue By default in Odoo, `datetime.now()` returns the UTC time, which is two hours behind the local time in Belgium. This leads to two tests failing when executed between 00:00 and 02:00 Belgian…
## Issue By default in Odoo, `datetime.now()` returns the UTC time, which is two hours behind the local time in Belgium. This leads to two tests failing when executed between 00:00 and 02:00 Belgian time: `test_ir_sequence_interpolation_dict` and `test_ir_sequence_iso_directives`. The `_interpolate_dict` method (responsible for interpolating the prefix/suffix from the sequences) specifies the tzinfo when calling `datetime.now()`: https://github.com/odoo/odoo/blob/9c67949be529eb86886b3d5bde08e81e048ecfe7/odoo/addons/base/models/ir_sequence.py#L211-L212 Since this is not the case in the tests, the tests evaluate the date using UTC. This creates a two hours difference between the time expected and the time actually used by `next_by_code`. The tests thus fail between 00:00 and 02:00 because the evaluate dates from both `datetime.now` calls differ, leading to a mismatch in the expected prefixes. ## Fix We force the `env.tz` on the `datetime.now()` call, to mimic the behavior from the `_interpolate_dict`. runbot-242662 Forward-Port-Of: odoo/odoo#284955
Financial reports no longer show the unallocated earnings or losses line when it has a zero balance in every column. This removes unnecessary clutter and makes reports easier to review without changing any underlying figures.
Original PR description
… zero The unallocated earnings/losses line was displayed even when its balance was zero in every column group, cluttering the report with uninformative rows. We therefore filter out lines whose balance is zero across all column groups. Forward-Port-Of: odoo/enterprise#129666 Forward-Port-Of: odoo/enterprise#129129
The website translation endpoint now bypasses website-specific routing because it already receives the requested language directly. This prevents unexpected language redirects and cookie conflicts when translations are loaded, helping pages show the correct language more reliably.
Original PR description
/website/translations does not require request.website or language redirection logic as `lang` is passed explicitly. Drop `website=True` to prevent unexpected language redirects and cookie conflicts. Backport of 4faddd8b44 (odoo/odoo#269325). runbot-231758 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284856 Forward-Port-Of: odoo/odoo#281738
After selecting a suggested partner, the form now correctly returns to its saved state instead of continuing to show inactive Save and Discard buttons. This avoids user confusion by making the screen status match the fact that the enriched partner record has already been saved.
Original PR description
Steps to reproduce: 1) open partner form view 2) type in the name field 3) select a suggestion from the autocomplete dropdown Issue: The record is enriched and saved, but the form still displays the save/discard buttons, and clicking them does nothing. The record dirty indicator is driven by 2 signals 1) `model.root.dirty`, which is cleared by save() call earlier in the onSelect() 2) the state `fieldIsDirty` of the `FormStatusIndicator` The second indicator is set to true when the user types in an input field, and selecting an option never clears it. The `setDirty` prop no longer exists, and therefore was deadcode. This commit emits `FIELD_IS_DIRTY` bus event, which is the only way to update the second indicator. With that, the indicator goes back to saved state once the record is updated. task-6475332 Forward-Port-Of: odoo/odoo#286651 Forward-Port-Of: odoo/odoo#285897