Friday, August 28, 2026
14 changes · 17.0
Security fixes and vulnerability patches
Neutralized database copies now remove saved outgoing email login details when mail sending is disabled. This reduces the risk of copied or shared databases carrying credentials that could still access the real email service.
Original PR description
backport of odoo/odoo#284960
Enhancements to existing features
French B2G invoices can now be identified and routed through Chorus Pro instead of Peppol when the customer is linked to the government platform in the official directory. Users mainly need to provide the required Chorus Pro invoice details, while the system handles the correct routing and updated invoice statuses.
Original PR description
B2G invoices are not sent via Peppol but to Chorus Pro (via the approved platform). Chorus Pro is the platform with ID 9999 on the annuaire. Any invoice to partner associated with that platform on…
Resolved issues and error corrections
This fix ensures sales order lines recalculate remaining timesheet hours when related unit or availability information changes. It helps keep project and service delivery tracking accurate without requiring manual refreshes or corrections.
Original PR description
The dependencies of _compute_remaining_hours do not match the fields actually used for the computation: it lists analytic_line_ids, which it never uses, and omits both remaining_hours_available, and product_uom. _compute_remaining_hours_available has the same issue: it uses product_uom but only depends on product_id.service_policy. analytic_line_ids, on the other hand, can be dropped: qty_delivered already depends on it, along with its so_line, unit_amount, product_uom_id and project_id, so the timesheet flow keeps triggering the recomputation. This PR fixes the dependencies for both aforementioned compute methods. Task-4748521
B2G invoices are not sent via Peppol but to Chorus Pro (via the approved platform). Chorus Pro is the platform with ID 9999 on the annuaire. Any invoice to partner associated with that platform on the annuaire is considered B2G (business to government). From a user point of view nothing much changes, except that they have to set some additional fields for which we rely on the existing module `l10n_fr_facturx_chorus_pro`. From a technical PoV we store the information whether a partner is behind Chorus Pro in the `peppol_supported_documents` field. (By putting the special document identifier for Chorus Pro invoices there.) We retrieve the information whether a partner is behind Chorus Pro / B2G from the annuaire lookup. The following new lifecycle statuses have been added. They are required for the functional tests for the Chorus Pro connection. - Sent (sent by the platform) - Suspended - Completed (to "resume" the "Suspended" state) See the related IAP PR: https://github.com/odoo/iap-apps/pull/1804 task-6278159
Companies in the same database that share the same French SIREN can now reuse a successful registration check from another company. This reduces repeated KYC work for organizations managing many branches or entities under the same identifier.
Original PR description
We have some clients that have several hundreds of companies/branches on the same db, with the same SIREN (incubateur or the like). They will need to do the kyc (that will be identical, as it's the same SIREN) for all the companies. It's especially cumbersome if it needs manual intervention So, if one company on that database, with the same SIREN, managed to register, then it means it has succeded the kyc. Meaning we can bypass the kyc for the other identifiers as well. task-6515315 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update speeds up internal database column lookups by using a more direct query instead of a slower generic system view. It can reduce time spent on these repeated checks during operations such as upgrades, helping improve backend performance without changing user-facing behavior.
Original PR description
Using the view `information_schema.columns` is slow compared to a simplified query using PG catalog tables. Here we propose to cherry pick the parts of the view that we actually use. Below we show…
Using the view `information_schema.columns` is slow compared to a simplified query using PG catalog tables. Here we propose to cherry pick the parts of the view that we actually use.
Below we show the timings of both queries as reported by the system on an upgrade 18->master with a runbot DB (many modules installed). All values are in milliseconds.
```
Original:
min: 0.931
max: 16.786
mean: 1.8790601284296555
sum: 25750.64
len: 13704
New:
min: 0.224
max: 11.832
mean: 0.8649024372446001
sum: 11852.623
len: 13704
```
Total time spent in queries was halved as seen in the `sum` statistic above.
Technically, the new queries are base on the original information schema view definition as returned by `\d+ information_schema.columns`. With all unused info removed.
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#216309The French PDP configuration no longer shows or uses the pilot phase option because the early participation period has ended. This simplifies setup for companies preparing for the standard French e-invoicing rollout and keeps workflows aligned with the current deadline status.
Original PR description
The pilot phase was there if people wanted to send before the deadline. The deadline has been reached, so we can remove the field from the view. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Recurring preventive maintenance requests no longer create an extra reminder on the request that was just completed. This keeps reminders focused on the next scheduled maintenance item and avoids confusing duplicate tasks for responsible users.
Original PR description
Steps to reproduce: 1. Create a maintenance request with these values: * Maintenance Type: Preventive * Recurrent: enabled * Repeat Every: 1 day, forever * Scheduled Date: today 2. Confirm that an…
Steps to reproduce: 1. Create a maintenance request with these values: * Maintenance Type: Preventive * Recurrent: enabled * Repeat Every: 1 day, forever * Scheduled Date: today 2. Confirm that an activity is created for the responsible user. 3. Mark the activity as done. 4. Move the request to `Repaired`, or another done stage. 5. Check the newly generated request in the recurring series. When a recurrent maintenance request is moved to a done stage, Odoo creates the next request in the series. The existing activity on the completed request is marked as done and automatically unlinked by `activity_feedback()`. Previously, `activity_update()` was then called on all requests whose stage changed. Since the completed request no longer had a pending activity, this created a new one on that request. The newly generated recurring request also received its own activity, resulting in one activity on the completed request and another on the new request. Only call `activity_update()` for requests that remain in a non-done stage. This prevents a new activity from being created on a completed request while preserving the reminder on the next recurring request. opw-6409396 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where static file paths could be split incorrectly on Windows after path normalization changed the separator format. The change helps ensure Odoo serves static resources reliably across operating systems.
Original PR description
In commit 31aad6c, path normalization was added which also resulted in `/` being converted into `\` on Windows. There the `path.split('/')` did not work.
This commit changes the `'/'` to `os.sep` to fix the issue.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#285216Colombian retention reports now calculate the payment amount subject to withholding correctly when vendor bills have partial credit notes. This prevents credit notes from being counted in the wrong direction, improving the accuracy of official tax certificates.
Original PR description
**STEP TO REPRODUCE** 1. install l10n_co_reports and account_accountant 2. Create a bill, with a line with a retention tax (3.50% RteFte). 3. Create a partial credit note (unit price less than what's on the bill). 4. Goes to the report 'Certificado de Renteciòn en Fuente', and notice the Monto del Pago Sujeto Retenciòn is not correct. **CAUSE** The sql query multiply tax_base_amount by -1 if debit > 0, which means (because we are dealing with vendor bills) the line is from a credit note, but tax_base_amount is already a signed value so credit notes ends up contributing to the tax base amount while they should reduce it. opw-6235830
Factur-X e-invoices received through Peppol are now correctly read even when their XML data is embedded inside a PDF. This prevents failed or incomplete imports, such as empty invoices or attachment-only records, and improves handling of self-billed documents.
Original PR description
When importing new documents from Peppol into the database, we determine whether they are self-billed by checking a Type Code in the XML file. Factur-X is an hybrid format where the XML is embedded inside a PDF. Currently, we are not extracting the XML before searching for that Type Code, and it leads to an error that prevents the document from being imported correctly: - V17, V18: An empty invoice is created and linked with the attachment. - V19+: Only the attachment is created. Additionnaly, we only check for InvoiceTypeCode or CreditNoteTypeCode, but the CII XML format embedded inside the hybrid Factur-X format use TypeCode instead. This PR aims at fixing both these issues. Ticket: opw-6417682 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents an unexpected error from appearing when Odoo handles certain report actions. It improves reliability for users by ensuring the system uses the correct context when processing these reports.
Original PR description
opw-6360013 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#274977
Refreshing a Twitter/X feed no longer shows a generic error when an account token is invalid. Instead, the account can be disconnected as expected, reducing confusion and helping users recover access more smoothly.
Original PR description
Bug === If the token because invalid, then an UserError is raised instead of disconnecting the account. This is because we "blind raise" all errors we get from X, instead of filtering the error linked to the stream configuration. Task-6499283 Forward-Port-Of: odoo/enterprise#129110
Odoo Studio now only offers fields that are safely available when users build conditions for properties like readonly, required, or invisible. This prevents confusing errors caused by choosing fields that are limited to specific user groups.
Original PR description
Before this commit, when creating a condition for a field property in studio (like readonly, required or invisible), the fields available for the construction of the condition expression, were all the fields in the arch of the view. So, if you were using a field that was inside of a node with a 'groups' attribute or that the field had a 'groups' attribute, then a notification error was shown but with no real explanation on the cause of the error. After this commit, the fields availables in the construction of the conditional expression, are the fields in arch without any 'groups' attribute or any parent node with a 'groups' attributes. Help Task ID: 3660703
Starshipit delivery rates now handle incomplete wallet checkout addresses without stopping the entire payment flow. Customers using Apple Pay or Google Pay can still see other available delivery options and complete checkout when Starshipit cannot rate the partial address.
Original PR description
#### Description of the issue/feature this PR addresses: Rating a Starshipit shipment for an incomplete delivery address makes the whole rating loop fail instead of skipping that carrier. This breaks…
#### Description of the issue/feature this PR addresses:
Rating a Starshipit shipment for an incomplete delivery address makes the whole rating loop fail instead of skipping that carrier. This breaks express checkout (Apple Pay / Google Pay), where the wallet only discloses a partial address before authorization: the customer gets "update postal address" and cannot pay, while manual checkout works.
#### Current behavior before PR:
delivery_starshipit is the only connector that rates a shipment without validating the addresses first, and it ignores the express_checkout_partial_delivery_address context key set by website_sale. The empty street is sent to /api/rates, which answers 200 with {"success": false, "errors": [{"details": "street parameter value is required"}]}, and _send_request turns that into a UserError. As starshipit_rate_shipment lets it propagate, it aborts the rating of every carrier instead of only this one, so no delivery method reaches the wallet. The same happens for errors only the api can report, such as invalid credentials.
#### Desired behavior after PR is merged:
Both the recipient and the warehouse address are validated before the api is called, as the other connectors already do, and the message is returned as an unsuccessful rate rather than raised. Starshipit requires the street, so a streetless address is still refused, but with a neutral message in the express checkout flow since the customer cannot complete it before paying. The Starshipit carrier is simply not proposed among the wallet's options, the other carriers are rated normally, and express checkout completes.
opw-6393393