Tuesday, July 14, 2026
14 changes · 18.0
Resolved issues and error corrections
French VAT reports sent through Aspone now use the latest required filing year identifier. This helps ensure submitted forms match current French reporting requirements and reduces the risk of rejected filings.
Original PR description
This commit will put the new millesime for all the form that we send though aspone. (Was done in 19.0 here: https://github.com/odoo/enterprise/commit/48454123fc4a419e22648df05e0e3c3bf892a277) task-6253745
The Dutch reports module no longer shows a link that pointed to an unrelated website. This avoids confusion for users looking at the app information and keeps the product details accurate.
Original PR description
The URL leads to a website that has nothing to do with what it used to be so it needs to be removed. Task-6360682 Forward-Port-Of: odoo/enterprise#123019
Shopee order lines now show the correct variant SKU instead of the general product template SKU when products have variants. This helps sales teams and customers identify the exact item ordered and reduces confusion during fulfillment.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110
Odoo Studio no longer shows an error when users rename fields with labels made up of non-Latin characters, such as Arabic. This makes field customization more reliable for multilingual users and avoids invalid internal names being generated behind the scenes.
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#121343
The WhatsApp identifiers component is now properly registered in the translation system. This helps ensure its text can be picked up for localization, reducing the chance of missing translations for users in different languages.
Original PR description
pot files must be registered there. See 9966b160972a053e051f2213846acc64d133f2a3 Forward-Port-Of: odoo/enterprise#124026
Newer IoT Boxes may no longer include manufacturer details when sharing device information. This fix allows setup to continue without that field, preserving compatibility across older and newer devices.
Original PR description
Newer IoT Boxes don't send the `manufacturer` along with other device data. We need then to make it optional to ensure backward compatibility. task-6384728
This fix removes unnecessary blank lines when Uruguayan electronic invoices include both addenda text and terms and conditions. It helps prevent short addenda content from being pushed onto a separate page unnecessarily, keeping invoice PDFs more compact and professional.
Original PR description
## Context When generating a CFE (Comprobante Fiscal Electrónico) that contains both a configured addenda (e.g. bank account details stored in `l10n_uy_edi_addenda_ids`) and terms & conditions from…
## Context
When generating a CFE (Comprobante Fiscal Electrónico) that contains both a configured addenda (e.g. bank account details stored in `l10n_uy_edi_addenda_ids`) and terms & conditions from the invoice's `narration` field, the resulting addenda string could end up with unnecessary blank lines between the two sections, causing the addenda to be rendered on a separate page even when the logical content fits within the 6-line threshold.
## Root Cause
`_l10n_uy_edi_get_addenda` joins both parts without stripping whitespace from either of them first, and adds two lines between addendas and terms and conditions:
addenda = addenda + "\n\n" + term_and_conditions if addenda else term_and_conditions
Two sources independently introduce extra newlines around the separator:
1. **Addenda content** — `_get_legends` returns the raw `content` field value of each addenda record. These fields commonly end with a trailing `\n`, so the addenda string already ends with a newline before the `"\n"` separator is concatenated.
2. **`html2plaintext`** — the `narration` field is stored as HTML. When converted to plain text, `html2plaintext` typically wraps paragraph content in leading/trailing newlines.
The combination of the trailing `\n` from the addenda, the explicit `"\n\n"` separator, and the leading/trailing `\n` from `html2plaintext` produces 2–3 consecutive newlines, which `splitlines()` counts as blank lines.
A realistic 4-line addenda + 1-line narration thus produces **7 lines** instead of the expected 5, crossing the 6-line threshold in `_get_report_params` and triggering `adenda=true` — which forces the addenda onto a separate page unnecessarily.
## Steps to Reproduce
1. Configure a `l10n_uy_edi.addenda` record of type `addenda` with multi-line content (4 lines)
2. Create and confirm an invoice with `narration` set to a short single-line term
3. Generate the CFE PDF via Uruware.
4. Observe that the addenda is rendered on a separate page despite the logical content being only 5 lines.
<img width="1042" height="448" alt="image" src="https://github.com/user-attachments/assets/b538211c-5f37-4648-979d-99cd75cf31c2" />
## Fix
Strip leading and trailing whitespace (including newlines) from both parts before joining them. The ternary is also replaced with an explicit `if/else` for clarity:
def _l10n_uy_edi_get_addenda(self):
addenda = self.l10n_uy_edi_document_id._get_legends("addenda", self)
if self.narration:
term_and_conditions = html2plaintext(self.narration).strip()
if addenda:
addenda = addenda.strip() + "\n" + term_and_conditions
else:
addenda = term_and_conditions
return self._l10n_uy_edi_clean_non_ascii_chars(addenda)
This guarantees exactly one `\n` separator between sections regardless of how the content fields were stored or how `html2plaintext` formatted the narration.
The threshold logic in `_get_report_params` is unchanged: addendas that genuinely exceed 6 lines (after wrapping at 140 chars) continue to be printed on a dedicated page.
Result
<img width="1117" height="456" alt="image" src="https://github.com/user-attachments/assets/3a2d942c-8c37-40f6-bc25-470c0bd25b08" />This fix assigns a Belgian payroll termination holiday rule to the correct salary structure. It helps ensure affected payslips are calculated and validated using the intended payroll configuration.
Original PR description
Oversight of 553ba7d0d066b4179b7f89f8ec9ef8f0bffe964d Forward-Port-Of: odoo/enterprise#124280 Forward-Port-Of: odoo/enterprise#123765
This update corrects a technical issue where specific error messages related to zero percentages in account reconciliation were inconsistent. The change aligns these messages with the correct amount type being validated, providing clearer guidance to users when entering zero values. This improves the user experience and helps ensure accurate reconciliation processes.
Original PR description
In _validate_amount(), setting a "Percentage of balance" line to 0 raises "Statement line percentage can't be 0", and setting a "Percentage of statement line" to 0 raises "Balance percentage can't be 0". Align each error message with the amount type being validated. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269393
This update resolves an issue where dropdown menus remained visible on the POS screensaver. The fix ensures that all active overlays, like menus, are properly closed when the screensaver is activated, improving the user experience and preventing visual clutter. This enhances the overall usability of the Point of Sale interface.
Original PR description
Currently, overlays remain open when the POS screensaver is loaded [^1]. #### Steps to reproduce: - Open the POS interface. - Open a dropdown/popover menu (e.g., the navbar hamburger menu). - Wait for the screensaver (SaverScreen) to trigger due to inactivity. - The open dropdown menu remains visible on top of the screensaver. #### Issue Dropdowns and popovers are rendered as active overlays outside the main screen container. While the screensaver setup closes active dialogs, it does not handle active overlays. #### Fix Retrieve the overlay service in SaverScreen and close all active overlays during its setup phase using a dedicated `closeAllOverlays` method. [^1]: 
This update resolves a minor technical issue within the Odoo accounting module. A typographical error was corrected in a calculation field used for analyzing profitability. This ensures accurate reporting and avoids potential discrepancies in financial data.
Original PR description
Fix field name typo. @qrtl QT6381
A bug in a test related to currency conversion within the event sale module was resolved. The test now correctly initializes exchange rates, ensuring accurate currency conversion calculations. This fix improves the reliability of our event sale pricing tests.
Original PR description
Before this commit, in the test `test_ticket_price_with_currency_conversion` the exchange rate was not correctly assigned because `rate_ids` was not initialized when running tests on app install. As a result the the rate was left empty and the currency conversion was not applied. This commit creates the rate_ids in the test to make sure the rates are correctly applied. Runbot error: https://runbot.odoo.com/odoo/error/242431 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves a technical error preventing Spanish companies using EDI modules (Veri*Factu, SII, TBAI) from correctly sending invoices. The fix addresses a change in the Requests library that caused a certificate loading error when using version 2.32 or higher. By setting up the certificate during adapter creation, the issue is now consistently resolved across all Requests versions.
Original PR description
CertificateAdapter presents a client certificate stored in the database instead of on disk when opening an HTTPS connection (used by the l10n_es EDI modules verifactu, sii and tbai). It loaded that…
CertificateAdapter presents a client certificate stored in the database instead of on disk when opening an HTTPS connection (used by the l10n_es EDI modules verifactu, sii and tbai). It loaded that certificate on the connection path of requests 2.31, but requests >= 2.32 changed that path (no longer calls get_connection()), so the step was skipped and the call crashed with: "TypeError: expected str, bytes or os.PathLike object, not certificate" Odoo pins requests 2.31.0 (max depending on Python version), but online databases can use the version shipped by the OS (2.32.x on recent Ubuntu 26). Set the certificate up when the adapter is created instead of on that connection call. That step runs the same on every requests version, so the fix works both before and after 2.32. Steps to reproduce: - Spanish company with Veri*Factu and a certificate, on a server running requests >= 2.32 (saas-19.3 database for exemple on ubuntu 26) - Post a customer invoice and send it to Veri*Factu. => TypeError Reference: https://github.com/psf/requests/blob/f361ead047be5cb873174218582f7d8b9fcd9f49/HISTORY.md?plain=1#L146 Ticket [link](https://www.odoo.com/odoo/project.task/6366028) opw-6366028
This update resolves an issue where the website editor was experiencing performance problems due to incorrect use of asynchronous callbacks within its code. The team has replaced `forEach` loops with traditional `for` loops, resulting in a more stable and efficient editor experience. This change ensures smoother operation for website content creation.
Original PR description
*: website, website_sale `forEach` is a synchronous operation, so it doesn't support promises. We refactor its usage to use `for` loops. task-4794299 Forward-Port-Of: odoo/odoo#275262