Daily updates from Odoo
Thursday, July 23, 2026
231 changes
16 changes
Resolved issues and error corrections
This fix prevents database upgrades from failing if a predefined HR employee document folder was previously deleted or disabled. The upgrade now skips unavailable folders when adding the HR Sign action, helping customers complete upgrades smoothly without restoring removed folders.
Original PR description
Steps to reproduce: 1 Install documents_hr and hr_sign on saas-19.1. 2 Go to Settings → Documents → disable Human Resources. 3 Open the Documents app and delete the Employees - My Company folder. 4…
Steps to reproduce:
1 Install documents_hr and hr_sign on saas-19.1.
2 Go to Settings → Documents → disable Human Resources.
3 Open the Documents app and delete the Employees - My Company folder.
4 Upgrade the database to saas-19.2.
Issue:
- During the upgrade, the post-init hook attempts to embed the HR Sign action into predefined document folders. Since the Employees - My Company folder has been deleted (or is inactive), the folder lookup returns no record, leading to the following error:
```python3
Traceback (most recent call last):
File "/home/odoo/src/odoo/saas-19.2/odoo/service/server.py", line 1664, in preload_registries
registry = Registry.new(dbname, update_module=update_module, install_modules=config['init'], upgrade_modules=config['update'], reinit_modules=config['reinit'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/tools/func.py", line 65, in locked
return func(inst, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/registry.py", line 186, in new
load_modules(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 465, in load_modules
load_module_graph(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 244, in load_module_graph
getattr(py_module, post_init)(env)
File "/home/odoo/src/enterprise/saas-19.2/documents_hr_sign/__init__.py", line 12, in _embed_sign_post_init
folders.with_user(SUPERUSER_ID)._embed_action(sign_action.id)
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1643, in _embed_action
folder.action_folder_embed_action(folder.id, action_id)
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1614, in action_folder_embed_action
return self.get_documents_actions(folder_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1522, in get_documents_actions
raise UserError(_('This folder does not exist or is not accessible.'))
odoo.exceptions.UserError: Esta carpeta no existe o no es accesible.
```
Root cause:
- As part of documents_sign, the documents_hr_sign action is embedded into predefined document folders (introduced in https://github.com/odoo/enterprise/pull/101890).
- The folder lookup relies on [_search()](https://github.com/odoo/odoo/blob/85992d5f5f8caeacdcc570fb9fefb4cfcec6460c/odoo/orm/models.py#L4681-L4691), which filters out inactive records
through the active test. Consequently, [search_fetch()](https://github.com/odoo/odoo/blob/85992d5f5f8caeacdcc570fb9fefb4cfcec6460c/odoo/orm/models.py#L1441-L1451) returns no matching
folder when the predefined folder has been deleted or deactivated. It will
try to get document actions of predefined folder here, so if the folder is
https://github.com/odoo/enterprise/blob/6d334a17d10faec33d60f4a8d7d263c091bb456e/documents/models/documents_document.py#L1592
inactive it will not be able to read the folder here.
https://github.com/odoo/enterprise/blob/6d334a17d10faec33d60f4a8d7d263c091bb456e/documents/models/documents_document.py#L1494
Fix:
- Instead of attempting to embed the Sign action into all company employee folders, filter out inactive folders before calling _embed_action().
- This ensures the post-init hook only processes active employee document folders. If a predefined folder has been deleted or deactivated, it is skipped preventing the upgrade from attempting to embed an action into an inaccessible folder and avoiding the resulting UserError.
opw-6358063
upg-4449902
Forward-Port-Of: odoo/enterprise#123846The chatter panel now remains fixed and visible on the right side of large financial reports. Users can keep communicating and reviewing notes without needing to scroll horizontally across wide reports.
Original PR description
Issue: - When reports are large/wide, the chatter component is pushed beyond the visible viewport, appearing only at the absolute right edge of the overflowing report rather than the right edge of the screen. Fix: - Updated the layout container to prevent the chatter from shrinking or overflowing with the report block, ensuring the main report scrolls independently while the chatter stays pinned to the screen viewport. Impact: - Keeps the chatter panel fully visible on the right side of the screen, allowing users to communicate without scrolling horizontally on wide reports. task-[6376792](https://www.odoo.com/odoo/project/967/tasks/6376792) Forward-Port-Of: odoo/enterprise#125126 Forward-Port-Of: odoo/enterprise#123734
This fixes where the express filing mention is placed in French VAT report submissions sent to AspOne. The change helps ensure the generated filing format is accepted by putting the express indication in the proper form section instead of an unsupported identification area.
Original PR description
in this commit: https://github.com/odoo/enterprise/commit/93c1a4fe15d1f09e4c3df3a5db0e06006121c027 we added a way to have an express mention in the xml sent to aspone. But we placed it in the "T-IDENTIF" zone, but this zone doesn't accept express mention. It should be located in the form it self. task-6253745 Forward-Port-Of: odoo/enterprise#124471 Forward-Port-Of: odoo/enterprise#123235
This fix ensures the confirmation message appears only after an appointment link has actually been copied. It prevents timing-related failures in automated checks, making appointment and CRM scheduling flows more reliable.
Original PR description
Prior to this commit, the success notification for copying an appointment link to the clipboard was triggered synchronously, while the actual `navigator.clipboard.writeText` execution was deferred inside a `setTimeout`. This caused a race condition (depending on the browser's cpu load) during tours (e.g., `appointment_crm_meeting_tour`). The tour would proceed and restore the mocked clipboard object (`oldWriteText`) before the deferred `setTimeout` block had a chance to execute. This commit fixes the issue by moving the notification logic inside the `setTimeout` callback. The tour is also updated to wait explicitly for the success notification before cleaning up the clipboard mock and proceeding to discard the slots. runbot-241004 Forward-Port-Of: odoo/enterprise#124439
Belgian XBRL annual statement exports no longer translate required fixed values when generated in Dutch. This prevents affected reports from being rejected by the Belgian National Bank validator.
Original PR description
Steps to reproduce: - Set the user language to Dutch. - Go to Accounting > Reporting > Annual Statements. - Generate the XBRL export for a report other than the "company, abridged" (acon) balance…
Steps to reproduce:
- Set the user language to Dutch.
- Go to Accounting > Reporting > Annual Statements.
- Generate the XBRL export for a report other than the "company,
abridged" (acon) balance sheet/P&L combination, e.g. an association
(asso_a/asso_f) or "company, full"/"company, capital" report.
- Open the file: the `<met:bln1>` boolean facts are exported as
"onwaar" instead of "false", which is not a valid XBRL boolean
lexical value and gets rejected by the NBB validator.
Cause of the issue:
QWeb templates translate static text nodes by default. The base
module ships a generic `msgid "false" -> msgstr "onwaar"` translation,
used elsewhere in the UI, which silently hijacks the literal
"false"/"true" and unit tokens ("iso4217:EUR", "pure") in the XBRL
data templates whenever the file is generated in Dutch.
Solution:
Add `t-translation="off"` on the `<met:bln1>` boolean facts and the
`<measure>` unit tokens in the 5 remaining XBRL templates,
so these fixed-vocabulary XBRL values are never subject to translation
opw-6395785
Forward-Port-Of: odoo/enterprise#124945Envia shipping rate requests now send insurance details in the format expected by the carrier API. This helps ensure quoted delivery prices reflect selected insurance coverage instead of staying unchanged.
Original PR description
Issue ----- Insurance request is not reflected on the rating given by Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - Create a MX client - Create a product (with some weight) - Create a SO - Add the product - Add envia delivery and get a rate - Update Envia delivery method - Set insurance to 50% - Go back to the SO - Add envia delivery and get a rate > The rate is the same both times Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment Follow up of 7258e4a ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#124923 Forward-Port-Of: odoo/enterprise#124700
Resetting a submitted tax return no longer changes the company-wide tax lock date, so closed periods stay protected for all users. The update also ensures companies can set the tax lock date before submitting a return without blocking the required closing entry.
Original PR description
To reproduce the issue: 1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January 3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock…
To reproduce the issue:
1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January
3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock date exception removing the tax lock date just for you, for 5 min. 5) Reset January's return
6) Reopen the lock date wizard.
====> Your exception is still there, but the tax lock date for everyone has been reset to December 31st.
This is plain wrong. Resetting a return should not automatically reopen the period for everyone. Lock dates exceptions/modifications are anyway required to reset the return ; they should pilot the whole flow. Nothing being magically hidden from the user means there can't be someone else mistakenly encoding something into the reopened period.
Another fix was required to make this one work: setting the tax lock date before submitting the return should work. In bigger environments, users might want to do that as a first step to reduce the number of people encoding data before actually doing the submission of the return. Therefore, the case where the tax lock date is already set at the date_to of the return when submitting it was supposed to be already supported, and allow the creation of the closing entry for that return, despite it being on the tax lock date. The test ensuring this was however badly written, and the feature didn't work: the closing was created at a later date than the lock date automatically, due to the Bills' Algorithm.
Forward-Port-Of: odoo/enterprise#124872
Forward-Port-Of: odoo/enterprise#124811Certificates added through emSigner now appear correctly aligned in signed PDF documents after recent emSigner interface and API changes. This prevents visibly misplaced certificate stamps and helps keep signed documents looking accurate and professional.
Original PR description
Before: - Certificate added by emSigner was misaligned in the signed PDF after recent UI changes. After: - Updated coordinates to ensure the emSigner certificate is properly aligned and displayed correctly in Odoo. task-6105264 Forward-Port-Of: odoo/enterprise#113402
Fixed an issue where closing a POS session could leave an invoice's amount to settle incorrectly recalculated, sometimes showing a negative value. This prevents customers from being overcharged in later settlement proposals and keeps the POS settlement option visible when it should be available.
Original PR description
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on…
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on `order_id.session_id.state`, but that state is not in the compute dependencies. When closing a session holding a settle order, `_validate_session()` first reconciles the settle payment with the invoice (which lowers `amount_residual_signed` and flags the field for recomputation) and only then writes `state = 'closed'` on the session. If the pending recomputation is executed in that window (any flush of `account.move` does it: recomputing the field for any other flagged record drags the whole queue along), the settle line is deducted from the already reconciled residual, i.e. counted twice, and the field is stored as `residual - settled` instead of `residual`. Since the session state is not a dependency, writing `state = 'closed'` does not flag the field again and the wrong value is never corrected. The partner's `invoices_amount_due` then goes negative, which hides the "Settle invoices" option in the POS partner list and inflates the "Settle due amount" proposal (`remainingDue = total_due - pos_orders_amount_due - invoices_amount_due`): a customer owing e.g. 500 is proposed, and charged, 700. Steps to reproduce: 1. Post a customer invoice of 1000. 2. In the POS, select the customer > Settle invoices, pick the invoice, set the amount to 700 and pay in cash. 3. Close the session. The issue only occurs when the pending recomputation runs during the closing, which depends on the other operations performed by it (not deterministic in real usage; the regression test forces it with a flush after the reconciliation). 4. The invoice's "Amount To Pay In POS" shows -400 instead of 300 and the POS proposes to settle 700 instead of 300. Add the session state to the compute dependencies so that the field is recomputed once the session is closed, yielding the correct amount regardless of any intermediate recomputation. opw-6375095 Forward-Port-Of: odoo/enterprise#123783
The point of sale barcode lookup flow now checks product creation permissions in a more direct and consistent way. This helps ensure users only see or use product creation options when their access rights allow it, reducing confusing behavior at checkout.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420 Forward-Port-Of: odoo/enterprise#125147 Forward-Port-Of: odoo/enterprise#123073
Signed employee contracts now appear correctly from the employee Documents button. This helps HR teams find completed contract documents without manually searching in the Documents app.
Original PR description
[FIX] documents_{hr|sign}: employee docs button for signed contracts Bug reproduction: 1 - In saas-19.4, install documents_hr and hr_contract_salary with demo data 2 - As Mitchell Admin, go to…
[FIX] documents_{hr|sign}: employee docs button for signed contracts
Bug reproduction:
1 - In saas-19.4, install documents_hr and hr_contract_salary with demo data
2 - As Mitchell Admin, go to Employees, open one, click on "Offers - New"
3 - Select employee_contract.pdf as PDF Template
4 - Use the button "Salary configurator" to fill in the configurator, review it and sign it.
5 - Go back to the backend, find the contract in Sign and sign it.
6 - Go back to the Employee form view, the Documents stat button shows 0 document when it should be 1.
7 - Click the stat button and you see 0 documents in Documents when there should be one.
Bug cause:
1 - The document is created for the employee in documents app
but smart button cannot open those
2 - The res_model of the documents.document is hr.version for signed doc
-> it is not hr.employee
3 - In current implementation:
3.1 -> only hr.employee's documents appear after that smart button
Bug solution:
1 - _compute_document_count is reimplemented:
-> to count also documents with res_model as hr.version
2 - override _get_documents_domain:
-> to add version domain as an alternative with OR
-> to get documents with res_model='hr.version'
Test:
1 - Unit test is added
2 - Create documents with the archived versions of the employee
-> and observe the document count of the employee
Note:
-> Also, we changed the final document name in documents of the employee
task-6373620Barcode delivery operations now correctly block a package from being scanned twice, even when multiple packages are part of the same transfer. This prevents duplicate stock movements and avoids incorrect negative inventory quantities after validation.
Original PR description
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in…
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in PACK001, 1 in PACK002 3. In the Barcode app > Operations > Delivery > New 4. Scan a first package PACK001, then a second different package PACK002 5. Scan the first package PACK001 again. Issue --- Re-scanning an already scanned package is meant to be rejected with a "This package is already scanned." warning, but the rejection stops working as soon as a second package is present in the transfer, so the package content gets added a second time and, once validated, the source quant goes negative (the package ends up holding a negative and a positive quant of the same product). Commit 23613c63947 added a canPackSomeLines flag that is set to true for every package line that is not the scanned one, so any other package in the transfer makes the alreadyDonePackId && !canPackSomeLines guard false and silently skips the warning. The scanned package already exposes whether it had something left to pack through scannedPackages, so gating the warning on that flag instead keeps the check working regardless of how many other packages are in the transfer. https://github.com/odoo/enterprise/blob/3cc1a162e61662814b0e52c0c720831952d208a8/stock_barcode/static/src/models/barcode_picking_model.js#L1976-L2006 opw-6279105 Forward-Port-Of: odoo/enterprise#125229 Forward-Port-Of: odoo/enterprise#121755
This fix prevents an error when users or integrations move Uruguayan electronic invoices back to draft status. It ensures the action completes cleanly, improving reliability for accounting workflows that use this localization.
Original PR description
Calling the method in RPC causes an error: ``` TypeError: cannot marshal None unless allow_none is enabled ``` Forward-Port-Of: odoo/enterprise#124740 Forward-Port-Of: odoo/enterprise#124653
Belgian VAT return submissions can include comments in the generated XML again. This restores a previously available capability that was removed by mistake, helping businesses submit the extra context required for their tax filings.
Original PR description
This feature had been mistakenly removed. Forward-Port-Of: odoo/enterprise#124865
Embedded views in Knowledge now keep the intended top alignment when they appear as the first editable item in an article. This prevents a small layout glitch caused by editor selection placeholders, making Knowledge pages look consistent while editing.
Original PR description
This commit updates the embedded view top-alignment selector to account for selection placeholders introduced by https://github.com/odoo/odoo/commit/edf7f7bb0c62978640c181eccb4934855d5d872d. This preserves the intended top-alignment behavior when an embedded view is the first editable element in the knowledge editor. Task-5951196 Forward-Port-Of: odoo/enterprise#125080
This update fixes an inconsistent automated test in Odoo Studio that could fail unpredictably. It helps keep quality checks stable, reducing false alarms during development without changing user-facing behavior.
Original PR description
runbot-error-940371
18 changes
Resolved issues and error corrections
The French VAT report export now places the express filing note in the correct part of the file sent to AspOne. This helps prevent filing rejections or processing issues caused by the note being included in an unsupported section.
Original PR description
in this commit: https://github.com/odoo/enterprise/commit/93c1a4fe15d1f09e4c3df3a5db0e06006121c027 we added a way to have an express mention in the xml sent to aspone. But we placed it in the "T-IDENTIF" zone, but this zone doesn't accept express mention. It should be located in the form it self. task-6253745 Forward-Port-Of: odoo/enterprise#124471 Forward-Port-Of: odoo/enterprise#123235
Some accounting report tests were failing because tax amounts were included when they should have been ignored. The tests now match the intended tax handling, helping keep automated checks reliable without changing customer-facing behavior.
Original PR description
Problem: Tests fail because taxes are taken into account when they should not be. Solution: Configure the affected tests to ignore taxes, matching the expected behavior. runbot-243183
Belgian XBRL annual statement exports now keep required true/false and unit values in the official format instead of translating them into Dutch. This prevents affected reports from being rejected by the National Bank of Belgium validator when generated by Dutch-speaking users.
Original PR description
Steps to reproduce: - Set the user language to Dutch. - Go to Accounting > Reporting > Annual Statements. - Generate the XBRL export for a report other than the "company, abridged" (acon) balance…
Steps to reproduce:
- Set the user language to Dutch.
- Go to Accounting > Reporting > Annual Statements.
- Generate the XBRL export for a report other than the "company,
abridged" (acon) balance sheet/P&L combination, e.g. an association
(asso_a/asso_f) or "company, full"/"company, capital" report.
- Open the file: the `<met:bln1>` boolean facts are exported as
"onwaar" instead of "false", which is not a valid XBRL boolean
lexical value and gets rejected by the NBB validator.
Cause of the issue:
QWeb templates translate static text nodes by default. The base
module ships a generic `msgid "false" -> msgstr "onwaar"` translation,
used elsewhere in the UI, which silently hijacks the literal
"false"/"true" and unit tokens ("iso4217:EUR", "pure") in the XBRL
data templates whenever the file is generated in Dutch.
Solution:
Add `t-translation="off"` on the `<met:bln1>` boolean facts and the
`<measure>` unit tokens in the 5 remaining XBRL templates,
so these fixed-vocabulary XBRL values are never subject to translation
opw-6395785
Forward-Port-Of: odoo/enterprise#124945Copying appointment links now confirms success only after the clipboard action has actually run. This prevents timing-related failures in automated checks and makes the appointment and CRM scheduling flow more reliable.
Original PR description
Prior to this commit, the success notification for copying an appointment link to the clipboard was triggered synchronously, while the actual `navigator.clipboard.writeText` execution was deferred inside a `setTimeout`. This caused a race condition (depending on the browser's cpu load) during tours (e.g., `appointment_crm_meeting_tour`). The tour would proceed and restore the mocked clipboard object (`oldWriteText`) before the deferred `setTimeout` block had a chance to execute. This commit fixes the issue by moving the notification logic inside the `setTimeout` callback. The tour is also updated to wait explicitly for the success notification before cleaning up the clipboard mock and proceeding to discard the slots. runbot-241004 Forward-Port-Of: odoo/enterprise#124439
Resetting a submitted tax return no longer changes the company-wide tax lock date, so closed periods stay protected for other users. The change also supports submitting a return when the tax lock date was already set for that return period, helping larger teams control data entry before final submission.
Original PR description
To reproduce the issue: 1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January 3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock…
To reproduce the issue:
1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January
3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock date exception removing the tax lock date just for you, for 5 min. 5) Reset January's return
6) Reopen the lock date wizard.
====> Your exception is still there, but the tax lock date for everyone has been reset to December 31st.
This is plain wrong. Resetting a return should not automatically reopen the period for everyone. Lock dates exceptions/modifications are anyway required to reset the return ; they should pilot the whole flow. Nothing being magically hidden from the user means there can't be someone else mistakenly encoding something into the reopened period.
Another fix was required to make this one work: setting the tax lock date before submitting the return should work. In bigger environments, users might want to do that as a first step to reduce the number of people encoding data before actually doing the submission of the return. Therefore, the case where the tax lock date is already set at the date_to of the return when submitting it was supposed to be already supported, and allow the creation of the closing entry for that return, despite it being on the tax lock date. The test ensuring this was however badly written, and the feature didn't work: the closing was created at a later date than the lock date automatically, due to the Bills' Algorithm.
Forward-Port-Of: odoo/enterprise#124872
Forward-Port-Of: odoo/enterprise#124811Shipping quotes from Envia now correctly include the requested insurance coverage. This ensures customers and sales teams see accurate delivery prices when insurance is enabled on Mexican Envia delivery methods.
Original PR description
Issue ----- Insurance request is not reflected on the rating given by Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - Create a MX client - Create a product (with some weight) - Create a SO - Add the product - Add envia delivery and get a rate - Update Envia delivery method - Set insurance to 50% - Go back to the SO - Add envia delivery and get a rate > The rate is the same both times Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment Follow up of 7258e4a ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#124923 Forward-Port-Of: odoo/enterprise#124700
Odoo Studio now handles field labels written with non-Latin characters, such as Arabic, without triggering an invalid custom field name error. This lets users rename fields in their own language more reliably and avoids interruptions when customizing views.
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#122094 Forward-Port-Of: odoo/enterprise#121343
The emSigner certificate now appears in the correct position on signed PDFs after recent changes in the emSigner interface and API. This helps ensure signed documents look professional and remain easy to read for users relying on Odoo Sign with emSigner.
Original PR description
Before: - Certificate added by emSigner was misaligned in the signed PDF after recent UI changes. After: - Updated coordinates to ensure the emSigner certificate is properly aligned and displayed correctly in Odoo. task-6105264 Forward-Port-Of: odoo/enterprise#113402
The barcode delivery flow now correctly rejects a package that has already been scanned, even when multiple packages are included in the same transfer. This prevents duplicate stock movements and avoids incorrect negative inventory quantities after validation.
Original PR description
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in…
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in PACK001, 1 in PACK002 3. In the Barcode app > Operations > Delivery > New 4. Scan a first package PACK001, then a second different package PACK002 5. Scan the first package PACK001 again. Issue --- Re-scanning an already scanned package is meant to be rejected with a "This package is already scanned." warning, but the rejection stops working as soon as a second package is present in the transfer, so the package content gets added a second time and, once validated, the source quant goes negative (the package ends up holding a negative and a positive quant of the same product). Commit 23613c63947 added a canPackSomeLines flag that is set to true for every package line that is not the scanned one, so any other package in the transfer makes the alreadyDonePackId && !canPackSomeLines guard false and silently skips the warning. The scanned package already exposes whether it had something left to pack through scannedPackages, so gating the warning on that flag instead keeps the check working regardless of how many other packages are in the transfer. https://github.com/odoo/enterprise/blob/3cc1a162e61662814b0e52c0c720831952d208a8/stock_barcode/static/src/models/barcode_picking_model.js#L1976-L2006 opw-6279105 Forward-Port-Of: odoo/enterprise#121755
This fixes a POS settlement issue where invoice amounts could be recalculated at the wrong moment during session closing. Customers will now see the correct remaining amount due, preventing overstated settlement proposals or accidental overcharging.
Original PR description
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on…
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on `order_id.session_id.state`, but that state is not in the compute dependencies. When closing a session holding a settle order, `_validate_session()` first reconciles the settle payment with the invoice (which lowers `amount_residual_signed` and flags the field for recomputation) and only then writes `state = 'closed'` on the session. If the pending recomputation is executed in that window (any flush of `account.move` does it: recomputing the field for any other flagged record drags the whole queue along), the settle line is deducted from the already reconciled residual, i.e. counted twice, and the field is stored as `residual - settled` instead of `residual`. Since the session state is not a dependency, writing `state = 'closed'` does not flag the field again and the wrong value is never corrected. The partner's `invoices_amount_due` then goes negative, which hides the "Settle invoices" option in the POS partner list and inflates the "Settle due amount" proposal (`remainingDue = total_due - pos_orders_amount_due - invoices_amount_due`): a customer owing e.g. 500 is proposed, and charged, 700. Steps to reproduce: 1. Post a customer invoice of 1000. 2. In the POS, select the customer > Settle invoices, pick the invoice, set the amount to 700 and pay in cash. 3. Close the session. The issue only occurs when the pending recomputation runs during the closing, which depends on the other operations performed by it (not deterministic in real usage; the regression test forces it with a flush after the reconciliation). 4. The invoice's "Amount To Pay In POS" shows -400 instead of 300 and the POS proposes to settle 700 instead of 300. Add the session state to the compute dependencies so that the field is recomputed once the session is closed, yielding the correct amount regardless of any intermediate recomputation. opw-6375095 Forward-Port-Of: odoo/enterprise#123783
The reset-to-draft action for Uruguayan electronic invoices now returns a proper response when called remotely. This prevents a technical error that could interrupt users or integrations when moving invoices back to draft.
Original PR description
Calling the method in RPC causes an error: ``` TypeError: cannot marshal None unless allow_none is enabled ``` Forward-Port-Of: odoo/enterprise#124740 Forward-Port-Of: odoo/enterprise#124653
This fix ensures Saudi GOSI contributions are calculated on the full eligible salary instead of being reduced through proration. It helps payroll teams produce more accurate payslips and accounting results for Saudi employees.
Original PR description
task-id: 6380239 Forward-Port-Of: odoo/enterprise#124529 Forward-Port-Of: odoo/enterprise#124122
The Peppol settings now apply the right requirement for the purchase journal when Documents-based import is configured. This prevents non-French companies from being incorrectly forced to select an invoicing journal when their Peppol documents folder is already set up.
Original PR description
Fixes the settings view for the account_peppol_purchase_journal_id. account_peppol, documents_account_peppol and l10n_fr_pdp all wants to use a specific condition for the required attribute of the view. With PDP especially, once l10n_fr_pdp is installed, the view forces the base condition, even if documents_account_peppol is installed, and even if the company is not even French. On a non-French company registered/registering on Peppol, the journal shouldn't be mandatory if documents_account_peppol_folder_id is set up. To ease things up, it is now using a computed field. task-6304479 Forward-Port-Of: odoo/enterprise#120723
This fix keeps existing tax returns aligned when their allowed workflow stages change, such as during upgrades. It prevents crashes when old returns still have a status that is no longer valid, helping users continue reviewing return lists reliably.
Original PR description
To reproduce the issue: 1) Create a company in Belgium 2) Instantiate its returns and review, submit and pay one of the VAT returns 3) Change the states_worklfow of the VAT return so that it only…
To reproduce the issue: 1) Create a company in Belgium 2) Instantiate its returns and review, submit and pay one of the VAT returns 3) Change the states_worklfow of the VAT return so that it only accepts "review" and "submit" stages, not "paid" anymore 4) Go to the list of returns, remove the TODO filter => traceback The problem is here that the existing returns don't recompute their state when the workflow of the type is modified. In some cases, this is fine, but it others, it's annoying. In our example, the terminal state changed, so all the returns in that terminal stage should change their state to the new terminal one. "paid" is not an accepted value anymore, it should become "submitted". Moreover, when the workflow is changed, the selection field actually containing the state must also change. As it is, it seems to work because "state" of account.return is stored, but the value it's based on (the workflow field) won't be consistent with it. It's not annoying now, but those inconsistencies could become a big source of trouble in the future (we know that from experience ... I'm looking at you, version 8 ! è-é). This issue typically happens at upgrade. We had cases in FR and AE already. We solve that by a generic override of the write to sort things out when such change needs to happen. An upgrade PR will also be done to adapt the script so that we eventually solve the inconsistencies on dbs that have already migrated to 19.0. Forward-Port-Of: odoo/enterprise#124144
This fixes an issue that prevented balance receipts from loading correctly for SIX payment terminals. Businesses using these terminals can restore expected receipt printing after upgrading the module so the new receipt template is available.
Original PR description
odoo/enterprise#104683 broke the balance receipt for six terminals trying to load an html template in a template name param. We fix this by extracting the template in its own file. Note: clients will have to upgrade the module in order to make the template available. task-6391500 Forward-Port-Of: odoo/enterprise#124521
This fix keeps embedded views properly aligned when they appear at the top of a Knowledge editor page. It prevents a visual layout issue caused by editor placeholders, preserving the expected appearance for users editing Knowledge content.
Original PR description
This commit updates the embedded view top-alignment selector to account for selection placeholders introduced by https://github.com/odoo/odoo/commit/edf7f7bb0c62978640c181eccb4934855d5d872d. This preserves the intended top-alignment behavior when an embedded view is the first editable element in the knowledge editor. Task-5951196 Forward-Port-Of: odoo/enterprise#125080
Restaurant scheduling now handles tables that are not linked to a bookable resource. This prevents the schedule view from crashing, helping staff keep reservations and table planning accessible.
Original PR description
When a table doesn't have a resource, the appointment_resource_id is undefined and the gantt renderer was crashing when trying to access its id. This commit adds a check to ensure that the appointment_resource_id exists before trying to access its id.
Belgian VAT return users can once again add comments to the XML file generated for submission. This restores a previously available capability that was accidentally removed, helping businesses include needed context in their VAT filings.
Original PR description
This feature had been mistakenly removed. Forward-Port-Of: odoo/enterprise#124865
20 changes
Resolved issues and error corrections
The asset screen now labels the related accounting lines more clearly as Related Items. Opening that list keeps users in the useful list view instead of sending them to an unhelpful journal item form, reducing confusion when reviewing asset entries.
Original PR description
If you create an asset and confirm it, you can see the Related Entries using the smart button Related Entries. The list view that opens is clickable, but it opens a quite useless form view of the Journal Items. - Rename breadcrumb button to Related Items - Make it behave like action_account_moves_all, to not open form view Ticket: [6385260](https://www.odoo.com/odoo/project/967/tasks/6385260)
This fix makes automated barcode scrap testing more reliable by ensuring entered scrap quantities are properly retained before saving. It helps prevent false test failures that could slow down validation and release workflows.
Original PR description
These barcode scrap tours randomly trigger "You can only enter positive quantities." on runbot: the quantity set with a raw input.value is dropped when the field re-renders before the scrap is saved, so it scraps 0. Dispatching an input event keeps the typed value. error-238911
This fix removes an outdated internal call that could cause an error when the timer feature was opened or used. It helps keep timer-related workflows stable without changing how users interact with the feature.
Original PR description
`getServerOffset` was removed from the timer service, so calling it in the `useTimer` hook causes a traceback once the hook is actually used. This PR removes the leftover call.
The French VAT report XML now places the express mention in the correct form section instead of the identification area. This helps ensure submissions to Aspone meet the expected format and reduces the risk of rejected filings.
Original PR description
in this commit: https://github.com/odoo/enterprise/commit/93c1a4fe15d1f09e4c3df3a5db0e06006121c027 we added a way to have an express mention in the xml sent to aspone. But we placed it in the "T-IDENTIF" zone, but this zone doesn't accept express mention. It should be located in the form it self. task-6253745 Forward-Port-Of: odoo/enterprise#124471 Forward-Port-Of: odoo/enterprise#123235
Opening transfers in the Barcode app now uses a default limit when loading reusable packages. This prevents very large package lists from causing long wait times, helping warehouses with high package volumes access transfers more quickly.
Original PR description
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local…
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local testing. The client of the tickets experiences loadings up to 120 seconds with 50k packages # Cause When opening a transfer, we load barcode data by doing an API call to `_get_stock_barcode_data` : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L85 During this we preload a lot of records, notably packages : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L128 The issue is that in the fields we read for the packages, two of them (`location_dest_id` & `contained_quant_ids`) have a `_read_group` in their compute (or in the compute of one of the fields they depend on) : https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L65 https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L146 Fortunately, this does not mean that we make a query for every records. Instead, in Odoo, we fetch records in batch of 1000. So, for the case of the client, every time he loads the database, the backend does 50 000 / 1000 x 2 = 100 queries, which hinders performance a lot A [PERF] commit was done to limit the number of packages that are fetched base on a config parameter. The problem is that this parameter does not have a default value, so clients still end up with the problem. [PERF]: https://github.com/odoo/enterprise/commit/efe18bc1ea479270e42846986d7ed449b0865617 # Proposed Solution Add a default value for that config parameter. The exact value is up to discussion opw-6200730 Forward-Port-Of: odoo/enterprise#124538 Forward-Port-Of: odoo/enterprise#123696
Fixed Belgian annual statement XBRL exports so required values like true/false and currency units are no longer translated when generated in Dutch. This prevents affected filings from being rejected by the National Bank of Belgium validator.
Original PR description
Steps to reproduce: - Set the user language to Dutch. - Go to Accounting > Reporting > Annual Statements. - Generate the XBRL export for a report other than the "company, abridged" (acon) balance…
Steps to reproduce:
- Set the user language to Dutch.
- Go to Accounting > Reporting > Annual Statements.
- Generate the XBRL export for a report other than the "company,
abridged" (acon) balance sheet/P&L combination, e.g. an association
(asso_a/asso_f) or "company, full"/"company, capital" report.
- Open the file: the `<met:bln1>` boolean facts are exported as
"onwaar" instead of "false", which is not a valid XBRL boolean
lexical value and gets rejected by the NBB validator.
Cause of the issue:
QWeb templates translate static text nodes by default. The base
module ships a generic `msgid "false" -> msgstr "onwaar"` translation,
used elsewhere in the UI, which silently hijacks the literal
"false"/"true" and unit tokens ("iso4217:EUR", "pure") in the XBRL
data templates whenever the file is generated in Dutch.
Solution:
Add `t-translation="off"` on the `<met:bln1>` boolean facts and the
`<measure>` unit tokens in the 5 remaining XBRL templates,
so these fixed-vocabulary XBRL values are never subject to translation
opw-6395785
Forward-Port-Of: odoo/enterprise#124945A test setup for AI embeddings was corrected so it no longer mixes demo data using a different provider format. This helps keep automated quality checks reliable and prevents false failures when validating Gemini-related AI behavior.
Original PR description
_cron_generate_embedding retrieves all the sources that don't have an embedding and generate embeddings for those using the model from the provider of the agent configured on the source. The agent configured on the demo sources has OpenAI as the provider and these sources don't have embeddings. When _cron_generate_embedding runs in the test case, it retrieves these demo sources + the source defined in the test case (Which relies on embeddings from Google) and generates the embeddings but then fails. This happens because the _request method is mocked to return the response in Google's format as the test case is specific to Gemini models. runbot.build.error-944173 Forward-Port-Of: odoo/enterprise#124977
Odoo updated its e-signature integration to match recent emSigner interface and API changes. Certificates added through emSigner should now appear in the correct position on signed PDFs, avoiding confusing or unprofessional document output.
Original PR description
Before: - Certificate added by emSigner was misaligned in the signed PDF after recent UI changes. After: - Updated coordinates to ensure the emSigner certificate is properly aligned and displayed correctly in Odoo. task-6105264 Forward-Port-Of: odoo/enterprise#113402
Delivery guides for Chilean electronic stock documents no longer fail when a kit includes components measured in a different unit type than the kit itself. The system now prices those component lines using the component product pricing instead of attempting an invalid unit conversion, allowing users to print delivery guides successfully.
Original PR description
When a kit is delivered, each component move is linked to the kit's sale order line. Pricing the delivery guide in "sale order" mode converted the component quantity into the kit's sale UoM. For a component sold in a different UoM category than the kit, this cross-category conversion raises a UserError. Steps to reproduce: - Create a BoM for a kit product with a component in a different UoM category - Create a customer with Delivery Guide Price = "From Sale Order" - Sold the kit in a sale order and deliver it - On the delivery, print the delivery guide -> error This fix makes the guide price for a component move to be "product" if the component's product is different from the related sale line product, avoiding the cross-category UoM conversion. opw-6327895 Forward-Port-Of: odoo/enterprise#125114 Forward-Port-Of: odoo/enterprise#122776
The timesheet progress percentage now updates immediately when timesheets are added, changed, or deleted. This keeps project and sales tracking information accurate on screen without requiring users to refresh the page.
Original PR description
Issue: The percentage is only updated after reloading the page. Cause: The percentage computation is performed inside `loadTimesheets`, which is only called when the timesheets are loaded. Fix: Move the percentage computation into a helper function and invoke it whenever a timesheet is added, updated, or removed. task-6401186 Forward-Port-Of: odoo/enterprise#125074
The Barcode app now correctly blocks a package from being scanned twice during deliveries, even when multiple packages are part of the same transfer. This prevents duplicated stock movements and avoids creating incorrect negative inventory quantities after validation.
Original PR description
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in…
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in PACK001, 1 in PACK002 3. In the Barcode app > Operations > Delivery > New 4. Scan a first package PACK001, then a second different package PACK002 5. Scan the first package PACK001 again. Issue --- Re-scanning an already scanned package is meant to be rejected with a "This package is already scanned." warning, but the rejection stops working as soon as a second package is present in the transfer, so the package content gets added a second time and, once validated, the source quant goes negative (the package ends up holding a negative and a positive quant of the same product). Commit 23613c63947 added a canPackSomeLines flag that is set to true for every package line that is not the scanned one, so any other package in the transfer makes the alreadyDonePackId && !canPackSomeLines guard false and silently skips the warning. The scanned package already exposes whether it had something left to pack through scannedPackages, so gating the warning on that flag instead keeps the check working regardless of how many other packages are in the transfer. https://github.com/odoo/enterprise/blob/3cc1a162e61662814b0e52c0c720831952d208a8/stock_barcode/static/src/models/barcode_picking_model.js#L1976-L2006 opw-6279105 Forward-Port-Of: odoo/enterprise#121755
Resetting a submitted tax return no longer removes the company-wide tax lock date, preventing closed accounting periods from being unintentionally reopened for all users. The change also ensures companies can set the tax lock date before submitting a return while still allowing the required closing entry to be created correctly.
Original PR description
To reproduce the issue: 1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January 3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock…
To reproduce the issue:
1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January
3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock date exception removing the tax lock date just for you, for 5 min. 5) Reset January's return
6) Reopen the lock date wizard.
====> Your exception is still there, but the tax lock date for everyone has been reset to December 31st.
This is plain wrong. Resetting a return should not automatically reopen the period for everyone. Lock dates exceptions/modifications are anyway required to reset the return ; they should pilot the whole flow. Nothing being magically hidden from the user means there can't be someone else mistakenly encoding something into the reopened period.
Another fix was required to make this one work: setting the tax lock date before submitting the return should work. In bigger environments, users might want to do that as a first step to reduce the number of people encoding data before actually doing the submission of the return. Therefore, the case where the tax lock date is already set at the date_to of the return when submitting it was supposed to be already supported, and allow the creation of the closing entry for that return, despite it being on the tax lock date. The test ensuring this was however badly written, and the feature didn't work: the closing was created at a later date than the lock date automatically, due to the Bills' Algorithm.
Forward-Port-Of: odoo/enterprise#124872
Forward-Port-Of: odoo/enterprise#124811This fixes an issue where setting certain Uruguay electronic invoicing records back to draft could fail when triggered remotely. The change ensures the action returns a valid response, preventing an error that could interrupt accounting workflows.
Original PR description
Calling the method in RPC causes an error: ``` TypeError: cannot marshal None unless allow_none is enabled ``` Forward-Port-Of: odoo/enterprise#124740 Forward-Port-Of: odoo/enterprise#124653
Point of sale IoT setup now works better with newer IoT Boxes that no longer report certain device details. The system avoids relying on missing subtype or manufacturer information, helping printers and payment terminals be found more reliably.
Original PR description
Newer IoT Boxes don't share device subtype or manufacturer. We then adapt the domains to avoid searching on fields that aren't filled. task-6388669 task-6388733 Forward-Port-Of: odoo/enterprise#124937 Forward-Port-Of: odoo/enterprise#124306
This fix ensures POS invoice settlement amounts are recalculated correctly when a POS session is closed. It prevents customers from being shown or charged an inflated settlement amount after a partial invoice payment.
Original PR description
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on…
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on `order_id.session_id.state`, but that state is not in the compute dependencies. When closing a session holding a settle order, `_validate_session()` first reconciles the settle payment with the invoice (which lowers `amount_residual_signed` and flags the field for recomputation) and only then writes `state = 'closed'` on the session. If the pending recomputation is executed in that window (any flush of `account.move` does it: recomputing the field for any other flagged record drags the whole queue along), the settle line is deducted from the already reconciled residual, i.e. counted twice, and the field is stored as `residual - settled` instead of `residual`. Since the session state is not a dependency, writing `state = 'closed'` does not flag the field again and the wrong value is never corrected. The partner's `invoices_amount_due` then goes negative, which hides the "Settle invoices" option in the POS partner list and inflates the "Settle due amount" proposal (`remainingDue = total_due - pos_orders_amount_due - invoices_amount_due`): a customer owing e.g. 500 is proposed, and charged, 700. Steps to reproduce: 1. Post a customer invoice of 1000. 2. In the POS, select the customer > Settle invoices, pick the invoice, set the amount to 700 and pay in cash. 3. Close the session. The issue only occurs when the pending recomputation runs during the closing, which depends on the other operations performed by it (not deterministic in real usage; the regression test forces it with a flush after the reconciliation). 4. The invoice's "Amount To Pay In POS" shows -400 instead of 300 and the POS proposes to settle 700 instead of 300. Add the session state to the compute dependencies so that the field is recomputed once the session is closed, yielding the correct amount regardless of any intermediate recomputation. opw-6375095 Forward-Port-Of: odoo/enterprise#123783
This fixes a layout issue in Knowledge where embedded views could lose their intended top alignment when placed as the first editable item. Users get a more consistent editing experience with embedded content appearing where expected.
Original PR description
This commit updates the embedded view top-alignment selector to account for selection placeholders introduced by https://github.com/odoo/odoo/commit/edf7f7bb0c62978640c181eccb4934855d5d872d. This preserves the intended top-alignment behavior when an embedded view is the first editable element in the knowledge editor. Task-5951196 Forward-Port-Of: odoo/enterprise#125080
This update fixes an unstable automated test in Web Studio that could fail unpredictably. It helps keep quality checks reliable so valid changes are less likely to be blocked by false test failures.
Belgian VAT returns can once again include comments in the generated XML file. This restores a previously removed capability, helping businesses add required context or explanations when submitting VAT returns.
Original PR description
This feature had been mistakenly removed. Forward-Port-Of: odoo/enterprise#124865
Account reports opened from a VAT return check now continue to work when the page is refreshed. This prevents users from hitting an error and losing access to the report in that workflow, while reports opened from menus are unchanged.
Original PR description
Opening an account report through the VAT return button on an account.return.check record returns an inline client action whose report_id only exists in context. On refresh, Odoo will throw an error because it will try to rebuild the action context based off of the URL which is deficient. This will not effect reports opened via the menu since those follow a different pathway. This fix anchors the inline action to the "path" property stored on the client action. A helper method was added for deriving the action_id from a given report. opw-6366964 Forward-Port-Of: odoo/enterprise#124560
The trial balance report now handles load-more rows that contain no column data, avoiding a crash in the Colombian partner-grouped view. This keeps users working smoothly when expanding large account sections with limited row loading enabled.
Original PR description
…umn dict Steps to reproduce: - Install l10n_co_reports and select CO company - Open the trial balance grouped by partner variant - Set the load more limit to 2 - Go back to report, unfold an account, and press load-more line -> Traceback because it's expected the column dict to contain a column group. The report engine, however, accepts lines with empty dicts. Therefore, the trial balance should handle this case. task-6384451 Forward-Port-Of: odoo/enterprise#124102
7 changes
Resolved issues and error corrections
The Vietnam Sales Tax Report now displays VAT base amounts as positive values at the detailed invoice level, matching the totals shown in higher-level report lines. This prevents confusion when reviewing VAT on sales and supports more consistent tax reporting for Vietnamese companies.
Original PR description
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should…
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should be consistent with the upper layers and kept positive ## Steps to reproduce: - Install l10n_vn (l10n_vn_reports will install as well) - Switch to VN Company - With demo data, go to Invoicing / Reporting / Tax Report - Change Tax Report (VN) to Sales/Purchase Tax Report (VN) - Unfold the lines all the way to the minimum layer: VAT on sales of goods and services 10% -> INV/2026/00003 - Observe that the VAT 10% line is at negative, which is inconsistent with the Total line below ## Cause of the issue: - In Odoo, tax journal items store tax_base_amount with the accounting sign (negative for sales). This is expected behavior - However, Vietnamese VAT listing expects commercial amounts, which means sales bases need to be displayed as positive numbers ## Fix: Normalized tax_base_amount sign in _query_tax_lines function before building the SQL query opw-6344577 Forward-Port-Of: odoo/enterprise#122785
Fixes an issue where Chilean delivery guides could fail when delivering kits that include components measured differently from the kit product. Businesses can now print delivery guides for these kit deliveries without encountering pricing-related errors.
Original PR description
When a kit is delivered, each component move is linked to the kit's sale order line. Pricing the delivery guide in "sale order" mode converted the component quantity into the kit's sale UoM. For a component sold in a different UoM category than the kit, this cross-category conversion raises a UserError. Steps to reproduce: - Create a BoM for a kit product with a component in a different UoM category - Create a customer with Delivery Guide Price = "From Sale Order" - Sold the kit in a sale order and deliver it - On the delivery, print the delivery guide -> error This fix makes the guide price for a component move to be "product" if the component's product is different from the related sale line product, avoiding the cross-category UoM conversion. opw-6327895 Forward-Port-Of: odoo/enterprise#125114 Forward-Port-Of: odoo/enterprise#122776
This fixes Belgian annual statement XBRL exports generated in Dutch so required true/false and unit values are no longer translated. The change prevents invalid files from being rejected by the Belgian National Bank validator for affected report types.
Original PR description
Steps to reproduce: - Set the user language to Dutch. - Go to Accounting > Reporting > Annual Statements. - Generate the XBRL export for a report other than the "company, abridged" (acon) balance…
Steps to reproduce:
- Set the user language to Dutch.
- Go to Accounting > Reporting > Annual Statements.
- Generate the XBRL export for a report other than the "company,
abridged" (acon) balance sheet/P&L combination, e.g. an association
(asso_a/asso_f) or "company, full"/"company, capital" report.
- Open the file: the `<met:bln1>` boolean facts are exported as
"onwaar" instead of "false", which is not a valid XBRL boolean
lexical value and gets rejected by the NBB validator.
Cause of the issue:
QWeb templates translate static text nodes by default. The base
module ships a generic `msgid "false" -> msgstr "onwaar"` translation,
used elsewhere in the UI, which silently hijacks the literal
"false"/"true" and unit tokens ("iso4217:EUR", "pure") in the XBRL
data templates whenever the file is generated in Dutch.
Solution:
Add `t-translation="off"` on the `<met:bln1>` boolean facts and the
`<measure>` unit tokens in the 5 remaining XBRL templates,
so these fixed-vocabulary XBRL values are never subject to translation
opw-6395785
Forward-Port-Of: odoo/enterprise#124945The Barcode app now correctly blocks a package from being scanned twice during deliveries, even when several packages are part of the same transfer. This prevents duplicate stock movements that could create incorrect negative inventory records after validation.
Original PR description
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in…
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in PACK001, 1 in PACK002 3. In the Barcode app > Operations > Delivery > New 4. Scan a first package PACK001, then a second different package PACK002 5. Scan the first package PACK001 again. Issue --- Re-scanning an already scanned package is meant to be rejected with a "This package is already scanned." warning, but the rejection stops working as soon as a second package is present in the transfer, so the package content gets added a second time and, once validated, the source quant goes negative (the package ends up holding a negative and a positive quant of the same product). Commit 23613c63947 added a canPackSomeLines flag that is set to true for every package line that is not the scanned one, so any other package in the transfer makes the alreadyDonePackId && !canPackSomeLines guard false and silently skips the warning. The scanned package already exposes whether it had something left to pack through scannedPackages, so gating the warning on that flag instead keeps the check working regardless of how many other packages are in the transfer. https://github.com/odoo/enterprise/blob/3cc1a162e61662814b0e52c0c720831952d208a8/stock_barcode/static/src/models/barcode_picking_model.js#L1976-L2006 opw-6279105 Forward-Port-Of: odoo/enterprise#121755
The Knowledge card on the customer portal now uses the same layout as the other portal cards. This fixes a visual inconsistency where the card appeared slightly wider, improving the page’s overall polish and consistency.
Original PR description
The knowledge portal card was injected directly into "o_portal_docs", causing it to render wider than other cards. This happened because other cards sit inside "o_portal_category" (row g-2 mt-3) divs, while, knowledge was a direct child of o_portal_docs, giving it a different grid context despite both using col-md-6. To fix the issue, we wrapped the portal_docs_entry in an "o_portal_category row g-2 mt-3" div to match the structure of all other portal cards. Steps to reproduce: 1. Go to the website. 2. Click on name drop down menu on the navbar like "Mitchell Admin" 3. Click on "My Accont" from the drop down menu 4. Once the page loads properly, you can see the knowledge card width is a little bit larger than other cards. opw-6251483 Forward-Port-Of: odoo/enterprise#119939
This fixes an issue where resetting certain Uruguayan electronic invoices to draft could fail when triggered remotely. The change ensures the action returns a valid response, preventing interruptions for users working with accounting documents.
Original PR description
Calling the method in RPC causes an error: ``` TypeError: cannot marshal None unless allow_none is enabled ``` Forward-Port-Of: odoo/enterprise#124740 Forward-Port-Of: odoo/enterprise#124653
Resetting a submitted tax return no longer changes the global tax lock date for all users. This prevents closed accounting periods from being unintentionally reopened, while still allowing authorized lock date exceptions to control corrections and resubmissions.
Original PR description
To reproduce the issue: 1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January 3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock…
To reproduce the issue:
1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January
3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock date exception removing the tax lock date just for you, for 5 min. 5) Reset January's return
6) Reopen the lock date wizard.
====> Your exception is still there, but the tax lock date for everyone has been reset to December 31st.
This is plain wrong. Resetting a return should not automatically reopen the period for everyone. Lock dates exceptions/modifications are anyway required to reset the return ; they should pilot the whole flow. Nothing being magically hidden from the user means there can't be someone else mistakenly encoding something into the reopened period.
Another fix was required to make this one work: setting the tax lock date before submitting the return should work. In bigger environments, users might want to do that as a first step to reduce the number of people encoding data before actually doing the submission of the return. Therefore, the case where the tax lock date is already set at the date_to of the return when submitting it was supposed to be already supported, and allow the creation of the closing entry for that return, despite it being on the tax lock date. The test ensuring this was however badly written, and the feature didn't work: the closing was created at a later date than the lock date automatically, due to the Bills' Algorithm.
Forward-Port-Of: odoo/enterprise#124872
Forward-Port-Of: odoo/enterprise#1248114 changes
Resolved issues and error corrections
Fixed an issue where importing a Chilean electronic document file with multiple documents could put all invoice lines and references onto the first vendor bill. Each imported document now keeps its own bill details, preventing incorrect totals and reconciliation problems.
Original PR description
When importing an EnvioDTE XML containing several DTEs (journal upload or incoming DTE mail server), one vendor bill is created per DTE, but the first bill receives the invoice lines and references…
When importing an EnvioDTE XML containing several DTEs (journal upload or incoming DTE mail server), one vendor bill is created per DTE, but the first bill receives the invoice lines and references of ALL the DTEs in the file, causing the total amount mismatch.
Cause: `_split_xml_into_new_attachments()` creates new attachments for the documents beyond the first one but leaves the original `file_data['xml_tree']` untouched; the decoder must scope itself to the first document (as l10n_it_edi and l10n_es_edi_facturae do), which `_l10n_cl_import_dte()` never did.
e.g. l10n_es_edi_facturae:633:
```python
# Only decode the first invoice of the Factura-e file.
tree = tree.xpath('//Invoice')[0]
```
Fix: scope the tree to the first DTE node before filling the bill. Kept behind a `len > 1` guard so files with a bare <DTE> root (matched by `xpath('//ns0:DTE')` but not by `findall('.//ns0:DTE')`) keep working.
Introduced in: https://github.com/odoo/enterprise/pull/75327.
opw-6378954This fix ensures the reset-to-draft action returns a proper response when called remotely. It prevents a technical error that could interrupt users working with Uruguayan electronic invoicing documents.
Original PR description
Calling the method in RPC causes an error: ``` TypeError: cannot marshal None unless allow_none is enabled ``` Forward-Port-Of: odoo/enterprise#124740 Forward-Port-Of: odoo/enterprise#124653
This fix ensures accounting reports correctly recognize when no report section has been opened yet. It prevents incorrect state handling in the report interface, supporting more reliable navigation behavior for users.
Original PR description
**Root Cause:**
At [1], the condition `this.lastOpenedSectionByReport === {}` always
return `false` because JavaScript compares objects by reference
rather than by value. As a result, the code never detects when
`lastOpenedSectionByReport` is empty.
**Fix:**
This commit ensures the code correctly detects an empty
`lastOpenedSectionByReport` object.
[1]:
https://github.com/odoo/enterprise/blob/ae4b461edb1d6b49c25d4e264380e7ae4b67f10c/account_reports/static/src/components/account_report/controller.js#L50
**No task ID**
Forward-Port-Of: odoo/enterprise#124223Chilean electronic invoice PDF copies now always show the legally required CEDIBLE disclaimer in Spanish. This prevents the footer from appearing in English when the customer’s preferred language is not Spanish, supporting compliant invoice presentation.
Original PR description
Steps to reproduce: - Set the database language to Spanish (Latin America). - Create a customer invoice, confirm it and send it to the SII. - Print it using Print > Invoice PDF copy (Chile). - Scroll…
Steps to reproduce:
- Set the database language to Spanish (Latin America).
- Create a customer invoice, confirm it and send it to the SII.
- Print it using Print > Invoice PDF copy (Chile).
- Scroll to the CEDIBLE section at the bottom of the PDF.
Cause of the issue:
The CEDIBLE footer is merged into l10n_cl.report_invoice_document, which account.report_invoice (odoo/addons/l10n_cl/views/report_invoice.xml) renders with t-lang set to the invoice partner's lang, not the database/user language. The disclaimer text was hardcoded in English and relied on the regular translation to be shown in Spanish, so as
soon as the partner's lang field isn't Spanish, the translation lookup falls back to the untranslated English source, regardless of the database language.
Solution:
This disclaimer is boilerplate mandated by Chilean law: it must always be printed in Spanish, independently of the invoice partner's or current user's language. The same template already follows that rule a few lines above for the SII stamp block ("Timbre Electrónico SII..."), which is hardcoded in Spanish instead of relying on translation.
opw-63902075 changes
Resolved issues and error corrections
Account Reports now correctly recognizes when no report section has been opened yet. This prevents incorrect behavior caused by treating an empty tracking record as if it contained data, improving reliability when navigating financial reports.
Original PR description
**Root Cause:**
At [1], the condition `this.lastOpenedSectionByReport === {}` always
return `false` because JavaScript compares objects by reference
rather than by value. As a result, the code never detects when
`lastOpenedSectionByReport` is empty.
**Fix:**
This commit ensures the code correctly detects an empty
`lastOpenedSectionByReport` object.
[1]:
https://github.com/odoo/enterprise/blob/ae4b461edb1d6b49c25d4e264380e7ae4b67f10c/account_reports/static/src/components/account_report/controller.js#L50
**No task ID**
Forward-Port-Of: odoo/enterprise#124223The Peppol settings now apply the right rule for when a purchase journal is required, especially when French PDP features are also installed. This prevents non-French companies using Documents for Peppol from being forced to configure an unnecessary invoicing journal, and ensures imports go only to the selected destination.
Original PR description
Fixes the settings view for the account_peppol_purchase_journal_id. account_peppol, documents_account_peppol and l10n_fr_pdp all wants to use a specific condition for the required attribute of the view. With PDP especially, once l10n_fr_pdp is installed, the view forces the base condition, even if documents_account_peppol is installed, and even if the company is not even French. On a non-French company registered/registering on Peppol, the journal shouldn't be mandatory if documents_account_peppol_folder_id is set up. To ease things up, it is now using a computed field. task-6304479 Forward-Port-Of: odoo/enterprise#120718
The Knowledge and Documents cards on the customer portal now align visually with the other portal cards. This fixes a small layout inconsistency, making the account portal page look more polished and consistent for users.
Original PR description
The knowledge and documents portal card was injected directly into "o_portal_docs", causing it to render wider than other cards. This happened because other cards sit inside "o_portal_category" (row g-2 mt-3) divs, while, knowledge was a direct child of o_portal_docs, giving it a different grid context despite both using col-md-6. To fix the issue, we wrapped the portal_docs_entry in an "o_portal_category row g-2 mt-3" div to match the structure of all other portal cards. Steps to reproduce: 1.Go to the website. 2.Click on name drop down menu on the navbar like "Mitchell Admin" 3.Click on "My Accont" from the drop down menu 4.Once the page loads properly, you can see the knowledge card width is a little bit larger than other cards. opw-6251483 Forward-Port-Of: odoo/enterprise#119939
The barcode app now correctly keeps only one delivery line selected when users switch between packaged and unpackaged products. This prevents confusion during warehouse picking and helps operators process mixed deliveries more reliably.
Original PR description
**Steps to reproduce:** - Enable "Move Entire Packages" setting on deliveries - Make a product A, that has a package P1, on hand qty of 1 - Make product B that don't have a package, but on hand qty…
**Steps to reproduce:** - Enable "Move Entire Packages" setting on deliveries - Make a product A, that has a package P1, on hand qty of 1 - Make product B that don't have a package, but on hand qty of 1 - Make a delivery that has both of those products, requested qty of 1 for both - Mark it as todo - Go to the barcode app, select the delivery - Select the line with product B - Select the line with product A --> The line with product B is not unselected **Why the fix:** When we have a mix of packaged products and products without a package on the same operation, they are handled separately. The products without a package are handled in https://github.com/odoo/enterprise/blob/98c79af3fb6cb354f46fd2f58e642a72a9271443/stock_barcode/static/src/models/barcode_model.js#L388-L392 that calls https://github.com/odoo/enterprise/blob/98c79af3fb6cb354f46fd2f58e642a72a9271443/stock_barcode/static/src/models/barcode_model.js#L1277-L1284 But as you can see, there are no mention of the selected package line, which is stored in **this.lastScanned.packageId**. As we do not touch this variable, the selected package line stays selected. The same is true for the other way around, when we select a package line we call https://github.com/odoo/enterprise/blob/98c79af3fb6cb354f46fd2f58e642a72a9271443/stock_barcode/static/src/models/barcode_model.js#L394-L398 This function does not care for the **selectedLineVirtualId** which represents the selected line without a package. To avoid this and make it so that only one line is selected even if they have different package, we now set the corresponding value to false to unselect the other line in all situation. This is basically how it's done in https://github.com/odoo/enterprise/blob/98c79af3fb6cb354f46fd2f58e642a72a9271443/stock_barcode/static/src/models/barcode_model.js#L1202-L1208 to unselect every line regardless of packages. opw-6266203 Forward-Port-Of: odoo/enterprise#124717 Forward-Port-Of: odoo/enterprise#122038
Fixed a rounding issue that could make a trial balance ending balance appear as a tiny scientific-notation number instead of zero in XLSX exports. This improves report accuracy and reduces confusion when accounts are fully balanced.
Original PR description
Steps to reproduce -------------------- - Install account_reports module; - Create a new account; - Create a miscellanous operation for the previous month using thenew account with a credit amount of $8.28; - Create a second MISC for the current month with two lines using the account : debit = 262.67 and credit = 254.39; - Open the trial balance report and filter the new account (end balance should be 0); - Export the report as XLSX; The end balance value is 2.84e-14 due to float rounding issues. opw-6369016
10 changes
Resolved issues and error corrections
Uploaded public holidays now receive the required work entry type before payslips are created. This prevents payroll processing from failing when companies import public holidays through the localization payroll tools.
Original PR description
Steps to reproduce: - Install payroll and timeoff. - Open the Public Holidays menu. - Upload public holidays. - Create a payslip. Issue: - A traceback occurs while creating the payslip. Cause: - The uploaded public holidays do not have a Work Entry Type assigned. As a result, the work entries are empty, which causes the payslip creation to fail. Fix: - Set Work Entry Type before creating payslips extending public holiday model. Task-6394524
Spanish VAT book exports now ignore negative tax components when calculating displayed tax amounts. This prevents valid EU vendor bill taxes from incorrectly appearing as zero, improving accuracy in tax reporting.
Original PR description
Problem: In the Spanish VAT books, taxes with negative component (like 21% EU G) always show their amounts as zero. Steps to reproduce: 1. Install the l10n_es_reports module and select the Spanish company 2. Create a vendor bill with a vendor from another EU country and add a product 3. Make sure the tax applied to the product has a negative component (like 21% EU G) 4. Confirm the bill 5. Go to Accounting > Reporting > Tax Return 6. Generate the VAT books from the action menu and check the tax amounts 7. Notice how the tax amount is zero, even though the tax was applied to the bill Cause: When calculating the tax amounts, the negative component cancels out the positive component, leading to the amount always showing as zero in the VAT books. opw-6169766 Forward-Port-Of: odoo/enterprise#124030 Forward-Port-Of: odoo/enterprise#123738
The timesheet assistant now recognizes events from coding editors correctly, so they display with the intended development icon. This makes assistant activity clearer for users who track work connected to development tools.
Original PR description
In the assistant, events from a coding editor use the "code" event type, which doesn't exist. This PR changes it to the correct value, which is "development". Task-6392585 Forward-Port-Of: odoo/enterprise#124502
Belgian payroll now correctly treats employees with a judicially separated marital status when calculating withholding tax and special social security contributions. This prevents affected payslips from applying zero rates or excessive reductions, improving payroll accuracy and compliance.
Original PR description
**Steps to Reproduce:** 1. Create a new employee. 2. Set their marital status to "Judicially Separated". 3. Generate a payslip. **Reason:** - The "Judicially Separated" marital status was not explicitly included in the conditions for calculating withholding taxes or special social contributions. As a result, employees with this status bypassed the calculations entirely, receiving a rate of 0 for both and a significantly larger reduction on master which also appears to be incorrect. **Solution:** - Included the 'separated' status in isolated tax and CSSS logic. Task-6321245 Forward-Port-Of: odoo/enterprise#124992 Forward-Port-Of: odoo/enterprise#121457
The barcode app now applies a default limit when loading reusable packages for transfers. This prevents very large package lists from causing long waits, improving responsiveness for warehouses with tens of thousands of packages.
Original PR description
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local…
# How to reproduce - Have a lot of reusable & locationless packages (e.g. > 10 000) - Go to any transfer via the barcode application # The issue There is a very long loading time, even in local testing. The client of the tickets experiences loadings up to 120 seconds with 50k packages # Cause When opening a transfer, we load barcode data by doing an API call to `_get_stock_barcode_data` : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L85 During this we preload a lot of records, notably packages : https://github.com/odoo/enterprise/blob/fe058ef501767b7ed9758fc9264f664b32c6bae8/stock_barcode/models/stock_picking.py#L128 The issue is that in the fields we read for the packages, two of them (`location_dest_id` & `contained_quant_ids`) have a `_read_group` in their compute (or in the compute of one of the fields they depend on) : https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L65 https://github.com/odoo/odoo/blob/625e6bcbd66c45ea2f699df14e2ea12e2e28a893/addons/stock/models/stock_package.py#L146 Fortunately, this does not mean that we make a query for every records. Instead, in Odoo, we fetch records in batch of 1000. So, for the case of the client, every time he loads the database, the backend does 50 000 / 1000 x 2 = 100 queries, which hinders performance a lot A [PERF] commit was done to limit the number of packages that are fetched base on a config parameter. The problem is that this parameter does not have a default value, so clients still end up with the problem. [PERF]: https://github.com/odoo/enterprise/commit/efe18bc1ea479270e42846986d7ed449b0865617 # Proposed Solution Add a default value for that config parameter. The exact value is up to discussion opw-6200730 Forward-Port-Of: odoo/enterprise#124538 Forward-Port-Of: odoo/enterprise#123696
The AI module’s automated tests were adjusted to focus only on editable email content after a related editor behavior change. This helps keep quality checks reliable without changing what end users see or do.
Original PR description
This commit updates the tests after https://github.com/odoo/odoo/pull/276332 to query only the editable content, ignoring the DOM clone created by `convert_inline`. opw-3776054 Forward-Port-Of: odoo/enterprise#124648
Envia shipping label requests now send the weight of each item when using Amazon shipping. This prevents Amazon from applying default weights that could incorrectly block shipments with larger quantities.
Original PR description
**Issue:** Envia API documentation is very bad. When trying to generate an Amazon Ground shipping with Envia, the API will sometimes reject the payload with the following error: `Total items weight…
**Issue:** Envia API documentation is very bad. When trying to generate an Amazon Ground shipping with Envia, the API will sometimes reject the payload with the following error: `Total items weight exceeds package weight. Please refer to API documentation for allowable limits. (D-703)` Even though the [Envia documentation](https://docs.envia.com/reference/create-shipping-label) doesn't include it, it seems that Amazon requires the weight for each product. If the payload doesn't include the per-item weight, Amazon will set a default weight, which will cause the error to show up if the delivery contains a high quantity. This can be a blocking issue for some customers. **Steps to reproduce on a fresh DB:** - Install Inventory, Sales, and Envia Shipping - Switch company to be based in India (need to provide an address to deliver from, I just used the Odoo India address - InfoCity Gate, Gandhinagar, Gujarat 382007) - Configure an Amazon delivery carrier with Envia (India seems to be the only country that supports Amazon with Envia) - Inventory > Configuration > Delivery Methods > Envia.com method - Must be in a Production environment (because Envia's sandbox server does not work for some reason?) - Add an Envia Production Access Token (will have to use one with some funds) - Change 'Ship From' to India - Configure the `Envia.com Service Name`, set Carrier and Service to AMAZON and AMAZON - Amazon Shipping Standard - Create a demo product, give it an arbitrary weight like 0.1 kg - Create a sales order to an Indian customer, include the demo product with a high quantity (like 20), confirm (might have to create a warehouse and configure the customer's information) - On the generated picking, set the Carrier to Envia.com on the Additional Info tab - When trying to Validate, it should throw the error **Fix:** When generating the payload in _get_shipping_lines() in envia_request, include the item weight in the dictionary. Related ticket: opw-6261682 Forward-Port-Of: odoo/enterprise#125017 Forward-Port-Of: odoo/enterprise#123935
Merging manufacturing orders now removes pending quality checks from the cancelled source orders. This prevents outdated quality tasks and buttons from remaining visible, reducing confusion for manufacturing and quality teams.
Original PR description
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that…
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that product - Create and confirm multiple Manufacturing Orders - Verify that each MO generates a quality check - From the MO list view, select the MOs and merge them from the gear menu(merge) Issue: ------ When Manufacturing Orders are merged, All MOs are cancelled but it keep their quality checks in the 'To Do' state. As a result: - The quality checks remain linked to cancelled MOs - The 'Quality Checks' smart button is still displayed on cancelled MOs Expected behavior: ------------------ - Pending quality checks should be deleted when the MO is cancelled - The 'Quality Checks' smart button should no longer be displayed Cause: ------ A previous [fix](https://github.com/odoo-dev/enterprise/commit/db93bd2ee313b6bb1959a41c9beb9850975b9959 ) introduced logic to remove pending quality checks when a Manufacturing Order is cancelled: This logic was implemented in `action_cancel()` by unlinking quality checks associated with the cancelled MO: https://github.com/odoo/enterprise/blob/20bc0eb5c2cec67eecd3b44450934e23370b48f2/quality_mrp/models/mrp_production.py#L94-L97 However, when MOs are merged, the merge flow does not call `action_cancel()`. Instead, it directly invokes `_action_cancel()` on the source Manufacturing Orders: https://github.com/odoo/odoo/blob/aca0b7289c68fc7a75d47ab313f5f791ebf30f7d/addons/mrp/models/mrp_production.py#L1778 Since the quality check cleanup is implemented only in `action_cancel()`, it is bypassed during the merge process. As a result, the source MOs are cancelled but their pending quality checks remain in place. --- Related community PR : https://github.com/odoo/odoo/pull/267987 --- opw-6260735
This fix ensures Starshipit delivery item details send the product barcode as the barcode and the internal reference as the SKU. This helps avoid confusion in shipping records and improves accuracy when matching delivered items.
Original PR description
Current behavior: --- Barcode is assigned to sku in the item model payload Fix: --- Assigned product barcode in barcode and internal reference in sku opw-6221412
The website AI now receives clearer guidance when creating or changing buttons, so visual edits such as text color are applied correctly and no longer get undone by page cleanup rules. Video additions are also handled more consistently by removing an unintended faded appearance.
Original PR description
Steps to see the issue: - start editing a page - ask AI to add a button - ask AI to change the text color of the dropped button => AI reports the change as applied, but the frontend rolls it back during normalization because the button keeps the `btn-primary` class, whose style takes precedence over inline color. To fix this, we add explicit instructions for button edits so AI uses `btn-custom` and defines complete button styling when changing button appearance. We also move video-related prompt into the same snippet specific instructions section for consistency and easier maintenance. task-6196298
15 changes
Resolved issues and error corrections
Embedded views at the top of a Knowledge article now keep their intended alignment even when editor selection placeholders are present. This avoids small layout glitches when users start an article with an embedded view, keeping the editing experience consistent.
Original PR description
This commit updates the embedded view top-alignment selector to account for selection placeholders introduced by https://github.com/odoo/odoo/commit/edf7f7bb0c62978640c181eccb4934855d5d872d. This preserves the intended top-alignment behavior when an embedded view is the first editable element in the knowledge editor. Task-5951196
The Vietnam Sales Tax Report now displays VAT amounts consistently as positive values at the detailed invoice level. This avoids confusion when reviewing sales tax figures and aligns detailed lines with the totals shown in the report.
Original PR description
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should…
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should be consistent with the upper layers and kept positive ## Steps to reproduce: - Install l10n_vn (l10n_vn_reports will install as well) - Switch to VN Company - With demo data, go to Invoicing / Reporting / Tax Report - Change Tax Report (VN) to Sales/Purchase Tax Report (VN) - Unfold the lines all the way to the minimum layer: VAT on sales of goods and services 10% -> INV/2026/00003 - Observe that the VAT 10% line is at negative, which is inconsistent with the Total line below ## Cause of the issue: - In Odoo, tax journal items store tax_base_amount with the accounting sign (negative for sales). This is expected behavior - However, Vietnamese VAT listing expects commercial amounts, which means sales bases need to be displayed as positive numbers ## Fix: Normalized tax_base_amount sign in _query_tax_lines function before building the SQL query opw-6344577
Account reports opened from the VAT return button no longer fail when the page is refreshed. This prevents interruptions for users reviewing tax return information and keeps the report accessible after a browser reload.
Original PR description
Opening an account report through the VAT return button on an account.return.check record returns an inline client action whose report_id only exists in context. On refresh, Odoo will throw an error because it will try to rebuild the action context based off of the URL which is deficient. This will not effect reports opened via the menu since those follow a different pathway. This fix anchors the inline action to the "path" property stored on the client action. A helper method was added for deriving the action_id from a given report. opw-6366964
Electronic invoices sent from a Colombian branch now use the parent company's legal name in the DIAN XML. This helps DIAN correctly match invoices to the registered tax ID and avoids rejection caused by branch names not being recognized.
Original PR description
The correct behavior should be to use the original company name in this specific XML tag For the DIAN, branch names will not be recognized as related to the NIT. So, when sending electronic invoices from a branch, the XML should use the name of the parent company of that branch. Ticket [link](https://www.odoo.com/odoo/project.task/6074280) opw-6074280
This fixes an issue where closing a POS session after settling part of an invoice could leave the customer’s remaining amount due incorrectly calculated. As a result, the POS will show the correct remaining balance and avoid proposing or charging too much in later settlements.
Original PR description
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on…
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on `order_id.session_id.state`, but that state is not in the compute dependencies. When closing a session holding a settle order, `_validate_session()` first reconciles the settle payment with the invoice (which lowers `amount_residual_signed` and flags the field for recomputation) and only then writes `state = 'closed'` on the session. If the pending recomputation is executed in that window (any flush of `account.move` does it: recomputing the field for any other flagged record drags the whole queue along), the settle line is deducted from the already reconciled residual, i.e. counted twice, and the field is stored as `residual - settled` instead of `residual`. Since the session state is not a dependency, writing `state = 'closed'` does not flag the field again and the wrong value is never corrected. The partner's `invoices_amount_due` then goes negative, which hides the "Settle invoices" option in the POS partner list and inflates the "Settle due amount" proposal (`remainingDue = total_due - pos_orders_amount_due - invoices_amount_due`): a customer owing e.g. 500 is proposed, and charged, 700. Steps to reproduce: 1. Post a customer invoice of 1000. 2. In the POS, select the customer > Settle invoices, pick the invoice, set the amount to 700 and pay in cash. 3. Close the session. The issue only occurs when the pending recomputation runs during the closing, which depends on the other operations performed by it (not deterministic in real usage; the regression test forces it with a flush after the reconciliation). 4. The invoice's "Amount To Pay In POS" shows -400 instead of 300 and the POS proposes to settle 700 instead of 300. Add the session state to the compute dependencies so that the field is recomputed once the session is closed, yielding the correct amount regardless of any intermediate recomputation. opw-6375095
Belgian POS receipts now show the VAT rate that was actually applied after fiscal position changes, instead of the product's default VAT. This prevents mismatches between the POS sale and the fiscal device receipt when tax mappings are used.
Original PR description
Steps to reproduce: =================== - Configure a product with a 12% VAT - Create a fiscal position that maps 12% → 6% - Open POS and apply the fiscal position to an order - Add the product and validate the sale - Download Receipt Issue: ====== - The POS correctly applies and displays the mapped 6% VAT - The payload sent to the FDM still uses the product's original 12% VAT - As a result, the receipt displays the wrong VAT rate Cause: ====== - VAT labels in the Blackbox payload were generated from product_id.taxes_id - Fiscal position tax mappings were ignored when building VAT inputs - Blackbox product prices were also computed without taking the fiscal position into account Fix: ==== - Use taxes after fiscal position mapping when generating VAT data for the Blackbox payload - Ensure VAT labels sent to the FDM match the taxes applied on the POS order - Apply fiscal position tax mapping when computing Blackbox product prices Task:6392006
The IVA Simple sales CSV now correctly reports buyers marked as “IVA No Alcanzado” under the exempt category. This prevents blank buyer type values in Argentine tax reports and improves compliance reporting accuracy.
Original PR description
### Description AFIP responsibility code `15` (IVA No Alcanzado) was missing from the `CASE WHEN` in `_vat_simple_build_sale_query`, so the "Tipo de sujeto comprador" (`responsibility_type_code`) column was left empty in the IVA Simple sale CSV for partners with that responsibility. This adds `15` to the exempt bucket (value `3`), next to its pair code `16` (IVA No Alcanzado - Otro), which was already handled there. ### Steps to reproduce 1. Set a partner's AFIP responsibility to "IVA No Alcanzado" (code 15). 2. Generate the IVA Simple sale CSV. 3. Before: the "Tipo de sujeto comprador" column is empty for that partner's rows. 4. After: it is reported as `3` (exempt bucket).
The Knowledge editor no longer offers website theme colors in its text color picker. This prevents article colors from changing unexpectedly when the website theme is updated, keeping published Knowledge content visually consistent.
Original PR description
**Steps to reproduce:** - Go to Knowledge app - Go to any article - Try to change the color of the text - Theme colors of the website are shown in the colorPicker - When applied they are mapped to `text-o-color-x` attributes - Changing the website theme affects the article colors - Published articles will have different colors if the theme was modified **Issue:** Some modules (`Knowledge`) should not be affected by the website styling. But there is no direct way to prevent this on the colorPicker. ``` // Overwrite user-defined website styles in Knowledge published articles, mainly // to avoid color customization from affecting articles content. ``` **Fix:** Remove the dynamic values from the knowledge color picker (for now). related: https://github.com/odoo/enterprise/commit/e042faab3d1d992cb471dcf9141d0a2756d06ced opw-5148839
This fix prevents an error when moving Uruguayan electronic invoicing records back to draft through remote system calls. It improves reliability for users and integrations that need to reset documents without encountering a technical failure.
Original PR description
Calling the method in RPC causes an error: ``` TypeError: cannot marshal None unless allow_none is enabled ``` Forward-Port-Of: odoo/enterprise#124740 Forward-Port-Of: odoo/enterprise#124653
This fixes Peppol document import settings so the purchase journal is only required when it is actually needed. It prevents non-French companies using Documents with Peppol from being blocked by French PDP-related requirements, and ensures imports go to the selected destination only.
Original PR description
Fixes the settings view for the account_peppol_purchase_journal_id. account_peppol, documents_account_peppol and l10n_fr_pdp all wants to use a specific condition for the required attribute of the view. With PDP especially, once l10n_fr_pdp is installed, the view forces the base condition, even if documents_account_peppol is installed, and even if the company is not even French. On a non-French company registered/registering on Peppol, the journal shouldn't be mandatory if documents_account_peppol_folder_id is set up. To ease things up, it is now using a computed field. task-6304479 Forward-Port-Of: odoo/enterprise#120720
This fix prevents system errors when a Knowledge article linked to an Annual Report is sent to the trash and automated cleanup runs. The related annual report data is now cleaned up together, keeping background maintenance from failing and reducing disruption for accounting users.
Original PR description
When a knowledge article linked to an Annual report is moved to the trash and the ``Base: Auto-vacuum internal data`` cron runs, a traceback will generate. Steps to reproduce the error: - Install…
When a knowledge article linked to an Annual report is moved to the trash and the ``Base: Auto-vacuum internal data`` cron runs, a traceback will generate. Steps to reproduce the error: - Install ``accountant_knowledge`` module - Go to Accounting > Review > Annual Report > Create a new annual report - Go to Knowledge > Open the knowledge article linked to the annual report > Send to Trash - Run the ``Base: Auto-vacuum internal data`` cron Traceback: ```py ForeignKeyViolation: update or delete on table "knowledge_article" violates foreign key constraint "audit_report_knowledge_article_id_fkey" on table "audit_report" DETAIL: Key (id)=(67) is still referenced from table "audit_report". ``` https://github.com/odoo/enterprise/blob/04cce2e400ce2e412f28aa1849078a7c40ff0e2c/knowledge/models/knowledge_article.py#L1069-L1070 The garbage collector deletes trashed knowledge articles that match its domain. Since this domain also includes articles linked to Annual Reports, the cron attempts to delete records that are still referenced by annual report, resulting in a foreign key violation error. Solution: Ensure linked audit reports are also deleted during knowledge article garbage collection. sentry-7488793071
Product managers can now use barcode lookup to automatically fill product details without needing full administrator access. This keeps product creation workflows efficient while avoiding unnecessary admin privileges.
Original PR description
Currently when a user with a product manager rights that is not admin tries to look up the product with barcode information is not auto filled. ## Steps to replicate: - Install stock with demo data -…
Currently when a user with a product manager rights that is not admin tries to look up the product with barcode information is not auto filled. ## Steps to replicate: - Install stock with demo data - Barcode Database > Setup barcode lookup credentials - Users > Marc Demo > Give Marc Demo > Master Data > Products > Create - Login as `Marc Demo` - Products > Barcode: `850049670180` > Click anywhere else ## Observed Behaviour: Information on the product template is not autofilled, as it would be when using a System Admin user(Mitchell Admin). ## Root cause: This issue occurs because barcode lookup is gated behind a check for System Admin rights. Although users in the Product Manager group have permission to create products, they do not satisfy this condition, so the barcode lookup never executes at [1]. [1]- https://github.com/odoo/enterprise/blob/c66995fda83e19b28a38312af8efdc1601881cf0/product_barcodelookup/models/product_template.py#L17-L22 ## Why this is an issue: The original restriction (task [2] and commit [3]) was intended to limit barcode lookup to users who can create products, preventing unnecessary API calls. This was a valid assumption in 17.3-18.0, where creating products in POS required System Admin rights but now after commit [4] this is no longer the case. In v18, task [5] introduced the Product Manager group, making product creation independent of System Admin rights or module rights. Later, v18.3 exposed these Master Data access rights to non-debug users through commit [6]. As a result, there are users who are legitimately responsible for product creation and maintenance (regardless of POS usage) they can no longer use barcode lookup unless they are also granted full System Admin privileges, which provides broader access than required. ## Solution: Remove the group-based permission check so that access is determined solely by product edit permissions. This ensures that only users with the ability to modify products can use the API call, preserving the original security intent. As a result, users no longer need unnecessary administrative privileges toperform barcode lookups. [2]: https://www.odoo.com/odoo/project/49/tasks/3911024 [3]: https://github.com/odoo/enterprise/commit/444df3e48cb8d479d3b5d4a03a4bfefa48650910 [4]: https://github.com/odoo/odoo/commit/821bbc4504fd80a508e2412c7490ee60dd03f7b8 [5]: https://github.com/odoo/odoo/commit/d4886faf12ccaf63d5e899c20df2543d1ce046ab [6]: https://github.com/odoo/odoo/commit/e74eaf628498155243db73ea229eaf5e74c24f2a opw-6290999
This fixes an issue in accounting reports where the system failed to recognize when no report section had been opened yet. The correction helps reports initialize and restore sections more reliably for users.
Original PR description
**Root Cause:**
At [1], the condition `this.lastOpenedSectionByReport === {}` always
return `false` because JavaScript compares objects by reference
rather than by value. As a result, the code never detects when
`lastOpenedSectionByReport` is empty.
**Fix:**
This commit ensures the code correctly detects an empty
`lastOpenedSectionByReport` object.
[1]:
https://github.com/odoo/enterprise/blob/ae4b461edb1d6b49c25d4e264380e7ae4b67f10c/account_reports/static/src/components/account_report/controller.js#L50
**No task ID**
Forward-Port-Of: odoo/enterprise#124223This fix updates expected Mexican chart of accounts labels used in trial balance report checks so they match the official account groups. It helps keep localization validation reliable and prevents report-related checks from failing because of incorrect expected names.
Original PR description
Enterprise companion of odoo/odoo#277615 — the forward-port to 19.0 of the `l10n_mx` fix that restores the SAT account group names copied from siblings. The `l10n_mx_reports` trial balance test asserts the full Chart of Accounts XML sent to the SAT with the group names hardcoded in the expected output. Two of them were wrong (copied from sibling groups) and are corrected by the community PR: - SAT group **602** (Gastos de venta): `Cost of sales` → `Selling expenses` (`Cost of sales` is 501.01). - SAT group **614** (Amortización contable): `Accounting depreciation` → `Accounting amortisation` (that name belongs to 613). Without this, `ci/l10n` fails on `TestL10nMXTrialBalanceReport.test_generate_coa_xml` and `...test_generate_coa_xml_with_prefix_7_accounts_having_debit_and_credit_tags`. Same branch name as the odoo PR so the mergebot pairs them.
This fixes the French VAT report so the BA zone is sent using the expected free-text format instead of a standard value field. This helps ensure VAT submissions match the required format and reduces the risk of reporting validation issues.
Original PR description
The value inside the BA zone needs to be a "TexteLibre1" and not a value no task id
4 changes
Resolved issues and error corrections
Guatemalan credit notes now reference the original invoice’s commercial issue date instead of a technical certification timestamp. This helps prevent SAT rejections when credit notes are created with a different date from the original invoice.
Original PR description
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification…
### Issue before this commit: When reverting a Guatemalan invoice (creating a credit note), the XML node FechaEmisionDocumentoOrigen incorrectly reports the EDI document's technical certification date instead of the original invoice's emission date. This causes the SAT to reject the document. ### Steps to reproduce the issue: 1. Download Accounting and l10n_gt 2. Revert an invoice (credit note) inserting a different date than the one of the invoice 3. See that FechaEmisionDocumentoOrigen report the date of the credit note instead of the one of the invoice ### Cause of the issue: The _l10n_gt_edi_add_reference_values method extracted the date from original_document.datetime (the technical timestamp of when the XML was generated) rather than using the actual accounting date of the original invoice. ### Reason to introduce the fix: SAT validation rules strictly require the reference date to match the exact commercial emission date of the original invoice. Fetching invoice_date directly ensures compliance, avoids timezone conversion errors, and prevents the XML from being rejected. Source: https://www.lawinsider.com/es/contracts/dJXl4Vo79L2 <img width="730" height="205" alt="2026-07-17_10-19" src="https://github.com/user-attachments/assets/802e7bb3-fcf9-48db-b86f-227b494001b6" /> opw-6394409
Users can now click and edit custom fields directly in the Documents list view. This removes an extra step and makes fields added through Studio behave like standard editable fields.
Original PR description
**Description of the issue/feature this PR addresses:** When adding a custom field (e.g., via Studio) to the Documents list view, clicking the cell directly does not trigger inline edit mode. The…
**Description of the issue/feature this PR addresses:** When adding a custom field (e.g., via Studio) to the Documents list view, clicking the cell directly does not trigger inline edit mode. The user has to first click a standard editable field (like "Owner") to put the row into edit mode before they can modify the custom field. This occurs because we use a hardcoded whitelist (`editableColumns`) of standard fields allowed to trigger edit mode. Custom fields (`x_`) are missing from this static list. This commit resolves the issue by dynamically injecting visible, non-readonly custom fields into the `editableColumns` whitelist. This allows user-created fields to be edited inline as expected. **Steps to reproduce:** - Documents > Studio > List view > Add any field that accepts user input (e.g. Text/char) > save/exit - In the same Documents list view > select a row > click the cell belonging to the newly created field > observe that the row does not enter edit mode - In the same Documents list view > select a row > click a standard editable cell, then click the cell belonging to our newly created field > observe that this then allows us to edit our field **Current behavior before PR:** - Custom fields do not trigger inline edit mode **Desired behavior after PR is merged:** - Custom fields trigger inline edit mode opw-6378102
This fixes when the Peppol purchase journal is marked as required in settings. Companies using document folders for Peppol, especially non-French companies affected by French PDP rules being installed, will no longer be incorrectly forced to select a journal.
Original PR description
Fixes the settings view for the account_peppol_purchase_journal_id. account_peppol, documents_account_peppol and l10n_fr_pdp all wants to use a specific condition for the required attribute of the view. With PDP especially, once l10n_fr_pdp is installed, the view forces the base condition, even if documents_account_peppol is installed, and even if the company is not even French. On a non-French company registered/registering on Peppol, the journal shouldn't be mandatory if documents_account_peppol_folder_id is set up. To ease things up, it is now using a computed field. task-6304479
This update corrects Swedish ISO 20022 payment files so they meet Swedbank’s expected format, including the required bank scheme value and debtor identifier format. It also updates Swedish payment address data to use structured address fields required from November 2026, helping prevent bank file rejections.
Original PR description
Fix some issues with the iso20022 XML file for Sweden:
1. Swedbank doesn't allow the us of `CUST` value in the `SchmeNm`
node but force the `BANK` value.
2. Currently, we use the same Id in both `InitgPty` & `Dbtr`, which
looks to be wrong with Swedbank. The format for Swedbank is
`06{company_registry}B001`.
opw-53957361 change
Resolved issues and error corrections
WinBooks imports now avoid combining supplier and customer contact details when their VAT numbers are explicitly different. This prevents valid imports from failing because mismatched contact data was merged and then failed VAT validation.
Original PR description
When importing a WinBooks zip, contacts sharing the same number might fail VAT validation if distinct contact data is merged incorrectly. Steps to reproduce: - Create a database with the Belgian…
When importing a WinBooks zip, contacts sharing the same number might fail VAT validation if distinct contact data is merged incorrectly. Steps to reproduce: - Create a database with the Belgian localization installed - Install the account_winbooks_import module - Navigate to Accounting > Configuration > Settings > Initial Setup > Import - Import the WinBooks zip Issue: The import fails with the following error: The VAT number [AAAAAA] for partner [BBBBBB] does not seem to be valid. Note: the expected format is BExxxxxxx. Analysis: In WinBooks, contacts can be of type Supplier or Customer, and it is possible for a supplier and a customer to share the same number. During the import, the system will merge contacts if found with the same number. In the specific case, the VAT number from one contact without country is combined with the country information from another contact, resulting in a VAT validation error. This change prevents the merger of partner data if their VAT numbers are explicitly different. opw-6251772