Tuesday, September 30, 2025
28 changes · saas-18.2
Enhancements to existing features
Email content conversion now handles border styles more reliably, especially for images. This helps ensure borders that users add in the editor remain visible and consistent when emails are sent or viewed.
Original PR description
This commit ports the following fixes to `convert_inline` of `mail`: - https://github.com/odoo/odoo/commit/8923f32426fc64e90db249fad47d7ca7e338adef [FIX] web_editor: adapt border-style value based on border widths - https://github.com/odoo/odoo/commit/7de31c6261d2fe9f58b0c6cb635977e77eecd9d6 [FIX] web_editor: ensure image border visible in emails --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228970
Tracking links now encode certain repeated-dot characters in redirect addresses so they are less likely to be blocked by some web server configurations. This helps ensure marketing or shared links continue to redirect reliably for users.
Original PR description
Purpose ======= It has been reported that some nginx configuration detect '...' as malicious. When testing, encoding the '...' solve the issue, and so we force the encoding for the redirection URL. Task-4920533 Forward-Port-Of: odoo/odoo#229060
This update adds standardized point-of-sale test flows across multiple country-specific localization modules. It helps ensure local checkout, fiscal, and compliance behavior keeps working consistently as Odoo evolves.
Original PR description
Thi commit add a generic tour that can be run in all pos l10n_modules. In some cases it requires some extra steps, this can be done with hooks. The hooks will execute different steps depending on the country the tour is run in. opw-4606788 Forward-Port-Of: odoo/odoo#222232
This update adds shared automated checks for point-of-sale localization across multiple countries, with country-specific steps where needed. It helps reduce the risk of regional compliance or receipt-processing issues reaching customers by validating more localized POS flows consistently.
Original PR description
Thi commit add a generic tour that can be run in all pos l10n_modules. In some cases it requires some extra steps, this can be done with hooks. The hooks will execute different steps depending on the country the tour is run in. opw-4606788 Forward-Port-Of: odoo/enterprise#91928
Resolved issues and error corrections
Creating a salesperson from a CRM opportunity no longer copies unrelated phone details from the lead. This prevents incorrect contact information from appearing on newly created salesperson records and helps keep customer and staff data accurate.
Original PR description
To reproduce: ============= 1- add a lead 2- add a phone and a mobile number 3- convert it to opportunity 4- create salesperson from that view 5- salesperson contains lead number Problem: ========= Before this fix, creating a Salesperson inherited the global context, which included unrelated values as active_model was set to crm.lead. This led to incorrect default values being applied. https://github.com/odoo/odoo/blob/d155edfd729ab9b53f38939fe24b6d1e7b578083/addons/web/models/models.py#L872C13-L872C21 The default values contained the lead phone and lead number and was applied in the creation of salesperson. Solution: ========== Since we have some synchronization of some fields (email, phone) that is automatically done normally, it's reasonable to remove the code and see what it gives. opw-4871069 Forward-Port-Of: odoo/odoo#217545
Fixes a mail composer issue where recipients without email addresses could appear twice after opening and closing the full composer. It also prevents an unrelated recipient popover from staying open, making chatter recipient handling cleaner and less confusing.
Original PR description
This commit fixes an issue with the newly introduced `RecipientsInputTagsListPopover` and the email-like system. The issue is that, when you have a partner that doesn't have an email address, opening the full composer from the chatter tries to remove the recipient. But when you close the composer without changing anything to it, then when opening the chatter you'll see a duplicated recipient if it is a suggested recipient. Plus, if you reopen the modal you'll see that the popover in the chatter still opens. This commit fixes both issues: 1. When the `suggestedRecipients` are updated we filter the `additionalRecipients` so that if we have the same partner_id in both they don't duplicate. 2. When you open the full composer the tags list is aware of that and doesn't open additional popovers. task-4747049 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
A mock server issue in the web module has been corrected so test records with many-to-many links are created properly. This improves reliability for development and testing, helping prevent false errors before changes reach users.
Original PR description
Before this commit, using CREATE Command on a many2many field would result in an error. This is because upon record creation the inverse field would be set to the single id, which is incorrect for a many2many field. This commit fixes the issue by setting the inverse field of a many2many to a list containing the new id. Forward-Port-Of: odoo/odoo#208524
The CRM periodic digest now shows the correct number of free credits for targeted lead generation. This prevents users from being misled by an overstated offer, changing the displayed amount from 200 credits to 20 credits.
Original PR description
## Versions 17.0+ ## Issue The Periodic Digest contains wrong information in a tip. 20 credits are given for specific target lead generation, not 200. opw-5114252 Forward-Port-Of: odoo/odoo#228791
Website editors can now select and edit the cover section on the forum page as expected. This fixes a blocker in the page builder caused by how a link inside the forum cover was handled, making forum page customization smoother.
Original PR description
Steps to reproduce: - Go to the "/forum" page and click "Edit". - Click the "s_cover" block. - Bug: the snippet is not editable. The cover snippet contains a link rendered with "t-attf-href", which makes the website builder refuse to mark the block as editable. This commit adds "t-ignore="True"" on the "oe_structure" so the branding stops before reaching the link and the snippet becomes editable again. task-5095234 Forward-Port-Of: odoo/odoo#227724
Vendor payment screens now correctly recognize when a user manually selects a trusted bank account. This prevents unnecessary warning banners during SEPA payment registration, reducing confusion for accounting teams.
Original PR description
**Steps to reproduce:** 1. Install the modules: `accounting` and `account_iso20022`. 2. Configure a bank journal with SEPA credit transfer in *Outgoing payment methods*. 3. Create a partner with two…
**Steps to reproduce:** 1. Install the modules: `accounting` and `account_iso20022`. 2. Configure a bank journal with SEPA credit transfer in *Outgoing payment methods*. 3. Create a partner with two bank accounts: one trusted, one untrusted. 4. Create a vendor bill for this partner. 5. Register a payment using the SEPA credit transfer method. 6. Manually select the trusted bank account from the dropdown. **Observed behavior:** * A warning banner is shown when the trusted account is selected. **Root cause:** * `_compute_trust_values` only validated the bank account from the batch (original invoice data) and ignored the `partner_bank_id` if the user changed it manually in the wizard. **Solution:** * Update `_compute_trust_values` to also validate the currently selected `partner_bank_id`, ensuring the trust check reflects the user’s actual selection. * added testcase for the same in account_iso20022 [#95124](https://github.com/odoo/enterprise/pull/95124) opw-5059740 Forward-Port-Of: odoo/odoo#227404
Changing a website theme color from the editor palette and saving now works without triggering an error. This improves reliability for users customizing website appearance and prevents disruption during the editing workflow.
Original PR description
This PR resolves a traceback that occurred when changing the theme color from the color palette and pressing the save button. This was due to an unhandled promise rejection. task-3919146 Forward-Port-Of: odoo/odoo#227946
Arabic invoice reports for Saudi Arabia now display the description column with consistent alignment. This makes printed invoices easier to read and better aligned with Saudi localization expectations.
Original PR description
**Steps to reproduce:** 1. Install l10n_gcc_invoice. 2. Add and Switch to a Saudi Arabia company. 3. Select boxed layout (or keep any layout). 4. Create and print an invoice. **Issue:** - The…
**Steps to reproduce:** 1. Install l10n_gcc_invoice. 2. Add and Switch to a Saudi Arabia company. 3. Select boxed layout (or keep any layout). 4. Create and print an invoice. **Issue:** - The description column is misaligned in the Arabic invoice report. According to Saudi localization, it should be aligned to the left for better readability. The current alignment makes Arabic text inconvenient to read. **Cause:** - Other columns (e.g., quantity, taxes) already use the `text-end` class, but the description column has no alignment class, causing inconsistent layout and misalignment. **Solution:** - Added the `text-end` class to the description column to ensure proper alignment and consistent readability in Arabic invoice reports. **Before FIX:** <img width="831" height="329" alt="image" src="https://github.com/user-attachments/assets/857f9f7f-d930-4c73-b2fa-eacd7a153ea3" /> **After FIX** <img width="788" height="354" alt="image" src="https://github.com/user-attachments/assets/929acdb1-bb13-4e1e-829c-8fdbe18334a4" /> **opw-5087770** Forward-Port-Of: odoo/odoo#228118
This update restores the correct handling of OIN identifiers in certain electronic invoice formats. It helps ensure compliant invoice data is generated for BIS3 and NLCIUS cases, reducing the risk of rejected or incorrect e-invoices.
Original PR description
We previously [1] fixed the EAS that was incorrectly set to 0106 instead of 0190 in case of OIN (lenght = 20). This fix was overriden in the backport of the 19.0 dict helpers [2]. [1]: https://github.com/odoo/odoo/pull/219424 [2]: https://github.com/odoo/odoo/pull/215610 opw-5107445 Forward-Port-Of: odoo/odoo#228624
Task lists now keep the allocated hours field visible and editable even when the value is zero. This lets users update planning for multiple tasks without being blocked by hidden empty-hour cells.
Original PR description
Before this commit, when the user would like to edit the allocated hours field of multiple tasks inside the list view, he cannot when the allocated hours is equal to 0. The reason is because the cell is hidden once the value is equal to 0. This commit makes that field is always editable in the list view of tasks even if the value is 0. task-5093288 Forward-Port-Of: odoo/odoo#228862 Forward-Port-Of: odoo/odoo#228188
Users who open a product’s View Diagram in a newly created company without a warehouse will now see a clear warehouse setup warning instead of an unexpected error. This helps guide users to complete the required warehouse configuration and prevents disruption in inventory workflows.
Original PR description
Currently, if a user creates a new company without configuring its warehouse, clicking 'View Diagram' raises an error. **Steps to Reproduce:** 1) Install sale_stock module.(with Demo Data) 2)…
Currently, if a user creates a new company without configuring its warehouse, clicking 'View Diagram' raises an error. **Steps to Reproduce:** 1) Install sale_stock module.(with Demo Data) 2) Navigate to Inventory>Configuration>Warehouses and create a new Warehouse. 3) Create a new company and switch to that company. 4) Navigate to Inventory>Products>Products 5) Open any product and click on 'View Diagram' in the 'inventory tab'. **Error:** `AttributeError: 'bool' object has no attribute 'origin'` **Root Cause:** On following above steps, `default_get` method is called. At [1], it attempts to fetch the ID of the warehouse. Because Odoo does not create a default warehouse for a newly created company, the value received by `res` at [2] looks like `[(6, 0, ['False'])]` which causes an error during further computation. **Fix:** Raise a `Redirect Warehouse Warning` when clicking 'View Diagram' if no warehouse is found. [1]- https://github.com/odoo/odoo/blob/a729578afb7fed79aac2d622aae4da4c0917f8e5/addons/stock/wizard/stock_rules_report.py#L35 [2]- https://github.com/odoo/odoo/blob/a729578afb7fed79aac2d622aae4da4c0917f8e5/addons/stock/wizard/stock_rules_report.py#L36 **Note**: not adding a test case, as the issue is not reproducible in test mode as default warehouse is created for a company in the test mode https://github.com/odoo/odoo/blob/de264d99c22283390d18beb7c7c62c29824f72b3/addons/stock/models/res_company.py#L197-L198 sentry-6575082178 Forward-Port-Of: odoo/odoo#227810
This update prevents Odoo Discuss from crashing when call session information arrives after the related session has already been removed. It improves reliability for users in chat and call workflows by safely ignoring outdated session updates.
Original PR description
Before this commit, since a regression introduced in https://github.com/odoo/odoo/pull/228601 A traceback could occur when updating a session that does not exist. For example if the event is received after the session is removed. Forward-Port-Of: odoo/odoo#229073
Loyalty rewards that add a free product to a sales order now use the reward’s custom description as the order line name. This avoids confusing product labels and keeps sales orders consistent with point-of-sale behavior.
Original PR description
Currently, the reward's product name is used as the SOL name for the free product, which can be confusing. **To reproduce this issue:** 1) Install the sale_loyalty module. 2) Create a loyalty program…
Currently, the reward's product name is used as the SOL name for the free product, which can be confusing. **To reproduce this issue:** 1) Install the sale_loyalty module. 2) Create a loyalty program that grants a free product. 3) Manually update the reward's description. 4) Create a SO with a SOL containing that product 5) Apply the reward and observe the behavior. **Issue / Cause:** - The free product's description is taken from the reward product's name instead of the manually updated description. - This is incorrect because, in the point of sale, the name is taken from the reward's `discount_line_product_id` rather than the `reward_product_ids`. https://github.com/odoo/odoo/blob/0abdcd9ef6ad3fc932dc0eb46d8aa973b00c34c2/addons/pos_loyalty/static/src/overrides/models/pos_order.js#L1162 **Solution:** To resolve this inconsistent behavior, the free product name in the sale order line will now be taken from discount_line_product_id. opw-4982774 Forward-Port-Of: odoo/odoo#225944 Forward-Port-Of: odoo/odoo#223755
This fix ensures packaging information is properly applied when creating products that have only one variant. It prevents missing packaging details in cases where product variants are created without attribute lines, helping keep product setup and sales operations accurate.
Original PR description
e158730ba16e898a13dd9a98ed96fa30fa95ab6f recently fixed a situation where one-variant products had duplicated packagings. In the aforementioned commit, we concluded that the logic to write (again) the templates values for variant-stored fields was useless because already applied to the generated variants. Nevertheless, while trying to remove in master this logic, we noticed that those varlues are only applied to variants of templates having at least one attribute line, whose creation will trigger the variants creation. This commit therefore partially reverts the previous commit, bringing back the first solution that is still the best approach in the end. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#229080
Manufacturing planning now handles extremely small operation or work order durations safely. This prevents scheduling from failing when invalid near-zero duration values appear, keeping production planning reliable.
Original PR description
Operation & Workorder duration is a float with 2 decimal digits to be expressed in minutes, meaning minimal duration is 1sec. However one can encounter numbers like 0.001, 0.00001, ... This can lead to : AttributeError: 'NoneType' object has no attribute 'astimezone' in function _get_first_available_slot task: 5090338 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#227253
This fixes an issue where highlight effects in website page templates could be carried over in the wrong expanded format when creating a new page. Business users can now select templates with highlighted content and get a cleaner, correctly structured new page.
Original PR description
Starting from [1], the code from the "Snippets Preview" and the "New Page Templates Preview" was adapted to be able to build a highlight using its simplified format when provided in XML. The goal of this PR is to fix the new page DOM when a template with highlights is selected. The DOM will be simply cloned and used for the created page, so we need to reset the inner highlights to their minimal format. [1]: https://github.com/odoo/odoo/commit/4a29fa66003ce1f42a7011bc56fc019f34a887f5 task-4215788 Forward-Port-Of: odoo/odoo#185820
The sales manufacturing test now uses the intended invoicing setting so kit products can be invoiced before delivery in the tested scenario. This helps keep automated checks aligned with the expected business workflow and reduces false build failures.
Original PR description
This change updates the test_sell_kit_invoice_before_delivery test to ensure that kit components and the kit product itself use an invoicing policy of Ordered Quantities rather than the default Delivered Quantities. build_error-232796 Forward-Port-Of: odoo/odoo#227870
After DIOT 2025 rework in 4e6bee49e98b055e5aebe89fb19ab6317003b682 the report is missing some es translations Steps to reproduce: - With an MX Company and Spanish es_419 language set - Open Accounting > Reporting > Tax Report - Choose report Diot MX opw-5016650 Forward-Port-Of: odoo/odoo#229085
Original PR description
After DIOT 2025 rework in 4e6bee49e98b055e5aebe89fb19ab6317003b682 the report is missing some es translations Steps to reproduce: - With an MX Company and Spanish es_419 language set - Open Accounting > Reporting > Tax Report - Choose report Diot MX opw-5016650 Forward-Port-Of: odoo/odoo#229085
The project dashboard now prevents users from editing a milestone percentage when there is no related sales order line. This avoids confusing edits that cannot be properly applied and makes milestone behavior clearer for sales-linked projects.
Original PR description
**Steps to Reproduce:** - Install sale_project. - Go to the project dashboard. - Click on Edit milestones. **Isuue:** When a sales order line exists, the quantity percentage can be updated. When no sales order line exists, the quantity percentage cannot be updated. **Fix:** Make the field readonly when no sales order line is linked. task-5068312 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Sales orders no longer keep an outdated quote calculator after the quotation template is changed. This prevents users from relying on calculator data from the previous template and keeps the sales order aligned with the selected template.
Original PR description
Step to reproduce: - Create a new SO - Add a customer and quotation template to the order - Click on quote calculator smart button - Return to sale order (click on SO number in top left) - Change the quotation template - Result: it does not change the quote calculator that is linked to the new quotation template Cause: - Clicking on Quote Calculator creates a copy of the quotation template spreadsheet and links it to the SO. https://github.com/odoo/enterprise/blob/8bc6098335d283e6d210dc788463a8ef8c559b14/spreadsheet_sale_management/models/sale_order.py#L30-L35 - When the quotation template is later changed, the spreadsheet linked to the old template remains attached to the SO. Fix: - On changing the sale_order_template, the old spreadsheet should be unlinked from the SO. - Keeping it linked is inconsistent, as it does not matches the current template opw-4998587 Forward-Port-Of: odoo/enterprise#93970
The SEPA payment flow now checks the bank account actually selected by the user, rather than only the account originally linked to the invoice. This prevents unnecessary warning banners when a trusted bank account is chosen, improving confidence during vendor payment processing.
Original PR description
**Steps to reproduce:** 1. Install the modules: `accounting` and `account_iso20022`. 2. Configure a bank journal with SEPA credit transfer in *Outgoing payment methods*. 3. Create a partner with two bank accounts: one trusted, one untrusted. 4. Create a vendor bill for this partner. 5. Register a payment using the SEPA credit transfer method. 6. Manually select the trusted bank account from the dropdown. **Observed behavior:** * A warning banner is shown when the trusted account is selected. **Root cause:** * `_compute_trust_values` only validated the bank account from the batch (original invoice data) and ignored the `partner_bank_id` if the user changed it manually in the wizard. **Solution:** * Update `_compute_trust_values` to also validate the currently selected `partner_bank_id`, ensuring the trust check reflects the user’s actual selection. opw-5059740 Forward-Port-Of: odoo/enterprise#95124
This fix ensures the main DATEV account is only set for companies based in Germany, preventing incorrect accounting setup for companies in other countries. It also improves how debit and credit lines are processed, making the German reports feature more efficient.
Original PR description
The main datev account should only be set for German companies (check for country code) Also fix the complexity of gathering the debit and credit lines: `+=` has a complexity of `O(n²)` whereas `filtered` has a complexity of `O(n)`. Forward-Port-Of: odoo/enterprise#69881
This fix removes a remaining source of inconsistent behavior in an automated Studio rename test. It helps keep validation stable so future changes can be checked more reliably without affecting daily users.
Original PR description
Similar to https://github.com/odoo/enterprise/commit/5574c52df8794b3f23d385a670cac8fb5355e229 There was still one indeterminism remaining runbot-232572 Forward-Port-Of: odoo/enterprise#95447
Spanish tax report logic now handles missing date information safely instead of stopping with an error. This improves reliability when records are created automatically or during system checks, without changing behavior when valid dates are provided.
Original PR description
The `_get_mod_period_and_year` method assumed that `options['date']` would always be present with `date_from` and `date_to`. However, during the automatic `TestEveryModel.test_computed_fields_without_dependencies`, this method is called on a `new()` record where no options are provided. This resulted in a `KeyError: 'date'`. We now gracefully handle missing or incomplete `options` by returning `(None, None)` instead of raising an exception. This ensures that tests and new records can be created without errors, while preserving the original validation logic when valid options are given. build_error-231511