Daily updates from Odoo
Thursday, August 13, 2026
40 changes · saas-19.1
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
Before this commit: - Refund orders of scheduled (with shipping date) orders always generated a new picking with negative quantities, even when the original delivery had not been completed. - This could lead to incorrect stock movements and negative quantity computations for undelivered pickings. After this commit: - When processing a refund of a scheduled (with shipping date) order, the behavior now depends on the state of the original picking: - If the picking has already been del
Original PR description
Before this commit:
- Refund orders of scheduled (with shipping date) orders always generated a new picking with negative quantities, even when the original delivery had not been completed.
- This could lead to incorrect stock movements and negative quantity computations for undelivered pickings.
After this commit:
- When processing a refund of a scheduled (with shipping date) order, the behavior now depends on the state of the original picking:
- If the picking has already been delivered, a return picking is created with the corresponding negative quantities.
- If the picking has not been delivered, the original picking is updated instead:
- The picking is cancelled for a full refund.
- Refunded product moves are removed from the picking for a partial refund.
- This prevents unnecessary negative stock movements and ensures stock operations remain consistent with the delivery status.
Task-5902424
Forward-Port-Of: odoo/odoo#271506This commit adds both Python and JS unit tests for the Mollie POS payment method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281742
Original PR description
This commit adds both Python and JS unit tests for the Mollie POS payment method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281742
Steps to reproduce: 0. Link a Stripe terminal to a payment method and add the payment method to a kiosk pos.config 1. Select products and initiate payment 3. Stripe error - TypeError: Cannot set properties of undefined(setting 'stripecardpresentnetwork') Paymentline uiState is never initialized because pos_stripe/static/src/overrides/models/pos_payment.js is missing from the payment_terminals bundles and is therefore never loaded in kiosk mode. This commit ensures that the file is loaded
Original PR description
Steps to reproduce: 0. Link a Stripe terminal to a payment method and add the payment method to a kiosk pos.config 1. Select products and initiate payment 3. Stripe error - TypeError: Cannot set properties of undefined(setting 'stripecardpresentnetwork') Paymentline uiState is never initialized because pos_stripe/static/src/overrides/models/pos_payment.js is missing from the payment_terminals bundles and is therefore never loaded in kiosk mode. This commit ensures that the file is loaded and that the PosPayment setup() is completed. opw-6419140 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
### [FIX] website: fix GMaps deprecation console warning for s_google_map Google deprecated the synchronous script loader for initializing the Maps JS API. This caused browser console warnings. The fix adopts Google's official `importLibrary()` bootstrap pattern, which loads map libraries (places, maps, marker) lazily on demand rather than all at once.The version is updated to `v=weekly`, which Google recommends as it receives updates weekly versus quarterly for version numbers(`v=num
Original PR description
### [FIX] website: fix GMaps deprecation console warning for s_google_map Google deprecated the synchronous script loader for initializing the Maps JS API. This caused browser console warnings. The…
### [FIX] website: fix GMaps deprecation console warning for s_google_map Google deprecated the synchronous script loader for initializing the Maps JS API. This caused browser console warnings. The fix adopts Google's official `importLibrary()` bootstrap pattern, which loads map libraries (places, maps, marker) lazily on demand rather than all at once.The version is updated to `v=weekly`, which Google recommends as it receives updates weekly versus quarterly for version numbers(`v=number`). Steps to reproduce: 1. Add the `s_google_map` snippet(not the`s_map`, enable debug mode) 2. Open the browser console and observe the deprecation warning ### [IMP] website: warn user to reload after GMaps config changes Switching from the legacy Google Maps APIs to the new APIs requires enabling additional services in Google Cloud. Existing maps using the legacy API continue to work, but when an admin edits a map without a proper configuration, the `GoogleMapAPIKeyDialog` dialog opens. Google Maps configuration changes (API key update or enabling services) do not take effect during the current editor session because the Maps JavaScript API is loaded at page initialization. Before this commit, such misconfigurations (disabled services or invalid API keys) only triggered a dialog showing a generic Google Maps error. After this commit, a notification informs the user that the page must be reloaded for configuration changes to take effect. The setup instructions are also updated to reference the "Places API (NEW)" service. ### [IMP] website: replace deprecated Places API calls in GPS picker The GPS picker relied on `PlacesService.nearbySearch` and `getDetails`, which are part of the deprecated Places API. The new places API replaces these with `Place.searchNearby` and `fetchFields`. Error handling is consolidated into a single try/catch since the new Places API throws on failure rather than returning a status code, removing the need for `PlacesServiceStatus` checks. ### [IMP] website, *: replace deprecated Google Autocomplete *: website_form_project google.maps.places.Autocomplete is deprecated in the new Places API. The replacement (`AutocompleteSuggestion.fetchAutocompleteSuggestions`) does not fire DOM events, making it incompatible with the old event-listener pattern used in GPSPicker. A new Owl component (`PlacesAutoComplete`) is introduced to wrap the new API, built on top of the existing `AutoCompleteWithPages`. References: https://developers.google.com/maps/documentation/javascript/load-maps-js-api https://developers.google.com/maps/documentation/javascript/advanced-markers/migration https://developers.google.com/maps/documentation/javascript/legacy/places-migration-overview task-[4441041](https://www.odoo.com/odoo/project/974/tasks/4441041) Forward-Port-Of: odoo/odoo#281029 Forward-Port-Of: odoo/odoo#242765
Resolved issues and error corrections
Users without accounting permissions could be prevented from confirming sales orders when a Studio approval rule referenced certain customer follow-up fields. This fix lets the approval check evaluate those rules correctly, avoiding unnecessary access errors while preserving the approval process.
Original PR description
continuation of [PR](https://github.com/odoo/enterprise/pull/121856) Issue: Inside _get_approval_spec filtered_domain is called a few times and due to a related field that calls an access rights group that the user who used the action isnt apart of is blocked by the filtered_domain. To Replicate: 1) Install studio, sale, Accounting and make sure "account_followup" is installed 2) create a related field on the sales.order form related to "customer -> follow up status" 3) Save 4) Create a "Studio Approval Rule" (studio.approval.rule) with a domain using the new related studio field -> method : "action_confirm" -> approver:admin 5)create a test user with no accounting access rights 6) in an incognito browser try and create a sales order, and then confirm it. it will throw the access rights error Solution: Go one up the stack where _get_approval_spec is called and add a syudo for those calls opw-6316069 Forward-Port-Of: odoo/enterprise#127412
The Replace button in helpdesk stock workflows now remains visible even when no customer is selected. This keeps the ticket interface consistent with related actions and prevents users from missing the replacement option.
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 update adjusts an automated accounting test to match a recent underlying fix in how grouped data is read. It helps keep the accounting module's quality checks accurate and prevents false test failures during validation.
Original PR description
The fix at https://github.com/odoo/odoo/pull/281911 adds bin_size: tru in the web_read_group. This commit adpats an accounting test as a consequence Forward-Port-Of: odoo/enterprise#127638
Users with read-only accounting access can now see the General section in the Accounting tab of contact records, including bank account details. This fixes a view configuration issue that accidentally hid information users were already allowed to access.
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
When receiving lot-tracked products with putaway rules, the Barcode app now keeps the correct destination shelf for each scanned lot. This prevents extra lots from being placed on the general stock location by mistake, improving warehouse accuracy.
Original PR description
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2…
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2 units of that product; putaway sets the reserved move line destination to WH/Stock/Shelf 1. 4. In the Barcode app, scan a first lot, then a second lot. The second lot lands on a separate line at WH/Stock instead of WH/Stock/Shelf 1. Issue --- The first lot reuses the reserved line and keeps its Shelf 1 destination. The second lot cannot reuse it because its tracking number differs, so `_findLine` returns nothing and `_getNewLineDefaultValues` builds a new line with `location_dest_id` set to `_defaultDestLocation()`, the picking's default destination (WH/Stock). https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L1591-L1601 Putaway relocates the destination on the move line at reservation, never on the picking, so only the reserved line carries Shelf 1. Since `groupKey` includes `location_dest_id`, the new line does not group with the first lot and shows separately at WH/Stock. This is not a regression: new lines have always defaulted to the operation destination. https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L239-L241 The new line now inherits the selected line's `location_dest_id`, already relocated by putaway, instead of the default. opw-6317077 Forward-Port-Of: odoo/enterprise#125309
Global invoice creation for Mexican point-of-sale orders now ignores cancelled refunds, so only completed refunds affect the invoice totals. This prevents valid invoices from failing when a cancelled refund exists alongside a paid refund.
Original PR description
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click…
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click "Return Products" to make a refund, but don't pay it, cancel it instead. 4. From the same order, click "Return Products" again to make a second refund, and pay it normally. 5. Go to the orders list, select the main order and the paid refund (not the cancelled one), then Actions > Create Global Invoice. -> Observation: error in the global invoice. In the CFDI tab of the main order the line is "Send Global In Error", and hovering on it the detail says "Failed to distribute some negative lines". Why: ---- When we make the global invoice, we remove the refunds from the order. A cancelled refund was never paid, so we should not count it. But we were counting it too. So we removed the refund amount twice in our case, one for the paid refund, and one for the cancelled one, and we end up with an order with negative amount that cannot be distributed. The fix: -------- We now skip the cancelled orders when we search the refunds, the same way it is done above when we collect the refunded orders. opw-6261404 Forward-Port-Of: odoo/enterprise#127560 Forward-Port-Of: odoo/enterprise#120996
Automated account transfers now balance correctly when destination percentages are below 100%. This prevents one-cent rounding differences from creating unbalanced journal entries, improving reliability for accounting workflows.
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 UK CIS report now correctly shows payments for receipts that include CIS tax, not just vendor bills. This helps businesses keep CIS reporting complete and accurate across more purchase document types.
Original PR description
With the l10n_uk_reports_cis module installed: - Create a vendor bills and add a CIS tax --> This vendor's bills appear correctly in the report. - Create a receipt and add a CIS tax --> This type of bill appears in the report, but the payment is not showing up. opw-6282548 Forward-Port-Of: odoo/enterprise#124043
This fix corrects an incorrect enumeration used in Swiss withholding tax mutation declarations. It helps ensure payroll declaration data is categorized properly when sent or prepared for Swiss reporting requirements.
Original PR description
task-6116327 Forward-Port-Of: odoo/enterprise#127745
This fixes an issue where signatures could disappear from downloaded signed PDFs when the original document used unusual page positioning from another PDF tool. Users can now trust that signatures visible during preview will also appear correctly in the final downloaded document.
Original PR description
Steps to reproduce (version 16+): 1) Obtain a pdf with a negative origin point: This can occur when a customer exports a pdf from another software, or it can be made manually using a python script 2) In the sign app, upload the pdf and create a new template, add a signature field to the document. 3) Sign the document. The preview will load correctly and the signature will be visible 4) Download and open the signed pdf. The signature is not on the document Notes: Issue occurs because the signature was added to the pdf outside of the visible area. The preview works because the signature is rendered on top of the unsigned document in the correct location. The issue can be fixed applying a translation to the canvas. Ticket: [6317223](https://www.odoo.com/odoo/project/49/tasks/6317223?debug=assets) Forward-Port-Of: odoo/enterprise#121960
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
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 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 and since the new read_group (which fetches records from open groups server side), images were loaded as base64, overloading the return payload and potentially triggering overload errors (MemoryError) This was because the bin_size = true context key was forgotten. After this commit, images are not loaded as base64 thanks to that context key Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged:
Original PR description
Before this commit and since the new read_group (which fetches records from open groups server side), images were loaded as base64, overloading the return payload and potentially triggering overload errors (MemoryError) This was because the bin_size = true context key was forgotten. After this commit, images are not loaded as base64 thanks to that context key 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#281911
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
Following this commit: ==== - When a combo is broken down, its items are assigned to their respective courses. - Remove a course when all its items are deleted from the cart. task-6121521
Original PR description
Following this commit: ==== - When a combo is broken down, its items are assigned to their respective courses. - Remove a course when all its items are deleted from the cart. task-6121521
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#281783When edit_translations is set, convert_to_record wraps translated terms in branding spans. Related (non-stored) fields re-read that already-wrapped value and ran the same wrapping again, producing nested spans. Only wrap terms for stored fields so related Html inherits the source branding unchanged. Also keep data-oe-translation-state in HTML safe_attrs so sanitization does not strip it. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior af
Original PR description
When edit_translations is set, convert_to_record wraps translated terms in branding spans. Related (non-stored) fields re-read that already-wrapped value and ran the same wrapping again, producing nested spans. Only wrap terms for stored fields so related Html inherits the source branding unchanged. Also keep data-oe-translation-state in HTML safe_attrs so sanitization does not strip it. 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#281729 Forward-Port-Of: odoo/odoo#280397
`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
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
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
Before this commit, the two steps posting "Hello everyone!" were spliced into the meeting view tour at the index of the step clicking on the Chat action, looked up with `steps.find`. That returns the step itself, so `splice` coerced it to NaN and inserted at 0: the message was posted as the very first thing the tour did, and the marker it searched for served no purpose. Reminder that the index it aimed for does not work: the meeting view is fullscreen with the invite panel open there, and the
Original PR description
Before this commit, the two steps posting "Hello everyone!" were spliced into the meeting view tour at the index of the step clicking on the Chat action, looked up with `steps.find`. That returns the step itself, so `splice` coerced it to NaN and inserted at 0: the message was posted as the very first thing the tour did, and the marker it searched for served no purpose. Reminder that the index it aimed for does not work: the meeting view is fullscreen with the invite panel open there, and the only composer belongs to the chat panel, which opens one step later. This commit writes the two steps at the head of the list and drops the marker, so the tour runs in the order it reads. Forward-Port-Of: odoo/odoo#282060
As the `requirements.txt` file path changed from `addons/iot_box_image` to `setup/iot_box_builder` the checkout from 19 to saas-19.4 can't find the file (looking at the former path instead of the new one). As a workaround, we add `sentry_sdk` requirement in v19.0. Forward-Port-Of: odoo/odoo#282001
Original PR description
As the `requirements.txt` file path changed from `addons/iot_box_image` to `setup/iot_box_builder` the checkout from 19 to saas-19.4 can't find the file (looking at the former path instead of the new one). As a workaround, we add `sentry_sdk` requirement in v19.0. Forward-Port-Of: odoo/odoo#282001
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_fr_pdp is installed. The module extends the method _compute_show_reset_to_draft_button which reads l10n_fr_pdp_sent_in_flow_ids. That field is only readable by the accounting groups while show_reset_to_draft_button is declared in the standard invoice form without any groups restriction < field name="show_reset_to_draft_button" invisible="1"/ > in account.view_move
Original PR description
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_fr_pdp is installed. The module extends the method…
Description of the issue/feature this PR addresses: A user without accounting rights cannot open an invoice form when l10n_fr_pdp is installed. The module extends the method _compute_show_reset_to_draft_button which reads l10n_fr_pdp_sent_in_flow_ids. That field is only readable by the accounting groups while show_reset_to_draft_button is declared in the standard invoice form without any groups restriction < field name="show_reset_to_draft_button" invisible="1"/ > in account.view_move_form Every user able to open an invoice therefore reads it. Steps to reproduce: - install `l10n_fr_pdp` - create a salesman user with sales rights but no accounting right (*Own Documents Only* is enough) - create a FR company and a FR customer - give the salesman access to the FR company - activate Peppol in the general settings - log in as the salesman - create a sale order in the FR company for the FR customer - confirm it - click **Create Invoice** - click **Create Draft** Current behavior before PR: An Access Error dialog is raised Failed to read field account.move.l10n_fr_pdp_sent_in_flow_ids You are not allowed to access 'French PDP Flow' (l10n.fr.pdp.reports.flow) records. This operation is allowed for the following groups: - Accounting/Administrator - Accounting/Invoicing - Show Accounting Features - Readonly - Show Full Accounting Features In odoo.sh, the standard test sale_management / TestSaleFlowTourPostInstall.test_basic_sale_flow_with_minimal_access_rights fails for the same reason as soon as l10n_fr_pdp is installed alongside sale_management. Desired behavior after PR is merged: On a database with l10n_fr_pdp installed, a non-accountant user having the possibility to create invoice should not have the error message displayed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280754
Many users were receiving duplicate vendor bills. The issue was that duplicates were never detected in the receiving flow. Every incoming message returned by the proxy was processed and turned into a new `account.move`, even if it had already been imported previously. This commit filters out messages whose UUID already matches an existing `account.move` before processing them, and acknowledges those duplicates on the IAP side so they are not received again on the next run. task-5930116
Original PR description
Many users were receiving duplicate vendor bills. The issue was that duplicates were never detected in the receiving flow. Every incoming message returned by the proxy was processed and turned into a new `account.move`, even if it had already been imported previously. This commit filters out messages whose UUID already matches an existing `account.move` before processing them, and acknowledges those duplicates on the IAP side so they are not received again on the next run. task-5930116 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280445 Forward-Port-Of: odoo/odoo#274963
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
Before this commit, `waitStoreFetch` returns before the answer is in the store: right after `waitStoreFetch("channels_as_member")`, the store holds no record for a channel that answer carries, on a hundred runs out of a hundred. A test that then asserts on the fetched data depends on timing. This happens because `listenStoreFetch` steps from the `onRpc` callback, which runs before the route is served. The `microTick` at the end of `waitStoreFetch` is meant to cover the rest of the round trip,
Original PR description
Before this commit, `waitStoreFetch` returns before the answer is in the store: right after `waitStoreFetch("channels_as_member")`, the store holds no record for a channel that answer carries, on a hundred runs out of a hundred. A test that then asserts on the fetched data depends on timing.
This happens because `listenStoreFetch` steps from the `onRpc` callback, which runs before the route is served. The `microTick` at the end of `waitStoreFetch` is meant to cover the rest of the round trip, but the answer only reaches the store six microtasks later.
This commit steps from `Store.fetchStoreData` instead, whose promise resolves once the answer is in the store, and drops the tick. The `onRpc` option keeps its route hooks, as tests use it to delay a request.
Forward-Port-Of: odoo/odoo#282043
Forward-Port-Of: odoo/odoo#281499Description of the issue/feature this PR addresses: Odoo supports WebP image fields, but `base_import` validates remote images with `PIL.Image.open()`. Odoo intentionally leaves Pillow's WebP decoder unloaded, so a valid WebP URL is rejected as an unidentified image. Current behavior before PR: Importing a valid WebP image URL fails with `cannot identify image file`. Oversized and unsupported WebP files are also rejected by Pillow before the import-specific size policy can be applied. Desire
Original PR description
Description of the issue/feature this PR addresses: Odoo supports WebP image fields, but `base_import` validates remote images with `PIL.Image.open()`. Odoo intentionally leaves Pillow's WebP decoder…
Description of the issue/feature this PR addresses: Odoo supports WebP image fields, but `base_import` validates remote images with `PIL.Image.open()`. Odoo intentionally leaves Pillow's WebP decoder unloaded, so a valid WebP URL is rejected as an unidentified image. Current behavior before PR: Importing a valid WebP image URL fails with `cannot identify image file`. Oversized and unsupported WebP files are also rejected by Pillow before the import-specific size policy can be applied. Desired behavior after PR is merged: Use Odoo's existing WebP header parser for dimension validation. Valid WebP URLs import unchanged, unsupported WebP remains rejected, and the existing 42-million-pixel import limit remains enforced. Tests cover valid, unsupported, and oversized WebP URL payloads. The complete `test_base_import` suite passes (56 tests, 0 failures/errors). --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281829 Forward-Port-Of: odoo/odoo#276648
Steps to Reproduce: ------------------------ - Install the Point of Sale module & create an order with a customer (partner). - Scan the QR code on the receipt to retrieve the invoice. Issue: ------- When clicking `Get My Invoice`, the invoice was not being generated. Cause: --------- - The correct partner was not being set. POS customer scanning the QR code is not logged into Odoo, so no partner is associated with the request. We were incorrectly using the logged-in user’s partner,
Original PR description
Steps to Reproduce: ------------------------ - Install the Point of Sale module & create an order with a customer (partner). - Scan the QR code on the receipt to retrieve the invoice. Issue: -------…
Steps to Reproduce: ------------------------ - Install the Point of Sale module & create an order with a customer (partner). - Scan the QR code on the receipt to retrieve the invoice. Issue: ------- When clicking `Get My Invoice`, the invoice was not being generated. Cause: --------- - The correct partner was not being set. POS customer scanning the QR code is not logged into Odoo, so no partner is associated with the request. We were incorrectly using the logged-in user’s partner, which resulted in an empty partner and therefore an empty VAT value. - The customer's country was also incorrect because the partner’s country was fetched but then overwritten by the order’s country due to improper value assignment. Fix: ---- - In most POS scenarios, the customer associated with the order is the one requesting the invoice. Therefore, if no logged-in user is found, we now correctly use the order’s partner to retrieve VAT and other required information. - The partner's country was corrected by ensuring the values are assigned in the proper order and no longer overridden incorrectly. task: 5406951 Forward-Port-Of: odoo/odoo#239811
Steps to reproduce: 1. Install CRM 2. Activate the Arabic language with English 3. Create a lead with a new email, a new company name, and the Arabic language 4. Save and try to send a message from the chatter Issue: - After the message is sent, the language of Lead is changed to EN from Arabic - Contacts created with the English language Cause: - When we send a message from the chatter of a Lead that has an email_from, a partner_name, and the Arabic language, this forces the creati
Original PR description
Steps to reproduce: 1. Install CRM 2. Activate the Arabic language with English 3. Create a lead with a new email, a new company name, and the Arabic language 4. Save and try to send a message from…
Steps to reproduce: 1. Install CRM 2. Activate the Arabic language with English 3. Create a lead with a new email, a new company name, and the Arabic language 4. Save and try to send a message from the chatter Issue: - After the message is sent, the language of Lead is changed to EN from Arabic - Contacts created with the English language Cause: - When we send a message from the chatter of a Lead that has an email_from, a partner_name, and the Arabic language, this forces the creation of a new contact First child contact is created with arabic language, but `parent_name` is present in the creation dictionary, so this triggers `_create_parent_from_name` that builds a dictionary to create the parent company, but it does not pass the language. As a result, the parent company is created with the English language. then `_create_parent_from_name` links the child to this new parent and this linking triggers the `_compute_lang` on the child and overwrites the child's language with the parent's language At last, Lead's own computed field `_compute_lang_id` triggers and sets the language to English Solution: - pass the language in the dictionary to create the parent company opw-6449407
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
Behavior before: When uploading an animated GIF to fields utilizing image responsive sizing or cropping (such as employee avatars or product images), no downscaling or cropping occurs for sub-variants like 'image_128' or 'image_1024'. The responsive fields replicate the exact file size and data footprint of the original large image, leading to heavy storage overhead and unnecessary frontend asset loading. Behavior after: Animated GIF images scale down and crop correctly to match requested r
Original PR description
Behavior before: When uploading an animated GIF to fields utilizing image responsive sizing or cropping (such as employee avatars or product images), no downscaling or cropping occurs for…
Behavior before: When uploading an animated GIF to fields utilizing image responsive sizing or cropping (such as employee avatars or product images), no downscaling or cropping occurs for sub-variants like 'image_128' or 'image_1024'. The responsive fields replicate the exact file size and data footprint of the original large image, leading to heavy storage overhead and unnecessary frontend asset loading. Behavior after: Animated GIF images scale down and crop correctly to match requested responsive dimensions and aspect ratios. Sub-variants take up significantly less space in the filestore, matching proportional dimensions without dropping or stripping the underlying animation loop. Large images that are smaller than requested boxes are safely left un-upscaled to maximize database deduplication. Root Cause: Historically, a legacy safeguard bypassed GIF resizing and cropping because older versions of the Pillow library did not gracefully handle multi-frame sequential image buffers. As a result, standard 'image.crop()', 'image.thumbnail()', or 'image.resize()' implementations would flatten multi-frame animated sequences down into a single, static first frame or throw dimension/mode mismatches during save operations. Fix: Intercept the image processing pipeline when encountering an asset identified as a GIF where 'is_animated' evaluates to True. Implemented a unified, in-place multi-frame helper routine (`_apply_gif_operation`) using PIL's 'ImageSequence.Iterator' to cleanly step through, normalize to a uniform color mode (RGBA), duplicate, and modify each animation frame individually. This single helper handles sequential workflows for both 'crop' and 'thumbnail' operations while preserving individual frame duration arrays and native loop metadata. Both 'resize' and 'crop_resize' leverage this logic to achieve precise dimensions cleanly. Crucially, upscaling (expanding) is intentionally unsupported for animated GIFs. Forcing a low-resolution, 256-color indexed animation to stretch beyond its native dimensions forces heavy color dithering across every single frame. This breaks the sequential LZW pattern compression, causing the resulting file sizes to skyrocket catastrophically. The logic utilizes thumbnail boundaries to completely block this expansion, protecting the filestore from accidental bloat. Benchmark: -------------------------------------------------------------------------------------------- | GIF size | Variant | Size Before (KB) | Size After (KB) | |---------------|--------------------|--------------------------|-----------------------| | (2.5MB) | image_1024 | 2475.87 | 2475.87 | | | image_128 | 2475.87 | 257.93 | |---------------|--------------------|--------------------------|-----------------------| | (3.8MB) | image_1024 | 3724.93 | 3724.93 | | | image_128 | 3724.93 | 463.62 | |----------------|-------------------|--------------------------|-----------------------| | (442KB) | image_1024 | 432.49 | 432.49 | | | image_128 | 432.49 | 36.14 | |----------------|-------------------|--------------------------|-----------------------| | (3.6MB) | image_1024 | 3491.98 | 3491.98 | | | image_128 | 3491.98 | 1728.25 | |----------------|-------------------|--------------------------|-----------------------| opw-6232841 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#273098