Daily updates from Odoo
Wednesday, August 19, 2026
155 changes
22 changes
Enhancements to existing features
Cached website generation requests now schedule a quick follow-up trigger instead of waiting or calling webhooks too early. This helps related notifications run reliably without tying up processing workers.
Original PR description
When a request is cached a webhook won't be called because if we did it immediatly it might arrive before the generator commited. And we don't want to delay the webhook call to not stall a worker just for that. So we simply scheldule a trigger if a request was cached. Forward-Port-Of: odoo/enterprise#128206
The Dutch payroll localization now includes the 2026 resident income tax rate values. This helps payroll calculations stay aligned with the latest tax rules for employees in the Netherlands.
Original PR description
Added 2026 values for the residents' income tax rates rule parameter. task-6462877 Forward-Port-Of: odoo/enterprise#127556
Users can now move through return items in the returns kanban view using the up and down arrow keys without triggering an error. This improves day-to-day navigation and prevents interruptions when reviewing or selecting returns.
Original PR description
In returns kanban view, a traceback occurs when pressing down. Fix this by adding the support for up/down keyboard navigation for returns selection. task-6281033 Forward-Port-Of: odoo/enterprise#128308 Forward-Port-Of: odoo/enterprise#125164
The default waiting time for certain web interface test checks has been increased from a very short window to 10 seconds. This reduces false test failures on busy machines without slowing successful test runs, improving confidence in automated quality checks.
Original PR description
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests…
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests give 10 seconds. 430 call sites in addons reach these three helpers and 29 pass an explicit timeout, so 12 frames is what the other 401 get. The problem is that 12 frames is less than what the client needs on a loaded machine. Measured on "should remove file from html editor if removed from attachment list", on the wait that follows the Full composer button: - 5 to 7 frames on an idle machine; - 11 to 18 frames over 8 runs with the machine at load 10 to 20, 5 of the 8 above the 12 frames the default allows. Those 5 are failing runs, and the same test at load 13 to 29 fails 6 runs out of 6 with the 200 milliseconds, 0 out of 6 with 10 seconds. Note that a longer timeout costs nothing on a green build: the wait ends on the frame the DOM matches, so it only delays the report of a test that was going to fail anyway. Hoot fails the test itself after 5 seconds, 15 in test_js.py, which keeps bounding a wait that never resolves. This commit raises the default to 10 seconds, the delay a tour step already gets in macro.js and the one contains() and expect.waitForSteps already have. https://runbot.odoo.com/odoo/error/946094 Forward-Port-Of: odoo/odoo#282702
Resolved issues and error corrections
The Project task Gantt view now avoids showing misleading progress bars on individual task rows when grouped by assignee in sparse mode. Instead, users see the task's allocated hours, making planning information clearer and less confusing.
Original PR description
## Current behavior: In the task gantt view grouped by assignees and displayed in sparse mode, task leaf rows reuse the row progress bar and display a misleading visual indicator on each task. ## Expected behavior: It would make more sense to not display anything for the progress bar of each task, rather display the allocated_hours per task ## Steps to reproduce: 1. Open Project tasks in Gantt view 2. Group by Assignees 3. Enable sparse display so each task appears on its own row 4. Notice that task rows show a progress bar that is not meaningful for the task itself ## Cause of the issue: Each task rows currently has no meaningful progress-bar semantics, but they still inherit the generic row progress-bar rendering ## Fix: Override the task gantt renderer to hide progress bars, and only show `allocated_hours` for each task opw-6352260
This fixes an issue that could cause Colombian point-of-sale order reports to crash when users grouped records by state. The problem came from an outdated internal name left after two localization modules were merged, and the update keeps reporting behavior stable.
Original PR description
l10n_co_edi and l10n_co_dian were two modules merged together, when that happened some of the dian models and systems were renamed to the standard `l10n_co_edi.` system. The sql compute for the state field on pos.order was missed/forward ported up to a version that didn't have that name and as such would crash if you try to group. task-none
Fixed an issue where Dominican Republic electronic consumer invoices could show the company name twice when company address details were not configured. Invoice headers now display the company name only once, making printed and previewed e-CF invoices cleaner and more professional.
Original PR description
Steps to Reproduce: 1. Install l10n_do_edi on a company configured with Dominican Republic localization. 2. Leave the company's address / Document Layout details unconfigured (Settings > Companies >…
Steps to Reproduce:
1. Install l10n_do_edi on a company configured with Dominican Republic localization.
2. Leave the company's address / Document Layout details unconfigured (Settings > Companies > Configure Document Layout).
3. Enable 'Use Documents' on the sales journal and create a Customer Invoice with Document Type = Electronic Consumer Invoice (e-CF).
4. Confirm/post the invoice and print/preview the PDF.
5. Observe the company name is printed twice in the header.
Root Cause:
l10n_do_edi.custom_header explicitly renders the company name via:
[`<span t-field='o.company_id.partner_id.name'/>`](https://github.com/odoo-dev/enterprise/blob/c23d526f53402471dccbbf9460cfd04ce377b5d0/l10n_do_edi/views/report_invoice.xml#L10)
immediately followed by a call to the core template web.company_address_list:
[` <t t-call='web.company_address_list'/>`](https://github.com/odoo-dev/enterprise/blob/c23d526f53402471dccbbf9460cfd04ce377b5d0/l10n_do_edi/views/report_invoice.xml#L11)
When the company's address/Document Layout is empty, `company.is_company_details_empty` evaluates True, causing `web.company_address_list` to fall back to a contact widget with `fields=['address', 'name']` — which renders the company name a second time. custom_header assumed `company_address_list` would never render the name itself, which does not hold in this empty-address state, resulting in the duplicate. This only surfaces on e-CF document types, since custom_header is only set via l10n_do_edi.report_invoice_document's routing (_get_name_invoice_report()), which standard invoices never hit.
Solution:
Made the explicit name span in `l10n_do_edi.custom_header` conditional on whether the company's details are configured. `web.company_address_list` (core, shared across other reports, left untouched) already renders the company name via its contact widget fallback when the address is empty — so the explicit span now only prints the name when `company_details` is populated, avoiding both sources printing it at once.
Result:
Company name now renders exactly once on e-CF invoices, regardless of whether the company's address/Document Layout is configured.
opw-6430918
Forward-Port-Of: odoo/enterprise#127542Fixes an issue where clearing a spreadsheet filter could also remove its default value from the edit panel. This keeps the value currently applied to a spreadsheet separate from the default value shown when editing the filter, making filter setup more reliable for users.
Original PR description
Current behavior before PR: - In [da282d4](https://github.com/odoo-dev/enterprise/commit/da282d4a031fa1c1377a6836acf662100c68bde0), date filter values were cleared when selecting 'All time'. - Based on this, we handled the crash by relying on the active filter value, but forgot that the same component is also used in the edit panel. - As a result, clearing a filter could make its default value disappear from the edit panel. Desired behavior after PR is merged: - Always use the `globalFilterValue` passed to `GlobalFilterInput`. - Keep the current filter value independent from the filter's default value. - This makes the component independent of the active filter state. Task: [6388147](https://www.odoo.com/odoo/project/2328/tasks/6388147) Forward-Port-Of: odoo/enterprise#125153
The document app’s automated tests were updated to reflect improved GIF thumbnail processing. This helps ensure resized GIF thumbnails are validated correctly without failing on outdated byte-by-byte comparisons.
Original PR description
Previously, test_document_thumbnail_status asserted that document thumbnails were byte-for-byte identical to the raw GIF content. Following improvements to GIF handling in image_process(), thumbnails are now correctly resized, causing the raw byte assertion to fail. Update the test to assert the presence and status of the thumbnail rather than matching exact raw unresized payload bytes. [odoo/odoo#281883](https://github.com/odoo/odoo/pull/281883) opw-6232841 Forward-Port-Of: odoo/enterprise#128150 Forward-Port-Of: odoo/enterprise#128032
Enabling Billing in Planning now automatically selects the expected default project after installation. This prevents setup confusion for teams using Planning with Field Service and sales timesheets.
Original PR description
Steps to reproduce: - 1. Create a new database and install Planning and Field Service. 2. Open the Planning settings and enable Billing. Issue: - Billing is enabled but no default project is selected. Cause: - The default of `res.company.planning_project_id` references the module's own `fsm_project` xmlid, but it is evaluated before the module's data files are loaded. The ref resolves to nothing and no value is written. Fix: - Set the project in the post-init hook, once the data files are loaded. task-6460106
Users can now see and select WhatsApp signing templates even before they are approved. This makes it clearer that templates must be submitted for approval, while keeping the related signing flow inactive until approval is complete.
Original PR description
Previously, users couldn’t see or select unapproved WhatsApp templates in Settings, which made it unclear that they needed to submit templates for approval first. Now, users can select unapproved templates, making the process clearer. The flow will still remain disabled until the template is approved. task-6306091 Forward-Port-Of: odoo/enterprise#127910
A leftover employee appraisal action that no longer worked has been removed. Users should use the existing Launch Campaign option to request appraisals for multiple employees, avoiding an error when starting appraisal requests.
Original PR description
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it…
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it raises AttributeError: 'hr.employee' object has no attribute '_create_multi_appraisals'. #### Current behavior before PR: Commit 8845eb2ac29 replaced the multi-appraisal flow with hr.appraisal.campaign.wizard: it deleted _create_multi_appraisals and repointed the employee list header button to action_open_appraisal_campaign_wizard, but left the action_create_multi_appraisals record in hr_appraisal/views/hr_employee_views.xml. Its code is now the only reference to the deleted method, so the action crashes whenever it is run. #### Desired behavior after PR is merged: The dangling action is gone. Requesting appraisals for several employees at once is done with the "Launch Campaign" button already present in the Employees list view; action_open_appraisal_campaign_wizard reads active_ids when active_model is hr.employee and pre-fills the selected employees. Nothing references the removed xml id, and the record is not noupdate, so _process_end removes it from existing databases on update; no migration script is required. Verified on a 19.0 database: with the orphan record loaded, updating hr_appraisal with this change deletes it. opw-6408609 Forward-Port-Of: odoo/enterprise#127983 Forward-Port-Of: odoo/enterprise#125630
This update prevents errors when payroll salary attachment names are generated for several employees at once. It helps payroll users view and process multiple salary attachments reliably without interruptions.
Original PR description
Currently, an error occurs when the display name is computed for multiple salary attachments. `ValueError: Expected singleton: hr.employee(58, 56)` After [recent commit], when computing the display name, the employee's display name is accessed through multiple attachment records at once. This results in accessing the display name of multiple employees simultaneously, which raises a singleton error. This commit ensures that the employee is accessed from each individual attachment record when computing the display name. [recent commit]: https://github.com/odoo/enterprise/commit/d9648ef695903113d6ed2f40cd4fcfdd68221fa8 [1]- https://github.com/odoo/enterprise/blob/d913de3097d06e723a08d24907024f83769b1fb8/hr_payroll/models/hr_salary_attachment.py#L150-L153 sentry-7665634830 Forward-Port-Of: odoo/enterprise#127765
The Belgian payroll warning for missing transport benefits will no longer appear for company executives. This prevents irrelevant alerts on executive contracts and keeps the warning focused on regular employees who may need transport benefits reviewed.
Original PR description
The transport benefit warning incorrectly applies to company executives (Joint Committee = 999). This warning is intended solely for regular employees. Steps to reproduce: 1. Go to an employee's contract and set the Joint Committee to 999. 2. Set a monthly wage that results in an annual salary below 34,654€. 3. Ensure no transport benefits are selected. 4. Save the contract; the missing transport benefit warning is incorrectly displayed. This change skips the validation for Joint Committee 999 to ensure the warning only triggers when applicable. task-6442880
The salary configurator now correctly shows included optional benefits as selected when an employee opens a contract offer. This prevents confusion during offer review by ensuring Yes/No benefit choices reflect what is already part of the offer.
Original PR description
Issue: When an employee opens the salary configurator for a contract offer, optional benefits configured with Yes/No radio choices (such as Medical Insurance) fail to pre-select 'Yes' even when the benefit is already included in the offer. Steps to Reproduce: 1. Go to Salary Configurator and open a contract offer that has an active benefit 2. Observe that 'Yes' is not selected for the benefit on initial load. Fix: Ensure that when a contract offer includes a benefit, the salary configurator automatically defaults the radio selection to `Yes`. task-6392064 Forward-Port-Of: odoo/enterprise#127544
Sendcloud return labels now avoid printing the customer's house number twice in the origin address. This improves label accuracy and helps prevent confusion during return shipments.
Original PR description
Issue ----- On return labels, the house number of the origin address (so the customer) is printed twice. Steps to reproduce ----- - Setup sendcloud - Select a return service - Enable "Generate Return Label" - Create a delivery using sendcloud - Validate the delviery > The return label has the house number printed twice Cause ----- For the origin address shown on labels, Sendcloud prints both the address line and the house number. There doesn't seem to be any parsing made on the address line to extract the house number. For the WH -> Customer label, the "from" address is taken directly from the Sendcloud account's configuration. For the Customer -> WH return, we provide it in the `from_` fields of the request. Note that, when including the house number on the address line in Sendcloud, the issue is also present. ----- Ticket: opw-6405054 Forward-Port-Of: odoo/enterprise#127855 Forward-Port-Of: odoo/enterprise#126250
Project Forecast no longer shows the Time Management section in project settings unless the Timesheets app is installed. This avoids displaying irrelevant settings and keeps project configuration clearer for users who do not use timesheets.
Original PR description
**Steps to reproduce:** - Install the project_forecast module. - Go to Projects -> Open the settings of any project (create one if none exist) -> Settings. - You will see the Time Management section. **Issue:** The project_forecast module was forcefully setting the invisible attribute of group_time_managment to 0. This caused the group to remain visible at all times, even when the Timesheets app was not installed. **Fix:** Remove the forced attribute setting from the project_project_view. The visibility is already properly managed by the hr_timesheet module, and project_forecast does not depend on timesheet_grid or hr_timesheet. task-6195716 Forward-Port-Of: odoo/enterprise#128159 Forward-Port-Of: odoo/enterprise#121454
This fix prevents an automated field service planning test from failing because of a conflict with another planning module. It keeps validation focused on the intended behavior, improving build reliability without changing user-facing functionality.
Original PR description
On runbot, the `test_onchange_break_time_after_removing_dates` test was failing during the "all" build due to the `planning_slot_check_datetimes_set_or_plannable_slot` SQL constraint introduced by the sale_planning module. The test previously used `odoo.tests.Form` as a context manager, which implicitly triggered a database save and flushed the dateless test shift to PostgreSQL. Can resolved this by instantiating the Form in memory to validate the frontend `@api.depends` logic without triggering the cross-module database constraint. runbot-6463625 Forward-Port-Of: odoo/enterprise#127859
A test setup for accounting reports now uses the correct PDF generation mock, avoiding crashes during automated validation. This helps keep reporting workflows reliably tested without needing a real PDF engine in the test environment.
Original PR description
Description of the issue this commit addresses: Commit d3b4294a56a5ead3f5ea60714eccdba586f72ef0 changed `_run_wkhtmltopdf` into a subprocess wrapper. A later FW, 64f46c270e062df94d4ce37e3065b3e0a0ba68db, did not account for that change and continued mocking the method with PDF bytes. When the wkhtmltopdf path is reached, reading from those bytes crashes. --- Desired behavior after this commit is merged: This commit mocks `_run_pdf_engine_without_processing`, whose contract is to return PDF bytes, so the tour can validate without invoking a real PDF engine. --- runbot-[944189](https://runbot.odoo.com/odoo/error/944189)
This change restores the expected description for a Point of Sale popup so automated tests can run without errors. It does not change the customer-facing behavior of the popup, but it prevents test failures that were blocking quality checks.
Original PR description
### Issue: In 19.3, the following hoot tests fail with a RunBot error: - "called at right time (when canceling order)" - "called at right time (when canceling order never sent to blackbox)" - "called…
### Issue:
In 19.3, the following hoot tests fail with a RunBot error:
- "called at right time (when canceling order)"
- "called at right time (when canceling order never sent to blackbox)"
- "called at right time (when canceling a combo order)"
### Cause:
Commit 0dfd71b9f4 removed `close` from `ControlButtonsPopup` as the Dialog patch now handles closing via `this.data.close()` With no remaining props to declare, `static props` was removed entirely
Without `static props`, Owl skips all prop validation but emits: "Component 'ControlButtonsPopup' does not have a
static props description"
`mountWithCleanup` forces `warnIfNoStaticProps` to `true` in hoot tests, causing the tests to fail
`close` is declared as optional since `dialog_service.js` always injects it via `subProps: markRaw({ ...props, close })` at runtime, but the component no longer uses it directly
### Steps to reproduce:
- Install `l10n_be_pos_blackbox`
- Enable Developer mode
- Open the JS test UI
- Run one of the failing tests
runbot-941231
Forward-Port-Of: odoo/odoo#277790This fix ensures the payment card shown in the customer portal follows the same rules as the /my/payment_method page. As a result, customers will see a consistent set of payment options in both places, avoiding confusion when cards appear or disappear unexpectedly.
Original PR description
Commit bcfeed4b24f51 introduce `ResPartner._get_payment_tokens` method to determine which tokens are available for a specific partner, in case that method is overridden in some way, the portal card will not be visible/hidden correctly. This commit, use that method to align the portal card visibility with the tokens that will effectively be shown on the `/my/payment_method` page. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The hidden avatar counter in chat-related lists now adjusts correctly when the number reaches double digits, so labels like "+10" are no longer cut off. This makes the count easier to read and avoids confusion in views that use avatar tags, such as Live Chat.
Original PR description
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This…
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This causes the text to get cut off, making the exact number unreadable. Solution: This commit updates the badge container to properly accommodate larger numbers. The text now fits entirely within the badge without overflowing, ensuring the hidden tag count remains fully readable. Steps to reproduce (runbot v19.3): 1. Open the Live Chat app (or any view using the many2many_avatar_user widget). 2. Add enough agents to a session so the remaining count hits double digits (10 or more). 3. Observe that the badge showing the remaining agent count (e.g., "+10") overflows the badge container, cutting off the text and making it unreadable. opw-6453976 <img width="2655" height="1111" alt="avatar_tag_193_before" src="https://github.com/user-attachments/assets/9c31007d-5300-4bb7-a703-01a13b5bdd10" /> <img width="2655" height="1112" alt="avatar_tag_193_after" src="https://github.com/user-attachments/assets/7b2a4074-3738-4a6c-9649-f6652601f3f3" /> Forward-Port-Of: odoo/odoo#281570
13 changes
Enhancements to existing features
The Dutch payroll module now includes the 2026 income tax rate values for residents. This helps ensure payroll calculations stay aligned with the latest statutory requirements for Dutch employees.
Original PR description
Added 2026 values for the residents' income tax rates rule parameter. task-6462877 Forward-Port-Of: odoo/enterprise#127556
The default waiting time for web interface test checks has been increased so tests are less likely to fail on busy machines. This improves the reliability of development and release validation without slowing successful test runs.
Original PR description
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests…
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests give 10 seconds. 430 call sites in addons reach these three helpers and 29 pass an explicit timeout, so 12 frames is what the other 401 get. The problem is that 12 frames is less than what the client needs on a loaded machine. Measured on "should remove file from html editor if removed from attachment list", on the wait that follows the Full composer button: - 5 to 7 frames on an idle machine; - 11 to 18 frames over 8 runs with the machine at load 10 to 20, 5 of the 8 above the 12 frames the default allows. Those 5 are failing runs, and the same test at load 13 to 29 fails 6 runs out of 6 with the 200 milliseconds, 0 out of 6 with 10 seconds. Note that a longer timeout costs nothing on a green build: the wait ends on the frame the DOM matches, so it only delays the report of a test that was going to fail anyway. Hoot fails the test itself after 5 seconds, 15 in test_js.py, which keeps bounding a wait that never resolves. This commit raises the default to 10 seconds, the delay a tour step already gets in macro.js and the one contains() and expect.waitForSteps already have. https://runbot.odoo.com/odoo/error/946094 Forward-Port-Of: odoo/odoo#282702
The Time Off configuration now displays the option to create a Calendar meeting when a leave request is approved. This makes the setting easier to find and helps teams control whether absences also appear in the Calendar app.
Original PR description
The `create_calendar_meeting` field on `hr.leave.type` allows users to choose if leave requests created with a given time off type generate a corresponding entry in the Calendar app. However, this field was not displayed on the form view. This commit adds `create_calendar_meeting` to the `hr.leave.type` form view inside the configuration section, along with dedicated help text explaining its behavior. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282698 Forward-Port-Of: odoo/odoo#280593
Resolved issues and error corrections
A failing automated test was adjusted so it validates the intended planning behavior without accidentally saving incomplete test data. This helps keep build checks reliable and reduces false failures during quality validation.
Original PR description
On runbot, the `test_onchange_break_time_after_removing_dates` test was failing during the "all" build due to the `planning_slot_check_datetimes_set_or_plannable_slot` SQL constraint introduced by the sale_planning module. The test previously used `odoo.tests.Form` as a context manager, which implicitly triggered a database save and flushed the dateless test shift to PostgreSQL. Can resolved this by instantiating the Form in memory to validate the frontend `@api.depends` logic without triggering the cross-module database constraint. runbot-6463625
Project settings no longer show the Time Management section when the Timesheets app is not installed. This avoids confusing users with options that are not available and keeps the project setup screen aligned with installed apps.
Original PR description
**Steps to reproduce:** - Install the project_forecast module. - Go to Projects -> Open the settings of any project (create one if none exist) -> Settings. - You will see the Time Management section. **Issue:** The project_forecast module was forcefully setting the invisible attribute of group_time_managment to 0. This caused the group to remain visible at all times, even when the Timesheets app was not installed. **Fix:** Remove the forced attribute setting from the project_project_view. The visibility is already properly managed by the hr_timesheet module, and project_forecast does not depend on timesheet_grid or hr_timesheet. task-6195716 Forward-Port-Of: odoo/enterprise#121454
A leftover “Request Appraisals” action that caused an error has been removed. Employees can still request appraisals in bulk through the existing “Launch Campaign” option, which correctly handles selected employees.
Original PR description
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it…
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it raises AttributeError: 'hr.employee' object has no attribute '_create_multi_appraisals'. #### Current behavior before PR: Commit 8845eb2ac29 replaced the multi-appraisal flow with hr.appraisal.campaign.wizard: it deleted _create_multi_appraisals and repointed the employee list header button to action_open_appraisal_campaign_wizard, but left the action_create_multi_appraisals record in hr_appraisal/views/hr_employee_views.xml. Its code is now the only reference to the deleted method, so the action crashes whenever it is run. #### Desired behavior after PR is merged: The dangling action is gone. Requesting appraisals for several employees at once is done with the "Launch Campaign" button already present in the Employees list view; action_open_appraisal_campaign_wizard reads active_ids when active_model is hr.employee and pre-fills the selected employees. Nothing references the removed xml id, and the record is not noupdate, so _process_end removes it from existing databases on update; no migration script is required. Verified on a 19.0 database: with the orphan record loaded, updating hr_appraisal with this change deletes it. opw-6408609 Forward-Port-Of: odoo/enterprise#127983 Forward-Port-Of: odoo/enterprise#125630
Return shipping labels generated through Sendcloud now avoid printing the customer's house number twice. This keeps customer address details clearer on return labels and reduces confusion during returns processing.
Original PR description
Issue ----- On return labels, the house number of the origin address (so the customer) is printed twice. Steps to reproduce ----- - Setup sendcloud - Select a return service - Enable "Generate Return Label" - Create a delivery using sendcloud - Validate the delviery > The return label has the house number printed twice Cause ----- For the origin address shown on labels, Sendcloud prints both the address line and the house number. There doesn't seem to be any parsing made on the address line to extract the house number. For the WH -> Customer label, the "from" address is taken directly from the Sendcloud account's configuration. For the Customer -> WH return, we provide it in the `from_` fields of the request. Note that, when including the house number on the address line in Sendcloud, the issue is also present. ----- Ticket: opw-6405054 Forward-Port-Of: odoo/enterprise#127855 Forward-Port-Of: odoo/enterprise#126250
The returns Kanban view now supports using the up and down arrow keys to move through return selections. This prevents an error that could interrupt users when navigating returns with the keyboard, making the workflow smoother and more reliable.
Original PR description
In returns kanban view, a traceback occurs when pressing down. Fix this by adding the support for up/down keyboard navigation for returns selection. task-6281033 Forward-Port-Of: odoo/enterprise#128135 Forward-Port-Of: odoo/enterprise#125164
Users now see a helpful message if the Belgian POS blackbox self-order module is missing, including guidance on how to install it. This prevents confusing technical errors when opening the point of sale and helps teams resolve the setup issue faster.
Original PR description
Replace the bare ValidationError with a user-friendly UserError that explains how to install the required 'l10n_be_pos_blackbox_self_order' module. Task-6388185
The website editor now shows dynamic snippet filter names in the editor user's preferred language instead of the website's default language. This prevents confusion for editors working on multilingual websites where the public site language differs from their own interface language.
Original PR description
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the frontend request language (see: `frontend_pre_dispatch()`), so the ORM context lang is set to the website language. As a result, translated fields such as name are read in that language. Force `request.env.user.lang` in the context when fetching the filters since their names should be displayed in the editor's preferred language. task-5979540 Forward-Port-Of: odoo/odoo#280743 Forward-Port-Of: odoo/odoo#275390
This change makes an automated image upload test more reliable by giving it a little more time to detect the uploaded image. It helps prevent random test failures on slower or heavily used systems, improving overall build stability.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281200
This fix ensures the order details popup closes before the payment screen opens when a cashier chooses to edit a payment from a ticket. It prevents two screens from overlapping, making the checkout flow clearer and less confusing for users.
Original PR description
Steps to reproduce: ----------- - Validate an order, then open it from the ticket screen - Open the order details popup, click "Edit Payment" - Redirected to PaymentScreen, but the order details popup stays open on top of it Cause: --------- OrderDetailsDialog (opened via the dialog service) and PaymentScreen (opened via pos.navigate) are two separate stacks. Navigating to PaymentScreen does not close the dialog. Fix: -------------- Call dialog.closeAll() before pos.editPayment(order) in the editPayment callback passed to OrderDetailsDialog, so the dialog closes before navigating to PaymentScreen. task-6463084 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The link preview popover now gives users a larger clickable area for the magic wand icon, making it easier to use and better aligned with accessibility guidance. The hover feedback has also been improved, and the dark theme edit button now looks clearer as a button.
Original PR description
According to accessibility recommendations, the magic wand icon link inside the link preview popover is too small. This commit makes it clickable on an area of 24px x 24px, and adds the missing effect to provide feedback on hover. task-6373506 Forward-Port-Of: odoo/odoo#282534 Forward-Port-Of: odoo/odoo#276929
14 changes
Enhancements to existing features
The Dutch payroll module now includes the 2026 resident income tax rate values. This helps payroll calculations stay aligned with upcoming Netherlands tax requirements.
Original PR description
Added 2026 values for the residents' income tax rates rule parameter. task-6462877 Forward-Port-Of: odoo/enterprise#127556
This update adds automated tests for the Mollie payment option in Point of Sale, covering both the backend and the POS interface. It helps catch issues earlier and reduces the risk of payment-related regressions affecting customers.
Original PR description
This commit adds both Python and JS unit tests for the Mollie POS payment method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282024 Forward-Port-Of: odoo/odoo#281742
The IoT box update schedule no longer runs on weekends. This better matches support availability and reduces the chance of updates happening when help may not be available.
Original PR description
This PR removes weekend days from dynamic update for the iot boxes. This allows to follow the support availabilities Forward-Port-Of: odoo/odoo#282780
Resolved issues and error corrections
A leftover “Request Appraisals” action that no longer worked has been removed. Users should use the existing “Launch Campaign” option to request appraisals for multiple employees, avoiding an error when starting the process.
Original PR description
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it…
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it raises AttributeError: 'hr.employee' object has no attribute '_create_multi_appraisals'. #### Current behavior before PR: Commit 8845eb2ac29 replaced the multi-appraisal flow with hr.appraisal.campaign.wizard: it deleted _create_multi_appraisals and repointed the employee list header button to action_open_appraisal_campaign_wizard, but left the action_create_multi_appraisals record in hr_appraisal/views/hr_employee_views.xml. Its code is now the only reference to the deleted method, so the action crashes whenever it is run. #### Desired behavior after PR is merged: The dangling action is gone. Requesting appraisals for several employees at once is done with the "Launch Campaign" button already present in the Employees list view; action_open_appraisal_campaign_wizard reads active_ids when active_model is hr.employee and pre-fills the selected employees. Nothing references the removed xml id, and the record is not noupdate, so _process_end removes it from existing databases on update; no migration script is required. Verified on a 19.0 database: with the orphan record loaded, updating hr_appraisal with this change deletes it. opw-6408609 Forward-Port-Of: odoo/enterprise#125630
The returns kanban view now supports using the up and down arrow keys to move through return selections. This prevents an error that previously appeared when users pressed the down arrow, making the workflow smoother and more reliable.
Original PR description
In returns kanban view, a traceback occurs when pressing down. Fix this by adding the support for up/down keyboard navigation for returns selection. task-6281033 Forward-Port-Of: odoo/enterprise#125164
The product catalog opened from Field Service tasks now gives more space to the unit of measure column. This improves readability and aligns the Enterprise catalog view with the related Community update.
Original PR description
Steps to produce: --- - Install `Field service` module. - Create a task and open it. - From the task open the catalog from smart button. Update the Product Catalog UI to match the Community PR changes. community PR: https://github.com/odoo/odoo/pull/267118 opw-6253382 --- Forward-Port-Of: odoo/enterprise#127996 Forward-Port-Of: odoo/enterprise#121139
Return shipping labels created through Sendcloud now avoid printing the customer's house number twice. This makes labels clearer and helps prevent address confusion during returns.
Original PR description
Issue ----- On return labels, the house number of the origin address (so the customer) is printed twice. Steps to reproduce ----- - Setup sendcloud - Select a return service - Enable "Generate Return Label" - Create a delivery using sendcloud - Validate the delviery > The return label has the house number printed twice Cause ----- For the origin address shown on labels, Sendcloud prints both the address line and the house number. There doesn't seem to be any parsing made on the address line to extract the house number. For the WH -> Customer label, the "from" address is taken directly from the Sendcloud account's configuration. For the Customer -> WH return, we provide it in the `from_` fields of the request. Note that, when including the house number on the address line in Sendcloud, the issue is also present. ----- Ticket: opw-6405054 Forward-Port-Of: odoo/enterprise#127855 Forward-Port-Of: odoo/enterprise#126250
Invoice extraction now compares scanned IBANs with partner bank accounts after removing spaces and punctuation on both sides. This helps the system correctly identify matching bank accounts even when saved IBANs include formatting characters, reducing missed matches during invoice processing.
Original PR description
When looking for a matching IBAN, we were searching on the `acc_number` field, which can contain spaces or special characters (dots, dashes, etc). But the OCR always returns the IBAN in a sanitized format, without any space or special characters, so it should be compared against the sanitized IBAN of the partners. task-none (issue found by chance) Forward-Port-Of: odoo/enterprise#127775
Validation errors on Indian employee contracts now reflect the employee's actual pay schedule instead of always referring to a monthly wage. This reduces confusion when allowances exceed the wage for employees paid on different schedules.
Original PR description
**Steps to reproduce:** - Create an indian employee. - Put total allowance `(basic salary + HRA + standard ALW + Perf bonus + travel ALW) > wage` - We will get validation error in employee stating that allowance sum can't be greater than wage. **Before:** - We were always showing monthly wage in the validation error, which was confusing to the end user. **After:** - We will use field `version.shedule_pay` to show dynamic validation error message. Task: [6449791](https://www.odoo.com/odoo/project/1251/tasks/6449791)
This change makes an automated test for image uploads more reliable by allowing a little more time for the uploaded image to appear. It helps reduce random test failures during busy system conditions, supporting smoother releases without changing user-facing behavior.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281200
The attendance kiosk no longer loads a presence status script that is not used in that view. This reduces unnecessary resource loading and helps keep the kiosk experience lighter without changing its functionality.
Original PR description
This commit removes the hr_attendance_presence_status.js file from the kiosk bundle, as it is not needed in the kiosk view and can cause unnecessary loading of resources. task-6468972 Forward-Port-Of: odoo/odoo#282410
The website editor now shows dynamic snippet filter names in the user’s preferred language instead of automatically using the website language. This makes the editing experience clearer and more consistent for multilingual sites.
Original PR description
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the frontend request language (see: `frontend_pre_dispatch()`), so the ORM context lang is set to the website language. As a result, translated fields such as name are read in that language. Force `request.env.user.lang` in the context when fetching the filters since their names should be displayed in the editor's preferred language. task-5979540 Forward-Port-Of: odoo/odoo#280152 Forward-Port-Of: odoo/odoo#275390
This change restores a small component definition needed by automated POS tests, preventing false failures during order-cancel flows. It does not change the customer experience, but it keeps the Point of Sale test suite reliable and unblocks builds.
Original PR description
### Issue: In 19.3, the following hoot tests fail with a RunBot error: - "called at right time (when canceling order)" - "called at right time (when canceling order never sent to blackbox)" - "called…
### Issue:
In 19.3, the following hoot tests fail with a RunBot error:
- "called at right time (when canceling order)"
- "called at right time (when canceling order never sent to blackbox)"
- "called at right time (when canceling a combo order)"
### Cause:
Commit 0dfd71b9f4 removed `close` from `ControlButtonsPopup` as the Dialog patch now handles closing via `this.data.close()` With no remaining props to declare, `static props` was removed entirely
Without `static props`, Owl skips all prop validation but emits: "Component 'ControlButtonsPopup' does not have a
static props description"
`mountWithCleanup` forces `warnIfNoStaticProps` to `true` in hoot tests, causing the tests to fail
`close` is declared as optional since `dialog_service.js` always injects it via `subProps: markRaw({ ...props, close })` at runtime, but the component no longer uses it directly
### Steps to reproduce:
- Install `l10n_be_pos_blackbox`
- Enable Developer mode
- Open the JS test UI
- Run one of the failing tests
runbot-941231
Forward-Port-Of: odoo/odoo#277790The link preview popover now gives the edit/magic wand control a larger clickable area and a hover effect, making it easier to find and use. In dark mode, the Edit button background has also been adjusted so it stands out properly against the popover.
Original PR description
According to accessibility recommendations, the magic wand icon link inside the link preview popover is too small. This commit makes it clickable on an area of 24px x 24px, and adds the missing effect to provide feedback on hover. task-6373506 Forward-Port-Of: odoo/odoo#282534 Forward-Port-Of: odoo/odoo#276929
8 changes
Enhancements to existing features
This change gives automated checks more time to wait for page updates before declaring a failure. It reduces false failures on busy machines without slowing successful test runs, helping teams get more dependable build results.
Original PR description
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests…
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests give 10 seconds. 430 call sites in addons reach these three helpers and 29 pass an explicit timeout, so 12 frames is what the other 401 get. The problem is that 12 frames is less than what the client needs on a loaded machine. Measured on "should remove file from html editor if removed from attachment list", on the wait that follows the Full composer button: - 5 to 7 frames on an idle machine; - 11 to 18 frames over 8 runs with the machine at load 10 to 20, 5 of the 8 above the 12 frames the default allows. Those 5 are failing runs, and the same test at load 13 to 29 fails 6 runs out of 6 with the 200 milliseconds, 0 out of 6 with 10 seconds. Note that a longer timeout costs nothing on a green build: the wait ends on the frame the DOM matches, so it only delays the report of a test that was going to fail anyway. Hoot fails the test itself after 5 seconds, 15 in test_js.py, which keeps bounding a wait that never resolves. This commit raises the default to 10 seconds, the delay a tour step already gets in macro.js and the one contains() and expect.waitForSteps already have. https://runbot.odoo.com/odoo/error/946094 Forward-Port-Of: odoo/odoo#282702
Resolved issues and error corrections
This fix prevents Mexican payroll processing from crashing when a company does not have a VAT number entered. It allows payslip checks to continue normally for companies with incomplete tax identifier information.
Original PR description
`res.company.vat` is not required and can be `False`. Guard the `len()` call so `_issue_mx_warnings` doesn't crash on payslips for companies without a VAT set.
```py
File "/home/odoo/src/enterprise/saas-19.3/hr_payroll/models/hr_payslip.py", line 1936, in _compute_issues
issues = generate_issue(slip, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py", line 235, in _issue_mx_warnings
if not slip.company_id.l10n_mx_curp and slip._l10n_mx_is_curp_needed():
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py", line 325, in _l10n_mx_is_curp_needed
or len(self.company_id.vat) == 13
^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: object of type 'bool' has no len()
```Invoice scanning now compares detected bank account numbers with a cleaned version of partner IBANs, ignoring spaces and punctuation. This helps match suppliers' bank details more accurately when scanned invoices use a standardized IBAN format.
Original PR description
When looking for a matching IBAN, we were searching on the `acc_number` field, which can contain spaces or special characters (dots, dashes, etc). But the OCR always returns the IBAN in a sanitized format, without any space or special characters, so it should be compared against the sanitized IBAN of the partners. task-none (issue found by chance) Forward-Port-Of: odoo/enterprise#127775
This fixes an issue where the calendar could show the wrong weekday for users in time zones where daylight saving time starts at midnight. Calendar headers now display the correct sequence of days, avoiding confusion when planning around those dates.
Original PR description
Current behaviour: In the Calendar view (day/week/month scale), when the user's timezone observes a DST transition that starts exactly at local midnight (e.g. Africa/Cairo, since 2023), the day…
Current behaviour: In the Calendar view (day/week/month scale), when the user's timezone observes a DST transition that starts exactly at local midnight (e.g. Africa/Cairo, since 2023), the day column right after the transition gets the wrong weekday name, duplicating the previous day's name. For ex. it renders "... THU THU FRI ..." instead of "... THU FRI SAT ...", for the week surrounding April 30th 2027. To fix this we add 1 hour to the Date before reading its weekday/day from it, mirroring the workaround FullCalendar itself adopted for this same bug. It has no effect on any ordinary day (adding 1h to a correct local midnight stays within the same calendar day), and it cannot overshoot into the next day since no real-world DST gap exceeds that margin. Note: This is a known bug (https://github.com/fullcalendar/fullcalendar/issues/7633), fixed in FullCalendar v6.1.17, a major version ahead of the v4.4.0, so the fix can't be applied directly without a full library upgrade. opw-6370140 Forward-Port-Of: odoo/odoo#279836 Forward-Port-Of: odoo/odoo#279343
This change ensures that when a user clicks a mention suggestion in the message composer, the name shown on screen is the one inserted. It prevents cases where the typed search text could remain instead of the selected contact, improving reliability when mentioning people with special characters in their names.
Original PR description
Before this commit, clicking a composer suggestion could leave the composer with the typed search instead of the selected name, as in the test "Mention a partner with special character (e.g. apostrophe ')" on runbot: Failed to find 1 of ".o-mail-Composer-input" with value "..." (Timeout of 10 seconds). Found 0 instead. This happens because NavigableList looks up the clicked option by index in its current props, while the item clicked comes from the last render. Typing "@" lists the two members of the channel and typing "Pyn" drops one of them: owl assigns the filtered options one frame before it patches the list, so a click in between looks up index 1 in a list of one option, finds nothing and returns. This commit passes the rendered option to the click handler, keeping the index lookup as a fallback so that the signature stays the same on a stable version. https://runbot.odoo.com/odoo/error/946154 Forward-Port-Of: odoo/odoo#282897
Clicking a table of contents entry in the HTML editor now scrolls a bit further so the target heading is clearly visible, not just barely shown at the edge of the screen. This makes navigation in longer HTML content feel more reliable and easier to follow for users.
Original PR description
When clicking on a title in the TOC, we auto-scroll to that section of the HTML, allowing users to read that part. Since [1], scrollIntoView is replaced to consider top-aligned sticky elements. As a result, instead of scrolling to make it comfortable to read the section, it stops as soon as the title is visible. Unless you are really attentive at the bottom of the screen, it can look like the scrolling did not work. This commit computes the appropriate offset to make the TOC heading more visible after scrolling. [1]: https://github.com/odoo/odoo/commit/f5cf8565e7d09edd3a29fd95537381fb70d75785 Task-6394193 Forward-Port-Of: odoo/odoo#278304
This fixes an issue in the HTML editor where formatting from an outer table could incorrectly overwrite the colors of a table placed inside it. Business documents and web content with nested tables will now keep their intended visual styling after editing or normalization.
Original PR description
Problem: When a `table` with a `color`/`backgroundColor` contains a nested `table`, `distributeTableColorsToAllCells` propagates the outer table's color to every `td` in the subtree, including cells…
Problem:
When a `table` with a `color`/`backgroundColor` contains a nested `table`, `distributeTableColorsToAllCells` propagates the outer table's color to every `td` in the subtree, including cells belonging to the inner table. The inner table's own color is then discarded since its `td`s already have a value.
Cause:
`table.querySelectorAll("td")` returns every `td` in the entire subtree, not just the table's own direct cells.
Solution:
Scope the selected `td`s to `td.closest("table") === table`, so a table's color is only distributed to its own cells.
Steps to reproduce:
1. Add a `background-color` to an outer `table`.
2. Nest a `table` with a different `background-color` inside one of its cells.
3. Load/normalize the content in the editor.
4. Observe both tables' cells carry the outer table's color.
opw-6438972
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281850
Forward-Port-Of: odoo/odoo#281413This change makes an automated image upload test more reliable by giving it a little more time to detect the uploaded image. It reduces random test failures on busy systems, helping keep build and deployment checks stable.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281200
3 changes
Resolved issues and error corrections
Vendor bank account matching during invoice OCR now compares normalized IBAN values instead of the raw account text. This helps invoices match the correct partner bank account even when stored IBANs include spaces, dots, or dashes.
Original PR description
When looking for a matching IBAN, we were searching on the `acc_number` field, which can contain spaces or special characters (dots, dashes, etc). But the OCR always returns the IBAN in a sanitized format, without any space or special characters, so it should be compared against the sanitized IBAN of the partners. task-none (issue found by chance) Forward-Port-Of: odoo/enterprise#127775
Split PDF pages now appear in a predictable order in Documents. This prevents confusion when multiple pages are created at the same time and previously appeared randomly in the kanban view.
Original PR description
steps: - upload a multi-page pdf - split all the pages -> they now show in a random order The issue is that the current documents are sorted by create_date desc, but the split creates all the different documents at the same time so they are sorted in the order they happen to be on the disk. We now add a sort by id to act as a tie-breaker. opw-6176840 Forward-Port-Of: odoo/enterprise#126683 Forward-Port-Of: odoo/enterprise#117255
The project Sales button now shows all linked sales, including rental orders, so the list matches the number shown on the project. This prevents users from missing rental-related orders when reviewing project sales activity.
Original PR description
Steps to Reproduce --- 1. Install sale_renting_project. 2. Create a Project linked to 1 standard Sales Order and 1 Rental Order. 3. Observe the "Sales" stat button counts 2 Sales. 4. Click the stat button. Only the standard Sales Order is displayed. Issue --- In saas-18.4, the project Sales stat button calls action_view_sos without the from_embedded_action context key. As a result, _get_sale_orders_domain applies the non-rental filter by default, causing rental orders to be excluded from the action even though they are included in the displayed counter. Expected Behavior --- The Sales stat button should display all orders linked to the project, including both standard and rental orders, matching its total counter. Fix --- Return the base project domain unmodified when from_embedded_action is not set in the context. task-6140201
8 changes
Enhancements to existing features
This change increases the default wait time used by web interface tests so they are less likely to fail on busy or slower machines. It aligns these waits with existing test behavior and improves confidence in automated test results without affecting normal successful runs.
Original PR description
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests…
Before this commit, waitFor, waitForNone and waitUntil gave the DOM 200 milliseconds, which the loop turns into 12 animation frames, while contains() and expect.waitForSteps sitting in the same tests give 10 seconds. 430 call sites in addons reach these three helpers and 29 pass an explicit timeout, so 12 frames is what the other 401 get. The problem is that 12 frames is less than what the client needs on a loaded machine. Measured on "should remove file from html editor if removed from attachment list", on the wait that follows the Full composer button: - 5 to 7 frames on an idle machine; - 11 to 18 frames over 8 runs with the machine at load 10 to 20, 5 of the 8 above the 12 frames the default allows. Those 5 are failing runs, and the same test at load 13 to 29 fails 6 runs out of 6 with the 200 milliseconds, 0 out of 6 with 10 seconds. Note that a longer timeout costs nothing on a green build: the wait ends on the frame the DOM matches, so it only delays the report of a test that was going to fail anyway. Hoot fails the test itself after 5 seconds, 15 in test_js.py, which keeps bounding a wait that never resolves. This commit raises the default to 10 seconds, the delay a tour step already gets in macro.js and the one contains() and expect.waitForSteps already have. https://runbot.odoo.com/odoo/error/946094 Forward-Port-Of: odoo/odoo#282702
Resolved issues and error corrections
Fixed an issue where embedded document actions linked to accounting journals could be incorrectly removed during automated cleanup when users were working in a different company. This helps preserve configured document shortcuts in multi-company setups.
Original PR description
Step to reproduce: - You must have at least 2 companies with an account Journal - Create a New Journal Entry actions (child or parent) - Embed it to a folder - Set your company on a different one than the journal's one - Run the Garbage collector cron (Base: Auto-vacuum internal data) - The embed action has been removed The cause of this is that in the `_get_base_server_actions_domain` method in `documents_account` module there is a check on company to avoid using/running the actions when not in the right company. But the garbage collector don't need to have this check. Task-6147618
Invoice scanning now compares detected bank account numbers against a cleaned version of partner IBANs, ignoring spaces and punctuation. This helps match vendors more reliably when stored bank details use different formatting.
Original PR description
When looking for a matching IBAN, we were searching on the `acc_number` field, which can contain spaces or special characters (dots, dashes, etc). But the OCR always returns the IBAN in a sanitized format, without any space or special characters, so it should be compared against the sanitized IBAN of the partners. task-none (issue found by chance) Forward-Port-Of: odoo/enterprise#127775
Opening spreadsheet version history now uses the correct type of database transaction. This avoids an unnecessary retry when contributor information is updated, making the action smoother and more reliable for users.
Original PR description
The get_spreadsheet_history method is marked as readonly, causing RPC requests to use a read-only transaction. However, retrieving the metadata of a document spreadsheet updates its spreadsheet contributors. Opening the version history consequently attempts an UPDATE in a read-only transaction and forces the request to be retried with a read-write cursor. Remove the readonly decorator so the request uses a read-write cursor directly. Task-6176364
Payment XML files now use uppercase encoding labels to satisfy stricter bank validation rules. This helps avoid warnings or rejections from providers such as SIX in Switzerland, while keeping the file content unchanged.
Original PR description
The W3C recommendations for XML state that the encoding defined for an XML document should not be case-sensitive. However, some banking providers (SIX for Switzerland) are stricter and may throw warnings or errors if upper-case is not used. https://www.w3.org/TR/2008/REC-xml-20081126/#NT-EncodingDecl opw-4948708 Forward-Port-Of: odoo/enterprise#125947 Forward-Port-Of: odoo/enterprise#125807
This change makes the peer-to-peer connection test wait until the full set of connections is established before measuring the result. It prevents random test failures on busy or slower machines, improving confidence in the chat system’s reliability.
Original PR description
Before this commit, "mesh peer to peer connections" fails at random on a loaded machine, counting fewer connections than its ten users make:
[toBe] expected values to be strictly equal
> Expected: 90
> Received: 81
This happens because the test counts the peers as soon as its addPeer calls resolve. addPeer awaits the readiness promise of the peer, which also resolves, with false, when that peer is disconnected. A connection slow to open reaches the recovery watchdog, which tells the other side to drop the peer, drops it locally and adds it back without awaiting it. The awaited promises can therefore all be settled while recovered peers are still connecting.
This commit waits for the mesh to reach its full size before counting, so that a recovery in flight no longer decides the result. With the browser CPU throttled, the test fails about half of its runs before this commit, and none after.
Forward-Port-Of: odoo/odoo#282719This update removes an old, unused view attribute from the Philippine 2307 wizard form. It does not change how the form works, but it keeps the configuration cleaner and avoids compatibility issues with newer Odoo versions.
Original PR description
The `modifiers` attribute was used in older Odoo versions to define field properties (invisible, readonly, required, etc.) Since the field already declares these same properties directly…
The `modifiers` attribute was used in older Odoo versions to define field properties (invisible, readonly, required, etc.) Since the field already declares these same properties directly [state](https://github.com/odoo/odoo/blob/14.0/addons/account/models/account_move.py#L150-L155) , [amount_tax_signed](https://github.com/odoo/odoo/blob/14.0/addons/account/models/account_move.py#L229)
(e.g. `invisible=...`, `readonly=...`), the `modifiers` attribute is redundant and serves no purpose.
This attribute was never added manually by us — it was auto-generated by Odoo Studio when the default view was created. Studio's default views inject `modifiers` alongside the direct attributes. [Here](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-dfebe5a93e1b8880e88268b024be4c6f106d144b20298d7bb6c4ae09a18bafd0L67-L145)
Also the `modifiers` attribute was fully simplified [removed](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-849f1ed2a35a8b0b9cdd67f8e34de5d2ea7bf928103a83828587ba7ec14a62e4L52) starting from version 17.0, where views rely exclusively on direct attribute expressions (`invisible`, `readonly`, `required`) instead of the `modifiers` JSON encoding [main Patch](https://github.com/odoo/odoo/pull/104741) Keeping it around in the arch is therefore dead code with no effect.
However it needs to give the error on 17.0+ like this
```
ERROR LOG:
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_NOELEM: Expecting an element data, got nothing
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_INVALIDATTR: Invalid attribute modifiers for element field
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_EXTRACONTENT: Element tree has extra content: field
```
As the modifer has been remove from the field [common.rng](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-849f1ed2a35a8b0b9cdd67f8e34de5d2ea7bf928103a83828587ba7ec14a62e4L52) RelaxNG schema but modifiers set on fields here root tag is **form**, and the modifiers sit on fields inside a nested list. And Form views aren't RNG-validated from 17.0 till now —
[@validate('calendar', 'graph', 'pivot', 'search', 'list', 'activity')](https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/odoo/tools/view_validation.py#L314) has no form, and there's no [form_view.rng](https://github.com/odoo/odoo/tree/19.0/odoo/addons/base/rng).
Current senario
<img width="998" height="415" alt="image" src="https://github.com/user-attachments/assets/1a678c8f-8401-4e12-826f-9e98f6f2fe20" />
After removing the modifer: it show the same view because of field property
<img width="998" height="415" alt="image" src="https://github.com/user-attachments/assets/1a678c8f-8401-4e12-826f-9e98f6f2fe20" />
After removing the modifer still it shows the **modifiers="{'readonly':true, 'required':true}"** because the modifer is stay in the 14.0 but the 17.0 onwards it was not please see the scrrenshot its field preprty always.
<img width="1003" height="462" alt="image" src="https://github.com/user-attachments/assets/5e833924-b17c-417f-9e63-5a01c185f588" />
This Fix removes the unused `modifiers` attribute from the view arch, keeping only the direct attribute already present, with no functional change to the view's behavior.
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281271
Forward-Port-Of: odoo/odoo#279976This change increases the waiting time in an automated image upload test so it has enough time to detect the uploaded image on slower systems. It helps prevent random test failures without changing the actual user experience.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281200
24 changes
Enhancements to existing features
This update refreshes icons across manufacturing lifecycle, work order, quality, and barcode screens with a newer, cleaner visual style. The change improves visual clarity and consistency without altering business processes or functionality.
Original PR description
Icons were updated with the newer, more clean ones. task-6443360
The Belgian payroll configuration now includes the required reporting details for recoverable 0% overtime. This helps ensure overtime is classified correctly for social security, withholding tax, and official Belgian payroll declarations.
Original PR description
- Extended the OVERTIME26 work entry type with essential Belgian reporting metadata: category_ids (Remuneration, ONSS, Withholding tax bases), dmfa_code=1, and l10n_be_egov3_code=1102001. Task: 6358853
Obsolete internal duplication logic was removed from Sales Subscription and Sales Renting to match the updated core product behavior. This reduces maintenance overhead and helps keep sales-related product handling consistent across Odoo.
Original PR description
Remove obsolete _duplicate_pricelist_rules_on_copy overrides from enterprise modules (sale_subscription, sale_renting) following its removal from the product module. This avoids dead code and ensures consistency with the updated core duplication behavior. task-5470688
The accounting reconciliation interface was updated to work with the newer OWL framework used by Odoo. This helps keep bank reconciliation and related accountant workflows maintainable and compatible without introducing major functional changes for users.
Original PR description
This pr will do some changes to be compliant with owl3. What has been done: - Change of some props to the new system - Remove use of useSubEnv - Remove use of onWillRender Also apply the EsLint on all files. task-6353237
This update makes a small internal change in Web Studio’s report template handling to support future improvements. It does not introduce visible changes for users today, but helps keep reporting customization capabilities ready for upcoming enhancements.
Original PR description
Pass compile_context in parameters of `_compile_expr` to prepare future improvements in QWEB according to expressions. Task-6466187
Spreadsheet-related automated tests were updated to align with the move to Material Symbols icons in the spreadsheet library. This helps keep quality checks reliable after the visual icon system change, with no expected direct impact on daily users.
Original PR description
this commit adapts the tests to the switch to Material Symbols icons in the external library o-spreadsheet. Task: 6276321
The signing activity is renamed from "Request Signature" to "Signature Request" so users see wording that matches the rest of the app. The activity icon is also muted to better align visually with other activity icons, creating a more consistent experience.
Original PR description
Renaming activity from "Request Signature" to "Signature Request" to better align with the wording used in other places. Change the template icon to muted to better match the other activities icons. Task-6317051
The Point of Sale navigation menu now displays icons and labels with consistent alignment and spacing. This makes the burger menu and LNA button easier to read and improves the overall visual clarity for users.
Original PR description
In this commit - ------------------------------- icon and label in the burger menu and LNA button are now properly aligned with consistent spacing for better visibility. Task-6391440 Related PR-https://github.com/odoo/odoo/pull/280203
The Ecuador ATS reporting tests were updated to match a platform-level change in how certain grouped results are ordered. This keeps automated checks aligned with the intended behavior and helps prevent false test failures without changing business functionality.
Original PR description
Following changes to the ORM methods _read_group_orderby and _order_field_to_sql, query results are now ordered according to the sequential definition of selection fields (if ordered by a selection field ofc). Adapt the tests to take this new ordering into account. Related: odoo/odoo#280940 Task: 6425647
The Belgian payroll employee type previously labeled "PFI/Activa" has been renamed to "PFI/IBO". This makes the label more accurate for regional training contracts in Wallonia and Flanders and avoids confusion with the unrelated Activa scheme.
Original PR description
The employee type "PFI/Activa" is incorrect because Activa is not related to Dimona Category IVT. Renamed "PFI/Activa" to "PFI/IBO" to properly reflect the Belgian regional training contracts (PFI in Wallonia, IBO in Flanders). Task: 6478957
Resolved issues and error corrections
Website-generated pages and blog posts now reuse the same image file instead of creating duplicate media entries. Cropped or customized image versions are also kept out of the general media picker, making it easier for users to find the right images.
Original PR description
Images referenced by several pages (or several blog posts) could get copied into extra ir.attachment records instead of being reused, because `_get_wg_attachment` iterated over the raw filenames list without deduplicating it first, and marked a filename "used" as soon as it was assigned once. The same visually-identical image would then end up cluttering the website media picker under several ids. Also stop customized/cropped image variants from showing up as regular library images in the media picker, since they're only meant to back a specific placement.
Payroll users can now manually adjust computed payslip lines without triggering an error when recalculating. This keeps draft payslip editing reliable and prevents disruption during payroll preparation.
Original PR description
Steps to reproduce:
- Open a draft payslip.
- Go to the Salary Computation tab.
- Manually change the amount of a computed line and compute.
- A traceback is raised (UnboundLocalError).
Reason:
When a line is manually modified, the standard computation is skipped and `explanation_info` is never defined.
Solution:
Initialize `explanation_info = {}` for manually modified lines.
Task-6462526The vehicle model engine section now keeps related power fields together, so the form no longer visually shifts when users change the selected power unit. An unused horsepower tax field was also removed, reducing clutter in fleet-related views.
Original PR description
The order of fields in "engine" section of car model is changed when selecting an other Power Unit. Cause: "power" and "horsepower" fields are conditionnaly invisible depending on the selected unit but at different positions. Solution: moving them next to each other. Removing "horsepower_tax" field as not used for any computation Task: 6428275
The Sign template editor no longer performs an unnecessary background lookup when opening or preparing templates. This removes wasted processing without changing the visible editing experience, helping keep the editor leaner and more reliable.
Original PR description
The editor fetched a sign.item.role record to set currentRole, which has no effect and no use, so every value computed from it is overwritten right after. task-6449467
The Phone app now shows the full Telnyx location when users search for phone numbers to buy, making it easier to identify where numbers are based. It also removes a misleading settings menu that opened a page without any Phone-specific settings.
Original PR description
When searching for a number to buy, the Location column showed only a
fragment of where the number comes from —> usually the bare state ("ON")
while Telnyx's own search shows the whole thing ("GRIMSBY, ON, CA").
This commit fixes that and shows the location like its shown on Telnyx +
a small ux change which is removing the configuration/settings menu
because Phone app doesn't have settings actually.
Task-6456328Users can now create a new warehouse directly while setting up stock-by-vehicle mappings. This removes an unnecessary setup blocker and makes configuring vehicle-based warehouse assignments faster.
Original PR description
Before this commit, users could not create a new warehouse directly from the 'stock by vehicle' mapping view because the `warehouse_id` field had the `no_create` option enabled.
With this commit, we remove `options="{'no_create': True}"` from the `warehouse_id` field in both the list and form views. This enables on-the-fly warehouse creation directly from the vehicle mapping settings.
task-6381795
Forward-Port-Of: odoo/enterprise#124240The bank journal screen now hides the “send now” reminder and connection request when the journal is no longer using online synchronization as its bank statement source. This prevents users from seeing misleading prompts that do not apply to the selected bank setup.
Original PR description
In this commit:https://github.com/odoo/enterprise/commit/86659741990de2ba9c8bf738207edf0e8a0ba8c4 the invisible condition on action send reminder was wrongly removed Now, the "send now" button and the connection request was shown as soon as we have an account online account link to the journal. But when changing the bank statement source, the information would still be there. Changing the invisible condition to hide it when the bank statement source is different from only_sync no task id
Code cleanup and technical improvements
The inventory barcode app was updated as part of a broader platform migration to keep it compatible with the next version of Odoo's interface framework. This is an internal cleanup with no expected change to day-to-day warehouse scanning or stock counting workflows.
Original PR description
As part of the Owl 3 migration, replace onWillUpdateProps hook with the appropriate Owl 3 alternatives.
This update simplifies how commission plan charts are displayed by using a shared chart handling mechanism already adopted elsewhere. It reduces duplicated code and prepares the feature for newer platform changes, with no expected change to day-to-day user workflows.
Original PR description
The commission plan graph duplicated the same Chart.js lifecycle as the community components: an `onWillStart` loading the `web.chartjs_lib` bundle, then render on mount, destroy and re-render on every patch, destroy on unmount. Here we drop it for the hook extracted in the community PR. `useChart(getConfig)` is called from the constructor as a field and owns the canvas signal ref, so the template takes its `t-ref` from `this.chart.ref`. `spreadsheet_edition` patches `GraphRenderer` and reads its chart instance, which now lives behind the hook's accessor. WHY: useLayoutEffect is deprecated in OWL3 NOTE: the `JSON.parse` of the record value that `setup` did is dropped - `renderChart` re-parsed it on every run anyway, and nothing reads `this.data` before the chart is built. Community PR: odoo/odoo#282745
The map view code was updated to use the newer application lifecycle approach required by the next Odoo web framework version. This is an internal technical cleanup with no expected change to user-facing map behavior.
Original PR description
Replace `useLayoutEffect` with `onMounted` (functionnaly 1:1 equivalent because of the empty dependency array). Seperating in its own commit for simplicity of security review. WHY: useLayoutEffect is deprecated in OWL3
This update refreshes internal code used by spreadsheet editing screens and VoIP call controls to align with newer platform standards. It should help maintain compatibility and reduce maintenance risk without changing the expected user experience.
This update simplifies internal invoice creation code across sales-related modules, including subscriptions, loyalty, tests, and Brazilian stock EDI. It should make future maintenance safer and more consistent without changing day-to-day user workflows.
The audio visualizer was updated to use the newer supported approach in Odoo’s interface framework, replacing an outdated internal mechanism. This reduces future upgrade risk and adds test coverage to help ensure the visualizer continues working correctly.
Original PR description
Replaced `useLayoutEffect` with `computed` because `useLayoutEffect` is deprecated in OWL3. `barHeights` is pure derived state from `props.frequencies` and `barCount` (a signal). `computed` auto-tracks both dependencies and re-evaluates without side effects, making it a natural fit for this case. When commenting out the useLayoutEffect there was no error, the code we refactored had NO TEST coverage. A test was written to ensure our fix was correct, and it was tested against the previous useLayoutEffect: - Passed with previous useLayoutEffect. - Failed with previous useLayoutEffect commented. - Passed with our OWL3 replacement.
This change renames an internal user access group to make its purpose clearer and more consistent across the system. It should not change day-to-day workflows, but helps maintain the platform and reduces confusion for future updates.
1 change
Resolved issues and error corrections
Peruvian accounting reports now use the exchange rate already saved on each accounting entry instead of recalculating it during report generation. This avoids small rounding differences and helps produce more reliable report figures.
Original PR description
Previously, the `_get_ple_report_data` method computed the currency rate when called. Since the calculation was based on the entry totals, it was prone to rounding errors. This PR makes it use the rate stored in the entry itself. This should lead to more accurate results. opw-6411322 Forward-Port-Of: odoo/enterprise#126882
5 changes
Enhancements to existing features
Adds a dedicated view for French e-reporting accounting entries so users can see relevant reporting details more easily. This avoids changing the standard accounting entry view while improving visibility for France-specific compliance workflows.
Original PR description
This commit will add a new view for the ereporting moves to be able to see some specific info without touching the base move view. task-6274213 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
The payment terminal lookup no longer depends on manufacturer information that newer IoT Boxes do not provide. This helps ensure payment terminals can still be found and used correctly with updated IoT hardware.
Original PR description
Newer IoT Boxes don't send the `manufacturer` key, so we need to remove it from the search domain of payment terminals in the db.
Odoo now compares scanned invoice IBANs with cleaned partner bank account numbers, ignoring spaces and punctuation. This helps the invoice extraction process find the correct bank account more reliably when supplier records store IBANs with formatting.
Original PR description
When looking for a matching IBAN, we were searching on the `acc_number` field, which can contain spaces or special characters (dots, dashes, etc). But the OCR always returns the IBAN in a sanitized format, without any space or special characters, so it should be compared against the sanitized IBAN of the partners. task-none (issue found by chance) Forward-Port-Of: odoo/enterprise#127775
Links added inside spreadsheet cell comments can now be opened with a normal click, as users would expect. This removes a small interaction issue that made it harder to follow shared references or supporting information in spreadsheet discussions.
Original PR description
Current behavior before PR: - Clicking a link in a cell comment did not work. A left click was blocked, while Ctrl+click (or Cmd+click) opened the link in a new tab. - This was caused by `t-on-click.prevent` on the comment thread and popover. It was originally added because the scroller service used the URL hash to scroll to anchors, which was removed in https://github.com/odoo/odoo/commit/711e9c9f24818714129f55283e2df64503d93605 Desired behavior after PR is merged: - `t-on-click.prevent` is removed and links in cell comments can be opened normally with both left click and Ctrl+click (Cmd+click on macOS). Task: [6448651](https://www.odoo.com/odoo/project/2328/tasks/6448651)
This fix prevents an error when users change a product to a service after removing its unit of measure. It improves reliability in Inventory product setup by safely handling products without a unit configured.
Original PR description
Steps to replicate: 1. Install `stock`. 2. In Inventory > Configurations > Settings, enable the setting "Units of Measure". 3. Create a new product. 4. Remove the Unit. 5. Enable "Track by Inventory". 6. Swap Product Type to Service. A traceback error results. https://drive.google.com/file/d/1S_5Xdlhfe03hGaykewdIACmaaraCQcOw/view?usp=sharing A product's unit of measure's precision is passed to `float_is_zero` without first confirming that the unit of measure exists. opw-6172389 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
2 changes
Resolved issues and error corrections
The Amazon sales connector version was updated after its Orders API migration. This helps customers and partners identify that the module includes the latest internal compatibility change for Amazon's newer API.
Original PR description
In https://github.com/odoo/enterprise/pull/114591, we migrated the Orders API from v0 to v2026-01-01 following Amazon's announce of v0's deprecation. In this commit, we update the version of the module to signal the internal change to the community. task-5972714
This fix ensures that when an image already linked to another record is copied, Odoo reuses the existing attachment instead of creating an unnecessary duplicate. This helps keep the database cleaner and avoids extra storage and clutter behind the scenes.
Original PR description
Copying an image attachment already linked to another record could leave a redundant duplicate behind instead of reusing the existing one. opw-6463012