Daily updates from Odoo
Wednesday, July 29, 2026
235 changes
21 changes
Enhancements to existing features
TikTok Shop configuration is now found under the new Marketplaces menu. This makes marketplace-related setup easier to find and keeps sales channel settings better organized.
Original PR description
- Move tiktok shop configuration to the new 'Marketplaces' menu PR Ref: https://github.com/odoo/enterprise/pull/113307
Users who try to create an expense card before Stripe is connected are now directed to the relevant settings page. This helps them complete the required setup faster and reduces confusion when card creation cannot proceed.
Original PR description
When a user tries to create a card but the configuration is not connected, redirect the user towards the settings to do the connection. task-6272805 Forward-Port-Of: odoo/enterprise#125113
Resolved issues and error corrections
Sales order information in planning slot forms is now shown correctly for companies using a single-company setup. This prevents important sales links from being accidentally hidden and helps users manage planning work consistently across company configurations.
Original PR description
The `sale_line_id` field was previously injected after `company_id`. Because the first instance of `company_id` in the base view is wrapped inside a `<t groups="base.group_multi_company">` block, the inserted fields were inadvertently hidden in single-company databases. This commit changes the XPath target to `role_id` to ensure the sales order fields are always visible in the planning slot form view, regardless of multi-company settings. task: 6398673 Forward-Port-Of: odoo/enterprise#125712
Vietnam Sales Tax Report details now show VAT base amounts with the same positive sign as the report totals. This removes confusing negative values in unfolded invoice details and helps users review Vietnamese VAT reports more reliably.
Original PR description
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should…
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should be consistent with the upper layers and kept positive ## Steps to reproduce: - Install l10n_vn (l10n_vn_reports will install as well) - Switch to VN Company - With demo data, go to Invoicing / Reporting / Tax Report - Change Tax Report (VN) to Sales/Purchase Tax Report (VN) - Unfold the lines all the way to the minimum layer: VAT on sales of goods and services 10% -> INV/2026/00003 - Observe that the VAT 10% line is at negative, which is inconsistent with the Total line below ## Cause of the issue: - In Odoo, tax journal items store tax_base_amount with the accounting sign (negative for sales). This is expected behavior - However, Vietnamese VAT listing expects commercial amounts, which means sales bases need to be displayed as positive numbers ## Fix: Normalized tax_base_amount sign in _query_tax_lines function before building the SQL query opw-6344577 Forward-Port-Of: odoo/enterprise#125257 Forward-Port-Of: odoo/enterprise#122785
The Australian payroll scheduled update now refreshes payroll rule category data before updating salary rules. This prevents errors when previously deleted categories are needed again, helping payroll maintenance run reliably.
Original PR description
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to…
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to `Payroll` > `Configuration` > `Salary` > `Rule Categories`. - Delete all records related to the `Australian Company`. - Go to `Scheduled Actions` and run `Payroll: Update Data`. `ValueError: External ID not found in the system: l10n_au_hr_payroll.rule_category_ote` After [this commit], the category_id field becomes non-required, allowing users to delete a rule category record even if it is linked to a salary rule. When updating the data file [1], an error is raised due to the missing rule category. This commit ensures that when updating the salary rule data, it updates the category data beforehand as like [here] [this commit]: https://github.com/odoo/enterprise/commit/c663fd2a81b7f6b34f8199fdbdc4a75c4f21379e [1] https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_au_hr_payroll/models/hr_payslip.py#L76-L83 [here]: https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_ch_hr_payroll/models/hr_payslip.py#L1074-L1087 sentry-7349905716 Forward-Port-Of: odoo/enterprise#121167
The timesheet timer now automatically returns focus to the description field after saving or resetting an entry. This removes an extra click for users entering multiple timesheets in a row and keeps time entry faster and smoother.
Original PR description
Steps to reproduce: - Install the timesheets application. - Open the timesheet timer menu from the systray. - Fill out the new timesheet entry. - Click the 'Save' or 'Reset' button (or use the keyboard hotkey). - Notice that the cursor focus is lost and the user must manually click back into the description field to start a new entry. Cause: - When a user clicks save or reset, the existing form is cleared via a DOM patch. Because the component is not remounted, the initial onMounted focus logic does not execute again. Fix: - Use onPatched to check if the save or discard button is the active element, and automatically re-focus the description input. task-6357438 Forward-Port-Of: odoo/enterprise#123697
Fixes an issue where the Planning Gantt view could crash when users grouped shifts by role if a role had no assigned resource or no working schedule. This keeps planning views usable in edge cases and prevents disruption when reviewing schedules by role.
Original PR description
Currently, an error occurs when grouping planning slots by role. **Steps to Reproduce:** - Install the `Planning` module. - Go to `Planning` > `Configuration` > `Roles`. - Create a `role` without…
Currently, an error occurs when grouping planning slots by role.
**Steps to Reproduce:**
- Install the `Planning` module.
- Go to `Planning` > `Configuration` > `Roles`.
- Create a `role` without assigning any resource to it (or assign a resource without a working time).
- Go to `Planning`, create a new `planning slot`, assign the `role` created above, set the start date to `20/07/2026 12:00 PM` and the end date to `21/07/2026 2:00 AM`.
- Switch to the `Gantt view` of the `planning slots`.
- Group by `Role` and set the custom date range to `07/19/2026 -> 07/20/2026`, then click `Apply`.
`KeyError: 1`
The error occurs when the user groups the planning slots by role in the Gantt view. During
the computation of the Gantt progress bar, if the existing slot's role has no resource, or has
a flexible resource without a calendar, the regular resources become empty [1]. Then it
attempts to compute the valid work intervals for these empty resources [2], resulting in an
empty calendar work interval dictionary ({}) [3]. Later, when computing the duration over the
period with the valid range slots, it tries to access the resource directly from the empty
calendar_intervals dictionary [4], which raises the error.
This commit ensures that, when no work intervals are available for a resource, an empty
work interval is used instead.
[1]- https://github.com/odoo/enterprise/blob/3871b75fb74a7b35bfea9610ca08b853eb723320/planning/models/planning_slot.py#L307
[2]: https://github.com/odoo/odoo/blob/5663509fe5caa1191fafcea3b3879dcef9ceca8f/addons/resource/models/resource_resource.py#L220
[3]: https://github.com/odoo/enterprise/blob/3871b75fb74a7b35bfea9610ca08b853eb723320/planning/models/planning_slot.py#L3415-L3417
[4]- https://github.com/odoo/enterprise/blob/3871b75fb74a7b35bfea9610ca08b853eb723320/planning/models/planning_slot.py#L3300
sentry-7620222164
Forward-Port-Of: odoo/enterprise#124991Draft invoices no longer show the vehicle field on invoice lines as a clickable link. This prevents users from opening or acting on related vehicle records before the invoice is officially posted, keeping behavior consistent with product links.
Original PR description
The vehicle under account on the invoice lines should not be clickable when the invoice is in draft. Only when it is posted, like the product. task-6385436 Forward-Port-Of: odoo/enterprise#125688 Forward-Port-Of: odoo/enterprise#124514
Chilean invoice PDFs now show the legally required CEDIBLE disclaimer in Spanish regardless of the customer's language settings. This prevents incorrect English text from appearing on official Chilean tax documents and supports compliance with local requirements.
Original PR description
Steps to reproduce: - Set the database language to Spanish (Latin America). - Create a customer invoice, confirm it and send it to the SII. - Print it using Print > Invoice PDF copy (Chile). - Scroll…
Steps to reproduce:
- Set the database language to Spanish (Latin America).
- Create a customer invoice, confirm it and send it to the SII.
- Print it using Print > Invoice PDF copy (Chile).
- Scroll to the CEDIBLE section at the bottom of the PDF.
Cause of the issue:
The CEDIBLE footer is merged into l10n_cl.report_invoice_document, which account.report_invoice (odoo/addons/l10n_cl/views/report_invoice.xml) renders with t-lang set to the invoice partner's lang, not the database/user language. The disclaimer text was hardcoded in English and relied on the regular translation to be shown in Spanish, so as
soon as the partner's lang field isn't Spanish, the translation lookup falls back to the untranslated English source, regardless of the database language.
Solution:
This disclaimer is boilerplate mandated by Chilean law: it must always be printed in Spanish, independently of the invoice partner's or current user's language. The same template already follows that rule a few lines above for the SII stamp block ("Timbre Electrónico SII..."), which is hardcoded in Spanish instead of relying on translation.
opw-6390207
Forward-Port-Of: odoo/enterprise#124916This fix improves how Belgian payroll notification files are analyzed, helping prevent errors during payroll declaration handling. It supports more reliable processing for Belgian HR payroll workflows without changing the user-facing process.
Original PR description
Forward-Port-Of: odoo/enterprise#125500
Sales commission achievement records with very large identifiers can now be opened correctly. This prevents users from seeing an incorrect “record does not exist” message when accessing affected achievement reports.
Original PR description
Steps to reproduce: - Open an achievement with id > JS limit Issues: - We get a pop-up saying the record does not exists The reason we get this error is because since we are browsing a record with an id greater than JS limit the browser truncate it. In order to solve this issue the following PR was made #108751. A field `id_str` was added but it still wasn't working as we weren't retrieving the `id_str`. We now do this by passing `id_str` in the context and retrieving it on the `web_read`. Forward-Port-Of: odoo/enterprise#123757 Forward-Port-Of: odoo/enterprise#113701
This fix prevents Swiss payroll pension fund numbers from being included where they are not expected during BVG-LPP status checks. It helps avoid incorrect declaration handling and supports smoother Swiss payroll compliance processing.
Original PR description
Forward-Port-Of: odoo/enterprise#126040
Swiss employee payslips now show the actual contract withdrawal date instead of a related version end date. This avoids incorrect termination dates appearing on payroll reports when those dates differ.
Original PR description
The Withdrawal Date in the payslip of CH employees was printing the date_end relative to the version related to the payslip. Instead, it should print the end of the contract of that version, since they can be different. The end date of the contract is in l10n_ch_withdrawal. Task: 6398291 Forward-Port-Of: odoo/enterprise#124848
### Issue before the commit: During the import of Italian e-invoices, Pension Fund taxes (Cassa Previdenziale) linked to a 0% VAT rate with a specific exemption reason (Natura, e.g., N2.2) are ignored and not applied to the invoice lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to vendor -> bills and import the bill in the ticket 3. Check that taxes are not imported as expected ### Cause of the issue: The system incorrectly used the Natura to search
Original PR description
### Issue before the commit: During the import of Italian e-invoices, Pension Fund taxes (Cassa Previdenziale) linked to a 0% VAT rate with a specific exemption reason (Natura, e.g., N2.2) are ignored and not applied to the invoice lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Go to vendor -> bills and import the bill in the ticket 3. Check that taxes are not imported as expected ### Cause of the issue: The system incorrectly used the Natura to search for the Pension Fund tax itself. Fiscally, the Natura belongs to the related VAT, not the Pension Fund. This incorrect domain caused the tax search to fail. The Pension Fund tax should not have a Natura setted. ### Reason to introduce the fix: To correctly apply Pension Fund taxes to exempt invoice lines. Ticket [link](https://www.odoo.com/odoo/project.task/6357133) opw-6357133 Forward-Port-Of: odoo/odoo#278704 Forward-Port-Of: odoo/odoo#275317
[1] added a bus channel for discuss categories. This can be done with or without any token. When the token is not passed, `verify_limited_field_access_token` is still called and crashes. When no token is provided, we should use category access rights instead and avoir verifying the token (which is `None`). [1]: https://github.com/odoo/odoo/pull/243131 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: ---
Original PR description
[1] added a bus channel for discuss categories. This can be done with or without any token. When the token is not passed, `verify_limited_field_access_token` is still called and crashes. When no token is provided, we should use category access rights instead and avoir verifying the token (which is `None`). [1]: https://github.com/odoo/odoo/pull/243131 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#277085 Forward-Port-Of: odoo/odoo#276931
Steps to Reproduce: - Go to Settings > Translations > Languages and select your active language. - Change the Time Format to a 13:00:00 (24-hour) - Click on the Attendance systray icon in the top navbar and Check In. - Notice that the recorded time still displays in a 12-hour format. Cause: - The attendance popup doesn't enforce a strict 12-hour or 24-hour rule. Because of this missing rule, your web browser just uses your computer's default time settings. As a result, Odoo's actual
Original PR description
Steps to Reproduce: - Go to Settings > Translations > Languages and select your active language. - Change the Time Format to a 13:00:00 (24-hour) - Click on the Attendance systray icon in the top…
Steps to Reproduce:
- Go to Settings > Translations > Languages and select your active language.
- Change the Time Format to a 13:00:00 (24-hour)
- Click on the Attendance systray icon in the top navbar and Check In.
- Notice that the recorded time still displays in a 12-hour format.
Cause:
- The attendance popup doesn't enforce a strict 12-hour or 24-hour rule. Because of this missing rule, your web browser just uses your computer's default time settings. As a result, Odoo's actual language and time settings are completely ignored.
Fix:
- Replaced the browser-based formatting with the existing formatting utilities.
- Used is24HourFormat() to determine whether the active time format uses a 12-hour or 24-hour clock.
Solution:
- Dynamically selected the display format using:
- HH:mm for 24-hour format
- hh:mm a for 12-hour format
- Applied the selected format consistently for both check-in and check-out times so the systray now correctly follows the configured language time format.
task-6120540
Forward-Port-Of: odoo/odoo#259918Steps to reproduce: - Open tasks from any project or open a task form, go to the Blocked By tab, and click Add a line to open the task selection view. - Apply the `Templates` filter - Observe that non-template tasks and tasks from template projects are also shown. Cause: - The domain condition checks for `default_project_id` and falls back to `Domain.TRUE`, allowing non-template tasks and tasks from template projects to bypass template-specific filtering. Fix: - Remove the `default_p
Original PR description
Steps to reproduce: - Open tasks from any project or open a task form, go to the Blocked By tab, and click Add a line to open the task selection view. - Apply the `Templates` filter - Observe that non-template tasks and tasks from template projects are also shown. Cause: - The domain condition checks for `default_project_id` and falls back to `Domain.TRUE`, allowing non-template tasks and tasks from template projects to bypass template-specific filtering. Fix: - Remove the `default_project_id` condition and enforce only `has_template_ancestor = True` in the domain, ensuring that only actual template tasks are shown. task-5966601 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277379 Forward-Port-Of: odoo/odoo#260624
When a product uses automated inventory valuation, scrapping it from an already validated (done) picking generated no inventory valuation journal entry, even though the stock move value and the on-hand quantity were correctly updated. The same scrap done from the Scrap menu, or from a picking that is not done yet, worked as expected. A stock move whose picking is already done is created directly in the 'done' state (stock.move.create). Such a move is filtered out of the recordset returned by
Original PR description
When a product uses automated inventory valuation, scrapping it from an already validated (done) picking generated no inventory valuation journal entry, even though the stock move value and the on-hand quantity were correctly updated. The same scrap done from the Scrap menu, or from a picking that is not done yet, worked as expected. A stock move whose picking is already done is created directly in the 'done' state (stock.move.create). Such a move is filtered out of the recordset returned by _action_done(), on which _create_account_move() is called, so the scrap move never received its journal entry. Steps to reproduce: - Use a storable product with automated inventory valuation - Create and validate a receipt for it - Open the completed picking, click Scrap, set a quantity and validate it - The stock is reduced but no journal entry is created. opw-6368258 Forward-Port-Of: odoo/odoo#278210 Forward-Port-Of: odoo/odoo#275847
Steps to reproduce: - Install the `l10n_br` module. - Go to Portal > Addresses > Add Address > select Brazil as the country. (Do not change the company's country to Brazil) Issue: - The address layout is broken: the Street input has no label and `Steet and Number` field is missing. Cause: - The `o_extended_address` elements are not rendered when the company country is not Brazil. When the user selects Brazil, `_setVisibility` looks for `o_extended_address` elements but finds none, s
Original PR description
Steps to reproduce: - Install the `l10n_br` module. - Go to Portal > Addresses > Add Address > select Brazil as the country. (Do not change the company's country to Brazil) Issue: - The address layout is broken: the Street input has no label and `Steet and Number` field is missing. Cause: - The `o_extended_address` elements are not rendered when the company country is not Brazil. When the user selects Brazil, `_setVisibility` looks for `o_extended_address` elements but finds none, so it fails to make the standard address fields visible. Fix: - Restore the company country condition in JS so `o_standard_address` is not hidden when no `o_extended_address` elements are rendered. Forward-Port-Of: odoo/odoo#278008
The mock server was computing the reaction sequence with `Math.min(reactionGroup.map(...))` instead of `Math.min(...reactionGroup.map(...))`. This returned `NaN`, making the sort order non-deterministic and causing the 'Reactions are ordered by id' test to be flaky. Fixes runbot error https://runbot.odoo.com/odoo/error/944188 Forward-Port-Of: odoo/odoo#278895
Original PR description
The mock server was computing the reaction sequence with `Math.min(reactionGroup.map(...))` instead of `Math.min(...reactionGroup.map(...))`. This returned `NaN`, making the sort order non-deterministic and causing the 'Reactions are ordered by id' test to be flaky. Fixes runbot error https://runbot.odoo.com/odoo/error/944188 Forward-Port-Of: odoo/odoo#278895
Miscellaneous changes
Deleting `loyalty.card` records causes severe performance bottlenecks due to a sequential scan during the foreign key constraint check on `pos_order_line.coupon_id` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278555
Original PR description
Deleting `loyalty.card` records causes severe performance bottlenecks due to a sequential scan during the foreign key constraint check on `pos_order_line.coupon_id` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278555
16 changes
Enhancements to existing features
Users who try to create an expense card before Stripe is connected are now directed to the correct settings page to complete the connection. This makes setup clearer and helps reduce confusion or support requests when card creation cannot proceed.
Original PR description
When a user tries to create a card but the configuration is not connected, redirect the user towards the settings to do the connection. task-6272805 Forward-Port-Of: odoo/enterprise#125113
Resolved issues and error corrections
The Vietnam Sales Tax Report now shows VAT amounts consistently as positive values at detailed invoice levels. This prevents confusion when reviewing sales tax data and aligns detailed lines with the report totals.
Original PR description
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should…
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should be consistent with the upper layers and kept positive ## Steps to reproduce: - Install l10n_vn (l10n_vn_reports will install as well) - Switch to VN Company - With demo data, go to Invoicing / Reporting / Tax Report - Change Tax Report (VN) to Sales/Purchase Tax Report (VN) - Unfold the lines all the way to the minimum layer: VAT on sales of goods and services 10% -> INV/2026/00003 - Observe that the VAT 10% line is at negative, which is inconsistent with the Total line below ## Cause of the issue: - In Odoo, tax journal items store tax_base_amount with the accounting sign (negative for sales). This is expected behavior - However, Vietnamese VAT listing expects commercial amounts, which means sales bases need to be displayed as positive numbers ## Fix: Normalized tax_base_amount sign in _query_tax_lines function before building the SQL query opw-6344577 Forward-Port-Of: odoo/enterprise#125257 Forward-Port-Of: odoo/enterprise#122785
The scheduled payroll data update for Australian payroll now restores needed salary rule category data before updating salary rules. This prevents an error if those categories were deleted, keeping payroll maintenance actions running reliably.
Original PR description
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to…
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to `Payroll` > `Configuration` > `Salary` > `Rule Categories`. - Delete all records related to the `Australian Company`. - Go to `Scheduled Actions` and run `Payroll: Update Data`. `ValueError: External ID not found in the system: l10n_au_hr_payroll.rule_category_ote` After [this commit], the category_id field becomes non-required, allowing users to delete a rule category record even if it is linked to a salary rule. When updating the data file [1], an error is raised due to the missing rule category. This commit ensures that when updating the salary rule data, it updates the category data beforehand as like [here] [this commit]: https://github.com/odoo/enterprise/commit/c663fd2a81b7f6b34f8199fdbdc4a75c4f21379e [1] https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_au_hr_payroll/models/hr_payslip.py#L76-L83 [here]: https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_ch_hr_payroll/models/hr_payslip.py#L1074-L1087 sentry-7349905716 Forward-Port-Of: odoo/enterprise#121167
Mexican payroll users can now clear a payslip start or end date without triggering an error. The change checks that dates are present before running salary-limit warning calculations, keeping payslip editing smoother and preventing avoidable interruptions.
Original PR description
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI`…
Currently, an error occurs when a user removes the payslip dates. **Steps to reproduce:** - Install the `l10n_mx_hr_payroll_account_edi` module with demo data. - Switch to `ZAPATERIA URTADO ÑERI` company - Go to `Payslips`, create a payslip. - Set an `employee`, and remove either the `start date` or the `end date` from Period.. `TypeError: unsupported operand type(s) for +: 'bool' and 'relativedelta'` After the [recent commit] adding a warning about the employee exceeding the salary limit, when the user removes the dates from the payslip, the compute method attempts to compute the warning from [1], and when it adds relativedelta to date_from, which is False, it raises the error [2]. This commit ensures that the payslip dates are checked first before adding relativedelta to the date and performing the comparison. [recent commit]: https://github.com/odoo/enterprise/commit/6abfa47dafe439f9328d606ef6ac5126ec6eb1f6 [1]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/hr_payroll/models/hr_payslip.py#L1446 [2]- https://github.com/odoo/enterprise/blob/53a7fd4d53ffd510ad42632c69ce9d3a22c59e70/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py#L272-L276 Forward-Port-Of: odoo/enterprise#125479 Forward-Port-Of: odoo/enterprise#122643
The payroll correction wizard no longer asks users to choose between correcting one or multiple payslips when launched from a specific payslip. This prevents accidental broader corrections and keeps the action focused on the payslip the user opened.
Original PR description
Steps to reproduce: - Validate and pay two payslips for the same employee - Change a payroll field (e.g. wage) on the employee form, flagging both payslips as having wrong data - Open one of the paid payslips and click "Correct" - The wizard shows the single/multi radio selection Hide the radio selection in the button flow, like the other button-flow-specific elements of the wizard view. The wizard then falls back to its default correction_choice 'single', correcting only the opened payslip. task-6391197
This update fixes an issue in Belgian payroll where ONSS notification files could be analyzed incorrectly. It helps ensure payroll declaration feedback is processed more reliably, reducing the risk of administrative errors for Belgian employers.
Original PR description
Forward-Port-Of: odoo/enterprise#125500
Chilean invoice PDF copies now always show the legally required CEDIBLE disclaimer in Spanish. This prevents the footer from appearing in English when the customer’s language is set to something other than Spanish, supporting compliant local invoicing.
Original PR description
Steps to reproduce: - Set the database language to Spanish (Latin America). - Create a customer invoice, confirm it and send it to the SII. - Print it using Print > Invoice PDF copy (Chile). - Scroll…
Steps to reproduce:
- Set the database language to Spanish (Latin America).
- Create a customer invoice, confirm it and send it to the SII.
- Print it using Print > Invoice PDF copy (Chile).
- Scroll to the CEDIBLE section at the bottom of the PDF.
Cause of the issue:
The CEDIBLE footer is merged into l10n_cl.report_invoice_document, which account.report_invoice (odoo/addons/l10n_cl/views/report_invoice.xml) renders with t-lang set to the invoice partner's lang, not the database/user language. The disclaimer text was hardcoded in English and relied on the regular translation to be shown in Spanish, so as
soon as the partner's lang field isn't Spanish, the translation lookup falls back to the untranslated English source, regardless of the database language.
Solution:
This disclaimer is boilerplate mandated by Chilean law: it must always be printed in Spanish, independently of the invoice partner's or current user's language. The same template already follows that rule a few lines above for the SII stamp block ("Timbre Electrónico SII..."), which is hardcoded in Spanish instead of relying on translation.
opw-6390207
Forward-Port-Of: odoo/enterprise#124916This fix prevents the Swiss payroll pension fund number from being included when checking BVG-LPP declaration status. It helps avoid incorrect status requests and supports smoother payroll declaration processing.
Original PR description
Forward-Port-Of: odoo/enterprise#126040
Expense card authorization updates now keep the merchant currency more reliably instead of falling back to the company currency. This helps avoid incorrect amounts or currency displays when Stripe sends authorization updates.
Original PR description
During updates of the authorization amounts the currency may revert to the company one Specifically, if the merchant currency cannot be found, it defaults to the company currency. We now broaden the search search on currency with the `ilike` operator Task [link](https://www.odoo.com/odoo/project.task/6345203) opw-6345203 Forward-Port-Of: odoo/enterprise#123772
Sales commission achievement records with very large IDs can now be opened correctly. This prevents users from seeing an incorrect “record does not exist” message when accessing those achievements.
Original PR description
Steps to reproduce: - Open an achievement with id > JS limit Issues: - We get a pop-up saying the record does not exists The reason we get this error is because since we are browsing a record with an id greater than JS limit the browser truncate it. In order to solve this issue the following PR was made #108751. A field `id_str` was added but it still wasn't working as we weren't retrieving the `id_str`. We now do this by passing `id_str` in the context and retrieving it on the `web_read`. Forward-Port-Of: odoo/enterprise#123757 Forward-Port-Of: odoo/enterprise#113701
Fixed an issue that could prevent the Payroll dashboard from opening when a payroll structure type had no scheduled pay configured. Users can now access the dashboard reliably even when this optional setting is left blank.
Original PR description
If one of the Payroll Structure Types has the Scheduled Pay field unset, opening the Payroll dashboard raises a traceback. Steps to reproduce the error: - Install ``hr_payroll`` module - Go to…
If one of the Payroll Structure Types has the Scheduled Pay field unset, opening the Payroll dashboard raises a traceback. Steps to reproduce the error: - Install ``hr_payroll`` module - Go to Payroll > Configuration > Settings > Set Payroll Closing Date > Save - Go to Payroll > Configuration > Structure Types > Create a new Structure Type > Unset Scheduled Pay - Open Dashboard Traceback: ```py AttributeError: 'bool' object has no attribute 'title' ``` https://github.com/odoo/enterprise/blob/9a3ea83a432f42f62076a50fca6bc771a2de96bf/hr_payroll/models/hr_payroll_warning.py#L413-L419 The dashboard collects the scheduled pay values from all structure types and later calls ``schedule.title()`` to build the labels. When a Structure Type has no Scheduled Pay configured, so ``schedule`` becomes ``False``, leading to the traceback. ``_get_schedule_pay`` method can return False at [1], So, It will generate the traceback from below line also. https://github.com/odoo/enterprise/blob/8a3d87d51a9a3c4df656a328a9179ee43541022d/hr_payroll/models/hr_payroll_warning.py#L401 Solution: Added a fallback value when default scheduled pay is False. [1]: https://github.com/odoo/enterprise/blob/8a3d87d51a9a3c4df656a328a9179ee43541022d/hr_payroll/models/hr_payroll_warning.py#L149-L154 sentry-7583037488 Forward-Port-Of: odoo/enterprise#122492
Swiss employee payslips now show the contract withdrawal date rather than the payroll version end date. This prevents incorrect end dates from appearing on payslip reports when those dates differ.
Original PR description
The Withdrawal Date in the payslip of CH employees was printing the date_end relative to the version related to the payslip. Instead, it should print the end of the contract of that version, since they can be different. The end date of the contract is in l10n_ch_withdrawal. Task: 6398291 Forward-Port-Of: odoo/enterprise#124848
Steps to Reproduce: - Go to Settings > Translations > Languages and select your active language. - Change the Time Format to a 13:00:00 (24-hour) - Click on the Attendance systray icon in the top navbar and Check In. - Notice that the recorded time still displays in a 12-hour format. Cause: - The attendance popup doesn't enforce a strict 12-hour or 24-hour rule. Because of this missing rule, your web browser just uses your computer's default time settings. As a result, Odoo's actual
Original PR description
Steps to Reproduce: - Go to Settings > Translations > Languages and select your active language. - Change the Time Format to a 13:00:00 (24-hour) - Click on the Attendance systray icon in the top…
Steps to Reproduce:
- Go to Settings > Translations > Languages and select your active language.
- Change the Time Format to a 13:00:00 (24-hour)
- Click on the Attendance systray icon in the top navbar and Check In.
- Notice that the recorded time still displays in a 12-hour format.
Cause:
- The attendance popup doesn't enforce a strict 12-hour or 24-hour rule. Because of this missing rule, your web browser just uses your computer's default time settings. As a result, Odoo's actual language and time settings are completely ignored.
Fix:
- Replaced the browser-based formatting with the existing formatting utilities.
- Used is24HourFormat() to determine whether the active time format uses a 12-hour or 24-hour clock.
Solution:
- Dynamically selected the display format using:
- HH:mm for 24-hour format
- hh:mm a for 12-hour format
- Applied the selected format consistently for both check-in and check-out times so the systray now correctly follows the configured language time format.
task-6120540
Forward-Port-Of: odoo/odoo#259918**Steps to reproduce:** - Go to Discuss app - Start a new meeting - Enable Push-To-Talk in voice settings - A banner for the discuss extension recommendation is added the first time you enable the setting - Banner makes the call window move down - Call actions are pushed to the bottom of the screen and not easily accessible **Issue:** An ad banner for the Push-To-Talk extension was added by [1], but it was inserted above the call window rather than on top of it, causing the content bel
Original PR description
**Steps to reproduce:** - Go to Discuss app - Start a new meeting - Enable Push-To-Talk in voice settings - A banner for the discuss extension recommendation is added the first time you enable the setting - Banner makes the call window move down - Call actions are pushed to the bottom of the screen and not easily accessible **Issue:** An ad banner for the Push-To-Talk extension was added by [1], but it was inserted above the call window rather than on top of it, causing the content below to be pushed down. **Fix:** Moved the banner inside the call window, but only when it is not compact (not in smaller chat window or mobile). Could fix with css but we probably don't want to show the banner in these cases anyway (as it would take too much space in the chat window, or not be relevant to mobile users). [1] https://github.com/odoo/odoo/commit/d45c92eb07cd16cc45b0e9c8bf9422fe974f0c62 opw-6250056 Forward-Port-Of: odoo/odoo#278804 Forward-Port-Of: odoo/odoo#277982
When a product uses automated inventory valuation, scrapping it from an already validated (done) picking generated no inventory valuation journal entry, even though the stock move value and the on-hand quantity were correctly updated. The same scrap done from the Scrap menu, or from a picking that is not done yet, worked as expected. A stock move whose picking is already done is created directly in the 'done' state (stock.move.create). Such a move is filtered out of the recordset returned by
Original PR description
When a product uses automated inventory valuation, scrapping it from an already validated (done) picking generated no inventory valuation journal entry, even though the stock move value and the on-hand quantity were correctly updated. The same scrap done from the Scrap menu, or from a picking that is not done yet, worked as expected. A stock move whose picking is already done is created directly in the 'done' state (stock.move.create). Such a move is filtered out of the recordset returned by _action_done(), on which _create_account_move() is called, so the scrap move never received its journal entry. Steps to reproduce: - Use a storable product with automated inventory valuation - Create and validate a receipt for it - Open the completed picking, click Scrap, set a quantity and validate it - The stock is reduced but no journal entry is created. opw-6368258 Forward-Port-Of: odoo/odoo#278210 Forward-Port-Of: odoo/odoo#275847
Miscellaneous changes
Deleting `loyalty.card` records causes severe performance bottlenecks due to a sequential scan during the foreign key constraint check on `pos_order_line.coupon_id` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278555
Original PR description
Deleting `loyalty.card` records causes severe performance bottlenecks due to a sequential scan during the foreign key constraint check on `pos_order_line.coupon_id` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278555
8 changes
Enhancements to existing features
Users who try to create an expense card before Stripe is connected are now directed to the right settings page. This makes setup clearer and helps avoid confusion or stalled card creation.
Original PR description
When a user tries to create a card but the configuration is not connected, redirect the user towards the settings to do the connection. task-6272805 Forward-Port-Of: odoo/enterprise#125113
Resolved issues and error corrections
The scheduled payroll data update for Australian payroll now restores required rule category data before updating salary rules. This prevents failures when users have deleted payroll rule categories, keeping the automated update process reliable.
Original PR description
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to…
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to `Payroll` > `Configuration` > `Salary` > `Rule Categories`. - Delete all records related to the `Australian Company`. - Go to `Scheduled Actions` and run `Payroll: Update Data`. `ValueError: External ID not found in the system: l10n_au_hr_payroll.rule_category_ote` After [this commit], the category_id field becomes non-required, allowing users to delete a rule category record even if it is linked to a salary rule. When updating the data file [1], an error is raised due to the missing rule category. This commit ensures that when updating the salary rule data, it updates the category data beforehand as like [here] [this commit]: https://github.com/odoo/enterprise/commit/c663fd2a81b7f6b34f8199fdbdc4a75c4f21379e [1] https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_au_hr_payroll/models/hr_payslip.py#L76-L83 [here]: https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_ch_hr_payroll/models/hr_payslip.py#L1074-L1087 sentry-7349905716 Forward-Port-Of: odoo/enterprise#121167
The Chilean invoice PDF now always shows the legally required CEDIBLE disclaimer in Spanish, regardless of the customer or user language settings. This prevents invoices from displaying the mandated footer in English when the customer language is not Spanish.
Original PR description
Steps to reproduce: - Set the database language to Spanish (Latin America). - Create a customer invoice, confirm it and send it to the SII. - Print it using Print > Invoice PDF copy (Chile). - Scroll…
Steps to reproduce:
- Set the database language to Spanish (Latin America).
- Create a customer invoice, confirm it and send it to the SII.
- Print it using Print > Invoice PDF copy (Chile).
- Scroll to the CEDIBLE section at the bottom of the PDF.
Cause of the issue:
The CEDIBLE footer is merged into l10n_cl.report_invoice_document, which account.report_invoice (odoo/addons/l10n_cl/views/report_invoice.xml) renders with t-lang set to the invoice partner's lang, not the database/user language. The disclaimer text was hardcoded in English and relied on the regular translation to be shown in Spanish, so as
soon as the partner's lang field isn't Spanish, the translation lookup falls back to the untranslated English source, regardless of the database language.
Solution:
This disclaimer is boilerplate mandated by Chilean law: it must always be printed in Spanish, independently of the invoice partner's or current user's language. The same template already follows that rule a few lines above for the SII stamp block ("Timbre Electrónico SII..."), which is hardcoded in Spanish instead of relying on translation.
opw-6390207
Forward-Port-Of: odoo/enterprise#124916This fixes an issue where Stripe expense card authorization updates could switch amounts back to the company's default currency when the merchant currency was not matched exactly. Currency matching is now more flexible, helping expense records stay accurate for international card transactions.
Original PR description
During updates of the authorization amounts the currency may revert to the company one Specifically, if the merchant currency cannot be found, it defaults to the company currency. We now broaden the search search on currency with the `ilike` operator Task [link](https://www.odoo.com/odoo/project.task/6345203) opw-6345203 Forward-Port-Of: odoo/enterprise#123772
This fix lets users type normally in the Timesheets Assistant, including using the space key, without keyboard navigation for suggestions interfering. It also keeps start times visible unless action buttons are actually shown, making suggestion rows clearer and less confusing.
Original PR description
Before this commit, when user wants to create a timesheet in timesheet assistant, he cannot use space key due to keyboard navigation for suggestions. This commit checks the event in keydown event targets an element inside the container containing all suggestions in Timesheets Assistant if yes then the process continues otherwise skip the process.
Swiss employee payslips now show the actual contract withdrawal date instead of a related version end date. This prevents incorrect dates on payroll documents when those two dates differ.
Original PR description
The Withdrawal Date in the payslip of CH employees was printing the date_end relative to the version related to the payslip. Instead, it should print the end of the contract of that version, since they can be different. The end date of the contract is in l10n_ch_withdrawal. Task: 6398291 Forward-Port-Of: odoo/enterprise#124848
**Issue**: Even if the currency rate is changed on the invoice, the today currency rate is used while generating stock landed cost. **Steps to reproduce**: - Enable two currencies (ex: Dollar and Euro) - Enable Landed Costs on the settings - Create a service product - Create a bill for that product for 100 dollar and click the Landed Costs check box - Change the currency rating (ex: 1 USD = 0.5 euro) and confirm the bill - Click on "Create Landed Costs" -> The cost is not 200 **Ca
Original PR description
**Issue**: Even if the currency rate is changed on the invoice, the today currency rate is used while generating stock landed cost. **Steps to reproduce**: - Enable two currencies (ex: Dollar and…
**Issue**: Even if the currency rate is changed on the invoice, the today currency rate is used while generating stock landed cost. **Steps to reproduce**: - Enable two currencies (ex: Dollar and Euro) - Enable Landed Costs on the settings - Create a service product - Create a bill for that product for 100 dollar and click the Landed Costs check box - Change the currency rating (ex: 1 USD = 0.5 euro) and confirm the bill - Click on "Create Landed Costs" -> The cost is not 200 **Cause**: While creating the landed cost: https://github.com/odoo/odoo/blob/e906eb23d698061f146ba67aae420eb7bb5e8a68/addons/stock_landed_costs/models/account_move.py#L21 it uses `_convert` from the currency: https://github.com/odoo/odoo/blob/e906eb23d698061f146ba67aae420eb7bb5e8a68/addons/stock_landed_costs/models/account_move.py#L35 which gets the `conversion_rate` defined on the currency, regardless whether `is_invoicing` is true: https://github.com/odoo/odoo/blob/e906eb23d698061f146ba67aae420eb7bb5e8a68/odoo/addons/base/models/res_currency.py#L294 https://github.com/odoo/odoo/blob/e906eb23d698061f146ba67aae420eb7bb5e8a68/addons/account/models/account_move.py#L6350-L6351 **Solution** It is safe to replace the `convert` calls by the `currency_rate` of the `Account.move.line` since: https://github.com/odoo/odoo/blob/e906eb23d698061f146ba67aae420eb7bb5e8a68/addons/account/models/account_move_line.py#L735-L747 `currency_rate` will be set as `_get_conversion_rate` when not invoicing. Also add rounding since `_convert` is called with `round=True` by default. opw-6047031 Forward-Port-Of: odoo/odoo#256394
Miscellaneous changes
Deleting `loyalty.card` records causes severe performance bottlenecks due to a sequential scan during the foreign key constraint check on `pos_order_line.coupon_id` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278555
Original PR description
Deleting `loyalty.card` records causes severe performance bottlenecks due to a sequential scan during the foreign key constraint check on `pos_order_line.coupon_id` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278555
12 changes
Enhancements to existing features
When an expense card cannot be created because Stripe is not connected, users are now directed to the relevant settings page to complete the connection. This reduces confusion and helps teams resolve setup issues faster without needing technical support.
Original PR description
When a user tries to create a card but the configuration is not connected, redirect the user towards the settings to do the connection. task-6272805 Forward-Port-Of: odoo/enterprise#125113
Give clearer, more accurately attributed error messages, and add validation to catch classification code / General Public TIN mismatches before they reach MyInvois. task-4651934 Forward-Port-Of: odoo/odoo#278208
Original PR description
Give clearer, more accurately attributed error messages, and add validation to catch classification code / General Public TIN mismatches before they reach MyInvois. task-4651934 Forward-Port-Of: odoo/odoo#278208
Resolved issues and error corrections
Expense card authorization updates now better recognize the merchant currency instead of falling back to the company currency. This helps keep expense amounts accurate when Stripe sends updated authorization information.
Original PR description
During updates of the authorization amounts the currency may revert to the company one Specifically, if the merchant currency cannot be found, it defaults to the company currency. We now broaden the search search on currency with the `ilike` operator Task [link](https://www.odoo.com/odoo/project.task/6345203) opw-6345203 Forward-Port-Of: odoo/enterprise#123772
Chilean invoice PDF copies now always show the legally required CEDIBLE disclaimer in Spanish. This prevents the footer from appearing in English when the customer language is not Spanish, helping businesses keep Chilean electronic invoices compliant.
Original PR description
Steps to reproduce: - Set the database language to Spanish (Latin America). - Create a customer invoice, confirm it and send it to the SII. - Print it using Print > Invoice PDF copy (Chile). - Scroll…
Steps to reproduce:
- Set the database language to Spanish (Latin America).
- Create a customer invoice, confirm it and send it to the SII.
- Print it using Print > Invoice PDF copy (Chile).
- Scroll to the CEDIBLE section at the bottom of the PDF.
Cause of the issue:
The CEDIBLE footer is merged into l10n_cl.report_invoice_document, which account.report_invoice (odoo/addons/l10n_cl/views/report_invoice.xml) renders with t-lang set to the invoice partner's lang, not the database/user language. The disclaimer text was hardcoded in English and relied on the regular translation to be shown in Spanish, so as
soon as the partner's lang field isn't Spanish, the translation lookup falls back to the untranslated English source, regardless of the database language.
Solution:
This disclaimer is boilerplate mandated by Chilean law: it must always be printed in Spanish, independently of the invoice partner's or current user's language. The same template already follows that rule a few lines above for the SII stamp block ("Timbre Electrónico SII..."), which is hardcoded in Spanish instead of relying on translation.
opw-6390207
Forward-Port-Of: odoo/enterprise#124916The French FEC export checks were updated to match a recent change in how accounting entry labels are chosen when fallback text is needed. This keeps automated validation accurate and helps ensure French accounting reports continue to be tested reliably.
Original PR description
Adjust the FEC export test expectations to match the updated `EcritureLib` fallback logic introduced in the related community change. Related: https://github.com/odoo/odoo/pull/257242 task-5346068 Forward-Port-Of: odoo/enterprise#112822
This fix adds a missing tax conversion factor to the invoice data sent to Avalara for Brazil fiscal reform requirements. It helps ensure sales quantities are interpreted correctly for compliance calculations, reducing the risk of invoice processing errors.
Original PR description
This commit adds the comexTaxUnitFactor to the json sent to Avalara when sending an invoice. comexTaxUnitFactor is a factor that convert sales quantity to comexTaxUnit, its value should be the same as cbsIbsUnitFactor. opw-6396462
Swiss employee payslip reports now show the actual contract withdrawal date instead of a related version end date. This prevents incorrect departure information from appearing on payroll documents when those dates differ.
Original PR description
The Withdrawal Date in the payslip of CH employees was printing the date_end relative to the version related to the payslip. Instead, it should print the end of the contract of that version, since they can be different. The end date of the contract is in l10n_ch_withdrawal. Task: 6398291 Forward-Port-Of: odoo/enterprise#124848
When a product uses automated inventory valuation, scrapping it from an already validated (done) picking generated no inventory valuation journal entry, even though the stock move value and the on-hand quantity were correctly updated. The same scrap done from the Scrap menu, or from a picking that is not done yet, worked as expected. A stock move whose picking is already done is created directly in the 'done' state (stock.move.create). Such a move is filtered out of the recordset returned by
Original PR description
When a product uses automated inventory valuation, scrapping it from an already validated (done) picking generated no inventory valuation journal entry, even though the stock move value and the on-hand quantity were correctly updated. The same scrap done from the Scrap menu, or from a picking that is not done yet, worked as expected. A stock move whose picking is already done is created directly in the 'done' state (stock.move.create). Such a move is filtered out of the recordset returned by _action_done(), on which _create_account_move() is called, so the scrap move never received its journal entry. Steps to reproduce: - Use a storable product with automated inventory valuation - Create and validate a receipt for it - Open the completed picking, click Scrap, set a quantity and validate it - The stock is reduced but no journal entry is created. opw-6368258 Forward-Port-Of: odoo/odoo#275847
Issue: If a product has a pricelist that updates on quantity and in quotation preview the customer changes the quantity the unit price doesn't update. Steps to reproduce: Create a product with price list that change depending on quantity. In a new quotation create a section and set it to optional. Add your product under this new section, and enter preview. Notice that if you change the quantity so that a different pricelist would apply the unit price still does not change. Cause: The va
Original PR description
Issue: If a product has a pricelist that updates on quantity and in quotation preview the customer changes the quantity the unit price doesn't update. Steps to reproduce: Create a product with price list that change depending on quantity. In a new quotation create a section and set it to optional. Add your product under this new section, and enter preview. Notice that if you change the quantity so that a different pricelist would apply the unit price still does not change. Cause: The value for unit price was not getting updated. Fix: After changing quantities update the price unit if there are active pricelists. As not all customers might want this change, it also checks for `sale.disable_sale_update`, so that the user can choose whether to update or not. opw-6377679 Forward-Port-Of: odoo/odoo#275868
Issue ----- International deliveries for fractions of items (eg 500g of a product sold by kg) are rejected by Sendcloud. Steps to reproduce ----- - Setup Sendcloud - Fedex international - Create a product - weight: 1kg - valid hs code - Create a contact (outside EU if the company is in EU) - Deliver 0.5 of the product to the contact > Error "... parcel not returned from Sendcloud" Cause ----- Sendcloud returns he folloing error: > "The total weight for declared items e
Original PR description
Issue ----- International deliveries for fractions of items (eg 500g of a product sold by kg) are rejected by Sendcloud. Steps to reproduce ----- - Setup Sendcloud - Fedex international - Create a…
Issue ----- International deliveries for fractions of items (eg 500g of a product sold by kg) are rejected by Sendcloud. Steps to reproduce ----- - Setup Sendcloud - Fedex international - Create a product - weight: 1kg - valid hs code - Create a contact (outside EU if the company is in EU) - Deliver 0.5 of the product to the contact > Error "... parcel not returned from Sendcloud" Cause ----- Sendcloud returns he folloing error: > "The total weight for declared items exceeds the total weight set for the shipment." This is because the `weight` set on the shipment https://github.com/odoo/enterprise/blob/99a13453cac8a7a4677cef3df8896329c90c9e99/delivery_sendcloud/models/sendcloud_service.py#L449-L464 corresponds to the weight of the package, whereas the weight set on the description of the product in `parcel_items` corresponds to the weight of one "full" unit of the product. https://github.com/odoo/enterprise/blob/99a13453cac8a7a4677cef3df8896329c90c9e99/delivery_sendcloud/models/sendcloud_service.py#L327-L335 We cannot change the quantity in `parcel_items` to match the actual delivered one because the field should be an integer. https://sendcloud.dev/api/v2/parcels/create-a-parcel-or-parcels#body-one-of-0-parcel-parcel-items-items-quantity The price is also off, because it gets taken from the `move_line`, so it reflects the price of the actual quantity and not a "full" item. https://github.com/odoo/odoo/blob/208a8a6a5adb8ec1f2710453c2ee3b54c55a9f1e/addons/stock_delivery/models/delivery_carrier.py#L235 Note that this issue is common to **all UoM types**. Solution ----- Since we cannot change the quantity, we can instead adapt the description and weight sent in `parcel_items`. For example, sending 300g of sugar, we would send - description: "Sugar (0.3 kg)" - weight: "0.300" ----- Ticket: opw-6346330 Forward-Port-Of: odoo/odoo#277440
Miscellaneous changes
Deleting `loyalty.card` records causes severe performance bottlenecks due to a sequential scan during the foreign key constraint check on `pos_order_line.coupon_id` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278555
Original PR description
Deleting `loyalty.card` records causes severe performance bottlenecks due to a sequential scan during the foreign key constraint check on `pos_order_line.coupon_id` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278555
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a registry recompute server-side, so a tight reconnection window makes all of those recomputes land together and pile up on the freshly started process. The jitter added to each reconnection delay was only one second, far too narrow to break up that wave. Widen it to thirty seconds so the retries of the m
Original PR description
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a…
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a registry recompute server-side, so a tight reconnection window makes all of those recomputes land together and pile up on the freshly started process. The jitter added to each reconnection delay was only one second, far too narrow to break up that wave. Widen it to thirty seconds so the retries of the many clients fan out over a much wider window and the registry recomputes spread over time instead of colliding. Raise the ceiling on the retry delay to two minutes to match that wider spread, and drop the exponential growth factor: with a thirty-second jitter accumulating on every attempt, the delay already climbs on its own, so scaling it further only pushed clients toward the ceiling sooner without spreading them any better. 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#278599 Forward-Port-Of: odoo/odoo#276869
3 changes
Resolved issues and error corrections
Studio report editing now keeps an empty paragraph in place when the last character is deleted. This prevents accidental layout changes and makes report editing behave more predictably, matching the website builder experience.
Original PR description
Problem: In Studio reports, deleting the last character of a paragraph removes the entire paragraph. Cause: `cleanEmptyStructuralContainers` removes the empty paragraph because it is considered empty. Solution: Disable `cleanEmptyStructuralContainers` for reports same as website builder. Steps to reproduce: - Create a new report. - Add multiple paragraphs. - Leave one paragraph with a single character. - Delete the character. - Observe that the paragraph is removed. task-6368965
Swiss employee payslips now show the contract withdrawal date instead of a related version end date. This helps ensure payroll documents display the correct employment end information when those dates differ.
Original PR description
The Withdrawal Date in the payslip of CH employees was printing the date_end relative to the version related to the payslip. Instead, it should print the end of the contract of that version, since they can be different. The end date of the contract is in l10n_ch_withdrawal. Task: 6398291
This fix prevents the Swiss payroll declaration process from including an unnecessary fund number when checking BVG-LPP pension status. This helps avoid incorrect or rejected status requests and improves compliance reporting reliability for Swiss payroll users.
Original PR description
Forward-Port-Of: odoo/enterprise#126040
5 changes
Resolved issues and error corrections
The Timesheets overtime display now keeps the same unit when users switch to another language. This prevents remaining time from unexpectedly changing from days back to hours, making workforce reporting clearer for multilingual teams.
Original PR description
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet…
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet in the past week for this employee (e.g. 8 hours). 4. Observe the overtime indicator for the employee (it shows 32 hrs) (Click the left arrow to display it). 5. Change the timesheet encoding unit to "Days / Half-Days". 6. Return to Timesheets and observe the overtime indicator (it now correctly shows 4 days). 7. Install a language other than English (e.g. French). 8. Return to Timesheets and observe the overtime indicator again. Issue: -------- The remaining time value changes unexpectedly and displays 32 hours instead of 4 days. Cause: --------- In `get_timesheet_and_working_hours_for_employees`, the code determines whether the timesheet UoM is expressed in days by comparing the UoM name with the string `"days"`. Since UoM names are translatable, this comparison becomes invalid when the user language changes (e.g. `"jours"` in French), causing the logic to skip the day conversion and return values in hours instead. https://github.com/odoo/enterprise/blob/c48290e90fdeadf4f9ca8c44b035e601e7ed380a/timesheet_grid/models/hr_employee.py#L165-L169 Solution: ----------- Compare the timesheet UoM record with the day UoM record directly instead of relying on translated string values. see commit: https://github.com/odoo/enterprise/commit/5fbf194c5056566453a124812fd2614edfe19a82 opw-6279133 Forward-Port-Of: odoo/enterprise#120595
This fix prevents Swiss pension fund numbers from being included in status checks for BVG-LPP payroll declarations. It helps avoid incorrect declaration status handling and supports more reliable Swiss payroll processing.
Original PR description
Forward-Port-Of: odoo/enterprise#126040
The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry therefore fires while the mock socket is still in the closing state. `_start` detects that socket and triggers the close event manually to keep the lifecycle consistent. In other cases, the error event will schedule a reconnect but in this case it will never arrive. The worker is then left with n
Original PR description
The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry…
The `bus_monitoring_service` test "connection considered as lost after failed reconnect attempt" fails about half of the time. Since [1], the reconnect delay in tests is much smaller. The retry therefore fires while the mock socket is still in the closing state. `_start` detects that socket and triggers the close event manually to keep the lifecycle consistent. In other cases, the error event will schedule a reconnect but in this case it will never arrive. The worker is then left with no socket, no listeners and no pending timeout: it never reconnects. Schedule the reconnection when handling a manually triggered close, since no error event will follow to do it. [1]: https://github.com/odoo/odoo/pull/278075 runbot-944578 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#278779
**Issue:** `test_mail_template_dynamic_placeholder_tour` tour is failing sometimes with the following error: `Tour mail_template_dynamic_field_tour → Step Click on contact (trigger: div[name="model_id"] .ui-autocomplete). TypeError: Cannot read properties of undefined (reading 'click')` **Cause:** It happens that the element is not loaded yet after the delay and clicking on an undefined element triggers the error. **Solution:** Make sure to only click on the element when it's ready.
Original PR description
**Issue:** `test_mail_template_dynamic_placeholder_tour` tour is failing sometimes with the following error: `Tour mail_template_dynamic_field_tour → Step Click on contact (trigger: div[name="model_id"] .ui-autocomplete). TypeError: Cannot read properties of undefined (reading 'click')` **Cause:** It happens that the element is not loaded yet after the delay and clicking on an undefined element triggers the error. **Solution:** Make sure to only click on the element when it's ready. runbot-223306 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277954
For an MO with component tracked by lot is possible to close it without assigning the lot number even when they are marked for manual consumption. From the shopfloor this will close the MO that will disappear when it's gone it will throw a user error, without the MO reappearing. Steps to reproduce --------------------------- **Issue 1** 1) Create a product "final" 2) Create a product "component" tracked by lot 3) Update the on hand quantity and don't assign a lot number 4) Create a BoM
Original PR description
For an MO with component tracked by lot is possible to close it without assigning the lot number even when they are marked for manual consumption. From the shopfloor this will close the MO that will…
For an MO with component tracked by lot is possible to close it without assigning the lot number even when they are marked for manual consumption. From the shopfloor this will close the MO that will disappear when it's gone it will throw a user error, without the MO reappearing. Steps to reproduce --------------------------- **Issue 1** 1) Create a product "final" 2) Create a product "component" tracked by lot 3) Update the on hand quantity and don't assign a lot number 4) Create a BoM for "final" with "component" as component and manual consumption 5) Create a MO and confirm it 6) Go to shopfloor 7) Set "final" quantity 8) Set "component" quantity 10) Close the MO -> The MO disappear (leaving a user error) -> Since the "component" does not have a lot number it should not disappear **Issue 2** Same steps as Issue 1 until step 6: 6*) Add "comp" as barcode to the product component 7*) Go to barcode 8*) Open the manufacturing order 9*) Add the quantity to final 10*) Scan "comp" 11*) Scan a non-existent lot number, ex: "12345" -> It raise the error Observation ---------------------- **Issue 1** When clicking on "Closing production" it will call [onClickValidateButton](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L481-L482)() that will lead us to validate, and validate will [call](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L511) the function [pre_button_mark_done](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L507) in python. in pre_button_mark_done, we will skip any check on the lot number, since we already have set qty_producing (when setting "final" quantity), it will avoid _set_quantities where a check for lot number is made: https://github.com/odoo/odoo/blob/9218d302b0fd56c1854d95d3756c0f5e9c9c8700/addons/mrp/models/mrp_production.py#L2235-L2239 https://github.com/odoo/odoo/blob/9218d302b0fd56c1854d95d3756c0f5e9c9c8700/addons/mrp/models/mrp_production.py#L2839-L2844 And it will also skip the consumption wizard since it doesn't check for lot number nor allow to set lot numbers: https://github.com/odoo/odoo/blob/35f804995118e6ffe150c9c7a7bad4844bd0e0ed/addons/mrp/models/mrp_production.py#L1658-L1660 After avoiding both checks we go back to validate. In validate and we update the variable underValidation which will [trigger the fadeout animation](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L154) When the [animation ends](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L662-L665), the call to realValidation will be triggered and will call productionValidation that will send a call to [button_mark_done](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L551) In button_mark_done, when calling _action_done on the move_lines, we will finally check that there is a lot number, which will trigger an error : https://github.com/odoo/odoo/blob/35f804995118e6ffe150c9c7a7bad4844bd0e0ed/addons/stock/models/stock_move_line.py#L664-L669 but because the fadeout animation is already over, the mo will have disappeared, which means we can't correct the userError that has been raised. **Issue 2** In barcode when scanning a lot after a product, it will not create a lot but only apply a lot_name : https://github.com/odoo/enterprise/blob/7b57a2927aeb8abf84d0f6acc64a7e9bbc8f608d/stock_barcode/static/src/models/barcode_model.js#L1306-L1311 this cause an issue with the existing condition since it only pass the check if there is a lot, but in this case there only is a lot_name. When we click on "Produce" in a Mo in barcode, it will call validate, that in this case, will call button_mark_done: https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode/static/src/components/main.xml#L163 https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode/static/src/models/barcode_model.js#L602-L605 https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L14 opw-6060310 Forward-Port-Of: odoo/odoo#257635
23 changes
Enhancements to existing features
When users open the new-product form from barcode lookup, existing notifications are no longer cleared automatically. This keeps helpful messages visible because mobile notifications now appear at the bottom and no longer block the form.
Original PR description
…n click This reverts commit https://github.com/odoo/enterprise/pull/68352. That commit cleared all open toast notifications before opening the new-product form, because on mobile a notification used to take up a large chunk of the screen, forcing the user to wait out its autoclose timeout before they could interact with the form underneath. Notifications on mobile are now anchored to the bottom of the screen (M3 snackbar), so they no longer overlap the form and this workaround is no longer needed.
This update refreshes icon usage in several Odoo Enterprise areas to align with the latest web interface standards. Users should see more consistent visual elements in affected screens, with minimal change to day-to-day workflows.
Belgian payroll screens and reference data were updated to make DMFA work location information clearer and more consistent. This helps payroll users identify and manage work location details more easily when preparing Belgian social security reporting.
Original PR description
[IMP] l10n_be: dmfa work location adjustments Renaming and view adjustments for dmfa work location task-6381334
Add a new notification in the bank reco widget when a user do a reconciliation with a partner different from the one on the st_line. The idea is to let the user chose if he wants to move the bank account from the st_line partner to the move he tries to reconcile. task-6303397 Forward-Port-Of: odoo/enterprise#125702 Forward-Port-Of: odoo/enterprise#120900
Original PR description
Add a new notification in the bank reco widget when a user do a reconciliation with a partner different from the one on the st_line. The idea is to let the user chose if he wants to move the bank account from the st_line partner to the move he tries to reconcile. task-6303397 Forward-Port-Of: odoo/enterprise#125702 Forward-Port-Of: odoo/enterprise#120900
Payroll users can now open the full Time Off request form directly from a leave entry in the Gantt view. The new expand button makes it easier to review or update all request details without navigating away manually.
Original PR description
Before this commit, users could click on a leave entry in the Gantt view of the Payroll app, but they could not open its full form view. This commit adds an expand button (double arrow icon) that allows users to open the complete Time Off request form. Task-6360136
When users try to create an expense card before Stripe is connected, they are now directed to the settings page to complete the connection. This reduces confusion and helps users resolve the setup issue more quickly.
Original PR description
When a user tries to create a card but the configuration is not connected, redirect the user towards the settings to do the connection. task-6272805 Forward-Port-Of: odoo/enterprise#125113
This update makes the field selection experience in Studio behave consistently when debug mode is enabled. It helps advanced users see the same options and behavior when configuring relational fields as they already do in domain filters.
Original PR description
This commit evaluates the `isDebugMode` prop which is passed to ModelFieldSelector so that the component acts the same for Relational field selector as in Domain field selector. Task~6369639
Marketing automation synchronization is now prepared to focus on campaigns that are currently running, helping avoid unnecessary processing for inactive campaigns. The related enrollment tests were reorganized to make future improvements easier to maintain.
Original PR description
Add some filters on main API synchronization methods so that they are limited to running campaigns. Move enroll sepcific tests into a new test file to ease future updates. Prepares Task-6425785 [marketing_automation] Incremental sync
Resolved issues and error corrections
This fixes outdated internal test expectations for marketing automation after a previous change was merged. It helps keep performance monitoring accurate and reduces false alarms in automated checks, with no direct change for end users.
Original PR description
Finally forgotten when merging odoo/enterprise#66823
The Vietnam Sales Tax Report now shows VAT amounts consistently as positive values when users expand report details to the invoice level. This prevents confusion from sales tax amounts appearing negative in detailed views while totals remain positive.
Original PR description
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should…
## Current behavior: In Vietnam's Sales Tax Report, when unfolding until the minimum layer, the VAT now displays the value in negative ## Expected behavior: The VAT value in the minimum layer should be consistent with the upper layers and kept positive ## Steps to reproduce: - Install l10n_vn (l10n_vn_reports will install as well) - Switch to VN Company - With demo data, go to Invoicing / Reporting / Tax Report - Change Tax Report (VN) to Sales/Purchase Tax Report (VN) - Unfold the lines all the way to the minimum layer: VAT on sales of goods and services 10% -> INV/2026/00003 - Observe that the VAT 10% line is at negative, which is inconsistent with the Total line below ## Cause of the issue: - In Odoo, tax journal items store tax_base_amount with the accounting sign (negative for sales). This is expected behavior - However, Vietnamese VAT listing expects commercial amounts, which means sales bases need to be displayed as positive numbers ## Fix: Normalized tax_base_amount sign in _query_tax_lines function before building the SQL query opw-6344577 Forward-Port-Of: odoo/enterprise#125257 Forward-Port-Of: odoo/enterprise#122785
Sales order information on planning slots is now visible for companies using a single-company setup. This prevents users from missing key sales order links when viewing or editing planning slot forms.
Original PR description
The `sale_line_id` field was previously injected after `company_id`. Because the first instance of `company_id` in the base view is wrapped inside a `<t groups="base.group_multi_company">` block, the inserted fields were inadvertently hidden in single-company databases. This commit changes the XPath target to `role_id` to ensure the sales order fields are always visible in the planning slot form view, regardless of multi-company settings. task: 6398673 Forward-Port-Of: odoo/enterprise#125712
Users without certain Planning or Project permissions can now open the product catalog from sales quotations without hitting an access error. The fix checks user permissions before reading restricted field service or planning information, keeping sales workflows usable for limited-access users.
Original PR description
A user without Project rights cannot add a product from the catalog on a sale order Steps to reproduce: 1. Install industry_fsm_sale module 2. Go to Settings > Users & Companies > Users and open user Marc Demo 3. Set Field Service and Project rights to No 4. Log in as Marc Demo 5. Go to Sales and open any quotation 6. Click on Catalog in the order lines 7. An access error is raised Issue: industry_fsm_sale overrides `action_add_from_catalog` and tries to read sale.order.tasks_ids but users can't always access this field as it requires Project rights Solution: Check that the user has Project rights before trying to read tasks_ids opw-6315647 Forward-Port-Of: odoo/enterprise#125526 Forward-Port-Of: odoo/enterprise#123228
The Australian payroll scheduled data update now restores required rule category data before updating salary rules. This prevents the scheduled action from failing if payroll rule categories were previously deleted, helping payroll maintenance run reliably.
Original PR description
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to…
Currently, an error occurs when the "Payroll: Update Data" scheduled action is run. **Steps to Reproduce:** - Install `l10n_au_hr_payroll` with demo data. - Switch to `Australian Company`. - Go to `Payroll` > `Configuration` > `Salary` > `Rule Categories`. - Delete all records related to the `Australian Company`. - Go to `Scheduled Actions` and run `Payroll: Update Data`. `ValueError: External ID not found in the system: l10n_au_hr_payroll.rule_category_ote` After [this commit], the category_id field becomes non-required, allowing users to delete a rule category record even if it is linked to a salary rule. When updating the data file [1], an error is raised due to the missing rule category. This commit ensures that when updating the salary rule data, it updates the category data beforehand as like [here] [this commit]: https://github.com/odoo/enterprise/commit/c663fd2a81b7f6b34f8199fdbdc4a75c4f21379e [1] https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_au_hr_payroll/models/hr_payslip.py#L76-L83 [here]: https://github.com/odoo/enterprise/blob/b6612dd58276646b81a3a12cd48e8427ea5359c2/l10n_ch_hr_payroll/models/hr_payslip.py#L1074-L1087 sentry-7349905716 Forward-Port-Of: odoo/enterprise#121167
Marketing Automation campaigns no longer trigger an error when a user clears the Target field while editing a campaign. This keeps campaign setup stable and avoids an unexpected interruption in the user workflow.
Original PR description
Currently, an error occurs when a user removes the target model from a marketing campaign. **Steps to Reproduce:** - Install the `marketing_automation` module. - Go to `Marketing Automation` >…
Currently, an error occurs when a user removes the target model from a marketing campaign. **Steps to Reproduce:** - Install the `marketing_automation` module. - Go to `Marketing Automation` > `Campaigns`. - Create a `new campaign` and clear the `Target` field. `KeyError: False` After the recent commit that added the recipients_count field and its computation [1], when the user removes model_id(Target), model_name is set to False [2]. The domain is then updated by a compute method, which triggers the computation of recipients_count. Since the computation only checks whether domain is set and does not verify that model_name is available, it attempts to access the model using model_name, raising the error [3]. This commit ensures that, when computing the recipient count, it also checks that model_name is set. Since model_id is a required field, once it is set, the recipient count is computed correctly based on the domain and model_name. [recent commit]: https://github.com/odoo/enterprise/commit/5485e8eaa7636c7dd0b305b4e26fb772aff6d030 [1]: https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L43 [2]: https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L33 [3]- https://github.com/odoo/enterprise/blob/1cbb21eaf0f24cedb4cc18a31065a76b1dd9783e/marketing_automation/models/marketing_campaign.py#L146-L148 sentry-7612724367 Forward-Port-Of: odoo/enterprise#124649
This fixes an internal test setup for Indian payroll so percentage calculations are checked using dedicated sample employee data. It helps prevent unrelated employee payroll values from affecting test results, without changing payroll behavior for users.
Original PR description
Use a dedicated employee/version for the percentage computation test instead of Rahul, whose existing payroll values affect copied version data. Define the test amounts in common and reuse `employee.version_id` in the test, so percentages are derived from amounts without changing payroll behavior. task-6340923 Forward-Port-Of: odoo/enterprise#124330 Forward-Port-Of: odoo/enterprise#121918
Draft invoices no longer show the vehicle field as a clickable link on invoice lines. This keeps draft invoice behavior consistent with products and prevents users from opening related vehicle records before the invoice is posted.
Original PR description
The vehicle under account on the invoice lines should not be clickable when the invoice is in draft. Only when it is posted, like the product. task-6385436 Forward-Port-Of: odoo/enterprise#125688 Forward-Port-Of: odoo/enterprise#124514
Timesheet descriptions in the assistant now expand automatically so long entries can be read in full instead of being cut off. This helps users review and edit detailed time entries without losing important context.
Original PR description
- changed the description field to expand dynamically to display long descriptions in full instead of truncating them in the assistant Task-6348575 Forward-Port-Of: odoo/enterprise#125536 Forward-Port-Of: odoo/enterprise#123428
This update corrects how Belgian payroll notification files are analyzed. It helps ensure payroll declarations are processed more reliably, reducing the risk of errors when handling official ONSS notifications.
Original PR description
Forward-Port-Of: odoo/enterprise#125500
Fixed Chilean invoice PDFs so the legally required CEDIBLE disclaimer is always shown in Spanish, regardless of the customer's language settings. This helps ensure printed invoice copies remain compliant with Chilean requirements.
Original PR description
Steps to reproduce: - Set the database language to Spanish (Latin America). - Create a customer invoice, confirm it and send it to the SII. - Print it using Print > Invoice PDF copy (Chile). - Scroll…
Steps to reproduce:
- Set the database language to Spanish (Latin America).
- Create a customer invoice, confirm it and send it to the SII.
- Print it using Print > Invoice PDF copy (Chile).
- Scroll to the CEDIBLE section at the bottom of the PDF.
Cause of the issue:
The CEDIBLE footer is merged into l10n_cl.report_invoice_document, which account.report_invoice (odoo/addons/l10n_cl/views/report_invoice.xml) renders with t-lang set to the invoice partner's lang, not the database/user language. The disclaimer text was hardcoded in English and relied on the regular translation to be shown in Spanish, so as
soon as the partner's lang field isn't Spanish, the translation lookup falls back to the untranslated English source, regardless of the database language.
Solution:
This disclaimer is boilerplate mandated by Chilean law: it must always be printed in Spanish, independently of the invoice partner's or current user's language. The same template already follows that rule a few lines above for the SII stamp block ("Timbre Electrónico SII..."), which is hardcoded in Spanish instead of relying on translation.
opw-6390207
Forward-Port-Of: odoo/enterprise#125463
Forward-Port-Of: odoo/enterprise#124916This fixes how Swiss payroll declarations check the status of BVG-LPP pension fund submissions. The fund number is no longer included where it should not be, helping avoid incorrect status lookups or rejected declaration handling.
Original PR description
Forward-Port-Of: odoo/enterprise#126040
Swiss employee payslips now show the actual contract withdrawal date instead of a related version end date. This helps ensure payroll reports display the correct employment end information when those dates differ.
Original PR description
The Withdrawal Date in the payslip of CH employees was printing the date_end relative to the version related to the payslip. Instead, it should print the end of the contract of that version, since they can be different. The end date of the contract is in l10n_ch_withdrawal. Task: 6398291 Forward-Port-Of: odoo/enterprise#124848
Code cleanup and technical improvements
This update refreshes internal component wiring to align with the latest Owl framework behavior. It helps keep several Odoo Enterprise apps maintainable and compatible without changing user-facing features.
Original PR description
Follow-up of the community commit removing `useChildRef` and `useForwardRefToParent`: Owl 3 refs are signals, so a parent creates its ref with `signal.ref()`, hands it to the child (which binds it with `t-ref`) and reads the element by calling it instead of through `.el`.
Default values for certain records are now initialized per record instead of being shared globally, reducing the risk of confusing or unintended behavior. The WhatsApp composer patch was also cleaned up to avoid copying stray data onto the shared model definition.
Original PR description
A plain value on a model prototype, typically from patch(Model.prototype, { flag: false }), is shared data: every record of the model reads the same value, and nothing tells a reader whether it got a default or a value set on the record. Such defaults belong to the record, so they move into setup().
The whatsapp composer went through Object.assign with a stray name argument between the target and the values, so the characters of that name were copied onto the prototype as numeric keys. It uses patch() like every other model patch.
https://github.com/odoo/odoo/pull/2791046 changes
Resolved issues and error corrections
Expense card authorization updates now keep the merchant currency instead of falling back to the company currency when the currency lookup is less exact. This helps keep expense amounts accurate for businesses using Stripe-issued cards across different currencies.
Original PR description
During updates of the authorization amounts the currency may revert to the company one Specifically, if the merchant currency cannot be found, it defaults to the company currency. We now broaden the search search on currency with the `ilike` operator Task [link](https://www.odoo.com/odoo/project.task/6345203) opw-6345203
The Benefits form now stops users from creating new employee, cost, or mandatory benefit records directly from selection fields. This helps keep salary benefit setup consistent by ensuring related records are created through the proper workflows.
Original PR description
This commit prevents creating new employee, cost or mandatory benefits records directly from the Benefits form by setting these fields' `'no_create'` to `True`. task-5156844 Forward-Port-Of: odoo/enterprise#96770
This fix keeps Australian payroll accounting tests consistent by locking them to a specific date. It prevents recent payroll rule changes from causing unrelated test failures, helping maintain reliable payroll updates.
Original PR description
The new qualifying earning rule introduced was breaking the tests that were not frozen in the past as it changed over to the new reporting code. runbot-940160 related too [11736](https://github.com/odoo/enterprise/pull/117367#event-26694075694)
Chilean invoice PDF copies now always show the legally required CEDIBLE disclaimer in Spanish. This prevents the footer from appearing in English when the customer's language is not Spanish, supporting correct legal presentation of Chilean electronic invoices.
Original PR description
Steps to reproduce: - Set the database language to Spanish (Latin America). - Create a customer invoice, confirm it and send it to the SII. - Print it using Print > Invoice PDF copy (Chile). - Scroll…
Steps to reproduce:
- Set the database language to Spanish (Latin America).
- Create a customer invoice, confirm it and send it to the SII.
- Print it using Print > Invoice PDF copy (Chile).
- Scroll to the CEDIBLE section at the bottom of the PDF.
Cause of the issue:
The CEDIBLE footer is merged into l10n_cl.report_invoice_document, which account.report_invoice (odoo/addons/l10n_cl/views/report_invoice.xml) renders with t-lang set to the invoice partner's lang, not the database/user language. The disclaimer text was hardcoded in English and relied on the regular translation to be shown in Spanish, so as
soon as the partner's lang field isn't Spanish, the translation lookup falls back to the untranslated English source, regardless of the database language.
Solution:
This disclaimer is boilerplate mandated by Chilean law: it must always be printed in Spanish, independently of the invoice partner's or current user's language. The same template already follows that rule a few lines above for the SII stamp block ("Timbre Electrónico SII..."), which is hardcoded in Spanish instead of relying on translation.
opw-6390207
Forward-Port-Of: odoo/enterprise#124916Australian payroll no longer crashes if an employee's Tax Treatment Category is temporarily removed. The system now safely leaves the related tax treatment code empty until the required category is set again, helping payroll users continue editing employee records without interruption.
Original PR description
Currently, an error occurs when a user removes the Tax Treatment Category of an Australian employee. Steps to Reproduce: - Install the `l10n_au_hr_payroll` module with demo data. - Switch to an…
Currently, an error occurs when a user removes the Tax Treatment Category of an Australian employee. Steps to Reproduce: - Install the `l10n_au_hr_payroll` module with demo data. - Switch to an `Australian company`. - Open any `Employee` > `Payroll` > remove the `Tax Treatment Category` value. `UnboundLocalError: cannot access local variable 'code' where it is not associated with a value` After the [change] in selection field behavior, users can clear the value of the field. When the user removes the Tax Treatment Category value, the system computes the tax treatment code [1]. During this process, if no condition matches, the code variable is not initialized. Converting this uninitialized variable to a string [2] raises an error. This commit ensures that when the tax treatment category is not set, the tax treatment code is set to False with an early return. Since the tax treatment category is required field and compute the correct tax treatment code, once the category is set. [change]: https://github.com/odoo/odoo/pull/214422/changes/8d2a42ac419fdf7943a0c11beb8c5de6c6f85bef [1]- https://github.com/odoo/enterprise/blob/017743cbe97b629e9d9f1895b655014d4c3abbcb/l10n_au_hr_payroll/models/hr_version.py#L450-L451 [2]- https://github.com/odoo/enterprise/blob/017743cbe97b629e9d9f1895b655014d4c3abbcb/l10n_au_hr_payroll/models/hr_version.py#L515 No task ID
The payment status display now refreshes correctly when users move between batch payment records. This prevents outdated payment information from being shown, helping users see the correct signing or initiation status for each batch.
Original PR description
To display the `payment_online_status` field, we use a widget called `account_online_payment_refresh_button`. The issue is that the widget don't update the field value when switching from one record to another. Steps to reproduce: 1. Create 2 batch payments 2. Do a payment initiation with the first one, and sign it 3. Do another payment initiation with the second one, but don't sign it. 4. Open 1 batch, and try to switch records with the pager 5. You should see the value is not updated task-6420585
3 changes
Resolved issues and error corrections
The Timesheets overtime indicator now shows the same unit after users switch languages. This prevents confusion where remaining time could appear as hours instead of days for companies using day or half-day timesheet entry.
Original PR description
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet…
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet in the past week for this employee (e.g. 8 hours). 4. Observe the overtime indicator for the employee (it shows 32 hrs) (Click the left arrow to display it). 5. Change the timesheet encoding unit to "Days / Half-Days". 6. Return to Timesheets and observe the overtime indicator (it now correctly shows 4 days). 7. Install a language other than English (e.g. French). 8. Return to Timesheets and observe the overtime indicator again. Issue: -------- The remaining time value changes unexpectedly and displays 32 hours instead of 4 days. Cause: --------- In `get_timesheet_and_working_hours_for_employees`, the code determines whether the timesheet UoM is expressed in days by comparing the UoM name with the string `"days"`. Since UoM names are translatable, this comparison becomes invalid when the user language changes (e.g. `"jours"` in French), causing the logic to skip the day conversion and return values in hours instead. https://github.com/odoo/enterprise/blob/c48290e90fdeadf4f9ca8c44b035e601e7ed380a/timesheet_grid/models/hr_employee.py#L165-L169 Solution: ----------- Compare the timesheet UoM record with the day UoM record directly instead of relying on translated string values. see commit: https://github.com/odoo/enterprise/commit/5fbf194c5056566453a124812fd2614edfe19a82 opw-6279133 Forward-Port-Of: odoo/enterprise#120595
This fix adjusts the Swiss payroll declaration status check so BVG-LPP pension fund requests no longer include an unnecessary fund number. This helps prevent incorrect or rejected status checks during Swiss payroll electronic transmissions.
Original PR description
Forward-Port-Of: odoo/enterprise#126040
--- ## Steps to Reproduce: 1. Create a service product invoiced on delivered quantities with timesheet tracking (`invoice_policy = 'delivery'`, `service_type = 'timesheet'`). 2. Invoice a Sales Order line using this product for 20h in period A. 3. Create a partial credit note refunding 8h of that invoice, also in period A. 4. In a later, unrelated period B, log 10 new hours on the same SO line. 5. Create Invoice again using "Timesheets Period" set to period B only. ## Issue: The new
Original PR description
--- ## Steps to Reproduce: 1. Create a service product invoiced on delivered quantities with timesheet tracking (`invoice_policy = 'delivery'`, `service_type = 'timesheet'`). 2. Invoice a Sales Order…
--- ## Steps to Reproduce: 1. Create a service product invoiced on delivered quantities with timesheet tracking (`invoice_policy = 'delivery'`, `service_type = 'timesheet'`). 2. Invoice a Sales Order line using this product for 20h in period A. 3. Create a partial credit note refunding 8h of that invoice, also in period A. 4. In a later, unrelated period B, log 10 new hours on the same SO line. 5. Create Invoice again using "Timesheets Period" set to period B only. ## Issue: The new invoice for period B (10h) becomes a credit note (`out_refund`) for -2h, instead of a normal invoice, even though the 10h were never billed. Only reproduces if the SO line has any refund from an earlier period. ## Root Cause: `_recompute_qty_to_invoice()` builds `refund_account_moves` from every refund the SO has ever had, with no date filter. This is used to subtract already invoiced quantity from the current period's delivered quantity (`mapping`), which is correctly scoped to period B. Since `refund_account_moves` isn't scoped, period A's 20h invoice and 8h refund (net 12h) get pulled in again and subtracted from period B's 10h: ``` qty_to_invoice = 10 (period B new hours) - 12 (period A net, wrongly reused) = -2 ``` The negative result auto-converts the invoice into a credit note. ## Fix: Added `invoice_date` filtering to `refund_account_moves`, restricting it to the same `start_date`/`end_date` already used for the delivered-quantity domain. Period A's refund, being outside period B, is no longer counted, so `qty_to_invoice` correctly comes out as 10. ## Result: Invoicing a new period after an earlier partial refund now produces a correct invoice for the actual new hours, instead of a wrong credit note. opw : [6373449](https://www.odoo.com/odoo/project/49/tasks/6373449)
3 changes
Resolved issues and error corrections
This fixes Swiss payroll reporting so BVG-LPP pension status checks no longer include a fund number where it should not be sent. The change helps prevent incorrect or rejected pension declaration status requests for Swiss payroll users.
Polish JPK tax exports now use the vendor bill reference for the purchase document field when it is available. This helps exported tax files match official guidance and reduces the risk of incorrect supplier document identifiers in reports.
Original PR description
**Steps to reproduce:** - Install the `l10n_pl_reports` module and switch to a `PL Company`. - Create and confirm a vendor bill with a `Bill Reference` and `Taxes`. - Navigate to Accounting >…
**Steps to reproduce:** - Install the `l10n_pl_reports` module and switch to a `PL Company`. - Create and confirm a vendor bill with a `Bill Reference` and `Taxes`. - Navigate to Accounting > Reporting > Tax Report and select `This Month`. - From the dropdown, click `JPK` > `Export XML`. - Open the generated XML file and observe the `DowodZakupu` field. **Observation:** `DowodZakupu` contains the vendor `Bill Number` even when a `Bill Reference` is set. **Root Cause:** At [1], `DowodZakupu` is populated only with the vendor `Bill number`(`move_name`) instead of using the `Bill reference`(`ref`) when available. **Fix:** This commit ensures `DowodZakupu` contains the `Bill Reference` when it is available in JPK exports. **Reference:** https://www.podatki.gov.pl/media/eqrn3dey/broszura-jpk_vat-z-deklaracj%C4%85-od-1-lutego-2026-r-en.pdf (page 41) [1]: https://github.com/odoo/enterprise/blob/4b0404058b280136f6865090562f95e18d4d7e0b/l10n_pl_reports/data/jpk_export_templates.xml#L208 opw-6299827
Issue: The MyInvois payload computed `cbc:PrepaidAmount` as `amount_total - amount_residual`, treating every reconciled payment as a prepayment. A payment made on or after the invoice date is an ordinary settlement, not a deposit, but the code recognized it as one anyway. The values reported for `PrepaidAmount` were wrong regardless of the invoice date, and for a fully paid invoice this also collapsed `PayableAmount` to 0.00, which LHDN rejects. Root Cause: LHDN only considers a reconciled
Original PR description
Issue: The MyInvois payload computed `cbc:PrepaidAmount` as `amount_total - amount_residual`, treating every reconciled payment as a prepayment. A payment made on or after the invoice date is an…
Issue: The MyInvois payload computed `cbc:PrepaidAmount` as `amount_total - amount_residual`, treating every reconciled payment as a prepayment. A payment made on or after the invoice date is an ordinary settlement, not a deposit, but the code recognized it as one anyway. The values reported for `PrepaidAmount` were wrong regardless of the invoice date, and for a fully paid invoice this also collapsed `PayableAmount` to 0.00, which LHDN rejects. Root Cause: LHDN only considers a reconciled payment a genuine deposit if it was received before the invoice date. The code applied no date condition at all, so any payment reconciled against the invoice was added to `PrepaidAmount` and reduced `PayableAmount` accordingly. Fix: Only sum reconciled payment partials whose date is strictly earlier than the invoice date as prepaid, so regular payments are no longer misclassified as deposits. As a safety net, if the valid prepaid sum still covers the full invoice amount (e.g. a full advance payment), reset it to 0 so `PayableAmount` always reflects the full amount_total instead of being reported as 0. Also omit the `PrepaidPayment` node entirely when there is no genuine prepayment, rather than emitting it with a 0.00 amount. [Task-6404296](https://www.odoo.com/odoo/my-tasks/6404296)