Daily updates from Odoo
Wednesday, June 10, 2026
13 changes · 18.0
Enhancements to existing features
This update introduces a new 'PINT' layer in the account_edi_ubl_cii module, bridging the gap between UBL and BIS3 invoice formats. This enhancement supports compliance with European regulations and standards, particularly those related to PEPPOL, by providing a standardized layer for invoice processing and data exchange.
Original PR description
Add the layer PINT between UBL and BIS3. task: 5890887
Resolved issues and error corrections
This update fixes a security issue where users could view financial budgets belonging to other companies. The change adds a security rule to the budget module, ensuring that users only see budgets associated with the company they are actively working with. This enhances data privacy and control.
Original PR description
**Steps to reproduce:** - Install the `account_reports` module. - Create a new company. - Navigate to Accounting > Configuration > Financial Budgets. - Create a new budget record. - Switch to another company. - Open the list view of Financial Budgets. **Observation:** The budget record created in another company is still visible. **Root Cause:** The model `account.report.budget` does not have any record rule restricting access based on company. As a result, users can see financial budgets belonging to other companies even if they are not connected to them. **Fix:** This commit allows users to hide financial budgets from companies they are not connected to by adding a record rule on `account.report.budget` opw-6083892
This update fixes a bug where untaxed invoice lines were incorrectly inheriting the Datev code from the previous line, leading to inaccurate reports. The change ensures that untaxed lines now correctly have an empty Datev code, resolving a reporting discrepancy. This improves the accuracy of financial reports generated for German businesses using the Datev system.
Original PR description
**PROBLEM** Untaxed move lines would take the datev code of the previous line instead of having no datev code like they should. **STEP TO REPRODUCE** 1. On a german company, create an invoice with a line with tax 19% I, and a line that is untaxed (with a non-null price). 2. On the general ledger, generate the datev zip. 3. Unzip, and open the account entries csv, and notice the 2nd line of the invoice as the datev code set to something instead of it being empty (column BU-Schlüssel). opw-6141003 Forward-Port-Of: odoo/enterprise#118486
This update resolves a problem where DHL delivery confirmations were failing due to incorrect scheduled dates (past dates). The system now automatically sets a future date (one hour ahead) to ensure successful confirmation, preventing delivery errors and improving order processing.
Original PR description
When confirming the delivery of an order using DHL shipping method we get an error that the date must be in the future. This happens when the scheduled date was not set, or set for a time in the past. This commit automatically sets the time to 1 hour in the future and bypasses the user error. opw-6148927 Forward-Port-Of: odoo/enterprise#116211
This update resolves a rounding issue that occurred when generating PEPPOL invoices, specifically impacting unit prices. The change reverts a previous update that introduced this problem, ensuring accurate pricing calculations for international transactions. This improves the reliability of invoices for our business partners using PEPPOL.
Original PR description
Reverts https://github.com/odoo/odoo/pull/262242 opw-6293201
This update resolves a problem where the PDF Quote Builder generated incorrect data due to how it handled temporary records during the demo setup. The fix ensures that all data changes are immediately applied within the transaction, preventing inconsistencies and errors when the builder is enabled. This ensures the PDF quote builder functions correctly after demo data is used.
Original PR description
Steps to produce: --- - Install sale_management and website_sale modules with demo data. - From settings, disable the PDF Quote Builder. - Go to Settings > Technical > Sequences & Identifiers >…
Steps to produce:
---
- Install sale_management and website_sale modules with demo data.
- From settings, disable the PDF Quote Builder.
- Go to Settings > Technical > Sequences & Identifiers > External Identifiers.
- Delete the `consu_delivery_02_product_template` identifier.
- From settings, try to enable the PDF Quote Builder again.
Issue:
---
```py
insert or update on table "quotation_document_sale_pdf_form_field_rel" violates foreign key constraint
"quotation_document_sale_pdf_form_fie_quotation_document_id_fkey"
DETAIL: Key (quotation_document_id)=(1) is not present in table "quotation_document".
```
Cause:
---
When the XML demo loader processes **`sale_pdf_quote_builder_demo.xml`**, it calls `create()` on `quotation.document` for each of the 5 demo records one by one. Each create() call receives vals_list that contains datas, the actual PDF base64 content.
Inside `super().create(vals_list) `[1], the ORM writes datas to `ir_attachment`. Since `form_field_ids` is a `store=True` computed field with `@api.depends('datas')` [2], the ORM knows it needs to recompute `form_field_ids`. But it does not run the computation immediately. It simply registers the records in a pending recompute set and moves on. Nothing hits the DB yet for this compute.
After `super().create() `returns, the `write({'res_model': ..., 'res_id': ...})` runs. Since `res_model` and `res_id` live on `ir_attachment` (the parent table via _inherits), this write is also not immediately flushed to the DB. The ORM marks it as dirty in the cache and defers it.
So after all 5 records are created, the ORM holds two deferred things: a dirty UPDATE ir_attachment write for all 5 records, and a pending recompute for `form_field_ids` on all 5 records. Nothing has been flushed to the DB yet.
When the demo XML tries to reference `product.consu_delivery_02_product_template` [3], which no longer exists,
a ValueError is raised. From `load_demo()` [4], the savepoint is rolled back.
After the except block logs the failure, execution continues in l`oad_module_graph()` which calls `env.cr.commit()`. This triggers f`lush() -> transaction.flush() -> flush_all() -> _recompute_all()`. The ORM processes the pending recompute registry and finds `form_field_ids` needs recomputing for quotation.document(1, 2, 3, 4, 5). It calls `_compute_form_field_ids`() on those stale ids. Inside that compute, `_create_or_update_form_fields_on_pdf_records()` tries to insert into `quotation_document_sale_pdf_form_field_rel` with quotation_document_id=1. But quotation_document id 1 no longer exists in the DB — it was rolled back — so PostgreSQL raises the foreign key violation.
This is confirmed by the traceback from `_compute_form_field_ids`, which shows the call chain going through `commit() -> flush_all() -> _recompute_all()` rather than through `create()`, proving the compute fired after the rollback using stale ORM cache state.
Fix:
---
Calling `docs.flush_recordset()` at the end of `create()` forces all pending writes and pending recomputes to be executed immediately, while still inside the savepoint scope:
- It flushes the dirty res_model/res_id write on the ir_attachment parent table, so UPDATE ir_attachment hits the DB inside the savepoint.
- It triggers `_recompute_all()` for the pending `form_field_ids` compute on docs, so `_compute_form_field_ids()` runs inside the savepoint and the INSERT into `quotation_document_sale_pdf_form_field_rel` happens while the quotation_document rows still exist in the DB.
If the savepoint then rolls back, the ORM cache has nothing dirty or pending left. The subsequent commit() in `load_module_graph()` finds nothing to flush, so no stale writes execute against non-existent ids and no foreign key violation occurs.
[1]https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/sale_pdf_quote_builder/models/quotation_document.py#L93-L98
[2]https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/sale_pdf_quote_builder/models/quotation_document.py#L62-L71
[3]https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/sale_pdf_quote_builder/data/sale_pdf_quote_builder_demo.xml#L44-L51
[4]https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/odoo/modules/loading.py#L89-L90
opw-6139555
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update fixes an issue where product matching by name was incorrectly associating products across multiple lines in imports. The fix adds a necessary cache key, ensuring that products are matched accurately based on their unique characteristics, preventing incorrect product assignments during import processes. This improves data integrity and import accuracy.
Original PR description
**PROBLEM** When retrieving a product by name, there is no cache_key for the search_method criteria. This leads to the cache_key frozendict being an frozen dict with None values. This means, once we retrieve a first product with the search_method criteria, all following product will match its cache_key, so we ends up associating a product to all subsequent lines, even if they don't have anything in common. **STEP TO REPRODUCE** 1. Create a product with the name: "CASTELTORRE MERLOT DELLE VENEZIE 75CL 10,5i" (it's important the name is not exactly matching) 2. Import the xml which is attached to the bug fix ticket. 3. Notice the product column on all the lines after a certain point have the CASTELTORRE product, even though the corresponding line in the ubl is for another product. opw-6227280
This update fixes an issue where refunds made from the PoS interface didn't accurately update the quantity invoiced on the associated sale order. The fix ensures that refund lines are correctly considered when calculating the invoiced quantity, resolving a previous inconsistency between PoS and backend refund processes.
Original PR description
When making a refund of a PoS order that was created from a sale order, the sale order qty_invoice was not updated correctly. Steps to reproduce: ------------------- * Create a sale order with any product and confirm it * Open a PoS and settle the order * At this point the qty_invoiced should be 1 on the sale order line * Refund the PoS order from the PoS > Observation: The qty_invoiced is still one. Why the fix: ------------ We now take refund lines into account when computing the qty_invoiced. Note: ------------ There was an inconsistency between a refund made from the PoS and a refund made from the backend. The former is not linking the sale order line to the refund line, while the latter does. This was causing issue when refunding from the backend as it would count the refund twice. To fix this we now remove the link to the sale order line when refunding from the backend. opw-4991405
This update resolves a problem where PDF links within the Odoo viewer were not working correctly. The fix adjusts the layering of elements to ensure clicks are properly directed to the PDF links, improving document navigation. This ensures users can reliably access links within PDF documents.
Original PR description
Version - 18.0 Steps to reproduce: 1. Upload a PDF document containing bookmarks and internal/external links 2. Open the document 3. Click on the links, some work and some do not Issue: `canvas_layer_0` is positioned over the PDF viewer with `z-index: 1`, intercepting clicks intended for PDF link annotations and making internal/external links unresponsive. The `.textLayer` already has `z-index: 2 !important` in iframe.css to prevent the same problem for text selection Fix: Added `z-index: 2 !important` to `.annotationLayer section` in `iframe.css` raising it above `canvas_layer_0`. Taskid = 6237688
This update resolves a requirement from Luxembourg auditors regarding the classification of partners in our SAFT reports. Specifically, it ensures that less than 30% of transactions with payable or receivable accounts have missing supplier or customer IDs, aligning with Luxembourg's FAIA reporting standards. The changes automatically update partner listings and maintain compatibility with older report formats.
Original PR description
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on…
This PR is one of many triggered by responses from Luxembourg auditors. See PR #113316 for a full list of these PRs. As described in PR #117799, the \CustomerID and \SupplierID elements on \Transaction\Line elements is determined by a partner's `customer_rank` and `supplier_rank`. This is a binary designation, one or the other. The Luxembourg FAIA report requires that less than 30% of \Transaction\Line elements with payable accounts (class 6) can not have \SupplierID. The same applies for \Transaction\Line elements with receivable accounts (class 7) and the \CustomerID element. TSB clarified that any partner on an receivable or payable line should be added to the Customer list or Supplier list respectively https://github.com/odoo/enterprise/pull/100749#issuecomment-3655127511. In addition, I verified that Luxembourg's analysis of four separate FAIA files (from ticket 5427296) aligns with this expectation. <img width="1322" height="690" alt="image" src="https://github.com/user-attachments/assets/1a82f99e-5b32-4dbb-96e1-1b25bab2629b" /> This commit adds partners to the \Supplier and \Customer lists if they have any payable or receivable lines, respectively. It also picks between the \CustomerID and \SupplierID based on a line's `account_type`. This logic is applied to `account_saft` and updates the other, country-specific SAFT reports where appropriate. It also retains the previous `customer_rank` and `supplier_rank` logic as a fallback for older XML reports and for accounts other than `asset_receivable` or `liability_payable`. opw-6118024 Forward-Port-Of: odoo/enterprise#118714
This update resolves an issue where attempting to create a new Global Invoice after cancelling a refund in the Mexican CFDI POS module would fail. The fix ensures that refund CFDI documents are correctly updated during the cancellation process, allowing for seamless invoice creation. This improves the reliability of the POS system for Mexican businesses.
Original PR description
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original…
Steps to reproduce 1. With a Mexican POS configured, create a POS order and sign a Global Invoice for it. 2. Open a new session and partially return the order; close the session. 3. On the original order, cancel the Global Invoice through the CFDI page. 4. Try to create a new Global Invoice for the original order. Issue The wizard raises "Orders <REFUND-NAME> are already sent or not eligible for CFDI." Validating the refund auto-signs an `invoice_sent` CFDI on the refund pos.order because its parent is `global_sent`, see `_l10n_mx_edi_check_autogenerate_cfdi_refund` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L98. Cancelling the GI only flips its own document to `ginvoice_cancel`; the refund's `invoice_sent` doc stays untouched, so the refund's computed `l10n_mx_edi_cfdi_state` stays `'sent'`. The chain check in `_l10n_mx_edi_check_orders_for_global_invoice` at https://github.com/odoo/enterprise/blob/5af8048f0b0956a024d7eaeb10600eec74bdf3ee/l10n_mx_edi_pos/models/pos_order.py#L184 then rejects the refund as already sent and the new GI cannot be created. opw-6181136
This update fixes an issue where the 'Due' button wasn't appearing for customers when their outstanding balance was present, specifically when the customer was only linked to a journal entry at the line level. The fix ensures all customers with balances are correctly identified, improving the user experience and preventing missed follow-up actions.
Original PR description
Steps to Reproduce: 1. Install Accounting module (without Point of Sale). 2. Create a customer. 3. Create a journal entry with that customer set only at line level. 4. Post the journal entry. 5. Open…
Steps to Reproduce: 1. Install Accounting module (without Point of Sale). 2. Create a customer. 3. Create a journal entry with that customer set only at line level. 4. Post the journal entry. 5. Open the customer form. Issue: The Due smart button is not visible on the partner form even though an outstanding balance exists for the customer. Note: This issue does not reproduce when Point of Sale is installed, as the POS module overrides `_compute_has_moves` with its own implementation that checks the outstanding balance directly. Root Cause: The `_compute_has_moves` method queries only `account.move `for partner matching. When a partner is referenced only at the account.move.line level, the partner is never picked up by this query, resulting in `has_moves = False` and the Due button remaining hidden. Fix: Replaced the EXISTS-based implementation with a UNION-based approach as the EXISTS implementation evaluated the query per partner row, whereas UNION processes all partners in a single batch query. Additionally extended the UNION to also include account.move.line partner matching, ensuring partners referenced only at the line level, are correctly detected and has_moves is set to True. Result: The Due smart button is now correctly visible for all partners with an outstanding balance, regardless of whether the partner is set at the journal entry level or only at the line level. owp = 6243562
This fix corrects a bug where refunded items appeared twice in POS receipts, leading to incorrect totals. The update ensures that refunded items are treated as a single line, resolving the issue and preventing double charges. This improves the accuracy of payment processing within the Point of Sale system.
Original PR description
**Steps to reproduce:** - Make a sale in the frontend - Refund it on the order in the backend - Reload the frontend page, the order is automatically set as the current one - Try to pay for it - There…
**Steps to reproduce:** - Make a sale in the frontend - Refund it on the order in the backend - Reload the frontend page, the order is automatically set as the current one - Try to pay for it - There are 2 lines on the ticket, and the total is thus wrong **Why the fix:** A line that has been refunded through the backend will appear twice in the receipt, causing it to be wrong. When loading the order from the backend, when we refresh the page after refunding it from the backend, we load the order and it's lines. The lines are found but they don't have any uuid set, so the pos sets one. Then at paying time, we load them again to check that nothing changed, but when loading the lines, we see that it does not have a uuid, as we did not write the frontend uuid to the backend yet. https://github.com/odoo/odoo/blob/0b17840fb3cc72935e1a6302a057fb55c253c498/addons/point_of_sale/static/src/app/store/pos_store.js#L1277-L1279 As we see we don't have a uuid on the line, we set it. The line is found again in the data in the snipped above. The line is then considered missing from the missingRecursive function, and when we try merge them with the existing lines, they don't have the same uuid so they are treated as different. This means we set 2 different uuids to a line that was in fact the same. The pos then sees 2 lines with 2 differents uuids, so it treats them as 2 different lines and we have to pay for both, even though they are the same and the second one should not have been added to the order and should have been ignored. Without this fix, the pos will think we don't have the line yet, even though we do, but just with another uuid so it will add it to the order even though it should not. We will then have the same line with two different uuid, so it will be considered as 2 different lines and both will be added to the receipt and have to be paid for. With this fix, the two lines now have the same uuid, and will be treated as the same line, as it should. opw-6235870