Friday, December 19, 2025
13 changes · saas-18.4
Resolved issues and error corrections
This update resolves a problem during the migration process where a required tax group wasn't being created, leading to errors. The migration script now automatically creates all necessary tax groups if they don't already exist, ensuring proper tax setup after upgrades. This prevents errors related to missing tax groups.
Original PR description
Before this commit: migration script only creates a new tax group. After this commit: migration script will create all tax groups that are required for new taxes if they do not already exist Why:…
Before this commit:
migration script only creates a new tax group.
After this commit:
migration script will create all tax groups that are required for new taxes if they do not already exist
Why:
During the migration if the tax group is not found then the value error is raised
There are 2 reason of why the tax group is not found :
1. User deletes it by themselves
2. In the upgrade script of account in version saas~16.2.1.2 the pre-migrate script where global scope of tax groups was converted to company-specific, [Ref](https://github.com/odoo/upgrade/blob/b4f278aa9f32dc5edab814af0c2a0339cd7400a6/migrations/account/saas~16.2.1.2/pre-migrate.py#L173) If the tax groups are not associated with any tax or any account_move_line then it is deleted.
User Traceback :
` File "/home/odoo/src/odoo/17.0/odoo/addons/base/models/ir_model.py", line 2203, in _xmlid_lookup
raise ValueError('External ID not found in the system: %s' % xmlid)
ValueError: External ID not found in the system: account.1_l10n_id_tax_group_non_luxury_goods`
account_tax_group records in production :
```
kdes_3444743=> select id,name from account_tax_group;
id | name
----+---------------------------------------------------------------
1 | {"en_US": "Taxes", "id_ID": "Pajak"}
2 | {"en_US": "Luxury Good Taxes", "id_ID": "Pajak Barang Mewah"}
3 | {"en_US": "Non-luxury Good Taxes", "id_ID": "Pajak Barang"}
4 | {"en_US": "Zero-rated Taxes", "id_ID": "Pajak Nol"}
5 | {"en_US": "Tax Exempted", "id_ID": "Bebas Pajak"}
(5 rows)
```
Query executed [here](https://github.com/odoo/upgrade/blob/b4f278aa9f32dc5edab814af0c2a0339cd7400a6/migrations/account/saas~16.2.1.2/pre-migrate.py#L152) :
```
WITH company AS (
SELECT "company_id" AS id,
"tax_group_id" AS tg_id
FROM "account_move_line"
WHERE "company_id" IS NOT NULL
AND "tax_group_id" IS NOT NULL
UNION
SELECT "company_id" AS id,
"tax_group_id" AS tg_id
FROM "account_tax"
WHERE "company_id" IS NOT NULL
AND "tax_group_id" IS NOT NULL
)
INSERT INTO account_tax_group ("country_id", "create_date", "create_uid", "name", "preceding_subtotal", "sequence", "write_date", "write_uid", company_id, _tmp_orig_id)
SELECT "tg"."country_id", "tg"."create_date", "tg"."create_uid", "tg"."name", "tg"."preceding_subtotal", "tg"."sequence", "tg"."write_date", "tg"."write_uid", company.id, tg.id
FROM account_tax_group tg,
company
WHERE company.tg_id = tg.id
```
Above selection query on user's DB :
```
kdes_3444743=> SELECT "company_id" AS id,
"tax_group_id" AS tg_id
FROM "account_move_line"
WHERE "company_id" IS NOT NULL
AND "tax_group_id" IS NOT NULL
UNION
SELECT "company_id" AS id,
"tax_group_id" AS tg_id
FROM "account_tax"
WHERE "company_id" IS NOT NULL
AND "tax_group_id" IS NOT NULL;
id | tg_id
----+-------
1 | 1
1 | 2
(2 rows)
```
As only 2 tax groups are associated with the account_move_line and account_tax
They are only being inserted to the able along with the company id prefix and company_id field set
, remaining enteries are deleted in [next query](https://github.com/odoo/upgrade/blob/b4f278aa9f32dc5edab814af0c2a0339cd7400a6/migrations/account/saas~16.2.1.2/pre-migrate.py#L173).
Same is the case with the records in [ir_model_data](https://github.com/odoo/upgrade/blob/b4f278aa9f32dc5edab814af0c2a0339cd7400a6/migrations/account/saas~16.2.1.2/pre-migrate.py#L174-L196).
OPW : 5358546
UPG : 3444743
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#238981YouTube recently changed how it handles video embedding, causing some of our website's videos to fail to load. This update corrects a configuration issue to ensure YouTube videos play correctly by enforcing the required security policy. This resolves a blocking error and maintains a smooth user experience.
Original PR description
Issue: YouTube has changed its referrer policy to enforce "strict-origin-when-cross-origin". Without this, it can throw a 153 error and block the video. To replicate in runbot ,add "<meta…
Issue: YouTube has changed its referrer policy to enforce "strict-origin-when-cross-origin". Without this, it can throw a 153 error and block the video. To replicate in runbot ,add "<meta name="referrer" content="no-referrer"/>" to any major page like the main layout or footer. This sets it for the entire page. Therefore, to enforce YouTube's calls to have the proper referrerpolicy, I hardcoded it directly. Fix: added 'referrerpolicy="strict-origin-when-cross-origin"' to the iframe. opw-5239363 Description of the issue/feature this PR addresses: Our website allows for customization, including the ability to modify meta tags. In ticket#523963, the customer added "<meta name="referrer" content="no-referrer" />" which forced all calls to be set with referrerpolicy="no-referrer" when it's required to have 'referrerpolicy="strict-origin-when-cross-origin"' for embeded videos to youtube Current behavior before PR: If a customer sets "<meta name="referrer" content="no-referrer" />" on any page, YouTube blocks it on that page; if it's in the header or footer, the entire website is then blocked. Desired behavior after PR is merged: After it now enforces the call to have 'referrerpolicy="strict-origin-when-cross-origin"' even if the tag <meta name="referrer" content="no-referrer" />". Allowing YouTube to be used. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#237182
This update fixes an issue where internal transfers using the barcode scanner wouldn't correctly assign a result package when the package already contained items. The fix ensures that packages with content are now properly recognized as the destination for internal transfers, improving the reliability of the barcode picking process.
Original PR description
Issue ===== When scanning a package as result package, if the package is empty, it works, but if this package already has content, it doesn't work. How to reproduce ================ 1. Enable…
Issue ===== When scanning a package as result package, if the package is empty, it works, but if this package already has content, it doesn't work. How to reproduce ================ 1. Enable "Packages" and "Storage Locations" settings; 2. Create two packages with some content in WH/Stock/Shelf 1; 3. Create an empty package; 4. Create an internal transfer directly from the Barcode app; 5. Scan Shelf 1 barcode and scan first package; 6. Scan the empty package => It's assigned as the result package; 7. Confirm the operation; 8. Create another internal transfer; 9. Scan Shelf 1 barcode and scan second package; 10. Scan the no more empty package => This time, it's not assigned as the result package. Reason ====== A package was assigned as the result package only if one of the following conditions is matched: 1. The scanned package is empty (it's what's happening in 6.); 2. The selected line has no result package yet and the scanned package is in the selected line's destination location. Here, it doesn't work because since we move a package, the barcode line has already a destination package (the same then the source package.) Fix === For the condition 2., adapt the condition to make it works too if the selected line has the same package as the source and result package. [opw-5326234](https://www.odoo.com/odoo/project/49/tasks/5326234) Forward-Port-Of: odoo/enterprise#102051 Forward-Port-Of: odoo/enterprise#101357
This update resolves a ZATCA XML validation error caused by incorrect decimal precision in invoice calculations. The fix ensures that tax amounts are rounded to the required 10 decimal places, preventing validation failures and allowing invoices to successfully pass ZATCA checks. This improves the accuracy of ZATCA reporting.
Original PR description
**Steps to reproduce:** * Install the **Accounting** and **l10n_sa_edi** modules. * Go to `Sales` journal and in ZATCA section click on **Re-Onboard**. * Create Tax with 15% tax with **included…
**Steps to reproduce:** * Install the **Accounting** and **l10n_sa_edi** modules. * Go to `Sales` journal and in ZATCA section click on **Re-Onboard**. * Create Tax with 15% tax with **included price** set as **tax-included**. * Create a customer invoice. * Set **price_unit = 200**, **quantity = 7**, with **15% tax included** and confirm the invoice. * Generate the **ZATCA XML** by clicking **Process Now** in the info banner displayed above the invoice. * Submit the XML to **ZATCA validation**. **Observed behavior:** * ZATCA validation fails with error **BR-KSA-EN16931-11** * The XML uses **PriceAmount (BT-146)** rounded to **2 decimals** (e.g., 173.91). * ZATCA computes: **173.91 × 7 = 1217.37**, but the XML’s **LineExtensionAmount (BT-131)** is **1217.39**, creating a mismatch and triggering validation failure. **Cause:** * In v19, `_add_document_line_price_nodes()` inherited from `account.edi.xml.ubl_20` uses `float_round` with **product_price_dp = 2 decimals** for **PriceAmount**. * This precision is insufficient when ZATCA recalculates totals for tax-included prices, causing rounding discrepancies. **Fix:** * Override `_add_document_line_price_nodes()` in **l10n_sa_edi** to round `gross_price_unit_currency` to **10 decimal places** instead of 2. * Ensures PriceAmount has sufficient precision to satisfy ZATCA validation rules. opw-5346886
This update resolves an error that occurred when sending invoices with a Turkish recipient bank. The issue stemmed from incorrect data handling when generating the invoice XML, specifically related to identifying the recipient's country. The fix ensures the system correctly identifies the bank's country, allowing invoices to be successfully generated and sent.
Original PR description
For the `Türkiye` localization, sending an invoice by email with a recipient bank causes an error. Steps to reproduce: 1) Install `accountant` and `l10n_tr_nilvera_einvoice` modules with demo data.…
For the `Türkiye` localization, sending an invoice by email with a recipient bank causes an error. Steps to reproduce: 1) Install `accountant` and `l10n_tr_nilvera_einvoice` modules with demo data. 2) Switch to TR Company. 3) Create a customer with country set to `Türkiye`. 4) Open the TR company contact and on the Accounting page edit an existing bank account, add a new bank (e.g., 'Test-Bank'), and set `Send Money` to `Trusted`. 5) Create an invoice for the customer, confirm it, and send it by email. ref video: https://drive.google.com/file/d/1OoUzJ-Dr2uuy4yk9P-CKUS0L6OSgeyJ3/view?usp=sharing Error: KeyError: 'country_id' Root Cause: When sending the invoice, the system generates the invoice XML. In the method `_get_address_node` (see [1]), there is a special case to determine the correct country for `res.bank`. However, when `vals['partner']` is a `res.bank` record, no `model` is provided in `vals`, so it defaults to `res.partner`. The code then attempts to access `partner['country_id']`, which does not exist on `res.bank`, raising the error. FIX: Ensure the `model` is set to `res.bank` when `vals['partner']` is a `res.bank` record, ensuring the correct country value is used. [1]- https://github.com/odoo/odoo/blob/0190bb7faca1dd5ce38dfdacbb8fa446f06d59a3/addons/l10n_tr_nilvera_einvoice/models/account_edi_xml_ubl_tr.py#L165-L181 opw-5103598
This update resolves an issue where the Client Nihil field was incorrectly set to 'YES' for Belgian VAT reports, violating regulations regarding year-end nihilization. The PR restores the checkbox option for this setting, ensuring compliance with Belgian tax laws. This prevents incorrect XML export files for VAT returns.
Original PR description
## Issue: When exporting the XML for a VAT return, the client nihil field was incorrectly set to YES According to Belgian regulations, this is only allowed on the last report of the calendar year…
## Issue: When exporting the XML for a VAT return, the client nihil field was incorrectly set to YES According to Belgian regulations, this is only allowed on the last report of the calendar year https://finances.belgium.be/sites/default/files/downloads/165-625-directives-2019.pdf ## Cause: Prior to 18.3, nihil was a checkbox option on export Since 18.3, it is automatically selected based solely on a price formula, without checking the report’s date This PR brings back the Client Nihil checkbox in 19.0 But didn't change the default value Causing the issue to still be present https://github.com/odoo/enterprise/pull/99496 ## Steps to reproduce: - Select the Belgian company - Open the Tax Return and select the VAT Return - Click Returns and enter an opening date in January - Click Review for the first available report - Ignore errors and return to previous page - Click on Submit -> Download XML - Before the fix, ClientListingNihil is set to YES ## Potential remaining issue: The legal document specify that it should also be checked in case of "cessation d’activité" So it may be interesting to consider adding the option back opw-5184056 Forward-Port-Of: odoo/enterprise#98982
This update fixes an issue where restaurant employees were always redirected to the floor page after logging in, regardless of their configured default product page. The fix ensures that users are consistently directed to the 'register' (products) page after login, as intended for restaurant POS systems. This improves the user experience and aligns with the restaurant's desired workflow.
Original PR description
Steps to reproduce ------------------ 1. For a restaurant, set the default page as "register", i.e. the products page 2. Enable 3. Now login with an employee, and notice that the page after the login page is the floor page, not the products page as set in the configuration of (step 1). Why the issue ------------- After successfully logging in, we were redirecting the user either to the products page, always if it's not a restaurant, or to the floor page, always if it's a restaurant. That means we were not taking into consideration, for the restauarnt case, whether the default page is the floor page or the products page. The fix ------- Now we redirect users after logging using the `defaultPage` getter, which takes into consideration the `default_page` cofiguration for a restaurant PoS. opw-5359514 Forward-Port-Of: odoo/odoo#237784
This update improves the speed of our website tests by caching the parsing of large snippet documents. Previously, each test had to re-parse these documents, which took a significant amount of time. Now, the system remembers the parsed results, dramatically reducing test execution time.
Original PR description
__Behavior before commit:__ - [`SnippetModel`] loads all snippets and parse them for every test that uses a snippet. - `getStructureSnippet` parse them as well This parsing may take around 80 ms for each test because it is 1MB long. __Fix:__ `DOMParser.parseFromString` is patched to cache its result when it's the snippet document. This significantly reduce the duration of the website builder test suite. [`SnippetModel`]: https://github.com/odoo/odoo/blob/4de72eeca8b8f9251ea18cd48330fc1c48bce1bd/addons/html_builder/static/src/snippets/snippet_service.js#L138 task-5269391
This update allows users to export Intrastat reports in XML format, addressing previous limitations that prevented successful report submissions. Previously, users needed to use a workaround to generate the XML, now a direct export option is available from the Intrastat Report view, ensuring compliance with Belgian regulations.
Original PR description
**Behavior:** Currently Intrastat reports are exported from the account.return view, and will be exported specifically in their extended mode and will contain both arrivals and dispatches. This…
**Behavior:** Currently Intrastat reports are exported from the account.return view, and will be exported specifically in their extended mode and will contain both arrivals and dispatches. This causes issues for some users that want more specific formats like standard over extended, only arrivals/dispatches or both, etc... And this can cause them to not be able to submit their reports. The solution is to currently reenable the user to export their report to XML from a cog menu in the Intrastat Report view. While still leaving the current flow through account.return possible, until a better solution is thought of. **Steps to reproduce:** - Connect to a company under Belgian Localisation. - Create a product and, under the Accounting tab, specify a Commodity code (eg Live asses) and Country of Origin (Belgium) - Create an Invoice containing the product to a Client in another EU Country (eg Luxembourg) and under the 'Other Info' tab, specify Intrastat Countrt (Belgium) - You can choose to leave out Intrastat Transport Mode and Incoterm, this will make the resulting XML have some missing informations - Create a Bill with the product with the same settings - If you go to Intrastat Report, after changing the 'Report' filter to Intrastat (Goods) you will now be able to see an arrival and a dispatch. The extended mode filter is enabled by default, if you didnt fill Intrastat Transport Mode and Incoterm, you will see these missing. - From this view there is currently no way to export the XML, to do that click the Returns button (select an Opening Date for accounting if needed), click on 'New' and specify Intrastat in the Return Type and a time window containing your Invoice and Bill. - Then you will see an Intrastat Report show up and after selecting Review, then Submit, you will be able to download the XML. which will contain dispatches and arrivals and will be in Extended Mode. Which, if missing Transport/Incoterm, will fail when submitted to OneGate opw-5347238
This update fixes issues with image dragging and dropping within the HTML editor, ensuring that formatting, captions, and image duplication problems are resolved. By using a standardized data transfer type, the editor now correctly handles image selection, copy-paste operations, and placement, leading to a more reliable editing experience.
Original PR description
**Current behavior before PR:** - When dragging and dropping elements with attributes and classes, any non-whitelisted attributes and classes were removed during the `cleanForPaste` process. This…
**Current behavior before PR:** - When dragging and dropping elements with attributes and classes, any non-whitelisted attributes and classes were removed during the `cleanForPaste` process. This caused structural issues and loss of formatting after the drop. - When an image had a caption and only the image was selected and cut, the image was removed but the caption incorrectly remained - When dragging and dropping an image without an active selection on the image, the image was not removed during the drop. This resulted in the image being duplicated, one at the original position and another at the drop location. - When selecting an image with a caption and performing copy-paste, only the image was copied and pasted. **Desired behavior after PR is merged:** - An `application/vnd.odoo.odoo-editor` dataTransfer type is now set during `dragstart` for editor elements. As a result, we no longer need to clean the `dataTransfer` content during drop, preserving the original structure and preventing the loss of attributes and classes. - Cutting an image that contains a caption now correctly removes both the image and its associated caption. - The image is now selected on pointerdown event . As a result, when the image is dropped, deleteSelection correctly removes the original image before inserting the new one, preventing duplication. - Now, when an image with a caption is selected and copy-pasted, the entire image along with its caption is correctly copied and pasted. task: 4914451
This update resolves a problem with the Chile invoice PDF report, where text was incorrectly formatted and overflowing. The fix ensures the invoice layout is correct and readable, preventing issues with printing and data display. This improves the accuracy and professionalism of invoices for Chilean customers.
Original PR description
Steps to reproduce: 1. Install l10n_cl_edi. 2. Create an invoice with a customer having a Chile address. 3. Print "Invoice PDF copy (Chile)". Issue: The PDF layout is broken: some text is rendered vertically and the content overflows across multiple pages. Cause: The footer right column row did not have an explicit width, causing wkhtmltopdf to shrink the container and wrap text letter by letter. Fix: Set w-100 on the inner row to stabilize the layout and prevent vertical text rendering. Before Fix : <img width="408" height="313" alt="image" src="https://github.com/user-attachments/assets/1d61412d-cfd3-48df-a4d4-eabd10df4865" /> After Fix: <img width="409" height="320" alt="image" src="https://github.com/user-attachments/assets/3a098227-7e43-44f0-9266-b4b0023f382c" /> opw-5348151
This update fixes an issue where customers could initiate subscription payments without providing their country, leading to payment failures. The change ensures that subscriptions, even for services, require country information for recurring payments, aligning with Odoo's requirements. This prevents payment errors and improves the reliability of subscription billing.
Original PR description
## Versions saas-18.3 > saas-18.4 Backport of OE's commit c02eb8584da1cef7d28310d9be947b56a38a5cbd ## Issue A customer subscribing to a service can checkout without filling its data (incl. country).…
## Versions
saas-18.3 > saas-18.4
Backport of OE's commit c02eb8584da1cef7d28310d9be947b56a38a5cbd
## Issue
A customer subscribing to a service can checkout without filling its data (incl. country). This leads to a failure of the next payment and a message in the chatter telling that "Automatic payment failed. No country specified on payment_token's partner".
## Steps to reproduce
*Ensure Sales app is installed*
- Create a customer account without filling personal data in;
- Navigate to the shop:
- Look for a subscription service (ending with "SUB") and add it to cart;
- Go to the cart and click the checkout button (automatically bypassing the addresses form);
- Pay with Demo.
- Logout and sign in as admin user:
- Go to Sales and open the latest SO (related to the test user):
- Duplicate the SO and activate debug mode;
- Open "Other Info" tab:
- Change the subscription starting date for any date in the past;
- Set the Payment Token selecting the available one; - Confirm the order.
- Navigate to Scheduled Actions:
- Look for "Sale Subscription: generate recurring invoices and payments" action and open it:
- Click "Run Manually".
- Come back to the duplicated subscription SO and look at the chatter's last message:
- OdooBot's message tells that "Automatic payment failed. No country specified on payment_token's partner".
## Cause
Task 4307281 introduced address info bypass to fasten checkout for services but subscriptions, even for services, require the country to be set for recurring payments as per https://github.com/odoo/enterprise/blob/f40e24e67a1664a13acdd01578d8269d084ee421/sale_subscription/models/sale_order.py#L1751-L1757
opw-5412037
Forward-Port-Of: odoo/enterprise#102168This update fixes an issue where the link popover was incorrectly positioned within the HTML editor, particularly when creating links. The fix addresses a problem with how the browser handles text selections and range management, ensuring the popover appears in the correct location. This improves the user experience and stability of the HTML editor.
Original PR description
Two related overlay reposition issues are solved separately out of iframe and in the iframe. **Commit 1:** [FIX] html_editor: avoid wrong range after insert and popover reposition Before this commit:…
Two related overlay reposition issues are solved separately out of iframe and in the iframe. **Commit 1:** [FIX] html_editor: avoid wrong range after insert and popover reposition Before this commit: The link popover is repositioned at the beginning of the text when editing url. When insert, we first delete the non-collapsed selection, then we split the text node by splitTextNode at the collapsed selection. However, splitTextNode resets the text node's value by its substring, which breaks the range of the collapsed selection. This range is stored and used to reposition the overlay when the selection is not in the editable. Reproduction: 1. selection some text, create a link 2. go the the url field and type something 3. the popover is replaced to the beginning of the text. After this commit: we use dom function splitText to split the text only when we need to, e.g. when the currently selection's offset isn't at the beginning or the end of the text node. The dom function keeps the range properly maintained after splitting. However, there is a limitation case from how we create the link on selection, how the browser manages the selection's range and how the overlay reacts to it. The limitation case is when the selection is inside one text node and selecting the whole text node of the range's startContainer (which is the same with endContainer). When the link is created, we do extractContent on the selection's range, put it in the link and insert the link at the collapsed selection. During this process, the browser loses the range's start/end container which leads to invalid start/end container. For this range isn't valid case, it triggers the overlay plugin's special handler which inserts one shadow caret (which is after the inserted link) and uses it to calculate the position. Because the shadow caret is inserted by the cloned collapsed range, we can't really have enough context from the range (about where to re-place the caret) to manipulate the position. **Commit2:** [FIX] html_editor: pass selection data to overlay to avoid reposition in iframe Before this commit: the overlay plugin uses the editable's document's selection to check if the current selection is in the editable. It works when there's no iframe, as the overlays are part of the document. However in an iframe's editable zone, e.g. the website editing zone, the overlays are not under the iframe document but under the outer window's document. When checking iframe document's selection, it cannot detect the selection in the overlay, which gives a wrong "inEditable" value. After this commit: we pass the getSelectionData to the overlay so it can use the existing currentSelectionIsInEditable task-5184799 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr