Monday, March 30, 2026
19 changes · saas-18.4
Resolved issues and error corrections
Creating a scrap order no longer crashes if the default scrap location has been deleted. This helps inventory users continue their workflow and avoids an unexpected error screen in a rare configuration state.
Original PR description
When user tries to create a scrap order without scrap location, A traceback is raised. Steps to reproduce the error: - Install ``stock`` module - Go to Inventory > Configuration > Settings > Enable Storage Locations > Save - Go to Configuration > Locations > Delete Virtual Locations/Scrap > Delete - Go to Operations > Scrap > New Traceback: ```py KeyError: 1 ``` https://github.com/odoo/odoo/blob/7d89c092ac25ffe149fb38fb52863fdaa3b6ed5f/addons/stock/models/stock_scrap.py#L93 When the Scrap location is deleted, ``locations_per_company`` becomes an empty dictionary. Accessing a key from this empty dictionary lead to the above traceback. sentry-7307394327 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252192
Restaurant self-order QR code PDFs now generate the correct pickup ordering links without unnecessary table information. This prevents customers from scanning links tied to a table when the business is using pickup zones, reducing ordering confusion.
Original PR description
Step to reproduce: - setup Restaurant and do the following config - set "self-ordering" -> "Qr Menu + Ordering" - set "service At" -> "pickup zone" - save and print the qr-code ( option is right…
Step to reproduce: - setup Restaurant and do the following config - set "self-ordering" -> "Qr Menu + Ordering" - set "service At" -> "pickup zone" - save and print the qr-code ( option is right there below these configs) Observation: - in downloaded pdf, we see a wrong url, which includes table_id, which shouldn't be. - QRs do not have table_id Cause: - there is issue in `generate_qr_codes_page` method, which uses table_id even if ordering mode is "pickup zone" Fix: - we only use table_id when ordering_mode = 'table'. **Before:** <img width="1002" height="397" alt="image" src="https://github.com/user-attachments/assets/e6dc50e5-6384-45b8-8ee5-817526769dc2" /> **After** <img width="1021" height="405" alt="image" src="https://github.com/user-attachments/assets/0be9b902-3870-4fc7-a409-e01265b7a1b3" /> opw-5095607 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254583 Forward-Port-Of: odoo/odoo#247184
Creating a new analytic item from an analytic account's gross margin button now automatically links it to the current analytic account. This prevents missing account information and reduces manual correction when reviewing margin details.
Original PR description
When accessing analytic items from the gross margin smart button on an analytic account, creating a new record does not pre-fill the analytic account field. This happens because the context does not set `default_account_id` for the active analytic account, leading to newly created lines not being linked at creation time. This commit ensures the analytic account is correctly passed through the context, so it is automatically set when creating a new analytic line from this flow. Steps to reproduce: - Open an analytic account - Click on the gross margin smart button - Create a new analytic item Before: analytic account not set by default After: analytic account is pre-filled via context task-3909624 Forward-Port-Of: odoo/odoo#256091 Forward-Port-Of: odoo/odoo#255726
This change makes the HTML editor's automated list indentation tests use the intended Roboto font consistently. It reduces false test failures across different environments, helping releases move through validation more smoothly without changing user-facing behavior.
Original PR description
Purpose of this PR: - Explicitly load Roboto using FontFace in indent.test.js to avoid fallback fonts (e.g. Ubuntu) across environments. This ensures consistent rendering and prevents flaky failures caused by font-dependent computed values. task-5916115 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256070
When a credit note is reversed and a replacement invoice is created, the new invoice now keeps the original Source information. This ensures invoice PDFs continue to show the right source document, improving traceability for customers and accounting teams.
Original PR description
### Issue before this commit: When creating a credit note using “Reverse and create invoice”, the generated invoice loses the Source field. While the original invoice correctly displays the source,…
### Issue before this commit: When creating a credit note using “Reverse and create invoice”, the generated invoice loses the Source field. While the original invoice correctly displays the source, the new invoice created after reversal does not, leading to missing information in the report. ### Steps to reproduce the issue: 1. Create a sales order for product A 2. Deliver product A 3. Create invoice 4. Create credit note by clicking on "Reverse and create invoice" 5. The new invoice correctly remains linked to the Sales order 6. However, the source document disapear on the PDF ### Cause of the issue: In the reversal flow, the new invoice is created using copy_data() without explicitly preserving the invoice_origin field. As a result, the newly created invoice does not inherit the source information from the original invoice, even though it is still logically linked. ### Reason to introduce the fix: To ensure consistency between invoices and preserve important traceability information, the invoice_origin field must be propagated to the new invoice created during the reversal process. This guarantees that the Source is correctly displayed in the PDF. opw-6034574 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254290
Tax names in the Spanish localization are now shown in Spanish instead of English. This reduces confusion for Spanish users when reviewing or configuring taxes.
Original PR description
It was a previous dev in which the fw-port failed. Here is the old [PR](https://github.com/odoo/odoo/pull/238857) The tax names were displayed in English, and it's confusing for the Spanish users. Now, the taxes are displayed in spanish task-6041023 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255674 Forward-Port-Of: odoo/odoo#255074
Website links that were given a custom color now keep that color after the editor is saved and closed. This prevents published pages from unexpectedly reverting links to the default color, keeping page designs consistent for visitors.
Original PR description
Problem: Colored links revert to the default link color after saving and closing the website editor. Cause: The rule forcing links to inherit color from their parent `<font>` element is defined in the `html_editor` module, whose stylesheet is unloaded when the editor is closed, so the rule no longer applies on the frontend. Solution: Add the rule to `website_common.scss` so it applies on the frontend regardless of whether the editor is loaded. Steps to reproduce: 1. Open the website editor. 2. Apply Color to selection. 3. Apply link to the subset of the selection. 4. Save and close the editor. 5. Observe the link reverts to its default color. task-5980854 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Creating a link from selected text and an icon now keeps the icon instead of removing it. This prevents accidental content loss when users add links in the HTML editor.
Original PR description
Problem: When a selection contains both text and an icon, creating a link removes the icon from the content. Cause: Icons should be treated the same way as images during link creation. If an icon is present in the selection but not handled like an image, it gets removed when the link is applied. Solution: Handle icons in the same way as images when processing selections for link creation, ensuring they are preserved. Steps to reproduce: - Add text "abc" followed by an icon. - Select both the text and the icon. - Create a link. - Observe that the icon is removed and only the text remains. opw-6066195 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256294 Forward-Port-Of: odoo/odoo#256002
This fix improves how online shop categories detect whether they contain published products. It reduces unnecessary database work, helping category pages stay consistently fast even when many categories or demo data are present.
Original PR description
`has_published_products` was previously computed recursively. For recursive fields, the ORM disables prefetch optimizations. In 3ffca1961cb1671e7028dd4dceca82d2e74a2e21, the computation switched to…
`has_published_products` was previously computed recursively. For recursive fields, the ORM disables prefetch optimizations.
In 3ffca1961cb1671e7028dd4dceca82d2e74a2e21, the computation switched to `_read_group` to avoid loading all published products into cache and prevent memory issues. However, this introduced an N+1 pattern when evaluating:
```python
categories.filtered(lambda categ: categ.has_published_products)
```
As a result, query count became dependent on the number of active categories, which broke SQL performance tests when demo data were installed.
This commit updates the computation again to avoid recursion and restore ORM prefetch optimizations, making the number of queries independent of the number of active categories.
This commit also removes redundant checks already enforced by ORM `ir.rule`. For example, the following pattern evaluates `has_published_products` three times: once in the user domain, once in the access rule domain added by `search`, and once in the filter.
```python
domain = [("has_published_products", "=", True)]
categs = self.env["product.public.category"].search(domain)
categs.filtered("has_published_products")
```
runbot-234948When a chatbot conversation is restarted, newly created tickets or leads now include only messages from the restarted session. This prevents old chat history from being copied into new customer records, keeping follow-up work clearer and more accurate.
Original PR description
Before this commit: When a chatbot conversation is restarted and the script creates a new ticket/lead, the description also includes messages from the previous session. After this commit: Only the messages sent after the chatbot conversation is restarted are included in the ticket/lead description. Task-5118966 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256295 Forward-Port-Of: odoo/odoo#253566
Fixed an issue where the editable content area could unexpectedly scroll back to the top after users closed the command palette by clicking outside it. This keeps the user’s cursor position and editing context stable, reducing disruption while writing or editing content.
Original PR description
Before this commit: the editable area scrolls to the top when the command palette is closed by clicking the gray zone After this commit: we override the focus function of the editable and use focusEditable instead, which keeps the selection. Note it's a succession fix of https://github.com/odoo/odoo/pull/250624 and both of them are a workaround without touching the ui_service and command palette. Also added super.destroy() in the previous fix till 18.4. task-6034339 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253638
The Swedish localization now correctly labels the 0% VAT for services sold outside the EU and maps it to the appropriate VAT report grid. This helps businesses produce more accurate Swedish VAT reporting and avoid confusion between EU and non-EU transactions.
Original PR description
Currently, the tax for "VAT Sale of service outside EU 0%" has the 0% EU RS name and is associated with the se_39 grid. Since it is for outside the EU, it's name should be 0% EX RS and the grid should be se_40 opw-5798152 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256402 Forward-Port-Of: odoo/odoo#251750
This fix improves how automated browser test logs are captured by saving them after the browser has fully shut down. It helps teams diagnose test failures more accurately and reduces cleanup problems when the browser does not close normally.
Original PR description
odoo/odoo#255054 saved the chrome log at the end of a tour (logging that as `INFO` on success and `RUNBOT` on failure). However as it turns out there are a few issues with that: 1. In case of chrome error during termination (`stop`), those errors can not be in the log, since the log was already saved. 2. Chrome buffers logs a lot more than anticipated, and because `--v=0` logs are a lot less chatty than `--v=1` the logs routinely show essentially nothing (a few tour steps are logged then nothing). Also make `stop` a bit more resilient to chrome issues: - handle errors around ws shutdown - wait for chrome to shut down before we try to remove the data directory - also add a fallback *killing* chrome if it doesn't seem to be shutting down Forward-Port-Of: odoo/odoo#256395 Forward-Port-Of: odoo/odoo#256061
A recent update caused partner names in the approval request report to be cut off when exceeding a certain length. This fix adds a column limit to the partner field, ensuring all data is displayed correctly and preventing data truncation. This improves the report's accuracy and readability.
Original PR description
step to reproduce: - install "approval" with demo data - have a partner with name length > 63 - open one of the approvals and change its type to "general approval" - add this partner in contact field - print approval request report Observation: - the partner overflows out of report Fix: - we limit the partner field with `col-9`. For a safe measure i have added `col-9` for `request_owner_id` and `approver_ids` **Before** <img width="1057" height="326" alt="image" src="https://github.com/user-attachments/assets/a8eea789-5cc7-4658-88b5-78751759d043" /> **After** <img width="994" height="330" alt="image" src="https://github.com/user-attachments/assets/bfbc061b-a6e0-4593-a3cc-c85cb81db6e2" /> opw-6005752 Forward-Port-Of: odoo/enterprise#111130
This update resolves an inconsistency in the tax report when vendor bills include expense lines with different vehicle assignments. The fix allows for accurate reporting by relaxing a strict matching rule that previously flagged mixed vehicle lines. This ensures all tax calculations are correct, regardless of whether a vehicle is associated with an expense line.
Original PR description
**Steps to reproduce:** * Install the **account** and **fleet** modules. * Create a vendor bill with two expense lines using the same tax. * Assign a vehicle_id to one line but leave the other…
**Steps to reproduce:** * Install the **account** and **fleet** modules. * Create a vendor bill with two expense lines using the same tax. * Assign a vehicle_id to one line but leave the other without a vehicle. * Confirm the vendor bill. * Go to **Accounting > Reporting > Tax Report** and Go to `Account > Tax` report. **Observed behavior:** * The tax report shows: 'This report contains inconsistencies. The affected lines are marked with a warning.' **Cause:** * The `_get_extra_query_base_tax_line_mapping()` override forced vehicle_id matching using `COALESCE(base_line.vehicle_id, 0) = COALESCE(account_move_line.vehicle_id, 0)`. * When lines share a tax but have different vehicle_id values (one set, one NULL), Odoo creates a single tax line with `vehicle_id = NULL`. * The strict COALESCE constraint prevented this tax line from matching either base line (NULL ≠ vehicle_id and NULL ≠ NULL when coalesced to 0), causing the inconsistency. **Fix:** * Changed the constraint to only enforce vehicle_id matching when both the base line and tax line have a vehicle_id set. * If either side is NULL, the match is allowed, letting shared tax lines work correctly across mixed vehicle/non-vehicle expense lines. opw-5956645 Forward-Port-Of: odoo/enterprise#112313 Forward-Port-Of: odoo/enterprise#110616
A test used an incorrect date reference (2027) which caused it to fail. This fix adjusted the test's date to 2026-02-28 to accurately reflect the payroll calculations, ensuring the test now passes. This resolves a potential issue with reporting accuracy.
Original PR description
[FIX] l10n_ch_hr_payroll_elm_transmission: fix avs test for faketime build
Bug reproduction:
1 - v.17->run test_generic_avs_deductions test with faketime 2027-01-01 12:00 UTC->test fails
Bug cause:
1 - In the test, compute_sheet()->_get_payslip_lines->_compute_rule->_get_avs_rates is called
2 - There is a line like that if line.date_from <= target and (not line.date_to or target <= line.date_to)
3 - I looked to avs_line_ids = fields.One2many(default=_get_default_avs_line_ids)
4 - In _get_default_avs_line_ids -> 'date_from': fields.Date.today().replace(month=1, day=1) date_from is calculated like that -> when the year is 2027, the date_from is 2027-01-01 and it is bigger than the target in the test.
Bug solution:
1 - I used @freeze_time("2026-02-28") in my test to prevent this behavior.
Runbot Error Link: https://runbot.odoo.com/odoo/runbot.build.error/240992
task - 6018940
Forward-Port-Of: odoo/enterprise#109975This update clarifies the error message displayed when an upsell's start date is set after the next invoice date. This change ensures users receive clearer guidance, preventing confusion and potential issues with subscription billing. It's a simple fix to improve the user experience.
Original PR description
Update the error message when an upsell start date is on or after the next invoice date, so it be more clear for the users. task-5893032 Forward-Port-Of: odoo/enterprise#106757
This update resolves a test failure within the industry_fsm_report module. The issue stemmed from a wizard opening unexpectedly when there was only one worksheet, causing test failures. A workaround was implemented by adding a worksheet before running the tour to prevent the wizard from opening.
Original PR description
When there is only one worksheet, the ‘**Explore Worksheets Using an Example Template**’ wizard opens. Because of this, the test fails without demo data. If we add steps for this wizard, it won’t open when there is more than one worksheet, which will again cause the test to fail. Also, we cannot add this conditon on step. Therefore, to ignore this wizard, i created a worksheet before running the tour so that the wizard does not open. https://github.com/odoo/enterprise/blob/85bd9d80a1a784f1baff1493b2eaec4a17ea9c9b/industry_fsm_report/models/project_task.py#L122-L135 task-4489657 runbot issue-240933
This update resolves a bug that occurred when creating contracts with a working schedule having zero hours. The issue caused a calculation error (division by zero) during wage computation. This fix ensures accurate wage calculations for all contract types, regardless of working hour values.
Original PR description
When a working schedule has 0 working hours, creating a contract raises a traceback during hourly wage computation. Steps to reproduce the error: - Install ``l10n_au_hr_payroll`` module - Switch to ``My Australian Company`` - Create a working schedule without any working hours - Create an employee and assign this working schedule > Save - Click on Contracts smart button Traceback: ```py ZeroDivisionError: float division by zero ``` https://github.com/odoo/enterprise/blob/bd746aa43f549c4f7813a849e00447b55e084f21/l10n_au_hr_payroll/models/hr_contract.py#L113-L115 The hourly wage is computed using the working schedule’s hours per day. When this value is 0, it results in the above traceback. sentry-7355577930 Forward-Port-Of: odoo/enterprise#111629