Friday, September 4, 2026
17 changes · saas-19.2
Resolved issues and error corrections
This update fixes outdated internal documentation about how temporary records are protected. It clarifies that standard access rights and record rules apply, reducing confusion for teams maintaining or auditing 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
The HTML editor now properly cleans up file-related event handling when an editor is closed or replaced. This prevents small memory leaks from accumulating across repeated editor use, helping keep the editing experience stable over time.
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
A previous Point of Sale data cleanup step was removed because a newer fix handles the issue more precisely. This reduces the risk of removing more order data than necessary while keeping loyalty reward line cleanup intact.
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
The website editor color picker now saves the gradient angle as soon as it is typed, preventing it from reverting after saving. This makes gradient styling more reliable for users editing page building blocks.
Original PR description
Problem: When changing the gradient angle input in the color picker and saving the record, the updated angle is not saved and reverts to the previous value. Cause: `setOnCloseCallback` runs before `onAngleChange` because the angle input fires the `change` event on blur/close. As a result, `onColorGradientChange` is called with the previous angle value, and `onColorGradientPreview` runs afterwards with the new value, causing the applied preview to be reverted later. Solution: Call `onAngleChange` on the `input` event instead of `change` so that state and preview update immediately each time the user types. Steps to reproduce: - Add a gradient to a building block. - Define a value of 180 degrees. - Save - If you open the color picker the value is still 135. task-6522533 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixed an issue where tables copied from Google Docs with multiple header rows could paste incorrectly into the editor. The editor now keeps the first row as the header and converts later header rows into normal rows, making pasted tables behave consistently.
Original PR description
Steps to Reproduce - Copy a table with multiple header rows from Google Docs. - Paste the table into the editor. Description of the issue: - The pasted table contains multiple header rows, but the editor supports only the first row as the table header row. Cause: - During paste, `cleanForPaste` does not handle tables with multiple header rows - As a result, header cells (`<th>`) in rows other than the first row remain as header cells instead of being converted to normal table cells (`<td>`). Solution: - Update `cleanForPaste` to handle tables with multiple header rows. - If a table contains `<th>` elements in any row other than the first row, replace those `<th>` elements with `<td>` elements. - This ensures that only the first row is treated as the table header row. task-6455248 Forward-Port-Of: odoo/odoo#283862 Forward-Port-Of: odoo/odoo#281234
The linked document field now shows a clearer prompt when a record still needs to be selected. This helps users avoid saving incomplete links that would otherwise disappear after refreshing the page.
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 inconsistent employee ordering when multiple employees linked to the same contact have the same name. It helps ensure leave return-date information is reliable and automated test results remain stable across environments.
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#286504 Forward-Port-Of: odoo/odoo#286236
The inventory report table layout has been corrected so its columns line up properly again. This avoids confusing or broken-looking inventory reports caused by mismatched table headers and rows.
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
This fixes an automated check for blog page editing so it consistently opens the website builder with the needed debug options enabled. It helps prevent false failures and ensures the blog dynamic snippet options remain properly validated before release.
Original PR description
The blog post dynamic snippet options tour needs debug mode because the dynamic snippet belongs to the Debug snippet group. The tour used to put `debug=1`in the preview iframe path, while the initial website preview client action was opened without debug. This meant `request.session.debug` was only updated once the iframe request was handled. If the snippet template was rendered before that request, QWeb used the empty session debug value and omitted the Debug snippet group. After this commit, we open the preview action directly in edit and debug mode from the Python test instead, so the first server request sets `request.session.debug` before the website builder loads the snippets. Forward-Port-Of: odoo/odoo#281433
This fixes how remaining hours are recalculated for timesheet-linked sales order lines when relevant details like unit of measure change. Businesses get more reliable project and service delivery tracking without unnecessary recalculations.
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 fixes time zone handling in Odoo's base test suite so date-based sequence checks use the same time zone as the application environment. It prevents occasional test failures around midnight in Belgium, improving release validation reliability without changing business functionality.
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
This fixes an issue where some already-applied website editor options could be ignored when determining the current selection. It helps ensure the editor reflects the correct option state, especially for combined actions, reducing confusion for users editing 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#286503
Product thumbnails on website product pages now display in consistent square slots when auto-cropping is disabled. This prevents unusually wide or tall product images from making the thumbnail strip look uneven or causing the main product image to sit awkwardly, improving the shopping experience.
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
This fix ensures paid French e-invoices automatically include the due date required by the latest French validation rules. It helps prevent invoice export or compliance validation failures when payment information is present.
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
Fixes an issue in the demo payment provider where refunds after manually captured payments could remain only authorized. This prevented completion of the refund and could leave transactions with incorrect negative authorized amounts.
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#286084 Forward-Port-Of: odoo/odoo#282315
A timing wait was added to prevent an intermittent failure in the IoT printer test caused by messages being sent before the frontend finishes subscribing. This helps keep automated test results reliable without changing customer-facing behavior.
Original PR description
When a new bus channel is subscribed to, the frontend waits for a 300ms debounce before sending the subscription to the server. If we try to send a message back before then, it won't be sent to the frontend. This behaviour caused the IoT printer test tour to occasionally fail. To fix the tour, we simply add a sleep for 500ms, which should guarantee enough time has passed to avoid the issue. Unfortunately there seems to be no cleaner way to wait for the channel list to be updated. This error only affects versions 19.1 and 19.2. In 19.3 the delay when adding a new channel was removed. runbot-241937 Forward-Port-Of: odoo/enterprise#130323
Selecting a suggested partner now correctly returns the form to its saved state after the record is updated. This prevents confusing save or discard buttons from staying visible when there are no remaining changes to save.
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#286268 Forward-Port-Of: odoo/odoo#285897