Daily updates from Odoo
Thursday, August 13, 2026
42 changes · saas-19.3
Enhancements to existing features
Add account 2284 GBRT Tax Payable and rework the GBRT tax distribution to book to it against 6771 Taxes & dues. Update the Traditional Chinese tax descriptions and remove the 0% Deemed Sales tax. task-6427283 Forward-Port-Of: odoo/odoo#281109
Original PR description
Add account 2284 GBRT Tax Payable and rework the GBRT tax distribution to book to it against 6771 Taxes & dues. Update the Traditional Chinese tax descriptions and remove the 0% Deemed Sales tax. task-6427283 Forward-Port-Of: odoo/odoo#281109
This commit adds a "Reload Data" button to the traceback dialog for PWA applications. When clicked, the user is asked to confirm the action. Once confirmed, all locally stored browser data is cleared, allowing the POS to recover from errors caused by corrupted or outdated local data. task-6388234 Forward-Port-Of: odoo/odoo#281734 Forward-Port-Of: odoo/odoo#276559
Original PR description
This commit adds a "Reload Data" button to the traceback dialog for PWA applications. When clicked, the user is asked to confirm the action. Once confirmed, all locally stored browser data is cleared, allowing the POS to recover from errors caused by corrupted or outdated local data. task-6388234 Forward-Port-Of: odoo/odoo#281734 Forward-Port-Of: odoo/odoo#276559
Resolved issues and error corrections
A test was adjusted to match improved spacing in plain-text tracking messages. This keeps automated checks aligned with the expected mobile notification output and helps prevent false test failures.
Original PR description
The enterprise commit adds a span in the tracking values template which adds a space between the values when converted to plaintext. This is a side-effect, but it's a good one. task-6456370
Users with Accounting Read-Only access can now see the General section in the Accounting tab of contact records, including bank account details. This fixes a visibility issue caused by a view customization that accidentally replaced existing access groups instead of adding the intended one.
Original PR description
Problem: The General group of the Accounting tab of the partner form view is not visible to some users, even if they have the access rights to see it. Steps to reproduce: 1. Create a user or edit an existing one, giving them Accounting Read-Only access rights. 2. Log in with that user. 3. Go to Contacts and select a partner. 4. Open the Accounting tab 5. Notice how the General group (with the bank account details) is not visible. Cause: In the account_accountant module, the partner form view is inherited in one of the views to add additional groups to the General group of the Accounting tab. However, it doesn't add the new group, but instead replaces the existing groups with the new one. opw-6413683 Forward-Port-Of: odoo/enterprise#126679
This update adjusts an internal automated test for mobile mail notifications after a tracking template change. It helps keep quality checks reliable without changing the user-facing product experience.
Original PR description
Task-6424104
Automatic account transfers now keep journal entries balanced when destination percentages are below 100%. This prevents small rounding differences, such as one-cent mismatches, from blocking or distorting transfer postings.
Original PR description
Before this commit, _get_transfer_move_lines_values computed the amount for the last destination line from the global transferred balance, instead of reusing the amount already removed from the source accounts. The two values are rounded independently and can differ by a cent whenever the removed amount comes from more than one rounded source, producing an unbalanced journal entry. Removing that condition the last destination line always absorbs the remainder fixes it. Steps to reproduce: 1. Transfer model with 2 source accounts and 1 destination line at 15%. 2. Post moves for the period: account A balance 395.88, account B balance 252.16 (total 648.04). 3. Run `action_perform_auto_transfer()`. Before: source lines -59.38 (395.88 * 15%) and -37.82 (252.16 * 15%), destination line +97.21 (648.04*15% rounded) -> entry off by 0.01. After: destination line takes the exact remainder, 97.20 -> balanced. OPW-6443928 Forward-Port-Of: odoo/enterprise#126877
The Point of Sale UrbanPiper ticket screen now shows the order info button on mobile as well as desktop. This ensures staff using mobile devices can access order details consistently, reducing friction during order handling.
Original PR description
Before this commit: ------------ - The order info button was not visible on the ticket screen in the mobile UI. After this commit: ------------ - Display the order info button in both the mobile and desktop views of the ticket screen. Related: - Community: https://github.com/odoo/odoo/pull/276568 Task-6388045
Belgian payroll now automatically applies an employee's default private-use fuel card amount when creating a payslip, as long as the employee has no company car or mobility budget. This prevents the taxable benefit from being missed and keeps payslips aligned with the employee's payroll settings.
Original PR description
Steps to reproduce: - Set a "Fuel Card - Private use" default on the employee's payroll tab (fuel_card_personal_use), with no company car. - Generate/compute a monthly payslip for that employee. - The FUEL_CARD_PRIV salary rule never fires, so the private-use benefit-in-kind stays at 0 and is missing from the payslip. FUEL_CARD_PRIV is a property_input salary rule, so its amount comes from the payslip's property inputs, but nothing ever copied the employee's fuel_card_personal_use default into them. Seed FUEL_CARD_PRIV from that default in _compute_input_line_ids(), gated on fuel_card, no company car (transport_mode_car) and no mobility budget, matching this version's own benefit view visibility conditions. Added tests covering the default, each exclusion case, and manual payslip overrides. Task 6469003
This fix ensures Belgian payroll declarations report the correct mobility budget balance when an employee's current contract no longer includes a mobility budget. The system now uses the previous quarter's contract information so the declared amount is not incorrectly set to zero.
Original PR description
When the mobility budget balance is paid on a contract that no longer carries a mobility budget, fall back to the previous quarter's contract to declare the correct amount instead of 0. Task-6384786
The Helpdesk Stock workflow now shows the Replace button even when no customer is selected. This keeps the ticket interface consistent with related actions and helps users access the replacement process without unnecessary data entry first.
Original PR description
Adjust the `invisible` condition to make the button visible even if no customer is selected, for consistency with other buttons --- task-6103996 Forward-Port-Of: odoo/enterprise#124467
This fixes an issue where the signing process could fail when an empty value was used without an automatic fallback value. Users should now be able to complete affected signing workflows without encountering an unexpected error.
This fixes an incorrect status value used in Swiss withholding tax mutation declarations. The change helps ensure employee payroll updates are reported with the right classification, reducing the risk of rejected or inaccurate declarations.
Original PR description
task-6116327 Forward-Port-Of: odoo/enterprise#127745
The timesheet menu has been adjusted to display more cleanly on mobile devices. This makes it easier for users to enter and manage timesheets from smaller screens without dealing with a clunky layout.
Original PR description
In this commit, we improve the display of the timesheet systray in mobile view as it was clunky. task-6332208
This fix prevents Swiss payroll settings from being applied automatically to employees outside Switzerland. It helps avoid incorrect employee contract information and keeps payroll-related screens and automated checks working as expected.
Original PR description
[FIX] l10n_ch: fix default contract type This task is runbot error fix that occured from 19.0 to 19.2 Bug reproduction: 1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute…
[FIX] l10n_ch: fix default contract type
This task is runbot error fix that occured from 19.0 to 19.2
Bug reproduction:
1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute test_version_timeline_auto_save_tour tour test 3 - It fails in .o_arrow_button_wrapper[data-tooltip^='Contract:'] step
Bug cause:
1 - When l10n_ch_hr_payroll_account is installed:
1.1 - contract type becomes "Permanent contract with monthly salary"
1.2 - the employee is not swiss but it has this CH contract type
2 - data-tooltip starts with Permanent contract instead of contract
2.1 - Tour fails
3 - contract_type_id is overwritten in swiss modules
3.1 - Default is assigned without looking to the country of self.env
Bug solution:
1 - If the country is not swiss, the default is assigned as False
1.1 -> fixed in l10n_ch_hr_payroll/hr_version
1.2 instead of assigning swiss contract type to the non-swiss emp.
Note: This is fix from saas-18.4 to master.
task-6392040
runbot error: https://runbot.odoo.com/odoo/runbot.build.error/941358
Forward-Port-Of: odoo/enterprise#126520This fixes an issue where Belgian SODA file imports could fail for users who do not have Analytic Accounting access. The import can now continue normally when Analytic Accounting is disabled, reducing unnecessary blockers in accounting workflows.
Original PR description
**Description of the issue/feature this PR addresses:** When importing a SODA XML file, users without the Analytic Accounting group encounter an access rights error. This occurs because the import…
**Description of the issue/feature this PR addresses:** When importing a SODA XML file, users without the Analytic Accounting group encounter an access rights error. This occurs because the import wizard reads the `analytic_account_id` field on the `soda.analytic.mapping` model to build an internal dictionary of departments. Because this field is restricted to the Analytic Accounting group, the evaluation of this field crashes the import for users even when the Analytic Accounting feature is disabled. This commit prevents the crash by using `.sudo()` when reading the analytic account ID. This safely bypasses the field-level group restriction, allowing the dictionary to be built with False values without interrupting the core import process. **Steps to reproduce:** - Log in as Mitchell Admin, change company to “My Belgian Company” - Settings > Users & Companies > Users > Mitchell Admin > Access Rights > Extra Rights > ensure “Analytic Accounting” is unchecked - Also ensure Mitchell Admin is not part of the “Analytic Accounting” group - Accounting Dashboard > remove “Favorites” from filter > drag & drop a SODA XML file to “Miscellaneous Operations” > save > observe Access Error **Current behavior before PR:** - Users who don't belong to the Analytic Accounting group encounter an access error when attempting to import SODA XML files, even when the Analytic Accounting feature isn't enabled **Desired behavior after PR is merged:** - Those users no longer receive an access error opw-6376039
Before this commit, some layouts had the customer address on the right (light, boxed, bold, striped) and some had it on the left (bubble, wave, folder). For the latter, when an information_block with the address existed, it would be inserted before the address pushing it further right. This was inconsistent since the address position should not depend on whether an information_block is present or not. The customer address must stay in a fixed place to match the transparent window of the
Original PR description
Before this commit, some layouts had the customer address on the right (light, boxed, bold, striped) and some had it on the left (bubble, wave, folder). For the latter, when an information_block with…
Before this commit, some layouts had the customer address on the right (light, boxed, bold, striped) and some had it on the left (bubble, wave, folder). For the latter, when an information_block with the address existed, it would be inserted before the address pushing it further right. This was inconsistent since the address position should not depend on whether an information_block is present or not. The customer address must stay in a fixed place to match the transparent window of the envelope when sending a physical letter by snailmail. This commit fixes this issue by ensuring that in all cases the customer address position stays fixed regardless of the presence or absence of the information_block and regardless of the layout used for the letter. It also fixes the addresses displayed on the sale order report: 1) If invoicing address = partner address != shipping address or invoicing address != partner address = shipping address then the three addresses would be printed, even though 2 addresses are identical. 2) The shipping address and the invoicing address are now printed horizontally rather than vertically to get rid of the resulting large blank block under the partner address in that case. backport of: https://github.com/odoo/odoo/pull/276622 task-6340467 Forward-Port-Of: odoo/odoo#281937 Forward-Port-Of: odoo/odoo#273640
Steps to reproduce: ------------------- 1. Install `hr` module 2. Create two employees (e.g., emp1 and emp2) and assign emp1 as the manager of emp2 → emp2 is now a direct subordinate of emp1 3. In the employee list view, apply the custom filter "Direct subordinates is set" (child_ids != False) → emp1 appears in the results as expected 4. Archive emp2 5. Apply the same filter again → emp1 still appears in the results even though it has no active subordinates Issue
Original PR description
Steps to reproduce: ------------------- 1. Install `hr` module 2. Create two employees (e.g., emp1 and emp2) and assign emp1 as the manager of emp2 → emp2 is now a direct subordinate of emp1 3. In…
Steps to reproduce: ------------------- 1. Install `hr` module 2. Create two employees (e.g., emp1 and emp2) and assign emp1 as the manager of emp2 → emp2 is now a direct subordinate of emp1 3. In the employee list view, apply the custom filter "Direct subordinates is set" (child_ids != False) → emp1 appears in the results as expected 4. Archive emp2 5. Apply the same filter again → emp1 still appears in the results even though it has no active subordinates Issue: ------ When an employee (e.g., `emp2`) is archived, their manager (`emp1`) should no longer appear in the "Direct subordinates is set" (child_ids != False) filter — since `emp1` no longer has any active subordinates. However, `emp1` still appears in the search results after `emp2` is archived, because the underlying EXISTS subquery checks all subordinates regardless of their active state. Cause: -------- Before this commit 5ef007a, `osv.expression`, filtering on a One2many field would automatically search against [active co-records ](https://github.com/odoo/odoo/blob/5f65e92d7fa341193df53f5aba1620b596f9a1ec/odoo/osv/expression.py#L1260-L1265)only by default. After that commit, the `condition_to_sql` method in `_RelationalMulti` constructs the comodel with [active_test=False](https://github.com/odoo/odoo/blob/463ca4cf867812890c17d1e1abf7640b04f70ad0/odoo/orm/fields_relational.py#L672-L686) when resolving relational field conditions. This causes the EXISTS subquery generated for `child_ids != False` to compare against all subordinates. (including archived ones rather than active ones only). Solution: --------- Added a callable `domain` attribute on the `child_ids` field definition so that only active subordinates are considered by default. This ensures [get_comodel_domain()](https://github.com/odoo/odoo/blob/2d8b24a791b6fe6bb214c32d4fb58b3d46eca70b/odoo/orm/fields_relational.py#L75-L85) returns a server-side domain that filters out archived subordinates, making the `child_ids != False` filter behave as expected. opw-6193104 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281222 Forward-Port-Of: odoo/odoo#266658
Description of the issue/feature this PR addresses: Installing Odoo via the .deb package continuously causes issues with the asset bundles. This is because of the following daisy chain of behaviors: - `dpkg-buildpackage` parses `SOURCE_DATE_EPOCH` from debian/changelog and then clamps the Modified date of all files to at max that epoch ([src](https://launchpad.net/debian/+source/dpkg/1.18.8)). The relevate date is the one written after the email in the topmost changelog entry - This is pr
Original PR description
Description of the issue/feature this PR addresses: Installing Odoo via the .deb package continuously causes issues with the asset bundles. This is because of the following daisy chain of behaviors:…
Description of the issue/feature this PR addresses: Installing Odoo via the .deb package continuously causes issues with the asset bundles. This is because of the following daisy chain of behaviors: - `dpkg-buildpackage` parses `SOURCE_DATE_EPOCH` from debian/changelog and then clamps the Modified date of all files to at max that epoch ([src](https://launchpad.net/debian/+source/dpkg/1.18.8)). The relevate date is the one written after the email in the topmost changelog entry - This is preserved when unpacking the .deb package, the OS does not change it - The Asset loading logic in ir.qweb and ir.asset relies on the Modified date (via [`os.path.getmtime`](https://github.com/odoo/odoo/blob/17.0/odoo/addons/base/models/ir_asset.py#L49)) to determine the hash that serves a Version for the asset bundles ([src](https://github.com/odoo/odoo/blob/17.0/odoo/addons/base/models/assetsbundle.py#L775), [src](https://github.com/odoo/odoo/blob/17.0/odoo/addons/base/models/assetsbundle.py#L148)) - The controller and ir.qweb compiler rely on this Version hash to correctly invalidate outdated asset bundles and force re-generation of the bundle content as neccessary Current behavior before PR: debian/changelog has not been changed or maintained since 2020 and its timestamp remains `Tue, 15 Dec 2020 10:28:49 +0100` This results in the Modified Date being clamped to 2020, which means the files no matter how much is changed always look like last modified on this date. Therefore the Version hash for the asset bundles never changes, and the asset reload logic does not trigger correctly. This is especially dangerous for setups which use several code sources with different file delivery methods, for example installing Community via .deb but Enterprise via git. This results in only some asset bundles not being updated (those not touched by Enterprise modules) while others are, which then generates an OWL error as it detects the content being different between the bundles ([src](https://github.com/odoo/odoo/blob/17.0/addons/web/static/lib/owl/owl.js#L3333)) For versions 18+, a very common result of this behavior is the portal chatter failing to work. This is because the same files like for example mail/static/src/core/common/thread.xml being loaded into both [`portal.assets_chatter`](https://github.com/odoo/odoo/blob/18.0/addons/portal/__manifest__.py#L69), which is not touched by an Enterprise module, but also into [`web.assets_frontend` ](https://github.com/odoo/odoo/blob/18.0/addons/im_livechat/__manifest__.py#L90) via im_livechat, which is a bundle touched by many modules, including Enterprise modules. Thus, is a file in the mail addon is changed, the changes are correctly applied to `web.assets_frontend`, but not `portal.assets_chatter`, causing an OWL error. This is extremely frustrating to fix, since it not only requires a manual Asset Rebuild, but also for every user to empty their Browser Cache, since the assets bundles are so large as to be guaranteed to be cached, and if the old version of the bundle is loaded from cache, the OWL error persists. A similar error can also happen with website, since the assets for the WYSIWIG editor are loaded as a module-specific bundle, `website.assets_wysiwyg`, which also fails to update, while of course the same assets being loaded to the general website asset bundle will be updated. Desired behavior after PR is merged: The builder for the nightly .deb package of Odoo writes a complete debian/changelog entry instead of merely replacing the first line. This entry includes the current date, thus ensuring the Modified date for the files is not clamped to years in the past. Down the line, this fixes the assets loading issue. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269458
Previously, refreshing the PoS caused categories with sequence = 0 to fall back to ID-based sorting from IndexedDB. Sequence-based ordering was already fixed in this [pr](https://github.com/odoo/odoo/pull/207172), but the fallback for sequence 0 still sorted by ID. This change ensures categories with sequence = 0 follow the expected ordering when refreshing. Task-6185359 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merge
Original PR description
Previously, refreshing the PoS caused categories with sequence = 0 to fall back to ID-based sorting from IndexedDB. Sequence-based ordering was already fixed in this [pr](https://github.com/odoo/odoo/pull/207172), but the fallback for sequence 0 still sorted by ID. This change ensures categories with sequence = 0 follow the expected ordering when refreshing. Task-6185359 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#281248 Forward-Port-Of: odoo/odoo#273954
The test "Image cropper Enter saves and Escape closes in website builder" fails indeterministically on runbot. The error seems to have appeared just after the merging of [1], which introduced a speed-up in test execution. The failure is caused by an image being "invisible" when queried by `contains()`. The most likely cause is that the image is not yet fetched by the time the test runs. The image source is replaced with a `base64` `data:` URL, so that no fetching is required for this
Original PR description
The test "Image cropper Enter saves and Escape closes in website builder" fails indeterministically on runbot. The error seems to have appeared just after the merging of [1], which introduced a speed-up in test execution. The failure is caused by an image being "invisible" when queried by `contains()`. The most likely cause is that the image is not yet fetched by the time the test runs. The image source is replaced with a `base64` `data:` URL, so that no fetching is required for this test. [1]: https://github.com/odoo/odoo/pull/279584 runbot-944664 Forward-Port-Of: odoo/odoo#281794 Forward-Port-Of: odoo/odoo#280333
### Issue before this commit: Before commit f2965048f60fe6c815b3e50fa714c97a93dfb5d3, company_type allowed manually selecting whether a contact was an individual or a company. After the commit, is_company became a stored computed field derived from the VAT number, with no manual override available in the standard UI, and no exception was added for Spanish DNI/NIE formats. ### Steps to reproduce the issue: 1. Download Accounting and l10n_es 2. Set as VAT of ES company 47857909S (or similar
Original PR description
### Issue before this commit: Before commit f2965048f60fe6c815b3e50fa714c97a93dfb5d3, company_type allowed manually selecting whether a contact was an individual or a company. After the commit,…
### Issue before this commit: Before commit f2965048f60fe6c815b3e50fa714c97a93dfb5d3, company_type allowed manually selecting whether a contact was an individual or a company. After the commit, is_company became a stored computed field derived from the VAT number, with no manual override available in the standard UI, and no exception was added for Spanish DNI/NIE formats. ### Steps to reproduce the issue: 1. Download Accounting and l10n_es 2. Set as VAT of ES company 47857909S (or similar but must be a DNI or NIE format) 3. Create an invoice for a Spanish customer 4. Send the invoice with Facturae 5. Check the XML created and see that the tag <PersonTypeCode> of <SellerParty> has a J (legal entity) rather than an F (individual) ### Cause of the issue: The Spanish localization's _compute_is_company override only adds the check for CIF-formatted VAT numbers (for [legal entities](https://sede.agenciatributaria.gob.es/Sede/ayuda/manuales-videos-folletos/manuales-practicos/guia-practica-cumplimentacion-modelo-censal-036/anexos/anexo-01-solicitud-nif-documentacion-aportar/informacion-sobre-numero-identificacion-fiscal/composicion-nif/personas-juridicas-entidades.html)) but it has no corresponding negative check for DNI or NIE formats (for [standalone individuals](https://sede.agenciatributaria.gob.es/Sede/ayuda/manuales-videos-folletos/manuales-practicos/guia-practica-cumplimentacion-modelo-censal-036/anexos/anexo-01-solicitud-nif-documentacion-aportar/informacion-sobre-numero-identificacion-fiscal/composicion-nif/personas-fisicas.html)). Here the [rules](https://factuo.es/herramientas/verificador-nif) for regex. https://github.com/odoo/odoo/blob/f014e0b7bc3ce56a9931e81339a4f8327a400422/addons/l10n_es/models/res_partner.py#L39-L51 As a result, any standalone partner with a valid non-void VAT inherits is_company = True from the base computation. https://github.com/odoo/odoo/blob/f014e0b7bc3ce56a9931e81339a4f8327a400422/odoo/addons/base/models/res_partner.py#L824-L833 ### Reason to introduce the fix: The Facturae 3.2.2 export directly derives PersonTypeCode (F/J) and the LegalEntity/Individual XML structure from partner.is_company. Since a self-employed individual (autónomo) is required to use their personal DNI/NIE as NIF and is their own commercial partner, the current logic misclassifies them as a legal entity (J), producing a Facturae invoice with an incorrect PersonTypeCode and structure. Explicitly setting is_company = False for DNI/NIE-formatted Spanish VAT numbers restores the ability to correctly represent individual entrepreneurs in Facturae exports. opw-6396314 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277228
Problem: `isVisibleTextNode` fails to check the space visibility in case it is preccedded with a `feff`. Cause: The final check uses `visibleCharRegex` on the preceding node, which excludes zero-width chars like `feff`. But `feff` is not whitespace, so it shouldn't make the adjacent space collapse either. Solution: Check for non-whitespace instead of visibility on the preceding node. task-6397398 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submi
Original PR description
Problem: `isVisibleTextNode` fails to check the space visibility in case it is preccedded with a `feff`. Cause: The final check uses `visibleCharRegex` on the preceding node, which excludes zero-width chars like `feff`. But `feff` is not whitespace, so it shouldn't make the adjacent space collapse either. Solution: Check for non-whitespace instead of visibility on the preceding node. task-6397398 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280331
We still have cases of people being confused by the fact that they send their invoices, reset it to draft, change something, then re-sending. Of course, the re-sending does not send on peppol, as it's already sent. It's more confusing than anything else. Prevent it if they're sent and not in error. task-6459869 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281525
Original PR description
We still have cases of people being confused by the fact that they send their invoices, reset it to draft, change something, then re-sending. Of course, the re-sending does not send on peppol, as it's already sent. It's more confusing than anything else. Prevent it if they're sent and not in error. task-6459869 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281525
Posting expenses opens the "Post Entries" wizard. When posting succeeds, the wizard's action redirects to the newly created journal entries, and the framework's action service closes the dialog with `noReload: true` while simultaneously destroying the current list view to mount the new action in its place. `ExpenseListController`'s `onClose` callback ignored this flag and unconditionally reloaded the list via `model.root.load()`. That call goes through `useService`'s `_protectMethod` wrapper, w
Original PR description
Posting expenses opens the "Post Entries" wizard. When posting succeeds, the wizard's action redirects to the newly created journal entries, and the framework's action service closes the dialog with `noReload: true` while simultaneously destroying the current list view to mount the new action in its place. `ExpenseListController`'s `onClose` callback ignored this flag and unconditionally reloaded the list via `model.root.load()`. That call goes through `useService`'s `_protectMethod` wrapper, which swaps in a promise that never resolves once the owning component is destroyed. Since the reload's RPC and the component's teardown race each other, the reload sometimes never resolved, so `onClose` never completed and the wizard dialog stayed open forever. Skip the reload when `noReload` is set: the list is being torn down anyway, and `onClick` already reloads it unconditionally right after the wizard dialog opens, so nothing is lost. opw-6372904 Forward-Port-Of: odoo/odoo#281464
Issue: ```python In [14]: receiver._get_peppol_proxy_endpoint('/2/get_services') Out[14]: '/api/peppol//2/get_services' In [15]: receiver._get_peppol_proxy_endpoint('2/get_services') Out[15]: '/api/peppol/2/get_services' ``` this raises: ```bash [ERROR] odoo.addons.account_peppol_response.models.account_edi_proxy_user Auto registration of peppol services for module: account_peppol_response failed on the user: ***, with exception: Invalid signature for request. This might be due to
Original PR description
Issue:
```python
In [14]: receiver._get_peppol_proxy_endpoint('/2/get_services')
Out[14]: '/api/peppol//2/get_services'
In [15]: receiver._get_peppol_proxy_endpoint('2/get_services')
Out[15]: '/api/peppol/2/get_services'
```
this raises:
```bash
[ERROR] odoo.addons.account_peppol_response.models.account_edi_proxy_user
Auto registration of peppol services for module: account_peppol_response failed on the user: ***, with exception: Invalid signature for request. This might be due to another connection to odoo Access Point server. It can occur if you have duplicated your database
```
OPW-6431279
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#281783Bug === When notifying by email a tracking change, the arrow and parenthesis are not rendered in the email body. Technical and Constraints ========================= The class `o_track` is only set in the web client template (`mail.Message`). There's no class in the body of the email that is sent. It can be rendered with "notification template" that we cannot change either (and they just do `t-out="message.body"`, so the body field of the mail message has to be properly rendered). We
Original PR description
Bug === When notifying by email a tracking change, the arrow and parenthesis are not rendered in the email body. Technical and Constraints ========================= The class `o_track` is only set in the web client template (`mail.Message`). There's no class in the body of the email that is sent. It can be rendered with "notification template" that we cannot change either (and they just do `t-out="message.body"`, so the body field of the mail message has to be properly rendered). We also need existing mail message to be rendered correctly, and so we need a way to differentiate mail message created before and after the fix to know when to disable the arrow and parenthesis. Task-6424104
Before this commit: ------------ - The order info button was not visible on the ticket screen in the mobile UI. After this commit: ------------ - Display the order info button in both the mobile and desktop views of the ticket screen. Related: - Enterprise: https://github.com/odoo/enterprise/pull/124485 Task-6388045
Original PR description
Before this commit: ------------ - The order info button was not visible on the ticket screen in the mobile UI. After this commit: ------------ - Display the order info button in both the mobile and desktop views of the ticket screen. Related: - Enterprise: https://github.com/odoo/enterprise/pull/124485 Task-6388045
An old refactor left some data around that are in conflict with other records for the same model. 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#281710 Forward-Port-Of: odoo/odoo#281276
Original PR description
An old refactor left some data around that are in conflict with other records for the same model. 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#281710 Forward-Port-Of: odoo/odoo#281276
Steps to reproduce the bug: - Install a localization that overrides invoice_policy defaults for storable products without an explicit company_id (e.g. l10n_ke_edi_oscu_stock, which forces 'delivery' in that case) - Run TestSaleMRPAngloSaxonValuation.test_sale_mrp_kit_bom_cogs (sale_mrp) or TestAngloSaxonValuation.test_anglo_saxon_cogs_partial_down_payment_credit_note (sale_stock) Problem: These tests create their products without setting invoice_policy explicitly, relying on the field's im
Original PR description
Steps to reproduce the bug: - Install a localization that overrides invoice_policy defaults for storable products without an explicit company_id (e.g. l10n_ke_edi_oscu_stock, which forces 'delivery'…
Steps to reproduce the bug: - Install a localization that overrides invoice_policy defaults for storable products without an explicit company_id (e.g. l10n_ke_edi_oscu_stock, which forces 'delivery' in that case) - Run TestSaleMRPAngloSaxonValuation.test_sale_mrp_kit_bom_cogs (sale_mrp) or TestAngloSaxonValuation.test_anglo_saxon_cogs_partial_down_payment_credit_note (sale_stock) Problem: These tests create their products without setting invoice_policy explicitly, relying on the field's implicit default. l10n_ke_edi_oscu_stock's _compute_invoice_policy (https://github.com/odoo/enterprise/blob/4e459417dac809caafea34aa2e487fc3c1f0ce1a/l10n_ke_edi_oscu_stock/models/product.py#L16-L21) forces invoice_policy to 'delivery' for any storable product whose company_id is not set, which is the case for products created in these test fixtures. Once invoice_policy becomes 'delivery', invoiced quantities are driven by qty_delivered instead of the ordered quantity, which the affected tests never account for (some deliver an arbitrary quantity instead of the exact BoM demand, others never validate a delivery at all), causing wrong COGS amounts or wrongly invoiced quantities as soon as such a localization is installed alongside these modules. Solution: Pin invoice_policy to 'order' explicitly wherever these test fixtures create their products, so the test outcome no longer depends on which other modules happen to be installed. runbot-243633 Forward-Port-Of: odoo/odoo#279277 Forward-Port-Of: odoo/odoo#278346
`test_orderpoint_activity_portal_context_leak` assumes that running the orderpoint will trigger a procurement exception. However, depending on which modules are installed (e.g., when `purchase_stock` is absent), standard stock rules for the test warehouse destination location can succeed in generating stock moves rather than raising an error. Deactivate all matching destination stock rules on the test warehouse prior to running procurement so the orderpoint is guaranteed to fail. runbot-94
Original PR description
`test_orderpoint_activity_portal_context_leak` assumes that running the orderpoint will trigger a procurement exception. However, depending on which modules are installed (e.g., when `purchase_stock` is absent), standard stock rules for the test warehouse destination location can succeed in generating stock moves rather than raising an error. Deactivate all matching destination stock rules on the test warehouse prior to running procurement so the orderpoint is guaranteed to fail. runbot-941316 Forward-Port-Of: odoo/odoo#279781
Before this commit, marking several manufacturing orders as done at once crashed or could post labour costs on the wrong account, because the labour posting loop read the product and the company from the whole recordset instead of the manufacturing order being processed. Steps to reproduce: - activate a second company, e.g. My Company (Chicago) - create a manufacturing order in each company and confirm them - in the Manufacturing Orders list view, select both orders and mark them as done
Original PR description
Before this commit, marking several manufacturing orders as done at once crashed or could post labour costs on the wrong account, because the labour posting loop read the product and the company from…
Before this commit, marking several manufacturing orders as done at once crashed or could post labour costs on the wrong account, because the labour posting loop read the product and the company from the whole recordset instead of the manufacturing order being processed. Steps to reproduce: - activate a second company, e.g. My Company (Chicago) - create a manufacturing order in each company and confirm them - in the Manufacturing Orders list view, select both orders and mark them as done A "ValueError: Expected singleton: res.company(...)" traceback is raised and none of the orders can be closed, even though each one can be marked as done individually. With same-company orders of different products, the production location resolved from the union of products, so the labour entry could be posted against another product's WIP account. Use the manufacturing order of the current loop iteration to resolve the production location, as the rest of the loop already does. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276586
In saas-19.1, `purchase_cdnur_regular` was renamed to `purchase_cdnur_overseas`. However, commit https://github.com/odoo/odoo/commit/c4b0911e061ff0619bd3d6a411701fc898dad258 still used the old section name. This commit updates `purchase_cdnur_regular` to `purchase_cdnur_overseas`. Forward-Port-Of: odoo/odoo#281895
Original PR description
In saas-19.1, `purchase_cdnur_regular` was renamed to `purchase_cdnur_overseas`. However, commit https://github.com/odoo/odoo/commit/c4b0911e061ff0619bd3d6a411701fc898dad258 still used the old section name. This commit updates `purchase_cdnur_regular` to `purchase_cdnur_overseas`. Forward-Port-Of: odoo/odoo#281895
Before this commit: --- - When a sale order line contained extra attribute addons, those values were not transferred to the POS order line while settling the sales order. After this commit: --- - Preserved extra attribute addons when creating POS order lines from SO. task-6204583 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276143
Original PR description
Before this commit: --- - When a sale order line contained extra attribute addons, those values were not transferred to the POS order line while settling the sales order. After this commit: --- - Preserved extra attribute addons when creating POS order lines from SO. task-6204583 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276143
Steps: - Install `account_peppol` module. - Set `Peppol` compatible country and related details - Go to my/account page. Issue: - Peppol related details always displayed on `my/account` page even though user select different invoice sending method like: `By Email`. Casue: - selector to manage visibility of Peppol related details in `my/account` is wrong and because of that those fields always display. Probably because https://github.com/odoo/odoo/pull/195764 and backport of this https
Original PR description
Steps: - Install `account_peppol` module. - Set `Peppol` compatible country and related details - Go to my/account page. Issue: - Peppol related details always displayed on `my/account` page even…
Steps: - Install `account_peppol` module. - Set `Peppol` compatible country and related details - Go to my/account page. Issue: - Peppol related details always displayed on `my/account` page even though user select different invoice sending method like: `By Email`. Casue: - selector to manage visibility of Peppol related details in `my/account` is wrong and because of that those fields always display. Probably because https://github.com/odoo/odoo/pull/195764 and backport of this https://github.com/odoo/odoo/pull/198327 merged at same time. Fix: - Update selector to fix this ### [FIX] account_peppol: fix error when setting wrong endpoint Steps: - Install `account_peppol` module. - Set `Peppol` compatible country and related details. - Go to my/account page. - Set some wrong Peppol value for `Peppol e-Address (EAS)` or `Peppol Endpoint` or `Electronic format`. Issue: - Not able to save those details without any error message on address page and getting error on console `Cannot read properties of undefined (reading 'classList')`. Casue: - In this PR https://github.com/odoo/odoo/pull/190312 when adapting portal page we set not existing fields in `invalid_fields` details and because of that it can't find related fields on address page and don't allow to save details without raising proper error message. Fix: - Updated `invalid_fields` values to properly target them ### [FIX] account_peppol: fix display issue for peppol related fields in address Forward-Port-Of: odoo/odoo#281718
Steps to reproduce: 1. Refund an order using a Glory Cash payment method 2. The machine refunds the cash correctly **Expected behaviour:** Odoo validates the refund **Actual behaviour:** Odoo sets the line amount to zero, refund incomplete The fix is to correctly remove the money dispensed from the payment total, resulting in a negative payment amount rather than zero. In addition, we remove similar logic for Cashdro machines that was also broken as the code path was never executed.
Original PR description
Steps to reproduce: 1. Refund an order using a Glory Cash payment method 2. The machine refunds the cash correctly **Expected behaviour:** Odoo validates the refund **Actual behaviour:** Odoo sets the line amount to zero, refund incomplete The fix is to correctly remove the money dispensed from the payment total, resulting in a negative payment amount rather than zero. In addition, we remove similar logic for Cashdro machines that was also broken as the code path was never executed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281938
Steps to reproduce the bug: - Enable 2-step delivery (pick + ship) on a warehouse. - Set both rules on the delivery route to "Pull" (instead of the default Pull + Push): - Pick rule (Stock -> Output): action = Pull, procure_method = make_to_stock - Ship rule (Output -> Customers): action = Pull, procure_method = make_to_order - Create a sale order for qty 1 and confirm it. - Validate the Pick transfer. - Return the Pick transfer. - Cancel the sale order. - Set it back to quotati
Original PR description
Steps to reproduce the bug: - Enable 2-step delivery (pick + ship) on a warehouse. - Set both rules on the delivery route to "Pull" (instead of the default Pull + Push): - Pick rule (Stock ->…
Steps to reproduce the bug:
- Enable 2-step delivery (pick + ship) on a warehouse.
- Set both rules on the delivery route to "Pull" (instead of the default Pull + Push):
- Pick rule (Stock -> Output): action = Pull, procure_method = make_to_stock
- Ship rule (Output -> Customers): action = Pull, procure_method = make_to_order
- Create a sale order for qty 1 and confirm it.
- Validate the Pick transfer.
- Return the Pick transfer.
- Cancel the sale order.
- Set it back to quotation and confirm it again.
Problem:
The newly created delivery (ship) move ends up asking for a wrong, inflated quantity instead of the ordered one (e.g. 3 times the ordered qty for the scenario above; the multiplier depends on the number of prior confirm/cancel/return cycles).
`_action_cancel` (addons/sale_stock/models/sale_order.py) only cancels pickings that are not `done`, so after the pick is validated and returned, cancelling the SO only cancels the still-pending ship move. The pick move and its return stay `done` and linked to the sale order line.
`SaleOrderLine._get_outgoing_incoming_moves` determines which rule "started" the pull/push chain by picking the rule of the first surviving (non-cancelled) move, grouped by warehouse: https://github.com/odoo/odoo/blob/d7bad3dc6c068ffe8643ecb01da1865d743bfb8f/addons/sale_stock/models/sale_order_line.py#L338-L347
Once the ship move is cancelled, it is excluded from that computation, so the Pick rule is wrongly identified as the "triggering" rule instead of the Ship rule. The done pick move and its return share that rule, so they both end up wrongly classified as incoming (returned) quantities instead of being excluded from the computation like before the cancellation, corrupting `_get_qty_procurement`. On reconfirm, `_action_launch_stock_rule` computes
`product_qty = product_uom_qty - qty`, inflating the quantity requested on the new ship move.
Solution:
Identify the triggering rule from the sale order line's full move history, including cancelled moves, so cancelling a move later doesn't change which rule is considered to have started the chain.
opw-6364113
Forward-Port-Of: odoo/odoo#280280Steps to reproduce the bug: - Create three storable products C1 ($10), C2 ($20), C3 ($5) - Create a product P1 with a BoM: 1x C1 + 1x C2 - Create a Manufacturing Order for P1 and validate it - Unlock the MO (Settings > Unlock) - Add C3 as an extra component on the unlocked MO - Open the MO overview Problem: The extra move had value=0 after creation, causing the unit_cost in the MO overview to appear as 0. When a move is added to a done picking or MO it is created with state='done' an
Original PR description
Steps to reproduce the bug: - Create three storable products C1 ($10), C2 ($20), C3 ($5) - Create a product P1 with a BoM: 1x C1 + 1x C2 - Create a Manufacturing Order for P1 and validate it - Unlock…
Steps to reproduce the bug: - Create three storable products C1 ($10), C2 ($20), C3 ($5) - Create a product P1 with a BoM: 1x C1 + 1x C2 - Create a Manufacturing Order for P1 and validate it - Unlock the MO (Settings > Unlock) - Add C3 as an extra component on the unlocked MO - Open the MO overview Problem: The extra move had value=0 after creation, causing the unit_cost in the MO overview to appear as 0. When a move is added to a done picking or MO it is created with state='done' and quantity set immediately. This triggers _set_quantity_done, which creates the move line and calls _set_value(correction_quantity=delta). Inside _set_value, for outgoing moves with a correction_quantity, the code computes: previous_qty = move.quantity - correction_quantity Since the move had no prior quantity, previous_qty=0. The original code then computed ratio=0 and applied move.value += 0, leaving value=0 instead of computing it from scratch. Solution: When previous_qty=0, skip the ratio branch and fall through to the existing from-scratch computation (standard_price * _get_valued_qty() for AVCO/standard costing, _run_fifo() for FIFO). opw-6377393 Forward-Port-Of: odoo/odoo#279962 Forward-Port-Of: odoo/odoo#276303
Before this commit, the html composer variant of "Opening thread with needaction messages should mark all messages of thread as read" failed at random on runbot: 11. [verifySteps] expected the following steps > Expected: [ "mark-all-messages-as-read", ] > Received: [] This happens because the channel of that variant holds no message, so the test goes to the inbox before the channel is loaded and it keeps scrollUnread set. Opening the channel again then loads its m
Original PR description
Before this commit, the html composer variant of "Opening thread with needaction messages should mark all messages of thread as read" failed at random on runbot: 11. [verifySteps] expected the…
Before this commit, the html composer variant of "Opening thread with needaction messages should mark all messages of thread as read" failed at random on runbot:
11. [verifySteps] expected the following steps
> Expected: [
"mark-all-messages-as-read",
]
> Received: []
This happens because the channel of that variant holds no message, so the test goes to the inbox before the channel is loaded and it keeps scrollUnread set. Opening the channel again then loads its messages around the 0 separator, and that fetch calls set_message_done, which marks the needaction message as read and leaves nothing for mark_all_as_read to mark.
This commit fixes the issue by giving the channel two messages, pointing the separator at the first one and waiting for their display: loading messages around the separator is skipped when that message is already loaded, so opening the channel again fetches nothing, which the closing assertion checks as well.
The text composer variant gets the same fixture, so that both variants read as master does, from commit 8cd330e3e2d5b1d857d3effb80aa8176d60b38f9. It does not fail: it already waits for a message of its own, and a fetch around its non-zero separator leaves the messages alone in the mock.
https://runbot.odoo.com/odoo/error/945744
Forward-Port-Of: odoo/odoo#282038
Forward-Port-Of: odoo/odoo#281714Steps to reproduce: - 1. In the website editor, open the portal "My Account" page and, in the Customize panel, disable the "Timesheets" option. 2. As a portal user, open My Account > Tasks for a project whose tasks have allocated time and logged timesheets. 3. Look at the task list, then open one of those tasks. Issue: - The task list still shows the per-group "Total: spent / allocated", and the task detail page still shows "Allocated Time", even though timesheets are hidden in the port
Original PR description
Steps to reproduce: - 1. In the website editor, open the portal "My Account" page and, in the Customize panel, disable the "Timesheets" option. 2. As a portal user, open My Account > Tasks for a project whose tasks have allocated time and logged timesheets. 3. Look at the task list, then open one of those tasks. Issue: - The task list still shows the per-group "Total: spent / allocated", and the task detail page still shows "Allocated Time", even though timesheets are hidden in the portal. Fix: - - Add `_show_portal_timesheets()` to the condition of the list "Total" column. - Gate the `portal_my_task_allocated_hours` block on `_show_portal_timesheets()` in the task detail page. task-6140807 Forward-Port-Of: odoo/odoo#272043
Before this commit, the test "Shows warning badge on mic/camera on non-granted permission in meeting conversations" failed on runbot, on 19.0: Failed to find 1 of "button[title='Turn camera on']" (Timeout of 10 seconds). Found 0 instead. This happens because the mock server numbers a new record with the highest id of the model plus one, so a record created right after the last one is deleted takes its id back. Joining another call leaves the meeting call first, and the session of the new c
Original PR description
Before this commit, the test "Shows warning badge on mic/camera on non-granted permission in meeting conversations" failed on runbot, on 19.0: Failed to find 1 of "button[title='Turn camera on']"…
Before this commit, the test "Shows warning badge on mic/camera on non-granted permission in meeting conversations" failed on runbot, on 19.0: Failed to find 1 of "button[title='Turn camera on']" (Timeout of 10 seconds). Found 0 instead. This happens because the mock server numbers a new record with the highest id of the model plus one, so a record created right after the last one is deleted takes its id back. Joining another call leaves the meeting call first, and the session of the new call carries the id of the one just left. Leaving broadcasts "discuss.channel.rtc.session/ended" for that id, and under load it lands after the join: the client reads it as its own session being closed and ends the call it has just joined. This commit numbers the records of a model with a counter, started above the ids its definition gives, as a database sequence does, so a notification about a deleted record can no longer name a live one. https://runbot.odoo.com/odoo/error/945965 Forward-Port-Of: odoo/odoo#282244
Documentation and clarification updates
Description of the issue/feature this PR addresses: Signing the Odoo Individual Contributor License Agreement v1.0. Name: Alejandro Martínez GitHub login: alexmbar Email: alexmbar891@gmail.com Country: México Current behavior before PR: I have no CLA signature on file, so my pending l10n_mx contributions (#264576, #264580, #264582, #264583) fail the legal/cla check and cannot be merged. Desired behavior after PR is merged: doc/cla/individual/alexmbar.md is present and the legal/
Original PR description
Description of the issue/feature this PR addresses: Signing the Odoo Individual Contributor License Agreement v1.0. Name: Alejandro Martínez GitHub login: alexmbar Email: alexmbar891@gmail.com Country: México Current behavior before PR: I have no CLA signature on file, so my pending l10n_mx contributions (#264576, #264580, #264582, #264583) fail the legal/cla check and cannot be merged. Desired behavior after PR is merged: doc/cla/individual/alexmbar.md is present and the legal/cla check passes for my contributions. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281391
Miscellaneous changes
- Compute the standard durations for all French leaves in a single `_get_durations()` call instead of recomputing them for each leave. - Reuse the precomputed duration mapping while calculating the French legal duration for each leave. - Keep the existing French-specific duration calculation unchanged, including public holidays, company calendar, date extension, and half-day handling. This avoids repeated ORM computations when processing multiple French leaves in a batch an
Original PR description
- Compute the standard durations for all French leaves in a single `_get_durations()` call instead of recomputing them for each leave. - Reuse the precomputed duration mapping while calculating the…
- Compute the standard durations for all French leaves in a single `_get_durations()` call instead of recomputing them for each leave. - Reuse the precomputed duration mapping while calculating the French legal duration for each leave. - Keep the existing French-specific duration calculation unchanged, including public holidays, company calendar, date extension, and half-day handling. This avoids repeated ORM computations when processing multiple French leaves in a batch and significantly improves the performance of leave duration computation. Performance testing was performed using the `hr.leave.employee.report` introduced in 19.1, which calls `_get_durations()` on a large batch of virtual leaves. Performance testing on a database containing 677 leaves, including 298 French leaves: | Metric | Before | After | |------------------------------------|-----------------|-------------| | Standard duration computations | 298 | 1 | | Total `_get_durations()` | >169s (timeout) | ~24s | not specific to the employee report and benefits any caller that invokes _get_durations() on a larger batch. **opw-6421323** --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281914 Forward-Port-Of: odoo/odoo#281165