Friday, August 7, 2026
15 changes · saas-18.3
Enhancements to existing features
Receipt printer selection in Point of Sale now uses the same broader printer matching rules already applied to preparation printers. This helps ensure compatible IoT printers can be selected consistently, reducing setup friction for stores.
Original PR description
In odoo/enterprise#124306, we removed the subtype from the printer domain, but only for preparation printers. We also update it for receipt printers. Forward-Port-Of: odoo/enterprise#125648
Resolved issues and error corrections
The appointment Google Reserve integration now prevents availability responses from showing more open spots than total spots. This avoids misleading booking information in rare cases where appointment capacity settings are inconsistent.
Original PR description
This commit makes sure that we never send more "spots_open" than there are "spots_total" when Google Reserve asks for availabilities. This could happen in very rare case when customers create configurations that do not make sense (for example a table of 6 but no management of capacities and configuring 125 spots per resource). Task-6449615 Forward-Port-Of: odoo/enterprise#126855
This fix keeps work orders in the Shop Floor view in the intended sequence after refreshes or filter changes. It prevents confusing reordering by preserving the display order based on work order status and scheduled start date.
Original PR description
Records already in cache are intended to be sorted by their position in `recordCacheIds` to preserve the previously computed display order. However, `recordCacheIds` stores database record ids (`resId`), and currently the cache lookup incorrectly uses `id` instead. As a result, every lookup returns `-1`, and could lead to inconsistent ordering. Steps to reproduce: 1. Create several manufacturing orders with work orders assigned to the same work center. 2. Give the work orders different states and scheduled start dates. 3. Open Shop Floor and display that work center. 4. Refresh the view or change a filter so the records are recomputed. It should use `resId` so the previously computed display order remains, which is based on state and scheduled start date. Related: odoo/enterprise#74421 opw-6402233 Forward-Port-Of: odoo/enterprise#125928
This fixes an issue where minimum income salary rule information was not being properly logged during Swiss payroll ELM transmission. The change improves payroll traceability and helps businesses maintain more complete records for Swiss payroll reporting.
Original PR description
Forward-Port-Of: odoo/enterprise#127241
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280556 Forward-Port-Of: odoo/odoo#280550
Original PR description
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280556 Forward-Port-Of: odoo/odoo#280550
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens. To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here. runbot er
Original PR description
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens.
To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here.
runbot error-944120
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#280384We use to have a chatter response for the IAP code "registrations_needed" that gives in plain text the sms account token. However this IAP code doesn't exist anymore. Task-6425300 Forward-Port-Of: odoo/odoo#280015
Original PR description
We use to have a chatter response for the IAP code "registrations_needed" that gives in plain text the sms account token. However this IAP code doesn't exist anymore. Task-6425300 Forward-Port-Of: odoo/odoo#280015
Description of the issue this commit addresses: The invoice product prediction test requires account_accountant but runs and fails when that optional module is not installed. --- Desired behavior after this commit is merged: This commit skips the test when account_accountant is not installed and enables product prediction when it is available. --- runbot-[941525](https://runbot.odoo.com/odoo/error/941525) --- I confirm I have signed the CLA and read the PR guidelines at w
Original PR description
Description of the issue this commit addresses: The invoice product prediction test requires account_accountant but runs and fails when that optional module is not installed. --- Desired behavior after this commit is merged: This commit skips the test when account_accountant is not installed and enables product prediction when it is available. --- runbot-[941525](https://runbot.odoo.com/odoo/error/941525) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280874
When an order lands in the database with missing lines or payments, the logs only give its name and uuid. That is not enough to tell whether the front end sent an incomplete payload or the write was only partially applied, and the payload dump that would answer it sits behind _logger.debug, which is unusable in production since lowering the whole log level there is not an option. Log the ids of the lines and payments effectively added to an existing order, so a mismatch can be traced back to
Original PR description
When an order lands in the database with missing lines or payments, the logs only give its name and uuid. That is not enough to tell whether the front end sent an incomplete payload or the write was only partially applied, and the payload dump that would answer it sits behind _logger.debug, which is unusable in production since lowering the whole log level there is not an option. Log the ids of the lines and payments effectively added to an existing order, so a mismatch can be traced back to the write that produced it. Add the `point_of_sale.log_order_data` config parameter to log the full order payload at INFO. It stays disabled by default, as the payload contains customer data. Backport of the logging part of eebe9b131a68 and 2446e19bda17. opw-6401146 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280709
Currently, people can get infinite loop in the cron that fetches messages from the ppf, as we don't catch the exception that may happen. At least catch them, so we can send an ack opw-6440955 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281170
Original PR description
Currently, people can get infinite loop in the cron that fetches messages from the ppf, as we don't catch the exception that may happen. At least catch them, so we can send an ack opw-6440955 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281170
### Issue before this commit: When generating ZUGFeRD or Factur-X electronic invoices, including an HTML hyperlink (such as an email or website) in the document layout caused the final PDF to fail PDF/A validation. Portals would reject the file with the error: "An annotation dictionary does not contain the key F". ### Steps to reproduce the issue: 1. Download Accounting and l10n_de 2. Go to Contacts > set Tax ID for company Bloem GmbH and also for DE company 3. Activate ZUGFeRD from setti
Original PR description
### Issue before this commit: When generating ZUGFeRD or Factur-X electronic invoices, including an HTML hyperlink (such as an email or website) in the document layout caused the final PDF to fail…
### Issue before this commit: When generating ZUGFeRD or Factur-X electronic invoices, including an HTML hyperlink (such as an email or website) in the document layout caused the final PDF to fail PDF/A validation. Portals would reject the file with the error: "An annotation dictionary does not contain the key F". ### Steps to reproduce the issue: 1. Download Accounting and l10n_de 2. Go to Contacts > set Tax ID for company Bloem GmbH and also for DE company 3. Activate ZUGFeRD from settings 4. Go to settings and click on Configure Document Layout and insert something like <a href="mailto:info@company.de_skr03example.com"> info@company.de_skr03example.com</a> into the footer 5. Create an invoice to Bloem GmbH and send it through ZUGFeRD 6. Download PDF and upload it on https://www.portinvoice.com/ 7. See error: An annotation dictionary does not contain the key F. With the exception of annotation dictionaries whose subtype value is Popup, all annotation dictionaries must contain the key F. ### Cause of the issue: The underlying PDF generation engine creates hyperlinks as PDF annotations but omits the /F (Flags) key. During Odoo's PDF/A conversion process, these annotations were left unmodified. This violates the strict PDF/A specification, which mandates that all non-Popup annotations must explicitly define the /F key. ### Reason to introduce the fix: This fix ensures full PDF/A compliance by iterating through all page annotations and injecting the missing /F key for any annotation that is not a Popup. This allows users to safely include clickable links in their invoice templates without breaking electronic document validation. opw-6388212 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279024
Sometimes the default_state remains in the context from a past action and when the subcontractor fills its components consumptions it will directly modify the quant's quantity. This trigger the automatic rules and generate an unwanted picking opw-6109661 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:
Original PR description
Sometimes the default_state remains in the context from a past action and when the subcontractor fills its components consumptions it will directly modify the quant's quantity. This trigger the automatic rules and generate an unwanted picking opw-6109661 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#280930 Forward-Port-Of: odoo/odoo#280733
Cash Basis moves should be posted at the date of the payment, not the date of the invoice nor the date when the reconciliation is done. If there is a lock date and the payment is before that lock date, it should be posted at the first day available after the lock date. task-6420600 Forward-Port-Of: odoo/odoo#278917
Original PR description
Cash Basis moves should be posted at the date of the payment, not the date of the invoice nor the date when the reconciliation is done. If there is a lock date and the payment is before that lock date, it should be posted at the first day available after the lock date. task-6420600 Forward-Port-Of: odoo/odoo#278917
Description of the issue/feature this PR addresses: Downloading an attachment from the file viewer fails with a `405 Method Not Allowed` error when the attachment belongs to a Discuss channel. I've already submitted a ticket to Odoo: #6430586 Steps to reproduce (on a 18.0 runbot): 1. open Discuss and send an image in a channel 2. click the image to open the file viewer 3. click the download button (either the one in the header or the one in the bottom toolbar) The server rejec
Original PR description
Description of the issue/feature this PR addresses: Downloading an attachment from the file viewer fails with a `405 Method Not Allowed` error when the attachment belongs to a Discuss channel. I've…
Description of the issue/feature this PR addresses:
Downloading an attachment from the file viewer fails with a `405 Method Not Allowed` error when the attachment belongs to a Discuss channel.
I've already submitted a ticket to Odoo: #6430586
Steps to reproduce (on a 18.0 runbot):
1. open Discuss and send an image in a channel
2. click the image to open the file viewer
3. click the download button (either the one in the header or the one in the bottom
toolbar)
The server rejects the request:
```
POST /discuss/channel/1/image/519861?filename=image.png&unique=32647b0f&download=true 405
```
and the user gets a `RPC_ERROR: Arbitrary Uncaught Python Exception` dialog reporting `405 Method Not Allowed`.
Cause: `download()` always issues a POST request, while the routes serving the attachments of a discuss channel only allow GET:
* `/discuss/channel/<int:channel_id>/attachment/<int:attachment_id>`
* `/discuss/channel/<int:channel_id>/image/<int:attachment_id>`
so the request never reaches the controller. Downloading the very same attachment from the attachment card in the conversation still works, because that one is a plain anchor navigation (GET).
This is a regression from fb152985f4b8 ("[FIX] web: download FileViewer files via blob helper"), which routed the file viewer download through `download()` in order to honor the filename sent by the server in the `Content-Disposition` header.
Only 18.0 is affected: saas-18.1 and saas-18.2 do not have the commit that introduced the regression, and from saas-18.3 on, the `urlRoute` override was dropped and channel attachments are served through the standard `/web/content` and /web/image` routes, which are not restricted to GET.
The download is still sent with POST on those branches though, hence forward-porting this up to master.
Current behavior before PR:
Downloading a Discuss channel attachment from the file viewer raises a 405 error and the file is not downloaded. Images and other file types are equally affected.
Desired behavior after PR is merged:
The file is downloaded, keeping the filename advertised by the server. The download is performed with a GET request through `downloadFile()`, which still goes through the blob helper, so the fix of fb152985f4b8 is preserved. This is already the way a file is downloaded from its url in `readonly_file.js`.
Added a test that downloads an image attachment of a channel from the file viewer and asserts the request is a GET on the channel attachment route. It fails before this fix with `POST /discuss/channel/1/image/1`.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#279232Otherwise using the "Update Apps List" wizard (`base.action_view_base_module_update`) and then trying to `_get` the new module may not work because `_get_id` is `ormcache`ed. To reproduce: 1. Install `account_peppol` and `l10n_fr` 2. Delete the `l10n_fr_pdp` module from the apps 3. Go to the settings and click "Activate Electronic Invoicing" 4. Make sure "France FRCTC Electronic Address" is selected 5. Click on "Activate Peppol (Demo)" 6. Click on "Update App List" in the warning 7. Cl
Original PR description
Otherwise using the "Update Apps List" wizard (`base.action_view_base_module_update`) and then trying to `_get` the new module may not work because `_get_id` is `ormcache`ed. To reproduce: 1. Install `account_peppol` and `l10n_fr` 2. Delete the `l10n_fr_pdp` module from the apps 3. Go to the settings and click "Activate Electronic Invoicing" 4. Make sure "France FRCTC Electronic Address" is selected 5. Click on "Activate Peppol (Demo)" 6. Click on "Update App List" in the warning 7. Click on "Update" 8. Start over at step 3. and the same warning appears again, but the module can be found in the "Apps" already. Everything works fine after a server restart. task-None Forward-Port-Of: odoo/odoo#280938