Daily updates from Odoo
Wednesday, August 12, 2026
197 changes
17 changes
Resolved issues and error corrections
A new test verifies that India's GSTR-1 report selects the correct tax rate group when GST and CESS taxes are used together. This helps prevent reporting errors in tax filings for affected Indian businesses.
Original PR description
This PR adds a test case to ensure that the correct tax rate group is selected in the GSTR-1 report when a combination of GST and CESS taxes is used. Community PR - https://github.com/odoo/odoo/pull/280571 Forward-Port-Of: odoo/enterprise#126770
Products created through the Barcode Lookup service now show the image retrieved from the external database. This prevents missing product pictures in the product form and helps users confirm they selected the right item.
Original PR description
Issue before this commit: ========================= When creating a product by adding a barcode using the Barcode Lookup service, the product image was fetched properly but was not displayed in the…
Issue before this commit: ========================= When creating a product by adding a barcode using the Barcode Lookup service, the product image was fetched properly but was not displayed in the UI. Steps to Reproduce: ========================= - Install the stock module. - Enable the Stock Barcode Database. - Add a valid API key for the Barcode Database. - Create a product by adding a barcode available in the Barcode Lookup API. - Notice that the product image is not displayed. Cause of the issue: ========================= This issue was introduced by this [PR](https://github.com/odoo/odoo/pull/244421), which improved the behaviour of **fields.Binary**. As a result, the image returned by the Barcode Lookup API was not converted to the expected binary format, preventing it from being displayed in the UI. With This Commit: ========================= With this commit, convert the fetched image to the expected binary format before assigning it to the product, ensuring that it is displayed correctly in the UI. opw-6434478 Forward-Port-Of: odoo/enterprise#126314
This fix updates how mandatory SSS and Pag-IBIG payroll contributions are calculated for Philippine payroll. It ensures the contribution bases use the correct salary categories, improving payroll accuracy and compliance reporting.
Original PR description
. SSS Mandatory contribution is categories['TAX_CASH_EARNINGS'] . Pag-IBIG Contribution is categories['PH_BASIC'] + categories['ECOLA'] . Update the corresponding tests task-6431960
Belgian payroll calculations now use greater precision when computing ONSS social security contribution amounts. This reduces rounding discrepancies and helps produce more accurate payslips and payroll reporting.
Original PR description
…unt calculation Task: 6431856
Salary offers now correctly display fields that rely on payroll information, even when accessed by HR users with appropriate permissions. The related salary configurator test flow was also updated to reflect real HR user access rather than administrator access.
Original PR description
A field displayed inside the offer should have been computed with sudo as it accesses some payroll field to compute. Also, the salary configurator tour has been adapted to use a HR user instead of an admin Forward-Port-Of: odoo/enterprise#127510
This fix prevents users in multi-company setups from hitting an unsolvable error when creating operation steps without the Quality Control module installed. It ensures quality team email aliases always have an appropriate company value, so manufacturing quality workflows continue smoothly across companies.
Original PR description
This commit actually reverts [1] and manually forwards [2]. Suppose `mrp_workorder` installed and `quality_control` uninstalled. Because of the default value provided by [1], the only existing quality team is linked to the first company. As a result, when using another company, if the user tries to create an operation step (i.e., a QCP), it will raise an error when the onchange tries to load the default team in charge: https://github.com/odoo/enterprise/blob/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e/quality/models/quality.py#L141-L142 However, the `quality` module doesn't provide any view to create such a team. tldr The module raises an error that is actually impossible to solve... Let's avoid it in the above situation. [1] https://github.com/odoo/enterprise/commit/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e [2] https://github.com/odoo/enterprise/commit/8cd5c9322bef7db49a90d4aef844dd0ba267058e Forward-Port-Of: odoo/enterprise#127438 Forward-Port-Of: odoo/enterprise#126364
This fix makes the payroll payrun automated test wait for the page to fully reload before continuing. It reduces false test failures and helps keep payroll quality checks stable without changing user-facing payroll behavior.
Original PR description
Currently in payroll_payrun_tour in hr_payroll module, if we put step_delay as paramater in tour test. the tour test will get fail, after the validation in payslip step. When return to Payrun View Page, the next step to click New Button and Select the Payrun in the Dropdown option. But New Button with dropdown only available in the Payslip steps. The reason it works in runboot before due to race conditions where the test still click new button in Payslip step, expected there is dropdown in this view. The reason it's not work in with step_delay, because step_delay make we have time to change the payrun view, when we trigger the new button, the button is no longer reflected to Payslip step but in PayRun View. In this PR, expected to wait the tour test to fully reload the Payrun View before click the New button, so it will work with or without step_delay. task-6455499
Sales users in Kenya can now open invoices they are allowed to view without being blocked by missing access to local electronic invoicing codes. The change grants employees read-only access to these non-confidential codes, reducing interruptions in sales and invoicing workflows.
Original PR description
The KE codes are used in invoices and when sales people who do not have accounting access, but still can see their own invoices open an invoice, right now they will have an access error because they do not have read access to the codes. So, we should just apply the same logic as is done in edi.documents and give base.group_user read access to those codes, which are not confidential anyways. Forward-Port-Of: odoo/enterprise#126825
Timesheet suggestions now behave correctly when users hold Ctrl and click them. Instead of opening an unwanted new browser window, the suggestion is added to the timesheet form as intended, reducing user confusion.
Original PR description
Currently, when a user use ctrl + click on a suggestion, instead of adding it to the view form, it opens a new window. This is due to the default behavior when ctrl+click is used on a link. Using a button instead of an a href="#" solves this issue. Forward-Port-Of: odoo/enterprise#126293 Forward-Port-Of: odoo/enterprise#126240
Payroll departure processing now correctly updates payslip history when new payslips are added, ensuring departure-related payroll records are generated in the right order. This helps avoid incorrect payroll results at the end of an employee collaboration.
Original PR description
Departure should be generated after payslips
The Helpdesk ticket quick create form now has clearer spacing between the customer field and action buttons. This small layout fix makes the form easier to read and reduces visual crowding for users creating tickets from the kanban view.
Original PR description
This commit add a space between the partner field and the buttons in ticket kanban quickreate. task-6443626 Forward-Port-Of: odoo/enterprise#126901
Subscription products now show discounted recurring prices correctly on shop product tiles. This prevents customers from seeing a price based on the one-time sale price when a discount is meant to apply to the subscription plan.
Original PR description
Steps to reproduce: =================== 1. Create a subscription product, allow one-time sale, sale price 5 2. Add a recurring price 10/month 3. On the pricelist, add an advanced rule: -10% for the…
Steps to reproduce: =================== 1. Create a subscription product, allow one-time sale, sale price 5 2. Add a recurring price 10/month 3. On the pricelist, add an advanced rule: -10% for the monthly plan 4. Open the shop page and look at the product tile Cause: ======= On the /shop page, the subscription price displayed on a product tile is computed by `_get_sales_prices`. The cart has no plan selected yet at that point, so `request.cart.plan_id.id` is empty and was passed as `plan_id` to `_compute_price`. In `product.pricelist.item._compute_base_price`, the recurring base price is only looked up when a `plan_id` is given: if rule_base == 'list_price' and product.recurring_invoice and plan_id: ... # find the recurring rule -> base = recurring price With `plan_id` empty, that branch is skipped and the percentage rule falls back on the product's one-time `list_price` instead of the recurring price. Example: one-time price 5, recurring price 10/month, pricelist rule -10% on the monthly plan. => Tile showed 4.5/month (5 * 0.9) instead of 9/month (10 * 0.9). Solution: ========= The chosen pricing already targets a plan, so pass `pricing.plan_id.id` to `_compute_price`, matching what the product page does in `_get_additionnal_combination_info`. opw-6307398 Forward-Port-Of: odoo/enterprise#124815 Forward-Port-Of: odoo/enterprise#120872
The point-of-sale self-order test was adjusted to match the current behavior where takeaway is selected automatically when it is the only option. This keeps quality checks aligned with the user experience and helps avoid false test failures.
Original PR description
In this commit: - The takeaway preset is now automatically selected when it is the only available option. Remove the explicit "Takeaway" selection step from the tour to match the updated behavior. Task:6217791 Community PR : https://github.com/odoo/odoo/pull/274301 Forward-Port-Of: odoo/enterprise#126889 Forward-Port-Of: odoo/enterprise#122979
The planning overlap warning no longer appears for private tasks that are not linked to a project. This prevents users from seeing irrelevant warnings while drafting tasks and keeps scheduling alerts focused on project-related work.
Original PR description
Steps to reproduce: - - Create a task without a project (do not save) - Set planned_date_begin and date_deadline so it overlaps with another task for the same assignee Issue: - - The overlap warning is shown even though the task has no project. Cause: - - When creating a new record, the overlap warning was shown before saving as there was no check for private tasks (tasks with no project), so the warning could appear even when the task had no project. Solution: - - Add a project check so private tasks never show the warning, and recompute it whenever the project changes. Related PR https://github.com/odoo/enterprise/pull/109988 task-6140800
Payslip CFDIs in Mexican payroll now have their SAT validation status updated correctly in Odoo. This prevents validated payroll documents from incorrectly showing an undefined status, improving compliance visibility for payroll teams.
Original PR description
l10n_mx_hr_payroll_account_edi introduces new l10n_mx_edi.document states (payslip_sent, payslip_sent_failed, payslip_cancel, payslip_cancel_failed) but never extends the two hooks the base l10n_mx_edi module relies on to keep sat_state in sync: - _get_update_sat_status_domains(), which builds the domain used by the SAT-status cron (and manual refresh) to pick documents to poll. Payslip states were missing from it, so their SAT status was never fetched at all. - _update_document_sat_state(), which routes a fetched SAT status to a per-source-document handler. It has no branch for the payslip states, so even a manual poll would silently do nothing. As a result, payslip CFDIs validated in the SAT always appeared as "not_defined" in Odoo. opw-6192651 Forward-Port-Of: odoo/enterprise#126294 Forward-Port-Of: odoo/enterprise#124006
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Original PR description
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
**Issue:** In the website builder, when entering "Edit" mode through "Edit" button, the main navbar is hidden. An animation is moving the navbar upwards and a "d-none" class is added to it after a delay of 200ms to avoid it disappearing suddenly. It is displayed again after saving the changes by removing the "d-none" class. However, when entering "Edit" mode and leaving it quickly, it is possible that the code hiding the navbar is executed after the code displaying it again because of the 20
Original PR description
**Issue:** In the website builder, when entering "Edit" mode through "Edit" button, the main navbar is hidden. An animation is moving the navbar upwards and a "d-none" class is added to it after a…
**Issue:** In the website builder, when entering "Edit" mode through "Edit" button, the main navbar is hidden. An animation is moving the navbar upwards and a "d-none" class is added to it after a delay of 200ms to avoid it disappearing suddenly. It is displayed again after saving the changes by removing the "d-none" class. However, when entering "Edit" mode and leaving it quickly, it is possible that the code hiding the navbar is executed after the code displaying it again because of the 200ms setTimeout(). The issue is not reproducible in the UI directly, but the `test_32_website_background_colorpicker` tour is often failing with the following error: ``` FAILED: [53/65] Tour website_page_options → Step <b>Click Edit</b> to start designing your homepage. (trigger: body:has(:iframe body[is-ready=true]) .o_menu_systray .o_menu_systray_item.o_edit_website_container button). Element (body:has(:iframe body[is-ready=true]) .o_menu_systray .o_menu_systray_item.o_edit_website_container button) has not been found. TIMEOUT step failed to complete within 10000 ms. ``` During the tour several clicks on "Save" and "Edit" are executed, leading to the navbar being unavailable when trying to click on "Edit". runbot-243712 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278645
12 changes
Resolved issues and error corrections
Planning managers without HR access can now change the assigned resource on a planning slot without accidentally publishing the shift. The change uses publicly available employee information for the check, avoiding permission-related side effects while keeping the workflow consistent.
Original PR description
For planning manager without HR access, if the user change the resource of the planning slot it will publish it automatically as the employee_ids field cannot be used without HR access. Prefer to use public employee to have better condition without using explicit sudo Caused-by: https://github.com/odoo/enterprise/commit/e88dcd0e545183b3f03e06b62158c52a1e6d2103 Forward-Port-Of: odoo/enterprise#127503
Adds a test to ensure India's GSTR-1 report selects the correct tax rate group when GST and CESS taxes are used together. This helps prevent reporting mistakes in mixed-tax scenarios and supports more accurate compliance checks.
Original PR description
This PR adds a test case to ensure that the correct tax rate group is selected in the GSTR-1 report when a combination of GST and CESS taxes is used. Community PR - https://github.com/odoo/odoo/pull/280571 Forward-Port-Of: odoo/enterprise#126770
The Helpdesk ticket quick create form now has better spacing between the customer field and action buttons. This small layout fix makes the form easier to read and use when creating tickets from the kanban view.
Original PR description
This commit add a space between the partner field and the buttons in ticket kanban quickreate. task-6443626
This fixes an error that could block deliveries when a product was changed into a kit after the transfer had already been confirmed. The Kenya OSCU stock integration now works with the actual component moves created during delivery, helping users complete the process without interruption.
Original PR description
When a stock move's product is turned into a kit after the transfer was confirmed, it explodes it into its component moves and unlinks the original one: https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/mrp/models/stock_move.py#L358-L363 https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/mrp/models/stock_move.py#L400 The `_action_done()` override of `l10n_ke_edi_oscu` localisation called `super()` first and then used `self.filtered(...)` on the pre-explosion recordset, which could still reference the now-deleted move, raising a `MissingError`: https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_stock/models/stock_move.py#L96-L99 Use the `super()` return value instead, which reflects the moves that were actually processed. runbot-243291 Forward-Port-Of: odoo/enterprise#127027
Australian payroll now matches unused leave balances to the correct employee when processing multiple payslips at once. This prevents eligible unused leave from being missed, helping final pay and related payroll calculations stay accurate.
Original PR description
`_l10n_au_get_unused_leave_by_type` compared leave allocations to `self.employee_id` while looping payslips. On a multi-recordset that is the whole employee set, so the match never holds and unused leave is skipped. Use `payslip.employee_id` so each payslip keeps its own allocations. task-6458480 Forward-Port-Of: odoo/enterprise#127330
Spreadsheet side panel items now use the same drag-and-drop behavior and visual feedback across list dimensions, sorting rules, pivot dimensions, and global filters. This makes reordering items more predictable and prevents accidental drag actions when using controls like delete buttons or selectors.
Original PR description
Current behavior before PR: - Dragging list dimensions and sorting rules felt visually different from pivot dimensions and global filters in the side panel. - The list side panel used a separate drag-and-drop utility that did not match the consistent UX of other spreadsheet components. Desired behavior after PR is merged: - List dimensions and sorting rules now share the same drag-and-drop behavior and visual feedback as pivot dimensions and global filters. - All reorderable items in the side panel now look and feel the same, providing a consistent user experience across the spreadsheet. Task: [6219600](https://www.odoo.com/odoo/project/2328/tasks/6219600)
Mexican payroll CFDIs now have their SAT validation status updated correctly in Odoo. This prevents validated payslips from incorrectly appearing with an undefined status, improving compliance visibility for payroll teams.
Original PR description
l10n_mx_hr_payroll_account_edi introduces new l10n_mx_edi.document states (payslip_sent, payslip_sent_failed, payslip_cancel, payslip_cancel_failed) but never extends the two hooks the base l10n_mx_edi module relies on to keep sat_state in sync: - _get_update_sat_status_domains(), which builds the domain used by the SAT-status cron (and manual refresh) to pick documents to poll. Payslip states were missing from it, so their SAT status was never fetched at all. - _update_document_sat_state(), which routes a fetched SAT status to a per-source-document handler. It has no branch for the payslip states, so even a manual poll would silently do nothing. As a result, payslip CFDIs validated in the SAT always appeared as "not_defined" in Odoo. opw-6192651 Forward-Port-Of: odoo/enterprise#126294 Forward-Port-Of: odoo/enterprise#124006
This fixes an issue where signatures or other fields could disappear from downloaded signed PDFs when the original document had unusual page positioning. Signed documents should now match the preview more reliably, reducing failed signing workflows and customer confusion.
Original PR description
Steps to reproduce (version 16+): 1) Obtain a pdf with a negative origin point: This can occur when a customer exports a pdf from another software, or it can be made manually using a python script 2) In the sign app, upload the pdf and create a new template, add a signature field to the document. 3) Sign the document. The preview will load correctly and the signature will be visible 4) Download and open the signed pdf. The signature is not on the document Notes: Issue occurs because the signature was added to the pdf outside of the visible area. The preview works because the signature is rendered on top of the unsigned document in the correct location. The issue can be fixed applying a translation to the canvas. Ticket: [6317223](https://www.odoo.com/odoo/project/49/tasks/6317223?debug=assets) Forward-Port-Of: odoo/enterprise#126921 Forward-Port-Of: odoo/enterprise#121960
When several xmlids point to the same record, PostgreSQL's UPDATE ... FROM can match multiple source rows to one target and pick an arbitrary value. Aggregate translations per res_id in import order so the later entry wins Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281686 Forward-Port-Of:
Original PR description
When several xmlids point to the same record, PostgreSQL's UPDATE ... FROM can match multiple source rows to one target and pick an arbitrary value. Aggregate translations per res_id in import order so the later entry wins Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281686 Forward-Port-Of: odoo/odoo#277818
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Original PR description
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
After this commit: = - LNA is only intended for kiosk mode where local hardware access is expected. Initializing it in mobile mode unnecessarily triggers permission checks. task-6412414 Forward-Port-Of: odoo/odoo#279964
Original PR description
After this commit: = - LNA is only intended for kiosk mode where local hardware access is expected. Initializing it in mobile mode unnecessarily triggers permission checks. task-6412414 Forward-Port-Of: odoo/odoo#279964
Before this commit it was possible to assign an arbitrary account_move to a pos.order by sending it in the order data. This commit prevents that by removing the account_move from the order data before creating the pos.order. Forward-Port-Of: odoo/odoo#280279
Original PR description
Before this commit it was possible to assign an arbitrary account_move to a pos.order by sending it in the order data. This commit prevents that by removing the account_move from the order data before creating the pos.order. Forward-Port-Of: odoo/odoo#280279
17 changes
Resolved issues and error corrections
This update adds a safeguard to verify that Indian GSTR-1 reports choose the correct tax rate group when GST and CESS taxes are used together. It helps reduce the risk of incorrect tax reporting in scenarios involving combined Indian indirect taxes.
Original PR description
This PR adds a test case to ensure that the correct tax rate group is selected in the GSTR-1 report when a combination of GST and CESS taxes is used. Community PR - https://github.com/odoo/odoo/pull/280571
Fixed an error that could occur when users turned the No Follow-Up option on or off for invoices with multiple payment installments. This keeps the Follow-Up Report usable when some installments are already paid and others remain open.
Original PR description
Steps to Reproduce: 1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments. 2. Create a Customer Invoice with this Payment Term. 3. Post the invoice.…
Steps to Reproduce:
1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments.
2. Create a Customer Invoice with this Payment Term.
3. Post the invoice.
4. Register a payment and fully reconcile one of the installments.
5. Navigate to the customer's Follow-Up Report (Accounting > Reporting > Partner Ledger > Report: Follow-Up Report).
6. Navigate to remaining open installment/account move line for that invoice.
7. Turn On or Off the No Follow-Up toggle for the invoice.
An error occurs when enabling or disabling the No Follow-Up toggle.
Issue:
Enabling or disabling the No Follow-Up toggle on a remaining open installment in the Follow-Up Report raises a server error when the invoice contains multiple installments and one or more installments are already fully reconciled.
Root Cause:
The Follow-Up Report only loads and sends non-fully reconciled account move lines from the JavaScript side through all_line_ids. In action_toggle_no_followup(), when the selected line belongs to an invoice, the code retrieves all receivable/payable lines of the invoice, including fully reconciled installments:
```
move.line_ids.filtered(
lambda line: line.account_type in ('asset_receivable', 'liability_payable'),
)
```
The method then attempts to map every receivable/payable line to a report line ID using aml_id_to_line_id. Since fully reconciled installments are not present in all_line_ids, they are missing from the mapping dictionary, causing a KeyError when accessing:
`aml_id_to_line_id[line.id]
`
Fix:
Restricted the impacted lines to those present in the report by adding a check that the account move line exists in aml_id_to_line_id before performing the mapping:
```
lambda line: line.account_type in ('asset_receivable', 'liability_payable')
and line.id in aml_id_to_line_id
```
opw-6245448
Forward-Port-Of: odoo/enterprise#126785
Forward-Port-Of: odoo/enterprise#126156Users can now open Bank Matching from a working file return even when no bank journal is selected. This prevents an error screen and lets staff continue reconciling bank statement lines from that workflow.
Original PR description
When accessing the reconciliation widget from the working file check, there is no journal to be selected, hence no journal in the context. This was tracebacking since we were trying to send a read query to the server with an undefined id. To reproduce: * create a bank statement line without reconciling * set up the return on the misc journal * open the return, then "Bank Matching" Forward-Port-Of: odoo/enterprise#127421
This update corrects a small issue in the Swiss payroll transmission process where the current date could be calculated without the proper context. It helps avoid errors during payroll-related submissions and keeps Swiss payroll workflows running reliably.
Original PR description
Fix https://github.com/odoo/enterprise/pull/126718 Forward-Port-Of: odoo/enterprise#127535
This fix ensures Mexican payroll CFDI payslips are included when Odoo checks their official SAT status. Businesses will now see the correct validation or cancellation status instead of an undefined status, improving payroll compliance visibility.
Original PR description
l10n_mx_hr_payroll_account_edi introduces new l10n_mx_edi.document states (payslip_sent, payslip_sent_failed, payslip_cancel, payslip_cancel_failed) but never extends the two hooks the base l10n_mx_edi module relies on to keep sat_state in sync: - _get_update_sat_status_domains(), which builds the domain used by the SAT-status cron (and manual refresh) to pick documents to poll. Payslip states were missing from it, so their SAT status was never fetched at all. - _update_document_sat_state(), which routes a fetched SAT status to a per-source-document handler. It has no branch for the payslip states, so even a manual poll would silently do nothing. As a result, payslip CFDIs validated in the SAT always appeared as "not_defined" in Odoo. opw-6192651 Forward-Port-Of: odoo/enterprise#126104 Forward-Port-Of: odoo/enterprise#124006
Tax closing entries now correctly include VAT credit carried over from the previous period. This prevents overstated tax payable amounts and ensures tax return journal entries match the expected carryover without extra user configuration.
Original PR description
### Issue before this commit: When generating a tax closing entry, the VAT credit carryover from the previous period is missing from the journal entry lines. This results in an incorrect net payable…
### Issue before this commit: When generating a tax closing entry, the VAT credit carryover from the previous period is missing from the journal entry lines. This results in an incorrect net payable amount. ### Steps to reproduce the issue: 1. Download Accounting 2. Go to Vendor > Bills 3. Create a vendor bill with date in June and price > 0 (ex. 1000$) and the 15% tax that produce a 150$ VAT tax 4. Go to Customers > Invoices 5. Create an invoice with price > 0 (ex. 9000$), the date in July and the 15% tax that will produce a 1350$ VAT tax 6. Go to Tax Return and validate all opened months up to July and see that for June the balance is -150$ 9. Then go to View Entries of July using the 3 dots next to the "submit" button and see that there is no mentioning of the 150$ carry over of credit from the month before ### Cause of the issue: During a forward-port merge conflict resolution, the code block responsible for retrieving the historical balance from the receivable_account_id was wrongly removed ([diff](https://github.com/odoo/enterprise/compare/b760c1dbee6bfb628bae32041c5b5c7dcaa623a4..4ea95b0c15f5f791d088330596c64ece58effa44)). Consequently, the system only checked the advance_account_id for previous balances, completely ignoring existing credits parked in the standard receivable account. ### Reason to introduce the fix: Restore the dropped logic and the _create_tax_receivable_current_line function. This ensures the tax closing process automatically factors in previous VAT credits from the receivable account, providing accurate closing entries out-of-the-box without requiring extra configuration from the user. opw-6438648
Australian payroll now correctly matches unused leave allocations to each employee when processing multiple payslips at once. This prevents unused leave from being skipped, helping ensure final pay calculations are accurate.
Original PR description
`_l10n_au_get_unused_leave_by_type` compared leave allocations to `self.employee_id` while looping payslips. On a multi-recordset that is the whole employee set, so the match never holds and unused leave is skipped. Use `payslip.employee_id` so each payslip keeps its own allocations. task-6458480 Forward-Port-Of: odoo/enterprise#127330
Fixed an issue where rental returns could fail after using stock transfers for serialized rental products. The system now keeps the pickup and return serial number history correctly, so users can complete later returns without manual errors or blocked workflows.
Original PR description
**Issue** When rental transfers are enabled and rental pickups/returns are processed through stock pickings, it may become impossible to perform a subsequent rental return through the rental return…
**Issue** When rental transfers are enabled and rental pickups/returns are processed through stock pickings, it may become impossible to perform a subsequent rental return through the rental return wizard. **Steps to reproduce** - Activate "Rental Transfers" in the settings - Create a rental product P, tracked by serial number - Create two serial numbers for P - Create and confirm a rental order for 2 units of P - Validate the pickup transfer - Partially validate the return transfer without creating a backorder - Open the rental order and click on "Return" -> The return wizard opens without any available serial number and validation fails with a serial number-related error. **Cause** When clicking on "Return", if there is no pending pickup/return transfer: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/models/sale_order.py#L62-L68 the rental return wizard is opened directly: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/models/sale_order.py#L316 No serial number is prefilled in the wizard because `returned_lot_ids` is empty: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L122-L124 This is because `returnable_lot_ids` is empty as well. `returnable_lot_ids` is computed while generating the wizard lines: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/wizard/rental_processing.py#L38 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/wizard/rental_processing.py#L47-L48 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L99-L106 and `returnable_lots` is empty because both `pickedup_lots` and `returned_lots` are. Those fields are currently only populated through the rental wizard flow: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L42-L43 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L160-L161 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L166-L167 Since this flow uses stock pickings instead of the rental wizard, those fields are never updated, preventing the wizard from determining any returnable serial number. opw-6150305 Forward-Port-Of: odoo/enterprise#126594 Forward-Port-Of: odoo/enterprise#119257
Refunding a POS order linked to Ecuador's generic "Consumidor Final" customer now shows the intended business error message instead of crashing. This helps cashiers understand why the refund cannot be validated and avoids an unexpected interruption at checkout.
Original PR description
When attempting to refund orders that were created with the "Consumidor Final" customer. The refund validation would crash with a TypeError instead of showing the proper error message. Steps to…
When attempting to refund orders that were created with the "Consumidor Final" customer. The refund validation would crash with a TypeError instead of showing the proper error message. Steps to reproduce: ------------------- In POS with l10n_ec_edi module activated: * Create a new order with "Consumidor Final" as customer * Add products and pay the order * Validate the order * Attempt to refund this order > Observation: The refund validation would crash with: TypeError: Cannot read properties of undefined (reading 'add') at OrderPaymentValidation.isOrderValid Why the fix: ------------ The code was trying to access `this.dialog` which is undefined in the OrderPaymentValidation class context. The dialog service should be accessed via `this.pos.dialog`, which is the correct pattern used throughout the base OrderPaymentValidation class. This fix ensures the error dialog is properly displayed when attempting to refund orders for the anonymous final consumer, instead of crashing with a TypeError. opw-6427113 Forward-Port-Of: odoo/enterprise#126308
This fix prevents an error when a product on a confirmed delivery is later changed into a kit. Kenyan OSCU stock reporting now uses the actual component moves processed, so deliveries can be completed without interruption.
Original PR description
When a stock move's product is turned into a kit after the transfer was confirmed, it explodes it into its component moves and unlinks the original one: https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/mrp/models/stock_move.py#L358-L363 https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/mrp/models/stock_move.py#L400 The `_action_done()` override of `l10n_ke_edi_oscu` localisation called `super()` first and then used `self.filtered(...)` on the pre-explosion recordset, which could still reference the now-deleted move, raising a `MissingError`: https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_stock/models/stock_move.py#L96-L99 Use the `super()` return value instead, which reflects the moves that were actually processed. runbot-243291 Forward-Port-Of: odoo/enterprise#127027
This fixes an issue where Swiss payroll settings could assign a Swiss contract type to employees outside Switzerland. The change prevents incorrect contract information from appearing and keeps automated checks stable across versions.
Original PR description
[FIX] l10n_ch: fix default contract type This task is runbot error fix that occured from 19.0 to 19.2 Bug reproduction: 1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute…
[FIX] l10n_ch: fix default contract type
This task is runbot error fix that occured from 19.0 to 19.2
Bug reproduction:
1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute test_version_timeline_auto_save_tour tour test 3 - It fails in .o_arrow_button_wrapper[data-tooltip^='Contract:'] step
Bug cause:
1 - When l10n_ch_hr_payroll_account is installed:
1.1 - contract type becomes "Permanent contract with monthly salary"
1.2 - the employee is not swiss but it has this CH contract type
2 - data-tooltip starts with Permanent contract instead of contract
2.1 - Tour fails
3 - contract_type_id is overwritten in swiss modules
3.1 - Default is assigned without looking to the country of self.env
Bug solution:
1 - If the country is not swiss, the default is assigned as False
1.1 -> fixed in l10n_ch_hr_payroll/hr_version
1.2 instead of assigning swiss contract type to the non-swiss emp.
Note: This is fix from saas-18.4 to master.
task-6392040
runbot error: https://runbot.odoo.com/odoo/runbot.build.error/941358
Forward-Port-Of: odoo/enterprise#126520Currently, the is_base_affected condition is only checked on the group tax. However, this condition should also be checked on the child taxes to ensure proper matching. Without checking the child taxes, incorrect matches can occur when the parent tax has is_base_affected set to True, while one of its child taxes has it set to False. Since the parent and child tax configurations are not necessarily synchronized, relying only on the parent tax can lead to incorrect matching. This fix ensures
Original PR description
Currently, the is_base_affected condition is only checked on the group tax. However, this condition should also be checked on the child taxes to ensure proper matching. Without checking the child taxes, incorrect matches can occur when the parent tax has is_base_affected set to True, while one of its child taxes has it set to False. Since the parent and child tax configurations are not necessarily synchronized, relying only on the parent tax can lead to incorrect matching. This fix ensures that is_base_affected is validated at both the parent and child tax levels, preventing such incorrect matches. Enterprise PR - https://github.com/odoo/enterprise/pull/126770
When several xmlids point to the same record, PostgreSQL's UPDATE ... FROM can match multiple source rows to one target and pick an arbitrary value. Aggregate translations per res_id in import order so the later entry wins Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281686 Forward-Port-Of:
Original PR description
When several xmlids point to the same record, PostgreSQL's UPDATE ... FROM can match multiple source rows to one target and pick an arbitrary value. Aggregate translations per res_id in import order so the later entry wins Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281686 Forward-Port-Of: odoo/odoo#277818
Steps to reproduce: 0. Create an employee with a fixed working schedule and an overtime ruleset, then enable Absence Management in attendances 1. Go to Attendances and make sure that the employee has no attendances recorded for the previous working day 2. Run the "Attendance: Detect Absences for employees" scheduled action 3. Observe the absence attendance created on the previous working day, along with the amount of overtime hours calculated 4. Create an attendance on the day that the ab
Original PR description
Steps to reproduce: 0. Create an employee with a fixed working schedule and an overtime ruleset, then enable Absence Management in attendances 1. Go to Attendances and make sure that the employee has…
Steps to reproduce: 0. Create an employee with a fixed working schedule and an overtime ruleset, then enable Absence Management in attendances 1. Go to Attendances and make sure that the employee has no attendances recorded for the previous working day 2. Run the "Attendance: Detect Absences for employees" scheduled action 3. Observe the absence attendance created on the previous working day, along with the amount of overtime hours calculated 4. Create an attendance on the day that the absence was recorded 5. Observe that the overtime hours on the absence attendance are not updated 5a. If a full day attendance is recorded on that day, the overtime hours on the absence attendance should change to 0, since we've now recorded hours worked for the day When an absence attendance is created from the Absence Management feature, overtime hours are calculated to represent the time the employee was unjustifiably absent on a given day. If an attendance is later created on the day the absence was recorded, the overtime hours should update to reflect the hours the employee actually worked. Changes were introduced in [this PR](https://github.com/odoo/odoo/pull/272447) that broke this functionality due to the use of `pytz`, which incorrectly calculated timezone offsets. This caused absence attendances to not be picked up by `_get_overtimes_to_update_domain()`, and overtime was not correctly updated. This commit ensures that we get proper time calculations with respect to the employees timezone. [opw-6380343](https://www.odoo.com/odoo/my-tasks/6380343?debug=assets) Forward-Port-Of: odoo/odoo#281613 Forward-Port-Of: odoo/odoo#279556
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Original PR description
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Before this commit it was possible to assign an arbitrary account_move to a pos.order by sending it in the order data. This commit prevents that by removing the account_move from the order data before creating the pos.order. Forward-Port-Of: odoo/odoo#280279
Original PR description
Before this commit it was possible to assign an arbitrary account_move to a pos.order by sending it in the order data. This commit prevents that by removing the account_move from the order data before creating the pos.order. Forward-Port-Of: odoo/odoo#280279
`#right-elements` (tax totals block) is floated (`float-end`). Per CSS spec, an `auto` margin on a floated element always resolves to 0, so the `ms-auto` class added by 9767e8f5c1da5a9c9e38472ad576ffa3c4e32075 is a no-op, leaving no gutter before adjacent content such as the legal notes paragraph. Partial revert of 9767e8f5c1da5a9c9e38472ad576ffa3c4e32075 Steps to reproduce: ------------------- * On a tax, set a multi-line paragraph in Legal Notes (Advanced Options tab) * Apply it on an
Original PR description
`#right-elements` (tax totals block) is floated (`float-end`). Per CSS spec, an `auto` margin on a floated element always resolves to 0, so the `ms-auto` class added by…
`#right-elements` (tax totals block) is floated (`float-end`). Per CSS spec, an `auto` margin on a floated element always resolves to 0, so the `ms-auto` class added by 9767e8f5c1da5a9c9e38472ad576ffa3c4e32075 is a no-op, leaving no gutter before adjacent content such as the legal notes paragraph. Partial revert of 9767e8f5c1da5a9c9e38472ad576ffa3c4e32075 Steps to reproduce: ------------------- * On a tax, set a multi-line paragraph in Legal Notes (Advanced Options tab) * Apply it on an invoice line and print/preview the invoice PDF > Observation: the legal notes text touches/overlaps the tax totals table, with no spacing. Why the fix: ------------ `ms-5` gives `#right-elements` a real left margin, restoring the spacing lost when `ms-auto` (a no-op on floats) replaced it. BEFORE: <img width="596" height="753" alt="Screenshot 2026-08-05 at 10 52 00" src="https://github.com/user-attachments/assets/c596d6e9-4b61-434c-9b38-3ff0797e7fa7" /> AFTER: <img width="494" height="596" alt="Screenshot 2026-08-05 at 10 51 44" src="https://github.com/user-attachments/assets/f9a1792d-22c2-4586-9a75-53c4695f17e4" /> opw-6384085 Forward-Port-Of: odoo/odoo#280654
9 changes
Resolved issues and error corrections
This fix prevents an error during delivery processing when a product is changed into a kit after a transfer has already been confirmed. It ensures the Kenya OSCU stock integration uses the correct updated delivery records, helping deliveries complete reliably without unexpected interruptions.
Original PR description
When a stock move's product is turned into a kit after the transfer was confirmed, it explodes it into its component moves and unlinks the original one: https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/mrp/models/stock_move.py#L358-L363 https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/mrp/models/stock_move.py#L400 The `_action_done()` override of `l10n_ke_edi_oscu` localisation called `super()` first and then used `self.filtered(...)` on the pre-explosion recordset, which could still reference the now-deleted move, raising a `MissingError`: https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_stock/models/stock_move.py#L96-L99 Use the `super()` return value instead, which reflects the moves that were actually processed. runbot-243291 Forward-Port-Of: odoo/enterprise#127027
Refunding Ecuador POS orders made with the “Consumidor Final” customer now shows the intended warning instead of crashing. This helps cashiers understand why the refund cannot be validated and avoids an unexpected interruption at checkout.
Original PR description
When attempting to refund orders that were created with the "Consumidor Final" customer. The refund validation would crash with a TypeError instead of showing the proper error message. Steps to…
When attempting to refund orders that were created with the "Consumidor Final" customer. The refund validation would crash with a TypeError instead of showing the proper error message. Steps to reproduce: ------------------- In POS with l10n_ec_edi module activated: * Create a new order with "Consumidor Final" as customer * Add products and pay the order * Validate the order * Attempt to refund this order > Observation: The refund validation would crash with: TypeError: Cannot read properties of undefined (reading 'add') at OrderPaymentValidation.isOrderValid Why the fix: ------------ The code was trying to access `this.dialog` which is undefined in the OrderPaymentValidation class context. The dialog service should be accessed via `this.pos.dialog`, which is the correct pattern used throughout the base OrderPaymentValidation class. This fix ensures the error dialog is properly displayed when attempting to refund orders for the anonymous final consumer, instead of crashing with a TypeError. opw-6427113 Forward-Port-Of: odoo/enterprise#126308
This fix corrects how leave intervals are adjusted in the Gantt view for employees using duration-based work schedules. It helps ensure planned absences display with the right timing, reducing confusion for HR teams and managers.
Original PR description
task-id: 6460078 Forward-Port-Of: odoo/enterprise#127487
Swiss payroll no longer assigns a Swiss-specific contract type to employees when the company context is not Switzerland. This prevents automated workflow failures and helps keep employee contract information aligned with the correct country settings.
Original PR description
[FIX] l10n_ch: fix default contract type This task is runbot error fix that occured from 19.0 to 19.2 Bug reproduction: 1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute…
[FIX] l10n_ch: fix default contract type
This task is runbot error fix that occured from 19.0 to 19.2
Bug reproduction:
1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute test_version_timeline_auto_save_tour tour test 3 - It fails in .o_arrow_button_wrapper[data-tooltip^='Contract:'] step
Bug cause:
1 - When l10n_ch_hr_payroll_account is installed:
1.1 - contract type becomes "Permanent contract with monthly salary"
1.2 - the employee is not swiss but it has this CH contract type
2 - data-tooltip starts with Permanent contract instead of contract
2.1 - Tour fails
3 - contract_type_id is overwritten in swiss modules
3.1 - Default is assigned without looking to the country of self.env
Bug solution:
1 - If the country is not swiss, the default is assigned as False
1.1 -> fixed in l10n_ch_hr_payroll/hr_version
1.2 instead of assigning swiss contract type to the non-swiss emp.
Note: This is fix from saas-18.4 to master.
task-6392040
runbot error: https://runbot.odoo.com/odoo/runbot.build.error/941358
Forward-Port-Of: odoo/enterprise#126520This fix corrects an internal module dependency for the Belgian point of sale black box setup with HR features. It helps ensure the right related module is installed and avoids configuration or automated test failures caused by the previous dependency mismatch.
Original PR description
Before this commit, the dependency of the module l10n_be_pos_blackbox_hr_pos_blackbox_be was set to pos_hr, which is not totally correct. The correct dependency should be l10n_be_pos_blackbox_hr. runbot-error: 941561 Forward-Port-Of: odoo/enterprise#124814
This fixes an issue where unused leave could be missed when processing payslips for multiple employees at once. Each payslip now uses the correct employee’s leave allocations, helping ensure Australian payroll amounts are calculated accurately.
Original PR description
`_l10n_au_get_unused_leave_by_type` compared leave allocations to `self.employee_id` while looping payslips. On a multi-recordset that is the whole employee set, so the match never holds and unused leave is skipped. Use `payslip.employee_id` so each payslip keeps its own allocations. task-6458480 Forward-Port-Of: odoo/enterprise#127330
Fixes an issue where using AI to update website SEO could fail when the AI agent relied on certain document-generated files, such as invoice PDFs. The AI feature can now correctly use those document sources, reducing interruptions for users optimizing website content.
Original PR description
### Problem When an AI agent includes a document source whose underlying `ir.attachment` has `res_field` set (e.g., an invoice PDF generated from a Sale Order), triggering **Update With AI** from…
### Problem
When an AI agent includes a document source whose underlying `ir.attachment`
has `res_field` set (e.g., an invoice PDF generated from a Sale Order),
triggering **Update With AI** from **Website → Site → Optimize SEO**
raises a `KeyError` in `_build_rag_context`.
### Steps to Reproduce
1. Open the **AI** app.
2. Configure the **Odoo Agent**.
3. Add a source → **Add From Documents**.
4. Select a document whose underlying `ir.attachment` has `res_field` set
(e.g., an invoice PDF generated from a Sale Order).
5. Go to **Website → Site → Optimize SEO**.
6. Click **Update With AI**.
7. Observe the following error:
```
KeyError: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
```
[Video](https://drive.google.com/file/d/1AAg0AvC3TRQzMLhI9hWFuSarOTHzQE-b/view?usp=sharing)
### Root Cause
In `ai/models/ai_agent.py`, `_build_rag_context()` retrieves the
`ai.agent.source` records corresponding to the embeddings by searching on the
attachment checksum:
```python
agent_sources = self.env["ai.agent.source"].search([
("attachment_id.checksum", "in", embeddings_attachment_checksums),
("agent_id", "=", self.id),
])
```
This domain traverses `attachment_id.checksum`, which internally calls
`ir.attachment._search()`.
As part of the standard attachment search behavior,
`ir.attachment._search()` automatically injects a
`('res_field', '=', False)` filter unless:
- `skip_res_field_check=True` is set in the context,
- the domain explicitly references `id` or `res_field`, or
- `bypass_access` is enabled.
```python
domain = Domain(domain)
if (
not self.env.context.get("skip_res_field_check")
and not any(d.field_expr in ("id", "res_field") for d in domain.iter_conditions())
and not bypass_access
):
disable_binary_fields_attachments = True
domain &= Domain("res_field", "=", False)
```
[Reference](https://github.com/odoo/odoo/blob/19.0/odoo/addons/base/models/ir_attachment.py#L630)
Because of this implicit filter, attachments with `res_field` set are excluded
from the search. Consequently, `agent_sources` does not contain all the sources
corresponding to the retrieved embeddings.
Later, `_build_rag_context()` builds a checksum-to-source mapping:
```python
source_map = {
source.attachment_id.checksum: source
for source in agent_sources
}
for embedding in similar_embeddings:
checksum = embedding.attachment_id.checksum
agent_source = source_map[checksum]
```
Since `source_map` is built from the incomplete `agent_sources` recordset, it is
missing entries for attachments filtered by `ir.attachment._search()`.
However, `similar_embeddings` still contains embeddings for those attachments.
As a result, the lookup:
```python
agent_source = source_map[checksum]
```
raises a `KeyError`.
### Solution
Bypass the implicit `res_field` filter when searching `ai.agent.source`:
```python
agent_sources = (
self.env["ai.agent.source"]
.with_context(skip_res_field_check=True)
.search([
("attachment_id.checksum", "in", embeddings_attachment_checksums),
("agent_id", "=", self.id),
])
)
```
This ensures that all `ai.agent.source` records matching the requested
attachment checksums are returned, including those referencing attachments with
`res_field` set. As a result, `source_map` contains all expected entries and
`_build_rag_context()` no longer raises a `KeyError`.
opw-6379816French VAT reimbursement declaration 3519 now includes the bank account holder name in the account details section. This helps meet declaration requirements and reduces the risk of rejected or incomplete reimbursement submissions.
Original PR description
For reimbursement declarations, the name of the holder of the account is required This commits adds holder's name to the account data zone no-task-id Forward-Port-Of: odoo/enterprise#127631 Forward-Port-Of: odoo/enterprise#127554
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Original PR description
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
2 changes
Resolved issues and error corrections
French VAT reimbursement declaration 3519 now includes the name of the bank account holder in the account information section. This helps ensure the declaration contains the required banking details and reduces the risk of rejected or incomplete reimbursement submissions.
Original PR description
For reimbursement declarations, the name of the holder of the account is required This commits adds holder's name to the account data zone no-task-id Forward-Port-Of: odoo/enterprise#127554
This fix prevents cancelled point-of-sale refunds from being counted when creating Mexican global invoices. Businesses can now generate the invoice correctly when an order has both a cancelled refund attempt and a completed refund, avoiding erroneous negative amounts.
Original PR description
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click…
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click "Return Products" to make a refund, but don't pay it, cancel it instead. 4. From the same order, click "Return Products" again to make a second refund, and pay it normally. 5. Go to the orders list, select the main order and the paid refund (not the cancelled one), then Actions > Create Global Invoice. -> Observation: error in the global invoice. In the CFDI tab of the main order the line is "Send Global In Error", and hovering on it the detail says "Failed to distribute some negative lines". Why: ---- When we make the global invoice, we remove the refunds from the order. A cancelled refund was never paid, so we should not count it. But we were counting it too. So we removed the refund amount twice in our case, one for the paid refund, and one for the cancelled one, and we end up with an order with negative amount that cannot be distributed. The fix: -------- We now skip the cancelled orders when we search the refunds, the same way it is done above when we collect the refunded orders. opw-6261404 Forward-Port-Of: odoo/enterprise#127454 Forward-Port-Of: odoo/enterprise#120996
5 changes
Resolved issues and error corrections
The Dutch tax reporting status process now skips or handles records that are missing their linked closing entry instead of crashing. This helps keep Digipoort tax return status updates running even when one record has incomplete data.
Original PR description
The `l10n_nl_reports_sbr_status_info` contains the `l10n_nl_reports_sbr.status.service` class. The class is responsible for fetching the status of sent Digipoort tax returns. The status is then posted as a chatter message to the tax return's closing entry. Issues can arise when one of the status service records is, for whatever reason, missing a closing entry. In such case, the message cannot be posted, resulting in an exception being raised. Since the records are processed in a loop without a try-catch, this causes the whole action to fail. This can lead to one broken record effectively shutting down the whole module's functionality. This PR adds some if-else checks to gracefully handle the case where the closing entry is missing. Related tickets: opw-5901446 and opw-6410082 Forward-Port-Of: odoo/enterprise#127389 Forward-Port-Of: odoo/enterprise#125996
French VAT reimbursement declarations now include the bank account holder's name in the required account information. This helps ensure declaration 3519 contains the information needed for successful processing by authorities.
Original PR description
For reimbursement declarations, the name of the holder of the account is required This commits adds holder's name to the account data zone no-task-id Forward-Port-Of: odoo/enterprise#127554
Users can now interact with Search More dialogs from document fields without the dialog unexpectedly closing. This prevents interruptions when choosing related records such as owners or customers in the Documents app.
Original PR description
Steps to reproduce: 1. Install Documents 2. In the Documents list view, select a document to display the inspector. 3. Edit a field such as Owner or Customer which uses a Many2one widget. 4. In the…
Steps to reproduce: 1. Install Documents 2. In the Documents list view, select a document to display the inspector. 3. Edit a field such as Owner or Customer which uses a Many2one widget. 4. In the field dropdown, click "Search More..." to open a modal dialog. 5. Click inside the "Search More..." modal (e.g., to sort columns or resize headers). Issue: - The modal dialog immediately closes, and the contact cannot be selected. Root cause: - When an inspector field is edited, the record row is put into edit mode. While in edit mode, the documents list renderer listens for global clicks. Clicking inside the "Search More..." modal dialog targets elements that have `.o_list_renderer` (since the modal dialog renders a list view). Because the click target is within a list renderer but is not a document row, `DocumentsListRenderer.onGlobalClick` executes and clears the selection of the main list view. Clearing the selection unmounts the edited field in the inspector, thereby destroying the modal dialog stack. Solution: - Modify DocumentsListRenderer.onGlobalClick to scope click handling to the current Documents list renderer. Ignore clicks outside this.root.el, so interactions in nested UI such as Search More... do not clear the main selection and destroy the inspector field. opw-6253360 Forward-Port-Of: odoo/enterprise#126614 Forward-Port-Of: odoo/enterprise#119262
Submitting Australian Single Touch Payroll records without payslips or employees now shows a clear validation message instead of causing an unexpected error. This helps payroll users understand what information is required before sending data to the ATO.
Original PR description
When submitting payroll data to the ATO from an STP record without any payslips or employees, a traceback is raised. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module -…
When submitting payroll data to the ATO from an STP record without any payslips or employees, a traceback is raised. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module - Switch to ``My australian Company`` - Go to Payroll > Configuration > Settings > In Australian Localization, Set BMS ID > Set STP Responsible and his date of birth - Go to Payroll > Reporting > Single Touch Payroll > Create a new record > Set Payment Date > Submit to ATO > Sign & Submit to ATO Traceback: ```py IndexError: tuple index out of range ``` https://github.com/odoo/enterprise/blob/b0e48baaf99bdc4faefd2ffdd3bd5637fb548593/l10n_au_hr_payroll_account/models/l10n_au_stp.py#L228-L233 The traceback occurs because ``_get_fiscal_year_start()`` assumes that the STP record always contains at least one payslip or one employee. When these recordsets are empty, indexing the first element raises an IndexError. Solution: This commit validates that the required payslips or employees are present before the submission and raises a validation error instead of a traceback. Forward-Port-Of: odoo/enterprise#124096
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Original PR description
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
24 changes
Resolved issues and error corrections
Opening Bank Matching from a working file now works even when no bank journal is selected. This prevents an error that interrupted users handling unreconciled bank statement lines and returns.
Original PR description
When accessing the reconciliation widget from the working file check, there is no journal to be selected, hence no journal in the context. This was tracebacking since we were trying to send a read query to the server with an undefined id. To reproduce: * create a bank statement line without reconciling * set up the return on the misc journal * open the return, then "Bank Matching" Forward-Port-Of: odoo/enterprise#127421
This fixes an internal test so it correctly accounts for archived call activity records before deleting an activity type. The change helps prevent false test failures and keeps quality checks stable without affecting day-to-day user functionality.
Original PR description
test_create_call_activity attempts to delete any 'phonecall' activity types. This is so it can test the functionality of create_call_activity when there is no existing 'phonecall' activity type. However, demo data inside voip creates an archived activity with the type mail_activity_data_call. https://github.com/odoo/enterprise/blob/cc4456ac16aeee59830db08505a27877e149f3a7/voip/demo/voip_call.xml#L4-L13 When searching for phonecall_activities the test only gets active activities. We need to alter this to fetch all. Otherwise, the test will then try to delete the activity type when there are still records using the type. opw-6443475 runbot-242850 Forward-Port-Of: odoo/enterprise#126540
Fixes a server error that could occur when users turned the No Follow-Up option on or off for invoices paid in multiple installments. This makes follow-up reporting more reliable when some installments are already settled and others remain open.
Original PR description
Steps to Reproduce: 1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments. 2. Create a Customer Invoice with this Payment Term. 3. Post the invoice.…
Steps to Reproduce:
1. Configure Payment Term (Accounting > Configuration > Payment Terms) containing multiple installments.
2. Create a Customer Invoice with this Payment Term.
3. Post the invoice.
4. Register a payment and fully reconcile one of the installments.
5. Navigate to the customer's Follow-Up Report (Accounting > Reporting > Partner Ledger > Report: Follow-Up Report).
6. Navigate to remaining open installment/account move line for that invoice.
7. Turn On or Off the No Follow-Up toggle for the invoice.
An error occurs when enabling or disabling the No Follow-Up toggle.
Issue:
Enabling or disabling the No Follow-Up toggle on a remaining open installment in the Follow-Up Report raises a server error when the invoice contains multiple installments and one or more installments are already fully reconciled.
Root Cause:
The Follow-Up Report only loads and sends non-fully reconciled account move lines from the JavaScript side through all_line_ids. In action_toggle_no_followup(), when the selected line belongs to an invoice, the code retrieves all receivable/payable lines of the invoice, including fully reconciled installments:
```
move.line_ids.filtered(
lambda line: line.account_type in ('asset_receivable', 'liability_payable'),
)
```
The method then attempts to map every receivable/payable line to a report line ID using aml_id_to_line_id. Since fully reconciled installments are not present in all_line_ids, they are missing from the mapping dictionary, causing a KeyError when accessing:
`aml_id_to_line_id[line.id]
`
Fix:
Restricted the impacted lines to those present in the report by adding a check that the account move line exists in aml_id_to_line_id before performing the mapping:
```
lambda line: line.account_type in ('asset_receivable', 'liability_payable')
and line.id in aml_id_to_line_id
```
opw-6245448
Forward-Port-Of: odoo/enterprise#126785
Forward-Port-Of: odoo/enterprise#126156The Timesheets Assistant now ignores the current user's own email address when matching Gmail emails to customers. This prevents irrelevant task or project suggestions when the user's own contact is listed as a customer.
Original PR description
Before this commit, the Timesheets Assistant resolved every address found in a read or composed email to a partner, then matched the event to a task or project having that partner as its customer. The current user is a recipient of every email they receive, so their own address is present in the "To" or "Cc" fields of every `reading_email` event. As a result, any task whose customer was the current user could be suggested for those emails. This commit excludes the current user's partner from that lookup. task-6438374 Forward-Port-Of: odoo/enterprise#127422 Forward-Port-Of: odoo/enterprise#126448
Shifts for employees with flexible schedules and no fixed start or end times are now included consistently in Planning and Timesheets reports. This prevents planned work from being missing in analysis views, giving managers a more accurate view of allocated time.
Original PR description
## Behavior Before the PR When an employee did not have explicit `hours_from` and `hours_to` values defined, their shift was in the **Schedule by X** pivot view but was not included in the **Planning…
## Behavior Before the PR When an employee did not have explicit `hours_from` and `hours_to` values defined, their shift was in the **Schedule by X** pivot view but was not included in the **Planning / Timesheets Analysis** report. ## Steps to Reproduce 1. Create an employee with a Flexible Working Schedule in the Employee form, or configure working hours where both `Hour from` and `Hour to` are left unset. 2. Add a shift for this employee linked to a project and a task. 3. Publish the shift. 4. Navigate to **Planning → Schedule → By Project**, switch to the pivot view, and observe that the shift created in step 2 appears and is counted. 5. Navigate to **Planning → Reporting → Planning / Timesheets Analysis**, switch to the pivot view, and observe that the same shift does not appear. ## Behavior After the PR When an employee does not have explicit `hours_from` and `hours_to` values, their shift is now considered valid in both the **Schedule by X** views and the **Planning / Timesheets Analysis** report. ## Additional Notes - In earlier versions of Odoo, the `Work From` and `Work To` fields were mandatory. With a change to flexible working schedules and the option to define only the total number of hours per day, these fields may now be left empty. This change exposed the underlying issue addressed by this fix. task-[5969788](https://www.odoo.com/odoo/project/4105/tasks/5969788) Forward-Port-Of: odoo/enterprise#127300 Forward-Port-Of: odoo/enterprise#110606
Users who have both Partner Commissions access and Purchase User access can now create and view purchase orders as expected. This prevents commission-related restrictions from accidentally blocking normal purchasing work, while keeping commission-only users limited appropriately.
Original PR description
## Current behavior: The user Partner Commissions access rights as All Documents or Own Documents and Purchase access rights as User. With this configuration, the user is unable to create new…
## Current behavior: The user Partner Commissions access rights as All Documents or Own Documents and Purchase access rights as User. With this configuration, the user is unable to create new Purchase Orders, and existing Purchase Orders are also not visible in the Purchase module. ## Expected behavior: The expected behavior is that the user should be able to create and view Purchase Orders with these access rights. Additionally, clarification is required regarding the purpose of the new Partner Commissions access group. ## Steps to reproduce: - Go to user and assign Partner Commission rights as All or own document. - On Purchase, select group as User. ## Cause of the issue: partner_commission adds commission-specific purchase order record rules, but purchase users have no matching purchase-order rule in that module. For mixed-role users, the commission rule ends up restricting standard purchase orders as well. ## Fix: Apply the module's explicit all-purchase rule to purchase users so mixed users keep base procurement access while commission-only users remain restricted by the commission rules. opw-6366074 Forward-Port-Of: odoo/enterprise#127188 Forward-Port-Of: odoo/enterprise#126003
Products created through Barcode Lookup now correctly show the image returned by the service. This helps users verify newly created products visually and avoids manual image updates after scanning or entering barcodes.
Original PR description
Issue before this commit: ========================= When creating a product by adding a barcode using the Barcode Lookup service, the product image was fetched properly but was not displayed in the…
Issue before this commit: ========================= When creating a product by adding a barcode using the Barcode Lookup service, the product image was fetched properly but was not displayed in the UI. Steps to Reproduce: ========================= - Install the stock module. - Enable the Stock Barcode Database. - Add a valid API key for the Barcode Database. - Create a product by adding a barcode available in the Barcode Lookup API. - Notice that the product image is not displayed. Cause of the issue: ========================= This issue was introduced by this [PR](https://github.com/odoo/odoo/pull/244421), which improved the behaviour of **fields.Binary**. As a result, the image returned by the Barcode Lookup API was not converted to the expected binary format, preventing it from being displayed in the UI. With This Commit: ========================= With this commit, convert the fetched image to the expected binary format before assigning it to the product, ensuring that it is displayed correctly in the UI. opw-6434478 Forward-Port-Of: odoo/enterprise#126314
This update fixes a payroll-related issue by removing outdated or unnecessary behavior covered by the payroll run test flow. It helps keep payroll processes reliable and reduces the chance of confusion from obsolete steps.
Original PR description
task-6455499
A spreadsheet sharing update was incorrectly running during every page load, sometimes disrupting navigation state in other parts of Odoo. This fix limits that behavior to spreadsheet pages only, reducing unexpected page navigation issues.
Original PR description
BUG:
To make make spreadsheet backend shareabable, a patch to the router was done, and ran on *every* page load. The code looks harmless (it already had a `if (pathParts.at(-2) !== "spreadsheet")` early return, but because of the implementation of replaceState, this we had global impact regardless.
Indeed the real problem is that `router.replaceState` routes through doPush(), which replaces `history.state` disregarding the previous history completly (with a debounce, explaining the indeterminism)
In our case the builder stored `{skipRouteChange: true}` in `history.state` which was sometimes wiped by the `replaceState` debounce
FIX:
As a quick fix (JPP is on holidays), we amend the code to make spreadsheet shareable only run if the targetted app is spreadsheet
runbot-error: https://runbot.odoo.com/odoo/error/945518
breaking PR: https://github.com/odoo/enterprise/pull/114484This fix ensures vendor price list entries always include a unit of measure, preventing incomplete purchasing data. It helps avoid downstream errors or confusion when products are planned, ordered, or priced using supplier information.
Several older icon references were replaced with their supported Material Symbols equivalents across affected apps. This prevents icons from disappearing when the legacy compatibility layer is removed and keeps the product aligned with current quality checks.
Original PR description
__Problem__ A few `fa`/`fa-*` icons survived the migration to Material Symbols. They still render today thanks to the compatibility mapping between the two sets, but will stop doing so once it is removed. They are also caught by the new `test_lint` icons check. __Quick fix__ Replace them by their Material Symbols equivalent, set through the `data-icon` attribute, the sizing and filling classes being kept through their `oi` counterparts (`fa-lg` → `oi-lg`, `fa-fw` → `oi-fw`, ...). Community PR: odoo/odoo#279361
Preparation tickets in self-ordering now follow the language set for the default self-order user. This helps kitchen or preparation staff receive tickets in the expected language, reducing confusion in multilingual setups.
Original PR description
Before this commit the preparation ticket wasn't using the lang of the default pos_self_order user. Now it will use it. Forward-Port-Of: odoo/enterprise#127113 Forward-Port-Of: odoo/enterprise#126903
A spreadsheet sharing update was unintentionally affecting navigation data across the system on every page load. This fix limits that behavior to spreadsheet pages only, reducing unexpected navigation issues in other apps.
Original PR description
BUG:
To make make spreadsheet backend shareabable, a patch to the router was done, and ran on *every* page load. The code looks harmless (it already had a `if (pathParts.at(-2) !== "spreadsheet")` early return, but because of the implementation of replaceState, this we had global impact regardless.
Indeed the real problem is that `router.replaceState` routes through doPush(), which replaces `history.state` disregarding the previous history completly (with a debounce, explaining the indeterminism)
In our case the builder stored `{skipRouteChange: true}` in `history.state` which was sometimes wiped by the `replaceState` debounce
FIX:
As a quick fix (JPP is on holidays), we amend the code to make spreadsheet shareable only run if the targetted app is spreadsheet
runbot-error: https://runbot.odoo.com/odoo/error/945518
breaking PR: https://github.com/odoo/enterprise/pull/114484The payroll validation flow now correctly opens any required follow-up step, such as a wizard for missing employee information. This prevents the Validate button from appearing unresponsive and helps users understand what needs to be fixed before completing a payslip.
Original PR description
action_validate() called action_payslip_done() without returning its result. When action_payslip_done() returns a client action (e.g. a wizard to fix missing employee data instead of raising), that action was lost and the Validate button appeared to do nothing, with no error or warning shown. task-6373549
Generating public holidays now works consistently outside Belgium by applying the same automatic public holiday time type behavior to all localizations. This prevents errors when users load public holidays and improves the out-of-the-box payroll experience.
Original PR description
Purpose: generating Public Holidays fails with an error on all localizations except Belgium, preventing users from loading public holidays. This is because the Belgium localization includes a dedicated Public Holiday time type, which is automatically selected when creating public holidays. Extending this behavior to all localizations will make the feature work out of the box and provide a consistent user experience. - removed the inheritance for `load.public.holiday.wizard.line` as it's implemented generally in `hr_holidays` task-id: 6448261
Creating an employee in Belgian payroll with a subtype but no active contract no longer triggers an error. This prevents interruptions during employee setup and makes public holiday allocation handling more reliable.
Original PR description
Step to reproduce: -> Go to employee -> Create an employee with a sub type but without a running contract You will have a traceback Reason: We will take the minimum start date between all versions but version without contract date start are not supported. task-6455669
Payroll users can now send several payslips to off-cycle processing at once without encountering an error. This makes bulk payroll corrections smoother and avoids interruptions when working from the payslip list.
Original PR description
Steps to reproduce: - Open payslip list view - Select multiple payslips - Select "Send to Off-cycle" action Issue: A traceback occurs with ValueError: Expected singleton when the action is executed on multiple payslips. Reason: - 'action_move_to_off_cycle()' assumes a singleton and directly accesses self.version_id.id - When multiple payslips are selected from list view then self contains several payslips and self.version_id returns multiple versions, causing the singleton error. Solution: - Iterate over each payslip individually when processing the off-cycle action and use the corresponding version for each record, allowing the action to work correctly in multi-record mode task-6320059 Forward-Port-Of: odoo/enterprise#125284
Spreadsheet sharing logic now only runs when users are actually opening a spreadsheet. This prevents unrelated pages from losing navigation state, reducing intermittent page behavior and improving reliability across the app.
Original PR description
BUG:
To make make spreadsheet backend shareabable, a patch to the router was done, and ran on *every* page load. The code looks harmless (it already had a `if (pathParts.at(-2) !== "spreadsheet")` early return, but because of the implementation of replaceState, this we had global impact regardless.
Indeed the real problem is that `router.replaceState` routes through doPush(), which replaces `history.state` disregarding the previous history completly (with a debounce, explaining the indeterminism)
In our case the builder stored `{skipRouteChange: true}` in `history.state` which was sometimes wiped by the `replaceState` debounce
FIX:
As a quick fix (JPP is on holidays), we amend the code to make spreadsheet shareable only run if the targetted app is spreadsheet
runbot-error: https://runbot.odoo.com/odoo/error/945518
breaking PR: https://github.com/odoo/enterprise/pull/114484This fix prevents access errors when displaying salary offer details that depend on payroll information. It also updates the salary configurator test flow to reflect use by an HR user rather than an administrator, helping ensure the feature works for normal HR staff.
Original PR description
A field displayed inside the offer should have been computed with sudo as it accesses some payroll field to compute. Also, the salary configurator tour has been adapted to use a HR user instead of an admin Forward-Port-Of: odoo/enterprise#127510
A new test verifies that India GSTR-1 reporting selects the correct tax rate group when GST and CESS taxes are combined. This helps reduce the risk of incorrect tax reporting for Indian businesses using these tax combinations.
Original PR description
This PR adds a test case to ensure that the correct tax rate group is selected in the GSTR-1 report when a combination of GST and CESS taxes is used. Community PR - https://github.com/odoo/odoo/pull/280571 Forward-Port-Of: odoo/enterprise#126770
This fix prevents users in multi-company setups from hitting an unavoidable error when creating quality-related operation steps. It ensures the default quality team works correctly with the current company, reducing blocked manufacturing or quality workflows.
Original PR description
This commit actually reverts [1] and manually forwards [2]. Suppose `mrp_workorder` installed and `quality_control` uninstalled. Because of the default value provided by [1], the only existing quality team is linked to the first company. As a result, when using another company, if the user tries to create an operation step (i.e., a QCP), it will raise an error when the onchange tries to load the default team in charge: https://github.com/odoo/enterprise/blob/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e/quality/models/quality.py#L141-L142 However, the `quality` module doesn't provide any view to create such a team. tldr The module raises an error that is actually impossible to solve... Let's avoid it in the above situation. [1] https://github.com/odoo/enterprise/commit/f9c99f937bd64e5a0acb4bc88b1fc08249250c4e [2] https://github.com/odoo/enterprise/commit/8cd5c9322bef7db49a90d4aef844dd0ba267058e Forward-Port-Of: odoo/enterprise#127438 Forward-Port-Of: odoo/enterprise#126364
This update restores previous Studio behavior after a recent change caused runtime crashes. It keeps the intended flexibility for an optional setting while improving stability for users editing views in Studio.
Original PR description
This commit mostly reverts the commit d9d90bfd6805355909faa28dadb249c88317c2b9 which caused crashes at runtime while keeping the main fix (keeping the prop optional).
The point of sale now correctly blocks payment when an order contains only deleted items. This prevents staff from completing empty orders with no payment and issuing blank receipts.
Original PR description
The payment screen could still be accessed even if the order only contained deleted (struck through) order lines. The user can then complete the order with no payment and an empty receipt. This commit fixes the issue by updating the `isEmpty` function on the order to take the deleted lines into account.
This fixes Mexican payroll payslip CFDIs so their SAT validation status is properly checked and shown in Odoo. Businesses will now see the correct tax authority status instead of an undefined value, improving payroll compliance visibility.
Original PR description
l10n_mx_hr_payroll_account_edi introduces new l10n_mx_edi.document states (payslip_sent, payslip_sent_failed, payslip_cancel, payslip_cancel_failed) but never extends the two hooks the base l10n_mx_edi module relies on to keep sat_state in sync: - _get_update_sat_status_domains(), which builds the domain used by the SAT-status cron (and manual refresh) to pick documents to poll. Payslip states were missing from it, so their SAT status was never fetched at all. - _update_document_sat_state(), which routes a fetched SAT status to a per-source-document handler. It has no branch for the payslip states, so even a manual poll would silently do nothing. As a result, payslip CFDIs validated in the SAT always appeared as "not_defined" in Odoo. opw-6192651 Forward-Port-Of: odoo/enterprise#126294 Forward-Port-Of: odoo/enterprise#124006
10 changes
Resolved issues and error corrections
Australian payroll now correctly matches unused leave balances to the employee on each payslip. This helps ensure termination or leave-related payouts are not missed when payroll is processed for multiple employees at once.
Original PR description
`_l10n_au_get_unused_leave_by_type` compared leave allocations to `self.employee_id` while looping payslips. On a multi-recordset that is the whole employee set, so the match never holds and unused leave is skipped. Use `payslip.employee_id` so each payslip keeps its own allocations. task-6458480
French VAT reimbursement declaration 3519 now includes the bank account holder name in the account information section. This helps meet the required declaration details and reduces the risk of reimbursement submissions being rejected or incomplete.
Original PR description
For reimbursement declarations, the name of the holder of the account is required This commits adds holder's name to the account data zone no-task-id Forward-Port-Of: odoo/enterprise#127554
This fixes an internal module dependency so the Belgian POS Blackbox HR integration loads the correct related component. It helps prevent installation or automated test failures without changing day-to-day point-of-sale behavior.
Original PR description
Before this commit, the dependency of the module l10n_be_pos_blackbox_hr_pos_blackbox_be was set to pos_hr, which is not totally correct. The correct dependency should be l10n_be_pos_blackbox_hr. runbot-error: 941561
This fix improves how time-off intervals are calculated for employees using duration-based work schedules. It helps ensure the Gantt planning view shows leave durations correctly, reducing confusion for managers and HR teams.
Original PR description
task-id: 6460078
When warehouse staff scan multiple lot numbers during a receipt, new lot lines now keep the putaway destination already assigned by the receipt. This prevents items from appearing in the wrong stock location and keeps barcode receiving aligned with warehouse putaway rules.
Original PR description
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2…
Steps to reproduce --- 1. Enable Storage Locations and Lots & Serial Numbers. 2. Add a putaway rule sending a lot-tracked product from WH/Stock to WH/Stock/Shelf 1. 3. Confirm a receipt reserving 2 units of that product; putaway sets the reserved move line destination to WH/Stock/Shelf 1. 4. In the Barcode app, scan a first lot, then a second lot. The second lot lands on a separate line at WH/Stock instead of WH/Stock/Shelf 1. Issue --- The first lot reuses the reserved line and keeps its Shelf 1 destination. The second lot cannot reuse it because its tracking number differs, so `_findLine` returns nothing and `_getNewLineDefaultValues` builds a new line with `location_dest_id` set to `_defaultDestLocation()`, the picking's default destination (WH/Stock). https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L1591-L1601 Putaway relocates the destination on the move line at reservation, never on the picking, so only the reserved line carries Shelf 1. Since `groupKey` includes `location_dest_id`, the new line does not group with the first lot and shows separately at WH/Stock. This is not a regression: new lines have always defaulted to the operation destination. https://github.com/odoo/enterprise/blob/314a79b774f30dc9377b2971492576c4b84483e1/stock_barcode/static/src/models/barcode_picking_model.js#L239-L241 The new line now inherits the selected line's `location_dest_id`, already relocated by putaway, instead of the default. opw-6317077
This pull request combines several business-facing fixes and improvements across Odoo Enterprise, including cleaner tax return screens, corrected rental availability checks, restored POS preparation ticket printing, and more accurate localized accounting reports. It also adds Romania's D390 EC Sales report support, helping Romanian companies meet electronic tax filing requirements.
Account transfer journal entries now stay balanced when destination percentages are below 100%. This prevents one-cent discrepancies caused by rounding across multiple source accounts, reducing posting errors and manual correction needs.
Original PR description
Before this commit, _get_transfer_move_lines_values computed the amount for the last destination line from the global transferred balance, instead of reusing the amount already removed from the source accounts. The two values are rounded independently and can differ by a cent whenever the removed amount comes from more than one rounded source, producing an unbalanced journal entry. Removing that condition the last destination line always absorbs the remainder fixes it. Steps to reproduce: 1. Transfer model with 2 source accounts and 1 destination line at 15%. 2. Post moves for the period: account A balance 395.88, account B balance 252.16 (total 648.04). 3. Run `action_perform_auto_transfer()`. Before: source lines -59.38 (395.88 * 15%) and -37.82 (252.16 * 15%), destination line +97.21 (648.04*15% rounded) -> entry off by 0.01. After: destination line takes the exact remainder, 97.20 -> balanced. OPW-6443928
The Helpdesk Stock workflow now keeps the Replace button visible even when no customer has been selected. This makes the ticket interface more consistent with related actions and reduces confusion for support teams handling stock replacements.
Original PR description
Adjust the `invisible` condition to make the button visible even if no customer is selected, for consistency with other buttons --- task-6103996
This fix prevents Swiss payroll settings from assigning a Swiss contract type to employees or environments that are not Swiss. It avoids test failures and helps ensure payroll contract defaults stay appropriate for the employee context.
Original PR description
[FIX] l10n_ch: fix default contract type This task is runbot error fix that occured from 19.0 to 19.2 Bug reproduction: 1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute…
[FIX] l10n_ch: fix default contract type
This task is runbot error fix that occured from 19.0 to 19.2
Bug reproduction:
1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute test_version_timeline_auto_save_tour tour test 3 - It fails in .o_arrow_button_wrapper[data-tooltip^='Contract:'] step
Bug cause:
1 - When l10n_ch_hr_payroll_account is installed:
1.1 - contract type becomes "Permanent contract with monthly salary"
1.2 - the employee is not swiss but it has this CH contract type
2 - data-tooltip starts with Permanent contract instead of contract
2.1 - Tour fails
3 - contract_type_id is overwritten in swiss modules
3.1 - Default is assigned without looking to the country of self.env
Bug solution:
1 - If the country is not swiss, the default is assigned as False
1.1 -> fixed in l10n_ch_hr_payroll/hr_version
1.2 instead of assigning swiss contract type to the non-swiss emp.
Note: This is fix from saas-18.4 to master.
task-6392040
runbot error: https://runbot.odoo.com/odoo/runbot.build.error/941358
Forward-Port-Of: odoo/enterprise#126520An accounting test was updated to align with a related platform fix in how grouped data is read. This helps keep automated checks accurate and reduces the risk of false test failures during accounting development.
Original PR description
The fix at https://github.com/odoo/odoo/pull/281911 adds bin_size: tru in the web_read_group. This commit adpats an accounting test as a consequence
3 changes
Resolved issues and error corrections
Fixed an issue where exporting the Deferred Revenue Report to XLSX could fail when the report included annotations. This helps accounting users reliably export annotated reports without encountering a server error.
Original PR description
**Steps to reproduce:** * Install the **Accounting** module. * Unhide the **Start Date** and **End Date** fields on invoice lines. * Create and post a customer invoice with deferred dates. * Go to…
**Steps to reproduce:** * Install the **Accounting** module. * Unhide the **Start Date** and **End Date** fields on invoice lines. * Create and post a customer invoice with deferred dates. * Go to **Accounting → Reports → Deferred Revenue Report**. * Add an annotation to a deferred revenue line by clicking the **annotate** from three dots next to the account. * Export the report in **XLSX** format. **Observed behavior:** * The export fails with a server error: `UnboundLocalError: cannot access local variable 'annotations_x_offset' where it is not associated with a value` **Cause:** * The variable `annotations_x_offset` is assigned inside the `for header_level_index, header_level in enumerate(options['column_headers'])` loop, which writes the "Annotations" column header for each header level. * The Deferred Revenue Report produces an empty `column_headers` list, so the loop body never executes and `annotations_x_offset` is never assigned. * When the code later tries to write annotation data for each report line, it references the unassigned variable, causing Python to raise `UnboundLocalError`. **Fix:** * Introduce a boolean flag `annotations_header_written = False` before the header loop to explicitly track whether the "Annotations" column header has already been written. * Inside the header loop, set `annotations_header_written = True` after writing the header. * After writing all individual column headers (where `x_offset` already points to the first free column after all data columns), add a fallback: if `report_annotations` is set but `annotations_header_written` is still `False`, assign `annotations_x_offset` from the current `x_offset` and write the "Annotations" header. opw-6354473
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
Original PR description
The selection options for l10n_id_coretax_add_info_07/08 and l10n_id_coretax_facility_info_07 were swapped: the "additional information" fields showed facility stamp text and vice versa. Also add the UoM codes and new kode faktur 07 additional info/facility stamp options published by DJP on 2026-01-26. task-6434742 Forward-Port-Of: odoo/odoo#281096
test fix task-6233756 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
test fix task-6233756 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
1 change
Resolved issues and error corrections
This fix prevents Swiss payroll settings from automatically assigning a Swiss contract type to employees outside Switzerland. It avoids incorrect contract labels and helps keep automated HR/payroll checks reliable across localized setups.
Original PR description
[FIX] l10n_ch: fix default contract type This task is runbot error fix that occured from 19.0 to 19.2 Bug reproduction: 1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute…
[FIX] l10n_ch: fix default contract type
This task is runbot error fix that occured from 19.0 to 19.2
Bug reproduction:
1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute test_version_timeline_auto_save_tour tour test 3 - It fails in .o_arrow_button_wrapper[data-tooltip^='Contract:'] step
Bug cause:
1 - When l10n_ch_hr_payroll_account is installed:
1.1 - contract type becomes "Permanent contract with monthly salary"
1.2 - the employee is not swiss but it has this CH contract type
2 - data-tooltip starts with Permanent contract instead of contract
2.1 - Tour fails
3 - contract_type_id is overwritten in swiss modules
3.1 - Default is assigned without looking to the country of self.env
Bug solution:
1 - If the country is not swiss, the default is assigned as False
1.1 instead of assigning swiss contract type to the non-swiss emp.
Note: I started to fix it from 17.0 BUT:
. in above versions field overwrite might be in different CH modules . fix all in the above versions
task-6392040
runbot error: https://runbot.odoo.com/odoo/runbot.build.error/941358