Daily updates from Odoo
Tuesday, August 11, 2026
29 changes · saas-19.2
Resolved issues and error corrections
When projects and tasks are created from templates, archived users linked through project roles are now excluded from task assignments. This prevents inactive employees from being assigned work automatically and keeps generated project tasks aligned with current team membership.
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#125637This fixes an intermittent error when accepting UrbanPiper delivery orders in Point of Sale. Orders that are already marked as printed are now handled gracefully, preventing occasional failed accept flows and unstable automated tests.
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
This fixes an error that occurred when saving an employee declaration without selecting an employee. Payroll users can now create or edit these records without being interrupted by a technical traceback.
Original PR description
When creating an employee declaration without selecting an employee, a traceback occurs. Steps to reproduce the error: - Install ``l10n_be_hr_payroll`` module with demo data - Switch to Belgian company - Go to Payroll > Reporting > Individual Accounts > Create a new Individual Account > Click on Eligible Employees > Create a new employee declaration without employee > Save Traceback: ```py ValueError: Expected singleton: hr.employee() ``` https://github.com/odoo/enterprise/blob/000544c3d5b93e194264e15bb73d9599525106e3/hr_payroll/models/hr_payroll_employee_declaration.py#L71 The ``_compute_version_id()`` method calls ``_get_version()``. When ``employee_id`` is empty, ``_get_version()`` is invoked on an empty ``hr.employee`` record, and its ``ensure_one()`` call raises the above traceback at [1]. [1]: https://github.com/odoo/odoo/blob/3c358ae2badad69b125695a97b4a14e8ab77fccd/addons/hr/models/hr_employee.py#L745-L750 sentry-7625826444
Bank statement reconciliation now uses an existing optimized lookup when searching for unreconciled accounting lines. This helps improve performance in accounting 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#127093The Timesheets Assistant no longer treats the user's own email address as a customer match when analyzing Gmail messages. This prevents irrelevant task or project suggestions for emails where the user appears only because they received the message.
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#126448
This fixes an issue where planning managers without HR access could unintentionally publish planning slots when changing the assigned resource. The update uses public employee information so managers can make the change without triggering the wrong publication behavior.
Original PR description
For planning manager without HR access, if the user change the resource of the planning slot it will publish it automatically as the employee_ids field cannot be used without HR access. Prefer to use public employee to have better condition without using explicit sudo Caused-by: https://github.com/odoo/enterprise/commit/e88dcd0e545183b3f03e06b62158c52a1e6d2103
Issue: Employees whose nationality differs from the country of their employing company can lose an otherwise valid Time Off Type while creating or updating a request. Even when the employee has a usable allocation for a type localized to the company country, changing the employee or requested dates can replace that type with a generic type or clear the field. The resulting fallback selection is inconsistent with both the initial default and the Time Off Type dropdown, which are localized acc
Original PR description
Issue: Employees whose nationality differs from the country of their employing company can lose an otherwise valid Time Off Type while creating or updating a request. Even when the employee has a…
Issue: Employees whose nationality differs from the country of their employing company can lose an otherwise valid Time Off Type while creating or updating a request. Even when the employee has a usable allocation for a type localized to the company country, changing the employee or requested dates can replace that type with a generic type or clear the field. The resulting fallback selection is inconsistent with both the initial default and the Time Off Type dropdown, which are localized according to the employee's company. Steps to reproduce: - Configure a company in Belgium. - Configure an employee of that company with United States nationality. - Configure an allocation-required Belgian Time Off Type. - Validate an allocation of that type for the employee. - Create a request whose current allocation-based type is not usable, then select the employee or change the request dates. - Observe that the allocated Belgian type is not considered as the replacement. Cause: When the employee or dates change, `_compute_work_entry_type_id()` searches for Time Off Types using the employee's nationality: https://github.com/odoo/odoo/blob/saas-19.2/addons/hr_holidays/models/hr_leave.py#L512-L525 Time Off Types are linked to the employee's company country. When the two countries differ, the allocated type is excluded before its allocation is checked. Solution: We need to use the employee's company country when searching for Time Off Types. This keeps the computation consistent with the form domain while preserving the existing generic type fallback. opw-6433755 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
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#274426Issue: ------- 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#263025## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe arise ## Cause: Two parts where causing this. First when creating a new calendar and we try to fetch default attendances we don't set the sequence in the newly created attendances https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resour
Original PR description
## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe…
## Steps to reproduce: - Install Employee - Create a 2-week working schedule and set it as the company default - Try to create a new working schedule - Notice when you click save a ValidationErroe arise ## Cause: Two parts where causing this. First when creating a new calendar and we try to fetch default attendances we don't set the sequence in the newly created attendances https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L735-L749 so it will get the default value which is 10 so when calling onchange for the attendance_ids_1st_week and attendance_ids_2nd_week each attendance will be set to the odd_week_seq https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L184-L200 which will then make this condition fail https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L615-L616 Second part was related to the `two_weeks_calendar` when saving, its value won't be passed to the vals_list in `web_save()` as when we read the values to be changed we ignore readonly fields and since two_weeks_calendar was used in invisible condition but isn't defined in a separate `<field>` the view create a tag for it ` <field name='two_weeks_calendar' invisible='True' readonly='True' data-used-by='invisible='flexible_hours or not two_weeks_calendar' (page,working_hours)' on_change='1'/> ` This tag would be readonly by default so when the ArchParser gets each field's info it puts `two_weeks_calendar` as a readonly field and ignore it in the creation values https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/web/static/src/views/fields/field.js#L276-L279 which then fails this condition and pass all the 2 weeks attendances in the else condition https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L134-L138 After fixing this another bug was found where if you saved the calendar the attendances will disappear. This was happening when we create the resource.calendar.attendance records it will call the inverse method of the attendance_ids_1st_week and attendance_ids_2nd_week where they are still not computed so it will set attendance_ids to empty https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L152-L156 so after when computing the two weeks attendance it will be empty as well and it will disappear. Last bug was if after creating this you tried to switch the calendar type it will call the same validation error mentioned earlier. As when calling _get_default_attendance_ids it will try to create attendances from the company's default working schedule which will have a conflict since the company's schedule is 2-weeks schedule and we are switching our schedule to 1-week schedule so we are gonna have attendances for 2-weeks in 1-week schedule so it will fail the same condition https://github.com/odoo/odoo/blob/b51dc298fd63d9586d0b8d7cff59764b0dee5cae/addons/resource/models/resource_calendar.py#L615-L616 ## Fix: To fix those issues we needed to set the sequence values when copying the data of the company's schedule when computing the default values. Also we need to skip the inverse method when we are still upon creating the records and to do so we are passing a context in the create method to skip the inverse. Last we need to check for the difference between the schedule type and the company's schedule when fetching the default attendances. opw-6374237 Forward-Port-Of: odoo/odoo#279182
### 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
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/31fa530f27 [REL] 19.2.24 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/1c775420e1 [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/ed5703a442 [IMP] composer: writing an number value should override date formats [Task: 6353692](https://www.odoo.com/odoo/232
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/31fa530f27 [REL] 19.2.24 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/31fa530f27 [REL] 19.2.24 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/1c775420e1 [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/ed5703a442 [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/3666729244 [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/2ba8b4d652 [PERF] vectorization: inline generateMatrix [Task: 6222157](https://www.odoo.com/odoo/2328/tasks/6222157) https://github.com/odoo/o-spreadsheet/commit/c24b7ead66 [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/ffab92f089 [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/944174e6ac [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/14b1d425be [PERF] vectorization: reuse args buffer across cells [Task: 6222157](https://www.odoo.com/odoo/2328/tasks/6222157) https://github.com/odoo/o-spreadsheet/commit/383e407540 [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>
*: website_event_exhibitor bug: `_get_srcset` defaulted `max_size` to '1920' when no `preview_image` option was given, causing srcset entries to be generated for image sizes larger than the rendered field. It also did not check whether each candidate field existed on the record, leading to missing or broken srcset entries. steps: - Add an event with a sponsor - add a logo to the sponsor - go on the website → events → the event you added - The sponsor have no logo fix: Fall bac
Original PR description
*: website_event_exhibitor bug: `_get_srcset` defaulted `max_size` to '1920' when no `preview_image` option was given, causing srcset entries to be generated for image sizes larger than the rendered…
*: website_event_exhibitor bug: `_get_srcset` defaulted `max_size` to '1920' when no `preview_image` option was given, causing srcset entries to be generated for image sizes larger than the rendered field. It also did not check whether each candidate field existed on the record, leading to missing or broken srcset entries. steps: - Add an event with a sponsor - add a logo to the sponsor - go on the website → events → the event you added - The sponsor have no logo fix: Fall back to `field_name` to cap the srcset at the size of the rendered field when `preview_image` is not set. Skip candidate fields not present on the record. reason: When rendering e.g. `image_512`, the srcset should not include larger sizes. Checking field existence avoids accessing fields the record does not carry. This bug already had fixes [1] and [2], this PR fixes the problem globally and reverts the old fixes. Bug introduced by https://github.com/odoo/odoo/commit/36e680feca4884940e020119de6a13cd7f927516. [1]: https://github.com/odoo/odoo/commit/6bd2de2f3dbdd1a54b85db1e5215ecbbe9049113 [2]: https://github.com/odoo/odoo/commit/c21602d98028ab135a997816eb2601bdbe6c0a61 task-6123503
**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
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
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
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
#### 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
[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
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#281488Steps to reproduce the bug: - Install repair and accounting - Create a user and grant them only Inventory / User access - Log in as that user and open any Repair Order Problem: Opening the repair order raised: "Failed to read field repair.order.invoice_ids You are not allowed to access 'Journal Entry' (account.move) records." `invoice_count` and `can_create_sale_or_invoice` are computed fields that read `invoice_ids`, a One2many to `account.move` Reading a One2many always queries the
Original PR description
Steps to reproduce the bug: - Install repair and accounting - Create a user and grant them only Inventory / User access - Log in as that user and open any Repair Order Problem: Opening the repair…
Steps to reproduce the bug: - Install repair and accounting - Create a user and grant them only Inventory / User access - Log in as that user and open any Repair Order Problem: Opening the repair order raised: "Failed to read field repair.order.invoice_ids You are not allowed to access 'Journal Entry' (account.move) records." `invoice_count` and `can_create_sale_or_invoice` are computed fields that read `invoice_ids`, a One2many to `account.move` Reading a One2many always queries the comodel, so this triggers an ACL check on `account.move` for the current user, even though the repair order has no invoice and the field is only used to display a count/boolean. A user with `stock.group_stock_user` but no accounting/sales rights has no access to `account.move`, so simply opening the form crashes. Solution: Read `invoice_ids` with `sudo()` inside `_compute_invoice_count` and `_compute_can_create_sale_or_invoice`, since only a derived count/boolean is exposed to the user, not the invoice records themselves. opw-6447829
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#281489The 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
[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#276295Since #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
runbot-944311 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
runbot-944311 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr