Daily updates from Odoo
Tuesday, August 11, 2026
51 changes · saas-19.3
Resolved issues and error corrections
Users with both Partner Commissions and Purchase access can now create and view purchase orders as expected. This prevents commission-related access rules from unintentionally blocking normal purchasing work while keeping commission-only restrictions in place.
Original PR description
## Current behavior: The user Partner Commissions access rights as All Documents or Own Documents and Purchase access rights as User. With this configuration, the user is unable to create new…
## Current behavior: The user Partner Commissions access rights as All Documents or Own Documents and Purchase access rights as User. With this configuration, the user is unable to create new Purchase Orders, and existing Purchase Orders are also not visible in the Purchase module. ## Expected behavior: The expected behavior is that the user should be able to create and view Purchase Orders with these access rights. Additionally, clarification is required regarding the purpose of the new Partner Commissions access group. ## Steps to reproduce: - Go to user and assign Partner Commission rights as All or own document. - On Purchase, select group as User. ## Cause of the issue: partner_commission adds commission-specific purchase order record rules, but purchase users have no matching purchase-order rule in that module. For mixed-role users, the commission rule ends up restricting standard purchase orders as well. ## Fix: Apply the module's explicit all-purchase rule to purchase users so mixed users keep base procurement access while commission-only users remain restricted by the commission rules. opw-6366074 Forward-Port-Of: odoo/enterprise#126003
Accepting an UrbanPiper order could intermittently fail because the system treated a repeated print-marking request as an error. This change makes that step safely ignore duplicates, reducing random failures during order acceptance and related automated checks.
Original PR description
mark_urbanpiper_prep_order_as_printed() raised ValueError when the 'urbanpiper_printed' flag was already set, to stop the same order from printing its preparation ticket twice…
mark_urbanpiper_prep_order_as_printed() raised ValueError when the 'urbanpiper_printed' flag was already set, to stop the same order from printing its preparation ticket twice (https://github.com/odoo/enterprise/pull/103894, Task-5353283). Accepting an UrbanPiper order fires this RPC from two places for the same order: synchronously from TicketScreen, and again via the DELIVERY_ORDER_COUNT bus notification the accept flow itself broadcasts. Under load, both requests race for the row lock; Odoo's retrying() replays the loser on lock contention, and by the time it replays the winner has already committed, so the loser hits the already-printed branch and raises. The raise is an unhandled ValueError, so it surfaces as a 500 and fails any tour that accepts an order (test_frontend.py, test_order_receipt.py), intermittently and CI-timing-dependent only. The only caller (pos_store.js: _sendDeliveryOrderForPreparation) already wraps the RPC in try/catch and treats a caught exception exactly like a falsy return value: either way it just skips sending the ticket to preparation. No other code reads or writes urbanpiper_printed, and no webhook path calls this method, so returning False is behaviorally identical for every real caller and safe to make the default. This also removes the mark_urbanpiper_prep_order_as_printed_patch monkeypatch added alongside the original raise in test_01_order_flow: it existed solely to swallow this exact ValueError for that one tour, which is no longer needed now that the method itself is idempotent. runbot error: 941514 Forward-Port-Of: odoo/enterprise#125840
Bank statement processing now uses the intended database shortcut when searching for unreconciled accounting lines. This should improve performance in reconciliation workflows without changing user-facing behavior.
Original PR description
We have a very efficient index for searching unreconciled lines on known accounts. Let's use it.
```python
_unreconciled_index = models.Index("(account_id, partner_id) WHERE reconciled IS NOT TRUE")
```
Before this change, the query planner didn't recognize the index because of its definition being slightly different wrt the null values.
Forward-Port-Of: odoo/enterprise#127093This fix prevents errors when creating operation steps in a multi-company setup where only the basic quality module is installed. It ensures quality team mail aliases have the right company context, so users are not blocked by a configuration issue they cannot resolve from the available screens.
Original PR description
This commit actually reverts [1] and manually forwards [2]. Suppose `mrp_workorder` installed and `quality_control` uninstalled. Because of the default value provided by [1], the only existing quality team is linked to the first company. As a result, when using another company, if the user tries to create an operation step (i.e., a QCP), it will raise an error when the onchange tries to load the default team in charge: https://github.com/odoo/enterprise/blob/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e/quality/models/quality.py#L141-L142 However, the `quality` module doesn't provide any view to create such a team. tldr The module raises an error that is actually impossible to solve... Let's avoid it in the above situation. [1] https://github.com/odoo/enterprise/commit/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e [2] https://github.com/odoo/enterprise/commit/8cd5c9322bef7db49a90d4aef844dd0ba267058e Forward-Port-Of: odoo/enterprise#127314 Forward-Port-Of: odoo/enterprise#126364
A test was corrected so it also considers archived call activity records before deleting a related activity type. This prevents false test failures caused by demo data and improves reliability of the enterprise test suite without changing user-facing behavior.
Original PR description
test_create_call_activity attempts to delete any 'phonecall' activity types. This is so it can test the functionality of create_call_activity when there is no existing 'phonecall' activity type. However, demo data inside voip creates an archived activity with the type mail_activity_data_call. https://github.com/odoo/enterprise/blob/cc4456ac16aeee59830db08505a27877e149f3a7/voip/demo/voip_call.xml#L4-L13 When searching for phonecall_activities the test only gets active activities. We need to alter this to fetch all. Otherwise, the test will then try to delete the activity type when there are still records using the type. opw-6443475 runbot-242850
This fix updates an automated payroll pay run test so it counts only rows containing actual data, rather than placeholder rows added by the interface. This prevents false test failures and helps keep payroll quality checks reliable without changing user-facing payroll behavior.
Original PR description
Issue: The original trigger was searching for 2 table rows, when it enforces 4 with added empty rows. The [getEmptyRowIds](https://github.com/odoo/odoo/blob/33dc65bbac165f33030ad3da59ea785b69482b3f/addons/web/static/src/views/list/list_renderer.js#L1104-L1110) enforces max of 4 rows. The condtional (one up the stack) !ctx["this"].props.list.isGrouped&&!ctx["this"].props.noContentHelp returns true, and it adds empty rows. Fix: Since this enforces 4 rows with empty rows we check the rows that have data instead of how many rows are added. Because anything less than or equal to 4 but greater than 0 records it will always be 4 table rows while the conditional above returns true . opw-6349513 <img width="1337" height="674" alt="Screenshot 2026-07-15 at 4 53 51 PM" src="https://github.com/user-attachments/assets/76f53521-ec9f-4807-9083-95533904b5de" />
VoIP contact search and keypad suggestions now recognize phone numbers even when country codes or formatting differ. This helps users find the right contact more consistently when placing calls, reducing failed or missing suggestions.
Original PR description
Before this fix, the keypad's callee suggestions only matched the search term against the raw `phone` field of contacts. When the user input was automatically prefixed with a country code (e.g. +86), the match could fail if the stored phone number lacked the international prefix. Now `phone_sanitized` is also sent to the frontend via the Store, and the callee suggestion matching falls back to the E164 sanitized number when the raw phone field does not match. Task-6290760 compr https://github.com/odoo/odoo/pull/278018 Forward-Port-Of: odoo/enterprise#127437 Forward-Port-Of: odoo/enterprise#124797
Tasks created from project templates will now ignore archived users when assigning people through project roles. This prevents inactive employees or former users from being added to new customer project work, keeping task ownership accurate.
Original PR description
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created…
Steps to reproduce:
-------------------------------------------------
1. Install the `sale_project` module
2. Create a test user with Project User rights
3. Create a Project Role with the Created User as a Team Member
4. Create a Template Project as follows:
* Add one task to the template project
* Add the created Project role to the Task
5. Create a Service Type Product with:
* Create on order: Project
* Project Template: Created Template
6. Archive the Created User
7. Create and Confirm the Sale Order with the Created Product
Observation:
-------------------------------------------------
The generated task is assigned to the archived user, although the archived user is no longer part of the Project Role.
Issue:
-------------------------------------------------
While creating Project and Tasks from template, the context disable active record filtering (e.g., `active_test=False`), causing the assignment logic to fetch both active and inactive/archived users linked to the role. https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/odoo/orm/models.py#L4868
After that, during the `copy_data` method, It takes all the users from the roles without checking weather user is active or not
https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/addons/project/models/project_task.py#L890-L904
And even if we pass only Active users from this method, on moving further, it reassigns the users from roles without checking the Active field of the user
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L501-L503
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L544-L553
Due to this, the Archived User is also assigned to the tasks from the project roles
Solution:
-------------------------------------------------
Apply a `filtered('active')` check directly on the project role's users `(role.user_ids)` within the core task-copying logic in both `project` and `project_enterprise` modules. This ensures archived users are universally excluded from task assignments during template copying, regardless of what triggers the template instantiation.
Related Community PR: https://github.com/odoo/odoo/pull/274426
opw-6350841
Forward-Port-Of: odoo/enterprise#125637HR Gantt views now apply search filters consistently when deciding which employees to show, including employees without leave or attendance records. The views also standardize employee-based grouping to avoid confusing or unsupported results from other grouping options.
Original PR description
`user_domain` (in the context) is supposed to contain the domain defined by the user (in the search bar). It was not the case for all gantt views, and produced inconsistent results, as that domain is…
`user_domain` (in the context) is supposed to contain the domain defined by the user (in the search bar). It was not the case for all gantt views, and produced inconsistent results, as that domain is used to know when to display the employees without leaves/attendances. The PR fixes that issue by creating the `HrGanttModel` class, that takes care of defining the `user_domain` correctly. This class also disables the *Group By* menu, and defaults to grouping by employees. This was decided for the following reasons: - All gantt views inheriting this class would group by employee - Grouping by other fields would already not work in some cases - It's very difficult to add employees without records if the gantt is grouped by multiple fields at once Affected `_get_gantt_data()` functions have been adapted accordingly The access models (the ones defined in the `access.csv` files) are implied, and thus never passed as a parameter to `get_gantt_data()`, so we need to also manually add them when converting the model to the related field used in `groupby` task-5502544
This fix prevents access errors when HR users view salary offers by ensuring required payroll-related values are calculated with the right permissions. It also updates the salary configurator test flow to reflect realistic HR user access instead of relying on administrator rights.
Original PR description
A field displayed inside the offer should have been computed with sudo as it accesses some payroll field to compute. Also, the salary configurator tour has been adapted to use a HR user instead of an admin
Fixed an error that could occur when users turned the No Follow-Up option on or off for invoices with multiple payment installments. This prevents Follow-Up Reports from crashing when some installments have already been paid and reconciled.
Original PR description
Steps to Reproduce: 1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments. 2. Create a Customer Invoice with this Payment Term. 3. Post the invoice.…
Steps to Reproduce:
1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments.
2. Create a Customer Invoice with this Payment Term.
3. Post the invoice.
4. Register a payment and fully reconcile one of the installments.
5. Navigate to the customer's Follow-Up Report (Accounting > Reporting > Partner Ledger > Report: Follow-Up Report).
6. Navigate to remaining open installment/account move line for that invoice.
7. Turn On or Off the No Follow-Up toggle for the invoice.
An error occurs when enabling or disabling the No Follow-Up toggle.
Issue:
Enabling or disabling the No Follow-Up toggle on a remaining open installment in the Follow-Up Report raises a server error when the invoice contains multiple installments and one or more installments are already fully reconciled.
Root Cause:
The Follow-Up Report only loads and sends non-fully reconciled account move lines from the JavaScript side through all_line_ids. In action_toggle_no_followup(), when the selected line belongs to an invoice, the code retrieves all receivable/payable lines of the invoice, including fully reconciled installments:
```
move.line_ids.filtered(
lambda line: line.account_type in ('asset_receivable', 'liability_payable'),
)
```
The method then attempts to map every receivable/payable line to a report line ID using aml_id_to_line_id. Since fully reconciled installments are not present in all_line_ids, they are missing from the mapping dictionary, causing a KeyError when accessing:
`aml_id_to_line_id[line.id]
`
Fix:
Restricted the impacted lines to those present in the report by adding a check that the account move line exists in aml_id_to_line_id before performing the mapping:
```
lambda line: line.account_type in ('asset_receivable', 'liability_payable')
and line.id in aml_id_to_line_id
```
opw-6245448
Forward-Port-Of: odoo/enterprise#126785
Forward-Port-Of: odoo/enterprise#126156The Attendance Gantt view now includes employees without contracts when they have attendance records in the selected period. This prevents valid attendance entries from being hidden in the default grouped view, giving managers a more complete schedule overview.
Original PR description
Issue: The default Employee grouped Attendance Gantt hides an attendance when its employee has no contract. The record remains accessible from the list view or after removing the default grouping.…
Issue: The default Employee grouped Attendance Gantt hides an attendance when its employee has no contract. The record remains accessible from the list view or after removing the default grouping. Steps to reproduce: - Create an attendance-based employee without a contract. - Create an attendance for the employee. - Open Attendances with the default Date and Employee groupings. Cause: In https://github.com/odoo/enterprise/blob/c8c91758b148cced1b7b5c59479fba7aaea033c1/hr_attendance_gantt/models/hr_attendance.py#L151-L164 `_get_gantt_data_group_by_employee()` builds `employees_on_page` using only employees whose versions overlap the displayed period. It then adds those employee IDs to `attendances_domain`. A contractless employee is therefore excluded before its otherwise valid attendance is fetched. Solution: Build the employee visibility domain from employees having either an overlapping contract or an attendance matching the effective Gantt domain. Apply the same domain to the employee query and group count so contractless employees with visible attendances are included while contractless employees without attendances remain hidden. opw-6416111
Shifts for employees with flexible schedules are now counted consistently in planning and timesheet reports, even when specific start and end hours are not set. This fixes a reporting gap so managers see the same planned work across schedule views and analysis reports.
Original PR description
## Behavior Before the PR When an employee did not have explicit `hours_from` and `hours_to` values defined, their shift was in the **Schedule by X** pivot view but was not included in the **Planning…
## Behavior Before the PR When an employee did not have explicit `hours_from` and `hours_to` values defined, their shift was in the **Schedule by X** pivot view but was not included in the **Planning / Timesheets Analysis** report. ## Steps to Reproduce 1. Create an employee with a Flexible Working Schedule in the Employee form, or configure working hours where both `Hour from` and `Hour to` are left unset. 2. Add a shift for this employee linked to a project and a task. 3. Publish the shift. 4. Navigate to **Planning → Schedule → By Project**, switch to the pivot view, and observe that the shift created in step 2 appears and is counted. 5. Navigate to **Planning → Reporting → Planning / Timesheets Analysis**, switch to the pivot view, and observe that the same shift does not appear. ## Behavior After the PR When an employee does not have explicit `hours_from` and `hours_to` values, their shift is now considered valid in both the **Schedule by X** views and the **Planning / Timesheets Analysis** report. ## Additional Notes - In earlier versions of Odoo, the `Work From` and `Work To` fields were mandatory. With a change to flexible working schedules and the option to define only the total number of hours per day, these fields may now be left empty. This change exposed the underlying issue addressed by this fix. task-[5969788](https://www.odoo.com/odoo/project/4105/tasks/5969788) Forward-Port-Of: odoo/enterprise#110606
Product images fetched through the Barcode Lookup service are now converted into the right format before being saved. This ensures newly created products display their images correctly, reducing manual cleanup for users.
Original PR description
Issue before this commit: ========================= When creating a product by adding a barcode using the Barcode Lookup service, the product image was fetched properly but was not displayed in the…
Issue before this commit: ========================= When creating a product by adding a barcode using the Barcode Lookup service, the product image was fetched properly but was not displayed in the UI. Steps to Reproduce: ========================= - Install the stock module. - Enable the Stock Barcode Database. - Add a valid API key for the Barcode Database. - Create a product by adding a barcode available in the Barcode Lookup API. - Notice that the product image is not displayed. Cause of the issue: ========================= This issue was introduced by this [PR](https://github.com/odoo/odoo/pull/244421), which improved the behaviour of **fields.Binary**. As a result, the image returned by the Barcode Lookup API was not converted to the expected binary format, preventing it from being displayed in the UI. With This Commit: ========================= With this commit, convert the fetched image to the expected binary format before assigning it to the product, ensuring that it is displayed correctly in the UI. opw-6434478
Users can now open Bank Matching from the working file check without encountering an error when no journal is preselected. This prevents a crash caused by looking up missing journal information and keeps the reconciliation flow accessible.
Original PR description
When accessing the reconciliation widget from the working file check, there is no journal to be selected, hence no journal in the context. This was tracebacking since we were trying to send a read query to the server with an undefined id. To reproduce: * create a bank statement line without reconciling * set up the return on the misc journal * open the return, then "Bank Matching" Forward-Port-Of: odoo/enterprise#127421
This fixes an issue in the Swiss payroll integration where today's date could be calculated without the right record context. It helps prevent errors during payroll-related transmissions and keeps processing reliable.
Original PR description
Fix https://github.com/odoo/enterprise/pull/126718 Forward-Port-Of: odoo/enterprise#127535
The Timesheets Assistant now ignores the employee's own email address when matching Gmail messages to customers. This prevents unrelated tasks or projects from being suggested simply because the current user appears as a recipient, improving the relevance of timesheet suggestions.
Original PR description
Before this commit, the Timesheets Assistant resolved every address found in a read or composed email to a partner, then matched the event to a task or project having that partner as its customer. The current user is a recipient of every email they receive, so their own address is present in the "To" or "Cc" fields of every `reading_email` event. As a result, any task whose customer was the current user could be suggested for those emails. This commit excludes the current user's partner from that lookup. task-6438374 Forward-Port-Of: odoo/enterprise#127422 Forward-Port-Of: odoo/enterprise#126448
Root cause: Trackings are written into the message body, so datetime values are formatted server side by format_datetime in _create_mail_tracking_values. Since https://github.com/odoo/odoo/commit/d3546b7ef394797d9c9fae5b803425a14a3afb83 the tz argument receives self.env.tz, which is a timezone object, while format_datetime expects a timezone name string. format_datetime tries to build a ZoneInfo from that object, this raises a TypeError that is caught silently, and the value falls back to UTC. E
Original PR description
Root cause: Trackings are written into the message body, so datetime values are formatted server side by format_datetime in _create_mail_tracking_values. Since…
Root cause: Trackings are written into the message body, so datetime values are formatted server side by format_datetime in _create_mail_tracking_values. Since https://github.com/odoo/odoo/commit/d3546b7ef394797d9c9fae5b803425a14a3afb83 the tz argument receives self.env.tz, which is a timezone object, while format_datetime expects a timezone name string. format_datetime tries to build a ZoneInfo from that object, this raises a TypeError that is caught silently, and the value falls back to UTC. Every tracked datetime change then shows UTC times in the chatter no matter the user timezone. Fix: Pass str(self.env.tz) in _create_mail_tracking_values in mail_track_mixin.py. str() on the timezone object gives its name, which is what format_datetime expects. These two lines are the only place passing env.tz to format_datetime, so the call site is fixed rather than format_datetime itself, which is used all over the codebase. In test_mail_tracking.py the tracking values creation test writes as the admin user, whose timezone is set to Asia/Kolkata in the test setup, and asserts as the employee user that has no timezone. The tracked datetime is now rendered in the admin timezone, so the employee gets the same timezone and the expected values are computed in the timezone the message was rendered with. Steps to reproduce: 1. Set your user's Timezone to Europe/Madrid in Settings > Users & Companies > Users 2. Go to Attendances > Management and open an attendance record 3. Edit the Check In time to 08:02 AM and save 4. Look at the tracking message in the chatter => the chatter shows 06:02 AM, the raw UTC value, instead of 08:02 AM Ticket [link](https://www.odoo.com/odoo/project/49/tasks/6374591) opw-6374591
Since commit ff57c836438b1fec32527db39270b02c68504955 the `website` module cannot be installed anymore. This is fixed in this commit. Reproduce: 1. Create a new empty db 2. Set language to German 3. Install Website 4. The install gets stuck and you can't access the db anymore. task-None
Original PR description
Since commit ff57c836438b1fec32527db39270b02c68504955 the `website` module cannot be installed anymore. This is fixed in this commit. Reproduce: 1. Create a new empty db 2. Set language to German 3. Install Website 4. The install gets stuck and you can't access the db anymore. task-None
Issue: Currently, the new mail tracking formating relies on CSS to separate the field name, old value, and new value. As a result, the tracking message is not rendered correctly in gmail inbox. Commit: in this commit formats the tracking message when sending emails instead of relying on CSS, ensuring it is displayed correctly in gmail. <img width="472" height="122" alt="image" src="https://github.com/user-attachments/assets/bb6cd96d-adad-4134-a1d0-68217947d91d" /> task-526061
Original PR description
Issue: Currently, the new mail tracking formating relies on CSS to separate the field name, old value, and new value. As a result, the tracking message is not rendered correctly in gmail inbox. Commit: in this commit formats the tracking message when sending emails instead of relying on CSS, ensuring it is displayed correctly in gmail. <img width="472" height="122" alt="image" src="https://github.com/user-attachments/assets/bb6cd96d-adad-4134-a1d0-68217947d91d" /> task-5260614
Issue: ------- After the fix: https://github.com/odoo/odoo/commit/f1557211d9e7f83761bb36e4800e4c2f62b234c5 we can't create a child menu for a mega menu or a menu can't be a mega menu when there's an existing child menu except the case of top level menu i.e; (url: /default-main-menu) and that menu will have no parent_id obviously... Now, as per the above pr conditions the top level can be set as mega menu since it has no parent id. And in version 17.3 in the pr https://github.com/odoo/odoo/
Original PR description
Issue: ------- After the fix: https://github.com/odoo/odoo/commit/f1557211d9e7f83761bb36e4800e4c2f62b234c5 we can't create a child menu for a mega menu or a menu can't be a mega menu when there's an…
Issue:
-------
After the fix:
https://github.com/odoo/odoo/commit/f1557211d9e7f83761bb36e4800e4c2f62b234c5 we can't create a child menu for a mega menu or a menu can't be a mega menu when there's an existing child menu except the case of top level menu i.e; (url: /default-main-menu) and that menu will have no parent_id obviously...
Now, as per the above pr conditions the top level can be set as mega menu since it has no parent id. And in version 17.3 in the pr https://github.com/odoo/odoo/commit/47af533e9f5f721b63570d3b301951f3855384a1 a 'Jobs' menu is being created and its parent_id refers to that top level menu which we have set as mega menu. And when the records gets validated during migration the database will get blocked.
Solution:
-----------
Restrict the user by throwing the same user error, when checking/selecting the top level menu as mega menu since it has existing child menus.
Step to reproduce:
-----------------------
1. Create a database in version 17.0 with 'website_hr_recruitment' installed.
2. Go to website menus, set a top level menu(/default-main-menu) as mega menu.
3. Migrate the database to version 18.0 or more.
Traceback:
```
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 5297, in _create
records._validate_fields(name for data in data_list for name in data['stored'])
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 1636, in _validate_fields
check(self)
File "/home/odoo/src/odoo/18.0/addons/website/models/website_menu.py", line 95, in _validate_parent_menu
raise UserError(_("A mega menu cannot have a parent or child menu."))
odoo.exceptions.UserError: A mega menu cannot have a parent or child menu.
File "/home/odoo/src/odoo/18.0/odoo/tools/convert.py", line 603, in _tag_root
raise ParseError('while parsing %s:%s, somewhere inside\n%s' % (
odoo.tools.convert.ParseError: while parsing /home/odoo/src/odoo/18.0/addons/website_hr_recruitment/data/config_data.xml:13, somewhere inside
<record id="website_menu_jobs" model="website.menu">
<field name="name">Jobs</field>
<field name="url">/jobs</field>
<field name="parent_id" ref="website.main_menu"/>
<field name="sequence">59</field>
</record>
```
Ref Images:
Before Fix:
<img width="1598" height="599" alt="image" src="https://github.com/user-attachments/assets/ef719945-a11b-4134-97f8-4b583c4ea6bc" />
After Fix:
<img width="1582" height="633" alt="image" src="https://github.com/user-attachments/assets/da326e45-0de8-4d42-ad47-845bfaedc84e" />
OPW - 6094298
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#263025The test scrolls to the top of the thread to trigger the `IntersectionObserver` on the `load-older`. In a loaded runbot the IO callback can arrive after `waitForSteps` times out, leaving the step list empty. We need to wait however long the browser takes to deliver the callback. Runbot: https://runbot.odoo.com/odoo/runbot.build.error/944560
Original PR description
The test scrolls to the top of the thread to trigger the `IntersectionObserver` on the `load-older`. In a loaded runbot the IO callback can arrive after `waitForSteps` times out, leaving the step list empty. We need to wait however long the browser takes to deliver the callback. Runbot: https://runbot.odoo.com/odoo/runbot.build.error/944560
### 1. Prevent tour failure by waiting on the correct loading class Before this PR, the tour introduced in commit [1] and modified in commit [2] could fail non-deterministically because it waited for `o_we_ui_loading` to disappear. However, this class was added with a delay in `operation.js`, allowing the next tour step to run before the loader was shown. After this commit, the tour waits for `o_loading_screen`, which is added immediately and remains visible until the operation finishes. T
Original PR description
### 1. Prevent tour failure by waiting on the correct loading class Before this PR, the tour introduced in commit [1] and modified in commit [2] could fail non-deterministically because it waited for…
### 1. Prevent tour failure by waiting on the correct loading class Before this PR, the tour introduced in commit [1] and modified in commit [2] could fail non-deterministically because it waited for `o_we_ui_loading` to disappear. However, this class was added with a delay in `operation.js`, allowing the next tour step to run before the loader was shown. After this commit, the tour waits for `o_loading_screen`, which is added immediately and remains visible until the operation finishes. This ensures that the tour waits correctly before proceeding. [1]: https://github.com/odoo/odoo/commit/091b8dee407fe30a115d4bb2e96d4d [2]: https://github.com/odoo/odoo/commit/544a03775119021442d66486c24711 **runbot:** [941508](https://runbot.odoo.com/odoo/error/941508) --- ### 2. Prevent tour failure by clicking the "Close" button instead of pressing "Escape" Before this PR, the tour step introduced in commit [1], which pressed the <kbd>Escape</kbd> key to close the Insert Snippet dialog, could fail non-deterministically with the error: > It is not allowed to do action on an element that's below a modal. After this PR, instead of pressing <kbd>Escape</kbd>, the tour clicks the **Close** (`X`) button to close the dialog. This is a more reliable way to close the dialog and prevents the non-deterministic failure of the sync color shape tour. [1]: https://github.com/odoo/odoo/commit/544a03775119021442d66486c24711d **runbot:** [944543](https://runbot.odoo.com/odoo/error/944543) Forward-Port-Of: odoo/odoo#279395 Forward-Port-Of: odoo/odoo#278743
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/25f760e34c [REL] 19.3.15 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/a220132754 [FIX] chart: geoChart uses same d3 projection for main and full screen chart [Task: 6395379](https://www.odoo.com/odoo/2328/tasks/6395379) https://github.com/odoo/o-spreadsheet/commit/9b6359f387 [FIX] carousel: crash on multiuser when deleting chart [Task: 6445004](https://www.odoo.com/
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/25f760e34c [REL] 19.3.15 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/25f760e34c [REL] 19.3.15 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/a220132754 [FIX] chart: geoChart uses same d3 projection for main and full screen chart [Task: 6395379](https://www.odoo.com/odoo/2328/tasks/6395379) https://github.com/odoo/o-spreadsheet/commit/9b6359f387 [FIX] carousel: crash on multiuser when deleting chart [Task: 6445004](https://www.odoo.com/odoo/2328/tasks/6445004) https://github.com/odoo/o-spreadsheet/commit/023d6442a6 [IMP] composer: writing an number value should override date formats [Task: 6353692](https://www.odoo.com/odoo/2328/tasks/6353692) https://github.com/odoo/o-spreadsheet/commit/e3605d9bec [PERF] vectorization: specialize formula call for common arities [Task: 6222157](https://www.odoo.com/odoo/2328/tasks/6222157) https://github.com/odoo/o-spreadsheet/commit/b8a6643f99 [PERF] vectorization: inline generateMatrix [Task: 6222157](https://www.odoo.com/odoo/2328/tasks/6222157) https://github.com/odoo/o-spreadsheet/commit/f5b8a5e0eb [PERF] vectorization: skip non-vectorized args in inner loop [Task: 6222157](https://www.odoo.com/odoo/2328/tasks/6222157) https://github.com/odoo/o-spreadsheet/commit/25d49f2b08 [PERF] vectorization: hoist argDefinitions out of vectorized inner loop [Task: 6222157](https://www.odoo.com/odoo/2328/tasks/6222157) https://github.com/odoo/o-spreadsheet/commit/6c4c970593 [PERF] vectorization: hoist per-arg getter resolution out of inner loop [Task: 6222157](https://www.odoo.com/odoo/2328/tasks/6222157) https://github.com/odoo/o-spreadsheet/commit/ef7c3a0e38 [PERF] vectorization: reuse args buffer across cells [Task: 6222157](https://www.odoo.com/odoo/2328/tasks/6222157) https://github.com/odoo/o-spreadsheet/commit/a162eb424b [FIX] figures: fix movement issue with arrow keys [Task: 6374091](https://www.odoo.com/odoo/2328/tasks/6374091) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
**Steps to reproduce:** 1. Install sale module 2. Log in as demo user 3. Open a product form 4. Hover over the product image **Issue:** - The pencil (Edit) and trash (Clear) buttons appear on the product image for users who have no write access to `product.template` - Clicking the pencil icon opens the media dialog, but attempting to save the new image throws an access error: *"You are not allowed to modify 'Product' (product.template) records."* - The buttons should not be visible whe
Original PR description
**Steps to reproduce:** 1. Install sale module 2. Log in as demo user 3. Open a product form 4. Hover over the product image **Issue:** - The pencil (Edit) and trash (Clear) buttons appear on the product image for users who have no write access to `product.template` - Clicking the pencil icon opens the media dialog, but attempting to save the new image throws an access error: *"You are not allowed to modify 'Product' (product.template) records."* - The buttons should not be visible when the field is readonly **Why this happens:** - Commit 63c0b17eca05c99507df2dcd3c43ae512d3fd7b0 introduced the `ImageFieldWithMediaDialog` template - This template inherits from `web.ImageField` and replaces the inner uploader `<div>` which is missing the readonly guard opw-6403982
Clearing the cache in the `write` of `ir.module` caused issues when installing `website`. Having it in `create` was enough for the original use case that prompted the PR. So we remove the `write` in this commit. Reproduce: 1. Create a new empty db 2. Set language to German 3. Install Website 4. The install gets stuck and you can't access the db anymore. task-None Forward-Port-Of: odoo/odoo#281465
Original PR description
Clearing the cache in the `write` of `ir.module` caused issues when installing `website`. Having it in `create` was enough for the original use case that prompted the PR. So we remove the `write` in this commit. Reproduce: 1. Create a new empty db 2. Set language to German 3. Install Website 4. The install gets stuck and you can't access the db anymore. task-None Forward-Port-Of: odoo/odoo#281465
Currently, when the user receives a product with an expiry date whose removal date is before the current date, creating a backorder for the corresponding subcontracting operation causes the system to crash. ## Steps to produce: - Install Manufacturing - Go to settings and enable: - Subcontracting - Lots & Serial Numbers - Expiration dates - Create a product named Vegetable Salad and set Tracking to By Unique Serial Number. - In the inventory section, enable Expiration date and
Original PR description
Currently, when the user receives a product with an expiry date whose removal date is before the current date, creating a backorder for the corresponding subcontracting operation causes the system to…
Currently, when the user receives a product with an expiry date whose removal date is before the current date, creating a backorder for the corresponding subcontracting operation causes the system to crash. ## Steps to produce: - Install Manufacturing - Go to settings and enable: - Subcontracting - Lots & Serial Numbers - Expiration dates - Create a product named Vegetable Salad and set Tracking to By Unique Serial Number. - In the inventory section, enable Expiration date and configure: - Expiration Date: 10 days after receipt - Removal Date: 8 days before expiration date - Create a BoM for Vegetable salad - BoM Type: Subcontracting - Subcontractor: Chef - Component: Vegetable - Create a receipt for 2 units of Vegetable Salad from Chef - Mark it as Todo > Details > Assign serial to both lines - Set the Removal Date of the second serial number to a date earlier than today, then Save and Validate the receipt. - In the expiry warning wizard, click Proceed Except Expired and create backorder ## Observed Behavior: Creating a backorder after proceeding with the expiry warning wizard fails with the following error: `ValueError: Expected singleton: stock.move(12, 13)` ## Root cause: This issue occurs because, when the user confirms the backorder, the current picking is validated at [1]. This calls `_action_done` at [2], which in turn calls `_action_done` on the todo moves at [3]. As part of this process, `todo_moves` creates backorders at [4] and then confirms those backorder moves at [5]. During confirmation, the subcontracting manufacturing order (MO) with a serial number that has expired is split at [6], creating a new MO. This new MO then creates two backorder moves at [7]: one for the finished product and one for the component. The problem arises because `default_lot_ids` are added to the context at [8] for the expiry wizard. That same context is unintentionally propagated to the backorder wizard during backorder confirmation. As a result, the ORM assigns those lot IDs to both the component and finished product moves. This triggers the `_set_lot_ids` inverse method, which calls `_prepare_move_line_vals` at [9]. However, `_prepare_move_line_vals` is an `ensure_one` method, while `self` now contains two moves (the component move and the finished product move). Because the method expects a single record but receives two, it raises a singleton error. [1]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/wizard/stock_backorder_confirmation.py#L64 [2]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_picking.py#L1428-L1429 [3]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_picking.py#L1273 [4]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_move.py#L2267-L2268 [5]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_move.py#L2332 [6]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/mrp_subcontracting/models/stock_picking.py#L158 [7]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/mrp/models/mrp_production.py#L2055-L2075 [8]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/product_expiry/models/stock_picking.py#L33-L38 [9]: https://github.com/odoo/odoo/blob/c744f123ae4c7a4969e9885ee1efa99be7775340/addons/stock/models/stock_move.py#L679 ## Solution: Sanitize the context before opening the backorder wizard so that `default_lot_ids` from the expiry wizard are not propagated. This prevents the ORM from incorrectly assigning lot IDs to the component and finished product backorder moves, avoiding the singleton error in `_prepare_move_line_vals`. With this change, users can successfully create backorder pickings and subcontracting manufacturing orders for products that are being removed without encountering any errors opw-6390571 Forward-Port-Of: odoo/odoo#278262
Steps to reproduce: - Set a Saudi company with a long legal name (e.g. "Golden Oasis Trading and Contracting Company Limited") - Make a POS order and look at the receipt QR code Issue: The QR code is drawn visibly smaller and denser than for a company with a short name, even though the image it sits in is the same 150px box: 90px of code at a 2px module pitch, against 111px at 3px. Cause: The ZATCA payload embeds the seller name, so a longer name needs a higher QR version, i.e. more mo
Original PR description
Steps to reproduce: - Set a Saudi company with a long legal name (e.g. "Golden Oasis Trading and Contracting Company Limited") - Make a POS order and look at the receipt QR code Issue: The QR code is…
Steps to reproduce: - Set a Saudi company with a long legal name (e.g. "Golden Oasis Trading and Contracting Company Limited") - Make a POS order and look at the receipt QR code Issue: The QR code is drawn visibly smaller and denser than for a company with a short name, even though the image it sits in is the same 150px box: 90px of code at a 2px module pitch, against 111px at 3px. Cause: The ZATCA payload embeds the seller name, so a longer name needs a higher QR version, i.e. more modules. ZXing's BrowserQRCodeSvgWriter draws each module at a whole number of pixels of the canvas it is given (multiple = floor(canvas / (modules + 8))), so asking it for a fixed 150x150 or 200x200 canvas leaves a leftover margin that varies with the module count. The code shrinks as soon as the module count crosses a multiple of the canvas size. opw-6399878 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281036 Forward-Port-Of: odoo/odoo#280000
With demo data, the default event TZ was not UTC. Now the test event tz is set to UTC and the test works with or without demo data. Runbot-945450 Task-6429727 Forward-Port-Of: odoo/odoo#281445
Original PR description
With demo data, the default event TZ was not UTC. Now the test event tz is set to UTC and the test works with or without demo data. Runbot-945450 Task-6429727 Forward-Port-Of: odoo/odoo#281445
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the l10n_fr_hr_holidays module. - Create a French company and set it as the active company. - Log in as a user whose working schedule is Flexible (i.e., the employee's Working Hours field is left blank). - Ensure the company's Time Off Type matches the leave type that the employee is requesting. - Set a Resource
Original PR description
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the…
**Issue:** Flexible employees in French companies cannot request the reference paid time off type, even when they have a sufficient allocation. **Steps to reproduce:** - Install the l10n_fr_hr_holidays module. - Create a French company and set it as the active company. - Log in as a user whose working schedule is Flexible (i.e., the employee's Working Hours field is left blank). - Ensure the company's Time Off Type matches the leave type that the employee is requesting. - Set a Resource Calendar on the company (this is required and must differ from the employee's flexible working schedule). - Attempt to create a Time Off request for the employee. **Cause:** https://github.com/odoo/odoo/blob/5e865aeec854ca012dc5537f36b2e626ee39cf0b/addons/l10n_fr_hr_holidays/models/hr_leave.py#L17-L27 `_l10n_fr_leave_applies()` considers an empty employee calendar different from the company calendar. This sends flexible leaves to `_get_fr_date_from_to()`, which requires attendance rows and rejects the request. **Solution:** We need to require a concrete employee calendar before applying the French part-time calendar adjustment, leaving flexible employees to the core flexible-duration computation. opw-6417220 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280288
Description ----------------- This fix ensures the allocation button appears consistently and that the parent-child relationships link correctly. Issue -------- The allocation smart button failed to appear when needed. Additionally, even when visible, creating an allocation did not properly generate the smartbuttons linking parent and child manufacturing orders together. Use Case ------------- 1. Create and confirm a manufacturing order that has a semi finished product 2. Cancel th
Original PR description
Description ----------------- This fix ensures the allocation button appears consistently and that the parent-child relationships link correctly. Issue -------- The allocation smart button failed to appear when needed. Additionally, even when visible, creating an allocation did not properly generate the smartbuttons linking parent and child manufacturing orders together. Use Case ------------- 1. Create and confirm a manufacturing order that has a semi finished product 2. Cancel the MO for the semi finished product 3. Create a new MO for the semi finished product manually 4. Go to the allocation smartbutton of the new MO and link the new MO to the final product **Task-id**: 6280980 Forward-Port-Of: odoo/odoo#269221
Steps to reproduce: - Go to Edit mode - Go to the Theme tab - Open a color preset to customize it - Change the "Headings" color => The color of "Title" did not change in the preview By changing the tag from "h3" to "h1", the color in the preview is now correctly updated in the theme tab. "fs-4" is added to keep the previous size. task-6299680 Forward-Port-Of: odoo/odoo#279324 Forward-Port-Of: odoo/odoo#278056
Original PR description
Steps to reproduce: - Go to Edit mode - Go to the Theme tab - Open a color preset to customize it - Change the "Headings" color => The color of "Title" did not change in the preview By changing the tag from "h3" to "h1", the color in the preview is now correctly updated in the theme tab. "fs-4" is added to keep the previous size. task-6299680 Forward-Port-Of: odoo/odoo#279324 Forward-Port-Of: odoo/odoo#278056
**Steps to reproduce:** - Install the `accountant` module. - Go to Settings and make sure `Review data` is disabled. - Open the `Mitchell Admin` user record and set the `Accounting` access right to `Invoicing & Banks` or `Invoicing`. - Create and confirm a new invoice. - Click `Reset to Draft`. **Error:** `AccessError: You don't have the access rights to perform this action.` **Expected Behavior:** When `Review data` is disabled, users should be able to reset invoices to draft
Original PR description
**Steps to reproduce:** - Install the `accountant` module. - Go to Settings and make sure `Review data` is disabled. - Open the `Mitchell Admin` user record and set the `Accounting` access right to `Invoicing & Banks` or `Invoicing`. - Create and confirm a new invoice. - Click `Reset to Draft`. **Error:** `AccessError: You don't have the access rights to perform this action.` **Expected Behavior:** When `Review data` is disabled, users should be able to reset invoices to draft. **Root Cause:** At [1], the review state access check is always enforced when resetting an invoice to draft, even when the Review data feature is disabled. As a result, users cannot reset their own invoices to draft. **Fix:** This commit ensures users can reset their own invoices to draft when Review Data is disabled. [1]: https://github.com/odoo/odoo/blob/0bc06aa88cbf83345ca7d266df4822430d691a5b/addons/account/models/account_move.py#L3956-L3957 opw-6409235
Before this commit: --- The company logo is displayed above the background on the customer display. After this commit: --- The company logo is displayed only when there is no background or QR code to display. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Before this commit: --- The company logo is displayed above the background on the customer display. After this commit: --- The company logo is displayed only when there is no background or QR code to display. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
We use to have a chatter response for the IAP code "registrations_needed" that gives in plain text the sms account token. However this IAP code doesn't exist anymore. Task-6425300 Forward-Port-Of: odoo/odoo#281088 Forward-Port-Of: odoo/odoo#280015
Original PR description
We use to have a chatter response for the IAP code "registrations_needed" that gives in plain text the sms account token. However this IAP code doesn't exist anymore. Task-6425300 Forward-Port-Of: odoo/odoo#281088 Forward-Port-Of: odoo/odoo#280015
Steps to Reproduce: ------------------------ - Install the Point of Sale module & create an order with a customer (partner). - Scan the QR code on the receipt to retrieve the invoice. Issue: ------- When clicking `Get My Invoice`, the invoice was not being generated. Cause: --------- - The correct partner was not being set. POS customer scanning the QR code is not logged into Odoo, so no partner is associated with the request. We were incorrectly using the logged-in user’s partner,
Original PR description
Steps to Reproduce: ------------------------ - Install the Point of Sale module & create an order with a customer (partner). - Scan the QR code on the receipt to retrieve the invoice. Issue: -------…
Steps to Reproduce: ------------------------ - Install the Point of Sale module & create an order with a customer (partner). - Scan the QR code on the receipt to retrieve the invoice. Issue: ------- When clicking `Get My Invoice`, the invoice was not being generated. Cause: --------- - The correct partner was not being set. POS customer scanning the QR code is not logged into Odoo, so no partner is associated with the request. We were incorrectly using the logged-in user’s partner, which resulted in an empty partner and therefore an empty VAT value. - The customer's country was also incorrect because the partner’s country was fetched but then overwritten by the order’s country due to improper value assignment. Fix: ---- - In most POS scenarios, the customer associated with the order is the one requesting the invoice. Therefore, if no logged-in user is found, we now correctly use the order’s partner to retrieve VAT and other required information. - The partner's country was corrected by ensuring the values are assigned in the proper order and no longer overridden incorrectly. task: 5406951 Forward-Port-Of: odoo/odoo#239811
#### Description of the issue this PR addresses: - The predicate loop kept climbing ancestors above the editable root when no match was found inside it. The later containment check would discard such a match anyway, so the predicate should never run outside the editable in the first place. - This ran the predicate on at least 14 unnecessary ancestors up to `<html>`, costly if the predicate is expensive. Stop the search at the editable boundary instead. - `movenode_plugin` calls closestElement
Original PR description
#### Description of the issue this PR addresses: - The predicate loop kept climbing ancestors above the editable root when no match was found inside it. The later containment check would discard such a match anyway, so the predicate should never run outside the editable in the first place. - This ran the predicate on at least 14 unnecessary ancestors up to `<html>`, costly if the predicate is expensive. Stop the search at the editable boundary instead. - `movenode_plugin` calls closestElement on every mousemove, so its predicate was needlessly re-evaluated on those 14+ ancestors on every single mouse move. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280011
**Steps to Reproduce:** 1. Send a message to Marc demo with Mitchell admin or vice-versa, read the message from reciever's side. 2. Click on seen-by indicator from sender's side, make sure the dialog appears and then Press `'ESC'`. 3. Chat window closes whereas the dialog should have closed. Since #169737, pressing 'esc' on the seen-by dialog closes the chat window instead of the dialog. The chat window's root element has a keydown handler that closes the window on `'escape'`, and cat
Original PR description
**Steps to Reproduce:** 1. Send a message to Marc demo with Mitchell admin or vice-versa, read the message from reciever's side. 2. Click on seen-by indicator from sender's side, make sure the dialog…
**Steps to Reproduce:** 1. Send a message to Marc demo with Mitchell admin or vice-versa, read the message from reciever's side. 2. Click on seen-by indicator from sender's side, make sure the dialog appears and then Press `'ESC'`. 3. Chat window closes whereas the dialog should have closed. Since #169737, pressing 'esc' on the seen-by dialog closes the chat window instead of the dialog. The chat window's root element has a keydown handler that closes the window on `'escape'`, and catches focus by default whenever something non-focusable is clicked inside it (e.g. the seen-by indicator). The seen-by dialog's content had no focusable element, so it never grabbed focus for itself, leaving focus on the chat window. Pressing 'escape' therefore closed the chat window instead of the dialog. This commit fixes the issue by adding tabindex on the template, letting the dialog grab focus like other dialogs/popovers already do, so `'escape'` is handled by the dialog first. task-4895004 Forward-Port-Of: odoo/odoo#281361 Forward-Port-Of: odoo/odoo#278847
Before this commit, the unread banner of a conversation showed up and disappeared right away when a message arrived while the user was scrolled up in the history. On a busy machine it is never rendered at all, which fails this hoot test: ``` show banner for new message after thread was read from another device Failed to find 1 of ".o-mail-Thread-banner:has(:text('1 new message'))" (Timeout of 10 seconds). Found 0 instead. ``` This happens because a message received while the composer h
Original PR description
Before this commit, the unread banner of a conversation showed up and disappeared right away when a message arrived while the user was scrolled up in the history. On a busy machine it is never rendered at all, which fails this hoot test:
```
show banner for new message after thread was read from another device
Failed to find 1 of ".o-mail-Thread-banner:has(:text('1 new message'))"
(Timeout of 10 seconds). Found 0 instead.
```
This happens because a message received while the composer has the focus is marked as read whatever the scroll position, while the counter the banner reads is frozen only when the conversation is scrolled to the bottom too. The counter therefore goes up for a scrolled up user, and back to zero as soon as the read reaches the server.
This commit marks a received message as read only when the conversation is scrolled to the bottom, as the other automatic reads already do.
https://runbot.odoo.com/odoo/error/945671
Forward-Port-Of: odoo/odoo#281488The value often comes from the user and may be a Domain, the search implementation may incorrectly handle it by using the wrong context. For most cases, transform 'any' Domain into a Query object before calling `Field.search` to freeze the context used the generate the query. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280368
Original PR description
The value often comes from the user and may be a Domain, the search implementation may incorrectly handle it by using the wrong context. For most cases, transform 'any' Domain into a Query object before calling `Field.search` to freeze the context used the generate the query. task-6446206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280368
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created User as a Team Member 4. Create a Template Project as follows: * Add one task to the template project * Add the created Project role to the Task 5. Create a Service Type Product with: * Create on order: Project * Project Template: Created Template 6. Archive the Created User
Original PR description
Steps to reproduce: ------------------------------------------------- 1. Install the `sale_project` module 2. Create a test user with Project User rights 3. Create a Project Role with the Created…
Steps to reproduce:
-------------------------------------------------
1. Install the `sale_project` module
2. Create a test user with Project User rights
3. Create a Project Role with the Created User as a Team Member
4. Create a Template Project as follows:
* Add one task to the template project
* Add the created Project role to the Task
5. Create a Service Type Product with:
* Create on order: Project
* Project Template: Created Template
6. Archive the Created User
7. Create and Confirm the Sale Order with the Created Product
Observation:
-------------------------------------------------
The generated task is assigned to the archived user, although the archived user is no longer part of the Project Role.
Issue:
-------------------------------------------------
While creating Project and Tasks from template, the context disable active record filtering (e.g., `active_test=False`), causing the assignment logic to fetch both active and inactive/archived users linked to the role. https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/odoo/orm/models.py#L4868
After that, during the `copy_data` method, It takes all the users from the roles without checking weather user is active or not
https://github.com/odoo/odoo/blob/8ec646e51497b38d34ea59296e0fc8644a50ee3a/addons/project/models/project_task.py#L890-L904
And even if we pass only Active users from this method, on moving further, it reassigns the users from roles without checking the Active field of the user
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L501-L503
https://github.com/odoo/enterprise/blob/5abb147f9bf725daafc202d8259a5bb8a9b78d94/project_enterprise/models/project_task.py#L544-L553
Due to this, the Archived User is also assigned to the tasks from the project roles
Solution:
-------------------------------------------------
Apply a `filtered('active')` check directly on the project role's users
`(role.user_ids)` within the core task-copying logic in both `project` and
`project_enterprise` modules. This ensures archived users are universally
excluded from task assignments during template copying, regardless of what
triggers the template instantiation.
Related Enterprise PR: https://github.com/odoo/enterprise/pull/125637
opw-6350841
Forward-Port-Of: odoo/odoo#274426Before this change, searching on hr.employee could return either employees from the selected company_ids, or employees managed by the current user. This means that sometimes, employees not in the currently selected company_ids could be shown (e.g.: on the gantt view). This caused issues, like, if on the gantt view, it shows employees from outside the company, then the gantt view will try to access the employee's resource (to get their unavailabilities). Since `resource.resource` is sco
Original PR description
Before this change, searching on hr.employee could return either employees from the selected company_ids, or employees managed by the current user. This means that sometimes, employees not in the currently selected company_ids could be shown (e.g.: on the gantt view). This caused issues, like, if on the gantt view, it shows employees from outside the company, then the gantt view will try to access the employee's resource (to get their unavailabilities). Since `resource.resource` is scoped only based on the company_ids, then we don't have the right to access them -> this leads to a traceback Since it makes little sense to show employees from outside the companies we selected (it should filter them!), I removed that from the domain in the `ir.access.csv` file Tests (of the gantt bug) have been added in enterprise. task-5502544
**Steps to reproduce:** - Go to Discuss app - Open a discussion - Add a reaction to one of the older messages - Create a new poll - Click on the vote number count - Close the vote dialog - Go back to the message that has the reaction - Open the reaction dialog for that message - Dialog opens, but the focus scroll down to the poll (also possible to reproduce with any visible active element, e.g. links or messages being edited) **Issue:** `Dropdown.closePopover()` re-focus the elemen
Original PR description
**Steps to reproduce:** - Go to Discuss app - Open a discussion - Add a reaction to one of the older messages - Create a new poll - Click on the vote number count - Close the vote dialog - Go back to the message that has the reaction - Open the reaction dialog for that message - Dialog opens, but the focus scroll down to the poll (also possible to reproduce with any visible active element, e.g. links or messages being edited) **Issue:** `Dropdown.closePopover()` re-focus the element that was active when the `MessageReactionList` dropdown was opened and `focus()` call doesn't use `preventScroll` so it moves back to `_focusedElBeforeOpen`. **Fix:** Use `focusToggleOnClosed` to prevent this behavior. opw-6355999 Forward-Port-Of: odoo/odoo#279705
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not create its own dropzone: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/core/common/composer.js#L197-L209 The chatter creates a dropzone covering the whole chatter that saves dropped files as attachments of the record: https://github.com/odoo/odoo/b
Original PR description
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not…
[FIX] mail: attach dropped files to the message in edition Root cause: When editing a message in the chatter, the composer shown inside the message does not get the dropzoneRef prop, so it does not create its own dropzone: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/core/common/composer.js#L197-L209 The chatter creates a dropzone covering the whole chatter that saves dropped files as attachments of the record: https://github.com/odoo/odoo/blob/5ca10578a2fd1b40cd371ed5ad20c1654dfe54d3/addons/mail/static/src/chatter/web/chatter_patch.js#L106-L138 Since the composer of the message in edition has no dropzone, a file dropped on it is caught by the chatter dropzone and ends up attached to the record instead of the message. Fix: Pass the message body as dropzoneRef to the composer in message.xml. The composer then creates its own dropzone over the message, the same way the chatter composer gets one from chatter.xml, and the dropped file is added to the message in edition. The chatter dropzone and the thread composer dropzone cover that same area and would show at the same time, so both are turned off while a message is in edition. The thread already knows which message that is through messageInEdition, so neither of them has anything to keep track of. Steps to reproduce: 1. Open the Contacts app and open any contact 2. Click Log note, type some text and click Log 3. Hover the note and click the pencil icon to edit it 4. Drag a file from the file explorer and drop it on the note => the file is added to the attachments of the contact instead of the note Ticket [link](https://www.odoo.com/odoo/project.task/6385377) opw-6385377 Forward-Port-Of: odoo/odoo#281340 Forward-Port-Of: odoo/odoo#278373
[FIX] hr_attendance: restricting visibility-monthly hours smart button Bug reproduction: 1 - v19 and later on 2 - Even though you don't have a group attendance_user or attendance_manager and you are not the attendance manager of some employee 3 - You can see the smart button "monthly hours" in the employee form view Bug cause: 1 - If the user is attendance officer (which means at least attendance manager of 1 employee) the smart button does always appear. Bug sol
Original PR description
[FIX] hr_attendance: restricting visibility-monthly hours smart button Bug reproduction: 1 - v19 and later on 2 - Even though you don't have a group attendance_user or attendance_manager and you are…
[FIX] hr_attendance: restricting visibility-monthly hours smart button
Bug reproduction:
1 - v19 and later on
2 - Even though you don't have a group attendance_user or attendance_manager and you are not the attendance manager of some employee
3 - You can see the smart button "monthly hours" in the employee form view
Bug cause:
1 - If the user is attendance officer (which means at least attendance manager of 1 employee) the smart button does always appear.
Bug solution:
1 - I declared new non-stored show_monthly_hours_button field to determine whether should I show the smart button or not.
2 - I used invisible in employee and employee.public views to hide the button when there is no authorization.
task - 6387595
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#276295Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device Issue: The second order is rejected by TicketBAI with the error 5040, the invoice number is already registered for that issuer, series and year. Cause: The invoice number sent to TicketBAI is the pos.order name. That name is built by _get_order_name_from_pos_reference out of the last part of
Original PR description
Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device…
Steps to reproduce: - a Basque company with TicketBAI enabled - one PoS config opened on two different devices (browsers) - make a sale from the first device - make a sale from the second device Issue: The second order is rejected by TicketBAI with the error 5040, the invoice number is already registered for that issuer, series and year. Cause: The invoice number sent to TicketBAI is the pos.order name. That name is built by _get_order_name_from_pos_reference out of the last part of pos_reference only, which is the receipt counter each device keeps in its own browser local storage and which restarts at 1. Both devices therefore name their first order "<config> - 000001", and _get_tbai_seq_from_name derives the same SerieFactura and NumFactura for the two of them. Fix: Send pos_reference instead. It is the number printed on the customer receipt and it also holds the device identifier, allocated by the device sequence of the config, which is what makes it unique. The device part ends up as the series and the counter as the number, so the numbering stays sequential inside the series of each device, and the series still starts with the year the duplicate check is made on. Both stay well below the 20 characters SerieFactura and NumFactura are limited to. The name of the refunded document is taken from the same helper, so a credit note cannot reference a number that was never registered. The pos.order name itself is not unique on any version from 19.0 on, but it cannot be changed in stable. opw-6442837 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280621
**Issue:** In the website builder, when entering "Edit" mode through "Edit" button, the main navbar is hidden. An animation is moving the navbar upwards and a "d-none" class is added to it after a delay of 200ms to avoid it disappearing suddenly. It is displayed again after saving the changes by removing the "d-none" class. However, when entering "Edit" mode and leaving it quickly, it is possible that the code hiding the navbar is executed after the code displaying it again because of the 20
Original PR description
**Issue:** In the website builder, when entering "Edit" mode through "Edit" button, the main navbar is hidden. An animation is moving the navbar upwards and a "d-none" class is added to it after a…
**Issue:** In the website builder, when entering "Edit" mode through "Edit" button, the main navbar is hidden. An animation is moving the navbar upwards and a "d-none" class is added to it after a delay of 200ms to avoid it disappearing suddenly. It is displayed again after saving the changes by removing the "d-none" class. However, when entering "Edit" mode and leaving it quickly, it is possible that the code hiding the navbar is executed after the code displaying it again because of the 200ms setTimeout(). The issue is not reproducible in the UI directly, but the `test_32_website_background_colorpicker` tour is often failing with the following error: ``` FAILED: [53/65] Tour website_page_options → Step <b>Click Edit</b> to start designing your homepage. (trigger: body:has(:iframe body[is-ready=true]) .o_menu_systray .o_menu_systray_item.o_edit_website_container button). Element (body:has(:iframe body[is-ready=true]) .o_menu_systray .o_menu_systray_item.o_edit_website_container button) has not been found. TIMEOUT step failed to complete within 10000 ms. ``` During the tour several clicks on "Save" and "Edit" are executed, leading to the navbar being unavailable when trying to click on "Edit". runbot-243712 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Since #247162, H11 is used in Odoo. It was added in the packages.txt used for the raspberry pi but not in the requirements.txt for the windows version. As we changed the version of the IoT to 19.4, new IoT and the ones that update will crash. This let the next image we generate to get the package. opw-6449851 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280825 Forward-Port-Of: odoo/odoo#280694
Original PR description
Since #247162, H11 is used in Odoo. It was added in the packages.txt used for the raspberry pi but not in the requirements.txt for the windows version. As we changed the version of the IoT to 19.4, new IoT and the ones that update will crash. This let the next image we generate to get the package. opw-6449851 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280825 Forward-Port-Of: odoo/odoo#280694
Following odoo/odoo@b325a1ee7955, on database will a lot of messages (> MAX_SEARCH_LIMIT) in case an AccessError for a mail.message is raised, the computation of the source ir.rule will crash will: `ValueError: Cannot search, too many messages` This commit add the `search_domain` hint when looking for the ir.rule that restrict access to those records, so that the access right check of mail.message (`_search_res_access()`) are limited to those records only. --- I confirm I have signed
Original PR description
Following odoo/odoo@b325a1ee7955, on database will a lot of messages (> MAX_SEARCH_LIMIT) in case an AccessError for a mail.message is raised, the computation of the source ir.rule will crash will: `ValueError: Cannot search, too many messages` This commit add the `search_domain` hint when looking for the ir.rule that restrict access to those records, so that the access right check of mail.message (`_search_res_access()`) are limited to those records only. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1) and confirm it 4. On the generated task, log **4.5 h on 15/06** and **3.5 h on 23/07** 5. *Create Invoice* with no timesheet period → 8 h, and post it 6. On that invoice: *Reverse* → *Partial Refund*, set the quantity to **3.5 h** and post it → 4.5 h invoiced 7. Log **1 h on 31/07** → 9 h delivered 8
Original PR description
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1)…
### Steps to reproduce 1. Install *Sales* and *Timesheets* 2. Create a service product: Invoicing Policy = *Based on Timesheets*, Create on Order = *Task* 3. Create a sale order for it (quantity 1) and confirm it 4. On the generated task, log **4.5 h on 15/06** and **3.5 h on 23/07** 5. *Create Invoice* with no timesheet period → 8 h, and post it 6. On that invoice: *Reverse* → *Partial Refund*, set the quantity to **3.5 h** and post it → 4.5 h invoiced 7. Log **1 h on 31/07** → 9 h delivered 8. *Create Invoice* again, with a **Timesheets Period of 01/06 → 31/07** ### Current behavior The invoice bills **9 h**: the 4.5 h that were invoiced and not credited are billed a second time. ### Expected behavior The invoice bills **4.5 h** — the quantity delivered minus the quantity invoiced. ### Cause of the issue Posting a partial credit note clears `timesheet_invoice_id` on every timesheet the reversed invoice had linked (`sale_timesheet/models/account_move.py`, `action_post`), because a credit note carries a quantity and never a set of timesheets, so there is no way to tell which hours it credited. All of those hours therefore become candidates again in `_recompute_qty_to_invoice`, which assigns their sum to `qty_to_invoice` without comparing it to what is still due on the line. ### Fix Timesheet links cannot express a partially invoiced timesheet, so they are used only to select the hours a period concerns, while the quantity that may still be billed is `qty_delivered - qty_invoiced`. The period lookup is capped by that remainder, and kept at zero or above so that an over-invoiced line is corrected by a deliberate credit note rather than as a side effect of invoicing a period. ### Tests Five tests are added to `addons/sale_timesheet/tests/test_sale_timesheet.py`. Three of them fail without the fix: | test | without the fix | | --- | --- | | `test_period_invoice_does_not_rebill_refunded_invoice_hours` | `9.0 != 4.5` | | `test_period_invoice_after_refund_is_computed_per_line` | `4.0 != 1.5` | | `test_period_invoice_after_refund_of_an_over_invoiced_line` | `8.0 != 1.0` | The other two cover behaviour that is not exercised today and that the fix must not break: an over-invoiced line (which must be left out rather than credited, and must not prevent the other lines of the order from being invoiced) and the reversed invoice's own `invoice_date`, which must not influence the quantity billed for a period. The full `sale_timesheet` suite passes (86 tests). Forward-Port-Of: odoo/odoo#281065 Forward-Port-Of: odoo/odoo#280536
Before this commit, `visitor leaving ends the livechat conversation` failed about once in a hundred runs: Failed to find 1 of "span" with text "This livechat conversation has ended." (Timeout of 10 seconds). Found 0 instead. This happens because the test only waits for the `channels_as_member` request to reach the server, from the `onRpc` callback that runs before the route is served. The answer holds `livechat_end_dt` as `false` and lands right after the `mail.record/insert` of t
Original PR description
Before this commit, `visitor leaving ends the livechat conversation` failed about once in a hundred runs: Failed to find 1 of "span" with text "This livechat conversation has ended." (Timeout of 10…
Before this commit, `visitor leaving ends the livechat conversation` failed about once in a hundred runs:
Failed to find 1 of "span" with text "This livechat conversation
has ended." (Timeout of 10 seconds). Found 0 instead.
This happens because the test only waits for the `channels_as_member` request to reach the server, from the `onRpc` callback that runs before the route is served. The answer holds `livechat_end_dt` as `false` and lands right after the `mail.record/insert` of the visitor leaving, so the date goes back to `false` and the conversation still looks open.
One solution could have been to use `waitStoreFetch`, but its step comes from that same callback, and the helper returns six microtasks before the answer is inserted, on a hundred runs out of a hundred.
This commit fixes the issue by waiting for the messaging menu to list a plain channel, which arrives with the `channels_as_member` answer only.
https://runbot.odoo.com/odoo/error/945672
Forward-Port-Of: odoo/odoo#281582
Forward-Port-Of: odoo/odoo#281489