Friday, July 17, 2026
6 changes · saas-19.1
Enhancements to existing features
Peruvian e-invoicing now includes the additional product classification codes required by SUNAT's upcoming validation rules. This helps businesses avoid invoice rejections for affected goods once the new requirements take effect.
Original PR description
SUNAT is updating its validation rules 2026-08-01, adding three mandatory annexes (25.1, 25.2, 25.3) to Product Catalog N25. E-invoices for these goods are rejected when the required UNSPSC code is not available in the database. Most of the required codes already exist and are active. The rest are handled here: two missing UNSPSC codes were added to the shared catalog, while the fourteen codes that exist but are inactive and the SUNAT-only code 11111111 (which is not part of the UNSPSC standard) are activated from the Peru localization instead. Doing the Peru-specific part in the l10n_pe_edi install hook and upgrade script, the way l10n_mx_edi and l10n_ke_edi_oscu do for their own codes, keeps these activations out of databases that do not use the Peruvian localization. Task-6366907 Forward-Port-Of: odoo/enterprise#124200 Forward-Port-Of: odoo/enterprise#123577
Resolved issues and error corrections
Odoo Studio now handles field labels written with non-Latin characters, such as Arabic, without creating an invalid internal field name. This prevents users from seeing an error when renaming custom fields in these languages, making Studio more reliable for multilingual teams.
Original PR description
Steps: - Install web_studio - Add any field (example char field) to any view - Rename it in arabic, example `السَّلَامُ عَلَيْكُمْ` - Error Custom field names cannot contain double underscores Webclient (view_editor_model) escape every non-alphabetic chars, so new label value contains nothing but a space which will be replaced by a _ this new label value will be concatenated to `x_studio_`. Resulting to the string `x_studio__`. A solution should be to prevent changing the technical name if the new label value (escaped) is empty. opw-6311027 Forward-Port-Of: odoo/enterprise#122094 Forward-Port-Of: odoo/enterprise#121343
Studio approval rules now work when their conditions reference fields that the acting user cannot directly access. This prevents sales order confirmations and similar actions from being blocked by an access rights error, improving reliability for users with limited permissions.
Original PR description
Issue: A studio.approval.rule.domain includes a related field that calls an access rights group that the user who used the action isn't 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 Fix: add a sudo to the filtered_domain opw-6316069 Forward-Port-Of: odoo/enterprise#121856
Preparation display orders no longer jump around when staff interact with individual order lines. Orders now keep their position until they move to a new preparation stage, making kitchen workflows easier to follow after a refresh.
Original PR description
**Steps to reproduce:** - Setup a preparation display - Go to the restaurant - Send an order to the kitchen, with 2 lines - Go to another table and send an order with 2 lines to the kitchen - On the display, click the first line of the first order - Reload the page - Order 1 and order 2 have swapped places **Why the fix:** We are currently sorting the orders based on their write_date, meaning that when we click a line, the write date is updated, and it goes to the end of the line. To prevent this, we are now using **last_stage_change** that is only updated when going from one stage to another. This means the cards will stay in the same order, and go to the back of the line once they change stage. To make it so that they are last when changing stage, we update the **last_stage_change** in the frontend as well when changing stage, because it was only done in the backend before this commit. opw-6361046 Forward-Port-Of: odoo/enterprise#124048
Invoices marked as excluded from follow-up are now also left out of follow-up email attachments and printed follow-up letters. This prevents customers from receiving documents for invoices the business intentionally removed from collection reminders.
Original PR description
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the…
Steps to reproduce: 1. Install Accounting and create an invoice for a customer which has a due date in the past 2. Make sure the payment term for the invoice is "Immediate Payment" and Send the invoice. 3. Open the contact form and click on the Customer Statement smart button 4. Exclude the invoice using the 'No Follow-Up' toggle 5. In the Accounting tab in the contact form, click on send 6. Open the internal link of the Content Template, go to the options tab and select 'Print Follow-up Letter' in Dynamic Reports 7. Save the configuration and send the email Issue: Excluded invoices still appeared as PDF attachments in the follow-up email and were merged into the printed follow-up letter PDF. Why this happens: Both `default_get` in `account_followup.manual_reminder` and `_get_invoices_to_print` in `res.partner` traversed `unreconciled_aml_ids` without filtering out lines where `no_followup = True`, so excluded invoices were included regardless. opw-6310602 Forward-Port-Of: odoo/enterprise#124541 Forward-Port-Of: odoo/enterprise#122249
Email buttons for appointments and event registrations now use the website tied to the appointment or event instead of a generic or recently used website address. This prevents customers on multi-website setups from being sent to the wrong site when managing bookings or registrations.
Original PR description
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from…
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. Case 1: - Have website A and website B - Create an appointment page website A - Log in via website B - As public user, make an appointment in Website A - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the appointment. This occurs because when an user log in, the system parameter 'web.base_url' is updated with the current url. This parameter is then used as fallback when we need to retrieve the base url without an active record Case 2: - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the event. This occurs because the record `event.registration` has no website_id field and the base url is taken from the company default website (website A) Backport with improvements of 15bae202d8f1b5bf70bbc63b2d89025e9237e6cf opw-4146760 opw-4336369 Forward-Port-Of: odoo/enterprise#124555 Forward-Port-Of: odoo/enterprise#122669