Daily updates from Odoo
Friday, August 7, 2026
319 changes
3 changes
Resolved issues and error corrections
Task-6429727 Forward-Port-Of: odoo/odoo#280446 Forward-Port-Of: odoo/odoo#279204
Original PR description
Task-6429727 Forward-Port-Of: odoo/odoo#280446 Forward-Port-Of: odoo/odoo#279204
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens. To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here. runbot er
Original PR description
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens.
To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here.
runbot error-944120
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#280384During the forward port of #278378, the dynamic NSI file path variable was overwritten by an old hardcoded one, breaking the IoT package build. Forward-Port-Of: odoo/odoo#280885
Original PR description
During the forward port of #278378, the dynamic NSI file path variable was overwritten by an old hardcoded one, breaking the IoT package build. Forward-Port-Of: odoo/odoo#280885
8 changes
Resolved issues and error corrections
Issue: The `shape_color_sync_with_theme_color` tour failed randomly at its last step i.e after changing a theme preset color, the image shapes of the saved (custom) snippet sometimes still had the old color. This happened because `updateContent` called its callback without awaiting it, so the re-processing of the custom snippet images ran in the background after the color change operation had already completed. At normal flow this operation finishes before the previews are looked at, but
Original PR description
Issue: The `shape_color_sync_with_theme_color` tour failed randomly at its last step i.e after changing a theme preset color, the image shapes of the saved (custom) snippet sometimes still had the old color. This happened because `updateContent` called its callback without awaiting it, so the re-processing of the custom snippet images ran in the background after the color change operation had already completed. At normal flow this operation finishes before the previews are looked at, but the tour reaches the `Custom` snippets category within milliseconds and could assert the colors before the re-processing was done - making the outcome depend purely on timing. Fix: Awaiting the callback ensures the custom snippets content is fully updated before the operation completes, so by the time the loading indicator disappears the previews are guaranteed to be in sync. runbot-[944175](https://runbot.odoo.com/odoo/error/944175) Forward-Port-Of: odoo/odoo#276862
Before this PR, the tour could fail non-deterministically because it waited for `o_we_ui_loading` to disappear. However, this class was added with a delay in `operation.js` file, allowing the next tour step to run before the loader was shown. After this PR, the tour waits for `o_loading_screen`, which is added immediately and remains until the operation finishes. This ensures the tour waits correctly before proceeding. runbot-[941508](https://runbot.odoo.com/odoo/error/941508) Forward-Por
Original PR description
Before this PR, the tour could fail non-deterministically because it waited for `o_we_ui_loading` to disappear. However, this class was added with a delay in `operation.js` file, allowing the next tour step to run before the loader was shown. After this PR, the tour waits for `o_loading_screen`, which is added immediately and remains until the operation finishes. This ensures the tour waits correctly before proceeding. runbot-[941508](https://runbot.odoo.com/odoo/error/941508) Forward-Port-Of: odoo/odoo#277869 Forward-Port-Of: odoo/odoo#277651
[*] = html_builder Steps to reproduce: 1. Go to the Website app and drop any snippet. 2. Apply a background or image shape. 3. If a background shape is applied, click the **Flip Shape** option. 4. Go to the **Theme** tab and change the color palette. Issue: The shape color is not updated after changing the color palette. Reason: In the [commit](https://github.com/odoo/odoo/commit/aec8918018b92cbb5cb3dd761824d4), an edge case was left uncovered where applied background/image shap
Original PR description
[*] = html_builder Steps to reproduce: 1. Go to the Website app and drop any snippet. 2. Apply a background or image shape. 3. If a background shape is applied, click the **Flip Shape** option. 4. Go to the **Theme** tab and change the color palette. Issue: The shape color is not updated after changing the color palette. Reason: In the [commit](https://github.com/odoo/odoo/commit/aec8918018b92cbb5cb3dd761824d4), an edge case was left uncovered where applied background/image shapes were not re-rendered after changing the theme color palette, so its color was not refreshed to match newly selected palette. Forward-Port-Of: odoo/odoo#278325 Forward-Port-Of: odoo/odoo#273337
### Current behavior: When exporting a quotation PDF from the Sales Order a multi-word product name, e.g. "Pick Up", is split into 2 lines ### Expected behavior: When exporting a quotation PDF from the Sales Order a multi-word product name, e.g. "Pick Up", should stay on a single line when there is enough horizontal space in the Description column ### Steps to reproduce: 1. Sales > new Sales Order 2. Add a product whose name has at least two words, e.g. "Pick Up" 3. Export the Sales O
Original PR description
### Current behavior: When exporting a quotation PDF from the Sales Order a multi-word product name, e.g. "Pick Up", is split into 2 lines ### Expected behavior: When exporting a quotation PDF from…
### Current behavior: When exporting a quotation PDF from the Sales Order a multi-word product name, e.g. "Pick Up", is split into 2 lines ### Expected behavior: When exporting a quotation PDF from the Sales Order a multi-word product name, e.g. "Pick Up", should stay on a single line when there is enough horizontal space in the Description column ### Steps to reproduce: 1. Sales > new Sales Order 2. Add a product whose name has at least two words, e.g. "Pick Up" 3. Export the Sales Order report to PDF 4. Observe the second word is pushed to a new line, even with free horizontal space ### Cause of the issue: Commit https://github.com/odoo/odoo/commit/6d695e53743a58560a00c163b3ac16ee1f149761 added a `d-flex` in 19.3 to keep product image and name on the same line. The `o_product_name_cell` uses default shrink wrap. Under wkhtmltopdf's old QtWebKit engine the shrink-wrapped width is computed marginally short of the real text width; this margin is font-metric dependent, so with the slightly wider font like Open Sans the last word crosses the boundary and wraps onto a new line, even though the surrounding cell has room. ### Fix: - Add the Bootstrap `flex-grow-1` utility class to the o_product_name_cell div so it grows to fill the remaining width of the flex row - The image keeps its fixed 48px width and stays on the same line - Small UI change, so no unit test. Only manual test: Before: <img width="357" height="211" alt="image" src="https://github.com/user-attachments/assets/29458867-c7d0-4cc8-8397-4c97b7a2b91d" /> After: <img width="342" height="196" alt="image" src="https://github.com/user-attachments/assets/9a1ca99c-916f-4179-b9b9-67879885e9d8" /> opw-6434410
Task-6429727 Forward-Port-Of: odoo/odoo#280446 Forward-Port-Of: odoo/odoo#279204
Original PR description
Task-6429727 Forward-Port-Of: odoo/odoo#280446 Forward-Port-Of: odoo/odoo#279204
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens. To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here. runbot er
Original PR description
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens.
To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here.
runbot error-944120
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#280384Since https://github.com/odoo/odoo/pull/239898 Opening a livechat session in debug mode as a user without livechat access throws a traceback: `Invalid props for component BadgeTag: onDelete is not a function` This happens because `null` is passed to the `onDelete` prop, while the component validation expects a function. This commit fixes the issue. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280910 Forward-Por
Original PR description
Since https://github.com/odoo/odoo/pull/239898 Opening a livechat session in debug mode as a user without livechat access throws a traceback: `Invalid props for component BadgeTag: onDelete is not a function` This happens because `null` is passed to the `onDelete` prop, while the component validation expects a function. This commit fixes the issue. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280910 Forward-Port-Of: odoo/odoo#280679
During the forward port of #278378, the dynamic NSI file path variable was overwritten by an old hardcoded one, breaking the IoT package build. Forward-Port-Of: odoo/odoo#280885
Original PR description
During the forward port of #278378, the dynamic NSI file path variable was overwritten by an old hardcoded one, breaking the IoT package build. Forward-Port-Of: odoo/odoo#280885
5 changes
Enhancements to existing features
This commit adds 3 new `Tax Exemption Reason Code`: - VATEX-FR-F - VATEX-FR-I - VATEX-FR-J task-6333649 Forward-Port-Of: odoo/odoo#280537 Forward-Port-Of: odoo/odoo#278086
Original PR description
This commit adds 3 new `Tax Exemption Reason Code`: - VATEX-FR-F - VATEX-FR-I - VATEX-FR-J task-6333649 Forward-Port-Of: odoo/odoo#280537 Forward-Port-Of: odoo/odoo#278086
Resolved issues and error corrections
Task-6429727 Forward-Port-Of: odoo/odoo#279204
Original PR description
Task-6429727 Forward-Port-Of: odoo/odoo#279204
When there is no default confirmation template, An error is raised: AttributeError: 'bool' object has no attribute 'exists'. This happens because default_template is False, So calling default_template.exists() results in the error. The issue occurs during the upgrade process. ``` File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3142, in _init_column value = field.default(self) File "/home/odoo/src/odoo/19.0/addons/website_sale/models/website.py", line 52, in _default_confi
Original PR description
When there is no default confirmation template,
An error is raised:
AttributeError: 'bool' object has no attribute 'exists'. This happens because default_template is False,
So calling default_template.exists() results in the error. The issue occurs during the upgrade process.
```
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3142, in _init_column
value = field.default(self)
File "/home/odoo/src/odoo/19.0/addons/website_sale/models/website.py", line 52, in _default_confirmation_email_template
if default_template.exists():
AttributeError: 'bool' object has no attribute 'exists'
```
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#240874
Forward-Port-Of: odoo/odoo#237686After removing sale_order_many2one widget https://github.com/odoo/odoo/commit/0ecaa6e4c359681daf90c1757bcf71ba5e4d305c , there's no need for multiple sale_order_id definitions in the form view. In this commit, cleaning the redundant field definitions and restrict visibility of Sale Order smart button. task-4661781 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280740 Forward-Port-Of: odoo/odoo#255367
Original PR description
After removing sale_order_many2one widget https://github.com/odoo/odoo/commit/0ecaa6e4c359681daf90c1757bcf71ba5e4d305c , there's no need for multiple sale_order_id definitions in the form view. In this commit, cleaning the redundant field definitions and restrict visibility of Sale Order smart button. task-4661781 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280740 Forward-Port-Of: odoo/odoo#255367
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens. To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here. runbot er
Original PR description
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens.
To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here.
runbot error-944120
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#2803841 change
Resolved issues and error corrections
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens. To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here. runbot er
Original PR description
Before this commit, this test was sometimes failing. `edit("...")` validates the value by default (i.e. is followed by enter). It may happen that the dropdown is already open when doing so, and in this case, the first value is selected. However, it may often happen that it isn't open yet, so nothing happens.
To turn tests more robust, we typically turn off the auto confirm and call runAllTimers() to ensure the dropdown is open, then select the value. That's also what we did here.
runbot error-944120
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#2803841 change
Resolved issues and error corrections
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280556 Forward-Port-Of: odoo/odoo#280550
Original PR description
MyInvois expects the CountrySubentityCode to be fixed as '17' for customers located outside Malaysia, since Malaysian state codes don't apply to them. Set it to '17' instead of the raw state name for non-Malaysian customers. task-6388521 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280556 Forward-Port-Of: odoo/odoo#280550
63 changes
New functionality added to Odoo
Adds support for the Philippines annual 1604-C payroll tax filing, including a yearly summary and employee income detail file. This helps companies prepare required year-end tax declarations more directly in Odoo, while improving related employee data handling and test performance.
Original PR description
Implement support for the yearly 1604-C. It has two parts: - One summary sheet which recaps the monthly 1601-C declarations done during the year. - One DAT file containing the detailled income…
Implement support for the yearly 1604-C. It has two parts: - One summary sheet which recaps the monthly 1601-C declarations done during the year. - One DAT file containing the detailled income information of all employees in the company. This is similar to a list of all the forms 2316 for the company. --- As we are adding support for the 1604-C, we need even more details from the previous employment of the employees which joined during the year. As it starts to make for a lot of fields, we'll move them to a new model to avoid adding too many columns on the version/employee model. --- Currently, the computation of _compute_work_contact_details is not correct in the Philippines. The compute should set the VAT, but it is missing from the depends causing it not to work as expected. Also add a computed field to store the branch code of the employee, allowing to easily fetch it when needed in the declarations. --- Improve the performance of the declarations test by batching as much as possible during the setup of the tests. Also merge the foreign employee and high earner 2316 tests in once to reduce duplications. This reduces the time it takes to run the current test suite by around 25% (calculated on the fly based on logs, to take with a grain of salt) and simplify the individual test implementations. It will also help keep the performances in line when adding tests for 1604-C which require to create 1601-C and 2316 for the period. task-6278100
Philippine payroll now supports preparing the monthly Social Security System contribution declaration required from employers. Businesses can generate the required semicolon-delimited employee contribution file more easily, reducing manual compliance work.
Original PR description
Philippine employers must submit a monthly contribution collection list to the Social Security System, as a semicolon delimited text file listing every employee, their compensation and their status. This adds a monthly SSS Contribution declaration from which that file can be generated. task-6321522
Enhancements to existing features
Belgian payroll now shows a warning when an employee has both private car kilometers and bike kilometers set for the same daily reimbursement context. This helps payroll teams spot combinations that cannot legally be reimbursed together without blocking their workflow.
Original PR description
Problem: Legally, the daily reimbursement of bike travel and private car travel cannot be cumulated. We don't want to prevent the user from doing so, but we still want to warn them. Solution: We added an explicit warning on the employee form using the `hr.payroll.warning` model. Task-6389211
Accounting-related automated tests were updated to match a platform change in how journal entry line descriptions are stored. This helps keep quality checks aligned with the latest accounting data model without changing business workflows.
Original PR description
This commit updates the HOOT tests to reflect the community change where the `account.move.line` `name` field has been converted from `Char` to `Text`. See the corresponding community commit for additional details. See Also: - https://github.com/odoo/odoo/pull/278081 - https://github.com/odoo/upgrade/pull/10909
Users can now prepare and send signature documents from a phone using a mobile layout with easy access to fields, signers, and documents. The editor also improves drag previews, selection highlighting, and touch controls so mobile setup is more practical and reliable.
Original PR description
Preparing a document for signature on a phone was nearly impossible. The editor relies on a desktop side panel that does not fit on a small screen: the field types could not be reached or dragged…
Preparing a document for signature on a phone was nearly impossible. The editor relies on a desktop side panel that does not fit on a small screen: the field types could not be reached or dragged onto the document, and there was no usable way to manage the signers or the documents. In practice, users had to wait until they were back on a computer to prepare and send a signature request. On small screens, the side panel is now replaced by a bottom sheet with three tabs (Fields, Signers, Documents). Fields are dragged from the sheet onto the document — the sheet steps aside during the drag — and signers and documents are managed like on desktop. The sheet resizes to a few useful heights and moves up while typing so the keyboard does not hide what is being edited. The layout is selected on env.isSmall, which swaps the sidebar for a new SignTemplateMobileShell while the SignTemplate root and its state stay shared. The shell is a bottom sheet that snaps between three heights (peek, half, full) via a handle drag with flick-velocity detection, and collapses on Escape or the hardware back button; while an input is focused it expands and pads its content by the keyboard overlap derived from the visual viewport. The Signers and Documents tabs extend the desktop sidebar components, inheriting their behavior and overriding only the template. task-5149968
Belgian payroll eco voucher calculations now use working days to determine employee entitlements. This improves payroll accuracy and helps align voucher amounts with actual work patterns and related compliance checks.
CRM lead cards no longer show the phone plus/minus control for quickly adding or removing call activities, reducing visual clutter for upcoming designs. Users now add call activities through a selection-based action in kanban or list views, also available for contacts, with clearer handling when records already have a call or lack a phone number.
Original PR description
*: test_mail_enterprise Before this commit, on CRM leads kanban cards, there was a phone and plus/minus icon button that allowed users to easily add/remove call activities due or overdue for today…
*: test_mail_enterprise Before this commit, on CRM leads kanban cards, there was a phone and plus/minus icon button that allowed users to easily add/remove call activities due or overdue for today for that lead. While this was nice, it encumbered the card and will not fit nicely in new designs anymore. Instead, this is replaced by an action button that appears when you select records, in kanban or lists. This is also added for simple contact records (all models using the `voip.queue.mixin` at the moment). Side-effects: - You don't have to possibility to delete calls from the queue easily anymore (you have to do it one-by-one). Functionally it might be better to have the opportunity to cancel and log the reason anyway. - If you try to add a call activity while there is already one, it does nothing for the related call. - If you try to add a call activity but there is no phone number, it will prevent you to add the activity on all selected calls (with a message explaining what record prevented the action). task-6377768
The Mexico electronic invoicing payment method settings are now placed under the main Accounting menu. This aligns the enterprise menu with recent community changes, making the option easier to find in its expected location.
Original PR description
Move to the accounting root menu where it belongs. See also: - https://github.com/odoo/odoo/pull/280715
The signing app had an unused internal messaging setup removed. This cleanup reduces maintenance overhead without changing how users create or manage signature requests.
Original PR description
This commit removes a `useSubEnv` which defined a bus and is not used anymore.
This update adds automated checks for the POS IoT payment connection logic. It helps reduce the risk of payment terminal issues reaching customers by catching problems earlier during development.
Original PR description
We add tests for the `PaymentInterfaceIot` class.
Users can now resend invitations to document members who were previously invited but have not signed up yet. This makes it easier to follow up with pending collaborators directly from the document sharing dialog, without affecting active members.
Original PR description
This commit allow users to re-invite document members who were previously invited but haven't logged in yet, from the document share dialog. The 're-send' option is only displayed for members who have not signed up yet. Task-6040696
The map view now uses the clicked item’s intended opening mode instead of guessing whether to open records in the current view, a new window, or a dialog. This makes interactions more consistent, reuses configured list and form views, and supports opening multiple records in a dialog when needed.
Original PR description
This is a follow-up of 75cac501edd, the controller no longer infers by itself whether a record should open in a dialog: the caller now passes an explicit target ('current', 'new_window' or 'dialog'), matching what the template already knows when a click comes from the unlocated records list.
Also reuse the list/form view ids defined on the action (same approach as the pivot view) instead of hardcoding false, and extend the dialog target to support opening several records at once.
task-6378012This update improves the reliability of automated tests by using a shared time-mocking helper across several Odoo Enterprise modules. It helps ensure date- and time-dependent test scenarios behave consistently, reducing false failures and supporting smoother quality checks.
Original PR description
Use the new function so that everything gets patched correctly. https://github.com/odoo/odoo/pull/280810
This update adds a sandbox mode for Belgian DMFA payroll declarations, allowing tests to simulate official reporting flows without affecting real submissions. It helps teams validate payroll accounting behavior more safely and reliably before production use.
Recruiters can now use the AI email composer when refusing an individual applicant, not just when handling multiple applicants. This makes it easier to draft and edit consistent, professional refusal messages in the single-applicant workflow.
Original PR description
…se wizard Refusing a single applicant now opens a dedicated wizard where the email body is rendered and editable. The mail_composer_chatgpt widget was only set up on the multi-applicant wizard, so it was missing there. Inherit the new applicant.refuse.single form to add the widget, mirroring what is already done for applicant.get.refuse.reason. task-6361850
Adds payroll withholding support for Michigan, Missouri, Kentucky, Utah, South Carolina, and Kansas. This improves payroll accuracy and compliance for employers operating in these states, including local city and county taxes where applicable.
Original PR description
Add state income tax withholding for Michigan, Missouri, Kentucky, Utah, South Carolina and Kansas. Michigan and Kentucky are flat rate states with a personal exemption or standard deduction.…
Add state income tax withholding for Michigan, Missouri, Kentucky, Utah, South Carolina and Kansas. Michigan and Kentucky are flat rate states with a personal exemption or standard deduction. Michigan also taxes residents and nonresidents of its 24 cities that have their own income tax. The rate depends on whether the employee lives or works there. Kentucky also has a county occupational tax. 87 of its 120 counties charge one, so we have to support it. We opted to create a new model l10n_us.res.county and add a m2o on res.city. It will be useful for tax reports down the line. Missouri and South Carolina use progressive brackets. Missouri also withholds a flat 1% earnings tax for employees who live or work in St. Louis or Kansas City. Utah uses a flat rate reduced by an allowance. That allowance gets smaller as wages go above a threshold, instead of a fixed exemption like other states. Kansas' brackets and allowances depend on both pay frequency and filing status. Married filing jointly uses different numbers, but single, head of household, and married filing separately all use the same ones. task-6270166
Belgian payroll now centralizes holiday attestation details for new hires and automatically calculates paid time off allocations and recoverable holiday pay amounts. This reduces manual work and errors when employees move between employers with different working schedules or rates.
Original PR description
[IMP] l10n_be_hr_payroll: Holiday attestations rework Encoding the holiday pay attested by a new hire's previous employer was split across separate simple/double N and N-1 fields on hr.employee and…
[IMP] l10n_be_hr_payroll: Holiday attestations rework Encoding the holiday pay attested by a new hire's previous employer was split across separate simple/double N and N-1 fields on hr.employee and an ad-hoc l10n.be.double.pay.recovery.line model, and the amount to recover and number of days to allocate had to be computed by hand from the certificate, which is complex and error-prone whenever the employee's work rate changes. This commit merges simple and double holiday pay encoding into a single l10n.be.holiday.attest model on the payroll tab, and compute automatically, from the certificate (previous year: days assimilated, working regime, work fraction) and the current contract (current regime and fraction): - the number of paid time off days to allocate (LEAVE120 allocation and a dedicated unpaid work entry type/leave type), - the maximum amount to recover, prorated against the employee's work rate so that a change of regime between the two employers no longer requires a manual computation. task-5928591
This update adjusts Belgian payroll work entry settings so the right working schedules remain available when new schedule-selection data is used. It also removes a recently added restriction that could unnecessarily limit schedule choices for payroll users.
Original PR description
related PR adds a new field resource_calendar_selectable in the module hr_work_entry this PR updates/sets the value of this filed for some work entry types and reverts Task#6333928 that added a restrictive domain on working schedules. Task#6364149
The subscription portal now hides sections that do not contain any billable lines. This makes customer-facing pages clearer and avoids confusion from empty optional sections that looked like errors.
Original PR description
In portal, a section was always displayed even when it had no billed line. Empty sections (especially optional ones) gave the impression the page was bugged. Only show a section when it contains at least one line to bill. task-6280705
The salary contract update process was adjusted to use a cleaner data format when handling contract changes. This should make the flow more reliable and easier to maintain, including for Belgian payroll-specific handling.
The Belgian payroll rules now include the 2026 night work premium hourly rate for CP 200 employees. This helps payroll calculations stay aligned with the latest required rate for the upcoming year.
Original PR description
. Add cp_200_premium_pay_night_hourly_rate value for 2026 task-6443017
Belgian payroll now includes additional official reasons for ending an employee collaboration. This helps HR teams select the correct standardized reason when processing departures and improves alignment with Belgian reporting requirements.
Original PR description
Before ending the collaboration with employee in Belgium. We should put the reason behind the end of collaboration. There is given official list of end reason that can be used to explain it. Currently, In belgium localization, there are few missing reason. In this PR expected to add the missing reason from the offical form: - (1) end of contract due to notice given by the employer - (2) end of contract due to termination by the employer - (5) Force majeure because of the employee's permanent incapacity for work - (7) End of contract for fix-term employmen - (8) End of contract for specific work task-6396239
This update prevents duplicate default prompt setups for the same AI agent context, reducing inconsistent behavior and runtime errors. Existing duplicates are cleaned up during upgrade so the new rule can be applied safely.
Original PR description
## Summary This PR adds a unique index on `ai.composer` to prevent duplicate **Default Prompts** for the same **AI Agent**, **interface key**, and **focused model**. Previously, multiple records…
## Summary This PR adds a unique index on `ai.composer` to prevent duplicate **Default Prompts** for the same **AI Agent**, **interface key**, and **focused model**. Previously, multiple records could exist for the same `(ai_agent_id, interface_key, focused_model_id)` combination, leading to inconsistent data and runtime issues such as singleton errors when the AI composer expected a single matching record. The unique index uses PostgreSQL's `NULLS NOT DISTINCT`, ensuring that `NULL` values in `focused_model_id` are treated as equal and duplicate generic Default Prompts are also prevented. ## Changes - Add a unique index on the `(ai_agent_id, interface_key, focused_model_id)` triplet. - Use `NULLS NOT DISTINCT` to enforce uniqueness even when `focused_model_id` is `NULL`. - Add test cases to verify the unique constraint behavior. ## Upgrade Duplicate `ai.composer` records are removed before applying the unique index. Upgrade PR: https://github.com/odoo/upgrade/pull/10819 --- opw-6323764 Forward-Port-Of: odoo/enterprise#121609
This update strengthens the automated checks around scheduled marketing campaign activity processing. It helps ensure background marketing actions run with the right settings and reduces the risk of future regressions as the feature is expanded.
Original PR description
Just quickly cover cron usage when executing activities, aka the other main marketing automation cron. Improve other tests about cron usage. Prepares Task-6425785 [marketing_automation] Incremental sync Prepares Task-3866422 [marketing_automation] Overhaul application
Payment files now include the building number in ISO20022 address data, aligning SEPA credit transfer and direct debit exports with requirements that become mandatory in November 2026. This helps businesses remain compliant with upcoming banking standards and reduces the risk of payment file rejections later.
Original PR description
This commit adds the <BldgNb> node in the iso20022 XML files, as it will be mandatory starting November 2026. Linked: https://github.com/odoo/odoo/pull/271855 task-6317758 Forward-Port-Of: odoo/enterprise#126734 Forward-Port-Of: odoo/enterprise#121674
Payroll accounting entries are now grouped more efficiently when many payslips are processed together. This reduces validation time for large payroll runs, helping accounting teams complete batch processing much faster without changing the resulting entries.
Original PR description
Description =========== When batch payroll journal items are enabled, all payslips for the same journal and accounting period contribute to one accounting move. For every salary line,…
Description
===========
When batch payroll journal items are enabled, all payslips for the same journal and accounting period contribute to one accounting move.
For every salary line, `_prepare_slip_lines()` searched the complete list of previously prepared move lines for both the debit and credit entries. It also created a new `line_ids + new_lines` list for every search. As the move grew, accounting validation time grew quadratically.
This commit keeps a shared index while preparing the move. It is keyed by the stable aggregation fields: line name, account, and analytic distribution.
Only lines in the matching bucket must then be checked for compatible debit or credit signs and tax tags.
Benchmark
=========
The blueprint creates 500 validated payslips and 10,000 payslip lines. All lines are accumulated into one accounting move.
On a fresh database with `hr_payroll_account` and `populate` installed, populate the data with:
```sh
./odoo-bin populate\
-d <database> \
-b hr_payroll_account.benchmark_payroll_account_move_creation \
--seed 42
-j 4
```
Run the benchmark with from the [gist](https://gist.github.com/pivi-odoo/3a5a21bb42f82d5ae10646d15986013b):
```sh
./odoo-bin shell \
-d <database> \
< benchmark_prepare_slip_lines.py
```
The benchmark measures `_get_account_move_vals()` with a cleared ORM cache before every sample.
| Payslips | Input lines | Move lines | Before | After | Speedup |
|---------:|------------:|-----------:|--------:|-------:|--------:|
| 20 | 415 | 398 | 0.634s | 0.093s | 6.8x |
| 50 | 1004 | 986 | 3.040s | 0.178s | 17.1x |
| 100 | 1992 | 1974 | 11.865s | 0.344s | 34.5x |
| 200 | 3942 | 3884 | - | 0.648s | - |
Reference
=========
task-6429789The Indian payroll module now uses clearer tooltip text for ESIC employee and employer contributions. The updated wording explicitly states the wage limits for regular employees and Persons with Disabilities, helping payroll users apply the rules with more confidence.
Original PR description
Clarify the ESIC employee and employer contribution tooltips by using clearer wording and explicitly mentioning the wage limits for regular employees and Persons with Disabilities (PwD). Task-6451829
Belgian payroll reporting now excludes employees marked as not subject to withholding taxes from key fiscal reports. This helps ensure employees who are not taxed in Belgium are not incorrectly included in 281 and 274 tax reporting.
Original PR description
Purpose: Some employees should not have any withholding tax and some should not have any fiscal report neither as they are not taxed in belgium. - excluded employees with `no_withholding_taxes` checked from 281 and 274 reports. task-id: 6377289
The Time Off Gantt view popover now lets users edit leave records directly and split a leave into two parts. This makes scheduling adjustments faster and reduces the need to navigate away from the planning view.
Original PR description
- Make the leave record in the popover editable. - be able to split a leave in 2 task-6345738
The Belgian payroll exemption wizard and reports now consistently show the Start-up and Micro-enterprise sections only when the company is eligible. This helps prevent employers from generating irrelevant or invalid 274.60/274.61 report sections when their SME exemption status is missing or expired.
Original PR description
Make the form view, PDF, and XLSX reports consistent when reporting the Start-up (274.60) and Micro-enterprise (274.61) exemptions. Specifically: - Hide the "Start-up/M-E" tab in the wizard form view if the company's exemption SME status setting is not configured. - Do not generate the 274.60/61 tab/worksheet in the XLSX file if the employer is ineligible (i.e. status is empty or CBE has expired). - Do not generate the 274.60/61 page in the PDF printout if the employer is ineligible. task-6421989
Live chat and Discuss now have a cleaner interface with fewer distracting icons. Users can translate new messages more easily within a conversation, canned responses are ordered by recent usage, and conversations can be downloaded before a chat ends.
Original PR description
This commit aims to improve the UI of livechat and discuss by removing clouding icons. It improves the UX by having the option to translate all new messages when translating one message, this is a client side option meaning it would need to be done again after refresh and is isolated to the current channel. We also improve the sort of canned responses by using the last used canned function Odoo-wide (depends on other users as well) and being able to download conversations even when the livechat is not ended. https://github.com/odoo/odoo/pull/270509 Task-6272656
Certificates of Completion for Sign requests now show timestamps in the sender's timezone instead of always using UTC. This makes the certificate easier to understand for signers and reduces confusion for teams working across regions.
Original PR description
The Certificate of Completion always displayed timestamps in UTC, which confused signers in non-UTC regions. They are now shown in the request sender's timezone. task-6046266
Belgian payroll now warns users when company car details are updated after the DMFA declaration has been prepared. It also records the update date, helping payroll teams identify changes that may affect reporting accuracy and compliance.
Original PR description
Task: 6201452
Improves the Brazilian fiscal localization screens and labels so business users can configure tax and fiscal data with clearer wording and fewer duplicate options. It also improves product and contact fiscal code handling, archiving of NBS codes, and gives clearer validation messages for correction letters before they reach external tax services.
Original PR description
This contains a bunch of UX and data cleanups across the Brazilian fiscal localization: - Selection labels for activity sector, tax regime and SPED type now have human-readable text instead of the…
This contains a bunch of UX and data cleanups across the Brazilian fiscal localization: - Selection labels for activity sector, tax regime and SPED type now have human-readable text instead of the raw API codes, SPED type is prefixed with its official code, - NCM codes get a new is_service flag distinguishing goods (NCM) from services (LC116), with search filters, a "NCM / LC Codes" menu and a product code field filtered on the product type, - NBS codes can now be archived, - Clean up the settings: rename "Simplified Regime ICMS Rate" to "ICMS Simplified Credit Rate" with a Brazil-specific tooltip, drop the duplicate CBS/IBS Normal toggle (kept on the company contact) and align the CNAE field, - Show the operation type Technical Name on its form, - Reorder the contact Fiscal Information fields and rename the product "Transport Cost Type" to "Additional Cost Type", - Open the partner form when a single contact is missing Avatax fields, and the Brazil-specific list for several, - Validate the correction letter reason length in Odoo so a short reason no longer shows a raw XML schema error from Avalara, task-6327269
Appointment pages now provide clearer placement information for floating content snippets. This helps ensure page elements are positioned more appropriately when editing appointment pages, improving consistency for website editors.
Original PR description
Community commit introduces a new plugin responsible for relocating floating snippets. In this commit we provide a scope that adds info of where the snippet can be on an appointment page. Community pr: https://github.com/odoo/odoo/pull/268301 task-6034130, task-5447310
Resolved issues and error corrections
The payroll pay run validation test now confirms the validation prompt before checking the result. This prevents automated checks from getting stuck and improves reliability of payroll quality testing.
Original PR description
The Validate button on the pay run payslip card carries confirm="Are you sure you want to proceed?", so clicking it opens a confirmation dialog instead of validating straight away. That confirm used to live only in hr_payroll_account, which is why only that module's tour patch clicks "Ok". 73a52f1c662 moved the attribute to the base hr_payroll view and dropped the hr_payroll_account override, but left the base tour clicking Validate and immediately asserting the payslip step is green. On builds where hr_payroll_account is not installed the modal stays open, the payslips stay draft, the pay run task-6449105
Several parts of the system now properly clean up background event listeners when screens or interactions close. This prevents gradual slowdowns and avoids repeated duplicate actions during long user sessions.
Original PR description
*: knowledge,social_push_notifications,web_studio Bus listeners were not removed on component/interaction destruction, causing memory leaks and duplicate event handling over a session. Add useBus() for Owl components and addBusListener() for public interactions to automatically manage listener cleanup.
This update adds a missing module dependency so barcode quality checks work reliably with manufacturing barcode features. It prevents test failures and ensures the related components load together as expected, with no expected change to daily user workflows.
Original PR description
Before this commit, this bridge patches the barcode mrp model of stock_barcode_mrp while not depending on it. This goes unnoticed in the backend, where every installed module lands in the same bundle, but a Hoot test file only loads the modules of the dependency closure of its addon, so the first test suite added here dies on "error while registering suite". This commit adds the missing dependency. stock_barcode_mrp is auto installed on top of stock_barcode and mrp, both already required here, so it comes along with this module anyway.
Fixes an issue where customer follow-up reminders could choose different overdue invoice lines in different parts of the system. This ensures the correct follow-up step and responsible person are applied consistently, avoiding missed or incorrectly assigned reminder activities.
Original PR description
[FIX] account_followup: fix oldest follow-up move line mismatch
`compute_followup_line` and the `_get_followup_data_query` SQL query were inconsistent when determining the oldest move line.
runbot-944619The salary calculator now keeps the selected net monthly budget view instead of briefly showing it and reverting to yearly values. This prevents confusion when HR users test salary scenarios and helps ensure temporary calculator changes are safely rolled back as intended.
Original PR description
### Description of the error in the salary calculator, when selecting 'net per month', the form glitches: it shows for a brief moment the desired behavior, until the budget type returns to yearly with yearly values. ### Explanation In the context helper of version, we can create a savepoint. This savepoint is important in the context of the calculator: if we select an employee, then play around with their numbers, it is important that the modification made are rolled back and that we reach a savepoint. However, we make sure that we don't run recursively the context helper. This is an issue: if the calling context, which is called with `invalidate = False`, calls once again the context (in the case of a compute triggering another compute for example) with `invalidate = True`, we will just get out of the context before validating it. __ task-6357973
The quality control spreadsheet tests were adjusted so they work consistently whether or not demo data is installed. This reduces false test failures and helps keep quality control spreadsheet features stable during development.
Original PR description
Commit [1], introduced through PR #122583, added tests for the quality spreadsheet selector and the session info insertion flag. These tests assumed that the template they created was the only quality spreadsheet template. This assumption does not hold when demo data is installed because the demo template remains after the test template is deleted. Consequently, the selector remains available and `can_insert_in_spreadsheet` remains true, causing the final assertions to fail. Remove existing quality spreadsheet templates at the beginning of each test so they fully control the template existence state. This makes the tests independent of demo data. The cleanup runs inside the test savepoint and is rolled back after each test. [1] https://github.com/odoo/enterprise/commit/ef3f2a2e4218d0ec8d83c2df2e8bdd518d41c7ca
Belgian payroll declarations now correctly treat non-equated time credit leave as having no reorganization measure. This prevents invalid ONSS declarations caused by reporting the wrong measure for affected employees.
Original PR description
According to the specifications, time credit not equated (LEAVE14713) should behave similarly to MEDIC01, but with one key exception: it must not trigger a reorganization measure. Previously, it was grouped with MEDIC01 in the DMFAOccupation initialization. This caused it to incorrectly evaluate to True and report a reorganization measure of 3 or 4 to the ONSS. This commit removes LEAVE14713 from that specific condition so it correctly falls through to the default block, assigning -1 (no measure) for the XML output, preventing invalid declarations. task-6431854
The timesheet assistant now highlights total hours correctly against expected working hours. It shows green when recorded time is below expected hours and avoids misleading coloring for flexible-hour schedules, helping users interpret their timesheet status more accurately.
Original PR description
Fix the wrong color selection of total hours on the timesheet assistant page before: green if total time > working hours after: - green if total time < working hours - no color for flexible hours --- task-6409938 Forward-Port-Of: odoo/enterprise#126484 Forward-Port-Of: odoo/enterprise#125177
The Vietnam reporting module now classifies short-term loan balances under held-to-maturity investments in line with Circular 99/2025. This helps businesses produce balance sheets that match current Vietnamese reporting requirements.
Original PR description
### Expected behavior: As per circular 99/2025, short-term loan (12831) balance is required to fall under Held to Maturity Investment (Code 123) instead of 112, translated: ``` Short-term held-to-maturity investments (Code 123): includes held-to-maturity investments with a remaining term of 12 months or less from the end of the accounting period, such as term deposits, bonds, commercial paper, loans, and other debt securities. This item does not include held-to-maturity investments that have been presented in the item “Cash equivalents” ``` ### Steps to reproduce: Install `l10n_vn_reports` module ### Fix: PO validated: Update the Balance Sheet code formula for the 12381 account opw-6413120 Forward-Port-Of: odoo/enterprise#126763
The Statement of Account option from the Malaysian reporting module is now shown and usable only for Malaysian companies. This prevents users in other countries from seeing or running a country-specific report that does not apply to them.
Original PR description
### Current behavior: After installing `l10n_my_reports`, the Malaysian's Statement of Account button appears on Aged Receivable for every company, and the partner Action "Print Statement of Account" can be run from non-MY companies ### Expected behavior: To avoid user confusion, it is advised to restrict its visibility so that it is only accessible to Malaysia-specific companies ### Steps to reproduce: 1. Install `l10n_my_reports` 2. Switch to a non-Malaysian company 3. Open Invoicing > Reporting > Aged Receivable 4. Observe the "Statement of Account" button on partner lines ### Cause of the issue: Missing checks for 'MY' company country code in UI and print report action ### Fix: - show the Aged Receivable SoA button only when `company_country_code === 'MY'` - guard `action_print_report_statement_account` for non-MY companies opw-6340854 Forward-Port-Of: odoo/enterprise#126597 Forward-Port-Of: odoo/enterprise#126172
Portal users editing Knowledge articles can now view and update existing voice transcription text without seeing the voice recording controls. This keeps the recording feature limited to internal users while preserving portal users' ability to work with article content.
Original PR description
Portal users can edit Knowledge articles but should not have access to the voice recording feature, which is reserved for internal users. The readonly component is already used in read-only views, so reusing it in the editor for portal users is safe, it still renders the existing transcription content correctly without exposing any recording controls. Portal users can still edit the text content inside the component thanks to the editable descendants concept, which allows the editor to manage specific editable areas even within a readonly component. Task-6320461 Forward-Port-Of: odoo/enterprise#126606
This fixes an issue in UK reports where selecting a tax unit while filing a VAT return could fail because the report options were read incorrectly after an internal framework change. Users can now confirm the tax unit selection without the process breaking.
Original PR description
Enterprise counterpart of odoo/odoo#281228 — same scope, same criterion. The Owl 3 migration changed contracts (refs became `signal.ref()`, `AccountReportController.options` became a signal) and left…
Enterprise counterpart of odoo/odoo#281228 — same scope, same criterion. The Owl 3 migration changed contracts (refs became `signal.ref()`, `AccountReportController.options` became a signal) and left some consumers reading the old shape. This PR collects **our own oversights**: call sites that were already on master when we changed the contract under them. Forward-ports that landed *after* a contract change are handled separately, in odoo/enterprise#127207, so the two can be reviewed and backported independently. ### Fixed - [x] `l10n_uk_reports` — `patch_button_report.js` read `this.options.available_tax_units` on what Reactivalypse had turned into a signal three weeks after this code landed. Confirming "Select Tax Unit" when filing a VAT return from a company that belongs to a tax unit throws on `[0]`, and `saveSessionOptions` was handed the signal itself rather than the options. ### Coverage Enterprise has not had the systematic sweep that odoo/odoo#281228 got. `rootRef.el` is clean, and the ref-contract check over forward-ports came back clean apart from #127207, but the equivalent of that PR's `signal.ref()`-declaration audit has not been run here, and reads of properties a refactoring turned into signals — the `options` shape above — have no syntactic tell and are not greppable at all. Expect more sites to land in this PR.
Customer balances in Point of Sale now show the correct amount when the company and PoS use different currencies. This prevents customers’ “Total Due” from being understated or overstated because pay-later payments were converted twice.
Original PR description
Steps to reproduce: - set the company currency to XCG - set the PoS sales journal currency and the PoS pricelist currency to USD - configure a XCG <-> USD rate - create a customer without any…
Steps to reproduce: - set the company currency to XCG - set the PoS sales journal currency and the PoS pricelist currency to USD - configure a XCG <-> USD rate - create a customer without any outstanding balance - open the PoS, create an order of USD 100 and validate it with the Customer Account (Pay Later) payment method - open the Customers screen and look at the Total Due of that customer Issue: The Total Due shows about USD 55.56, i.e. the amount converted once too many, instead of the expected USD 100. Cause: get_total_due() sums two amounts that are not expressed in the same currency before converting them. partner.total_due comes from the accounting entries, it is the sum of account.move.line.amount_residual and is therefore in company currency, while total_settled is the sum of pos.payment.amount of the still open sessions, which is in the currency of the order, so the PoS one. The addition is done first and the result is then converted from the company currency to the PoS one, so the pay later payments end up converted a second time. opw-6403320 Forward-Port-Of: odoo/enterprise#126849 Forward-Port-Of: odoo/enterprise#125798
This fix restores a required loading component for public signing pages. It prevents automated user journeys and related signing interactions from failing, helping maintain a stable document signing experience.
Original PR description
The [linked community PR] retriggers clicks for interaction once they have started, using the existing lazyloader logic. [Commit 407903c] removed the lazyloader from the `sign.assets_public_sign` bundle. This new PR highlighted that removing it there caused several test tours to fail (within `sign` and other modules depending on it). [linked community PR]: https://github.com/odoo/odoo/pull/247404 [Commit 407903c]: https://github.com/odoo/enterprise/commit/407903cedca635a16929634afe41f489d3b56970 task-5221179
This fixes an issue where quickly clicking to expand the same financial report line could create duplicate hidden or visible rows and then stop the line from collapsing properly. Users can now expand and collapse report lines reliably, even on slow connections or with repeated clicks.
Original PR description
Steps to reproduce:- - Open any report. - Click on a particular line to unfold more than once very fast(or throttle network to 3G) - Once line is unfolded click again to fold that line. - Line is not…
Steps to reproduce:- - Open any report. - Click on a particular line to unfold more than once very fast(or throttle network to 3G) - Once line is unfolded click again to fold that line. - Line is not folding. Cause:- - When we clicked multiple times to unfold line, duplicate child lines were created(as many times as many times we clicked). - Because when first promise was not resolved so `unfolded = false` and we clicked again so new promise also tries to unfold the same line, resulting in unfolding the same line multiple times. - In version 17.0 these duplicate child lines are created but somehow not visible but it breaks `foldLine`. From version 18.0 onwards these duplicate child lines are visible. Solution: In `unfoldLine` set the flag `unfolding`. So in all clicks other than first, we get `unfolding = true` and don't proceed further, preventing unfolding the same line multiple times. task-6260425 Forward-Port-Of: odoo/enterprise#126765 Forward-Port-Of: odoo/enterprise#120392
This fixes an issue where Tyro card payments with a surcharge could sometimes validate the point-of-sale order before the surcharge was added. Businesses using Tyro can now rely on the final order total including the surcharge consistently.
Original PR description
Currently when completing a Tyro payment with a surcharge fee in some cases there is a race condition preventing the surcharge line to be added to the pos order before its validation This PR fixes that issue opw-6402191 Forward-Port-Of: odoo/enterprise#126035 Forward-Port-Of: odoo/enterprise#125852
This fixes an error that occurred when updating start or end contract dates for multiple Belgian payroll employees at once. HR teams and automated processes can now apply these date changes in batches without the operation failing.
Original PR description
Currently, attempting to update the `contract_date_start` or `contract_date_end` fields on a recordset containing multiple employees triggers a `ValueError: Expected singleton`.
Steps to reproduce:
1. Ensure the `l10n_be_hr_payroll` module is installed.
2. Attempt to execute `employees.write({'contract_date_start': '2026-01-01'})` where `employees` is a recordset of multiple employees.
3. Observe the `ValueError: Expected singleton` traceback.
task-6442141
task-6409893This fixes incorrect gender values in Belgian payroll demo employee records. It updates 23 employees and fills one missing value, improving the accuracy of payroll test/demo data.
Original PR description
Some records got the gender mixed when adding importing demo data. This fix solves the issue for 23 employees and add a gender for a employee with that field previously empty. related-6364398
Commission achievement reports now include adjustments dated in the future when they fall within the relevant plan period. This gives businesses a more complete and accurate view of expected commission performance instead of hiding valid planned adjustments.
Original PR description
Before: - Adjustments dated after today were hidden in the Achievement report, even when the date was within the plan period. After: - Removed the today fallback from date filters in the achievement report. - All adjustments within the plan period are now visible. Task: 6292361
The VoIP keypad behavior has been clarified so only the main dialer or transfer flow can start calls or transfers. This prevents an in-call keypad action, such as pressing Enter after typing tones, from accidentally starting a new call.
Original PR description
The keypad had 3 calling usecases: - Hitting "Enter" in the number/contact input - Clicking a call/phone button - Longpress on the voicemail button This commit moves the responsibility of those…
The keypad had 3 calling usecases: - Hitting "Enter" in the number/contact input - Clicking a call/phone button - Longpress on the voicemail button This commit moves the responsibility of those actions to the parent component. Indeed, the keypad is used in 3 places: - Dialer: the main one. In the end the only wants who wants to initiate actual calls. It now passes "how to call" to the keypad, which does it for "Enter" / click a call button. It also passes "how to voicemail" which becomes the condition to display the voicemail button in the first place (instead of the keypad hardcoding "am I in the dialer?"). - Transfer during a call: same as the dialer, it passes "how to transfer" which the keypad does at the same places as "how to call". - DTMF keypad during a call: that one definitely don't need to know how call / transfer / voicemail so it is not given anything about that. Funny enough: the third case was actually buggy. If during a call you opened the DTMF keypad, hit numbers then hit "Enter"... you would start a new call with the DTMF numbers. This is fixed here but that part will get a dedicated minimal fix in stable, with a test, forwarding up to master later on. Related to task-6365445 Related to task-6455637
Uploading a document from a contact now places it in the intended default area instead of reusing the last folder selected in Documents. This prevents files from being misplaced, such as contact uploads accidentally ending up in Finance.
Original PR description
Steps to reproduce ================== 1. Open Documents. 2. Select Finance. 3. Return to the home page and open the Contacts app. 4. Open any contact. 5. Click the Documents stat button. 6. Upload a document. Issue ===== The document is uploaded to the Finance folder instead of My Drive. Reason ====== When uploading a document using the upload button, we use `currentFolderAccessToken` to determine the destination folder. When opening the Documents view from a contact, `searchpanel_default_folder_id` is set to `False` so that documents are uploaded to the `All` workspace. However, when the search model is loaded, we do not reset `currentFolderAccessToken` when `folder_id` is `False`, causing the previously selected folder (Finance) to be reused. Task-6352242 Forward-Port-Of: odoo/enterprise#123285
Code cleanup and technical improvements
This update refreshes internal timing helper code to remove a deprecated dependency, keeping the system aligned with the newer OWL framework. It should not change day-to-day user behavior, but reduces future maintenance risk across several business apps.
Original PR description
- community: https://github.com/odoo/odoo/pull/279121 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Knowledge app's properties panel was updated to use the newer interface expected by the platform. This keeps the panel behavior stable during future upgrades while preserving the existing user experience.
Original PR description
Replaced `useLayoutEffect` with `useEffect` (from `@odoo/owl`) because `useLayoutEffect` is deprecated in OWL3. `useEffect` was chosen as the replacement because the original effect reacted to…
Replaced `useLayoutEffect` with `useEffect` (from `@odoo/owl`) because `useLayoutEffect` is deprecated in OWL3. `useEffect` was chosen as the replacement because the original effect reacted to dependency changes (`this.props.record.resId` and `this.hasProperties`) — pattern 3 in the OWL3 migration guide. A `void this.props.record.resId;` statement was added at the top of the callback to subscribe to the plain prop dep that is not auto-tracked. The `useLayoutEffect` refactored in this PR has test coverage — below are some tests that failed when the effect was commented out: - @knowledge/options_dropdown/Toggle Properties Panel (desktop) - @knowledge/options_dropdown/Toggle Properties Panel (Mobile) see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2596677/build/114854261 Note: `useEffect` runs asynchronously after paint, whereas `useLayoutEffect` ran synchronously after DOM mutations. The properties panel visibility logic may require synchronous updates; post-merge monitoring of the knowledge test suite is advised.
The Knowledge app now uses a newer, supported way to manage comment screen updates, helping keep the feature compatible with upcoming platform changes. This also removes an obsolete scroll behavior and helps prevent comments from disappearing when switching or reloading articles.
Original PR description
Replaced `useLayoutEffect` with `useEffect` (from `@odoo/owl`) because `useLayoutEffect` is deprecated in OWL3. All 7 effects read their reactive deps naturally inside the body, so `useEffect` auto-tracks them without an explicit dep array. Two effects (`loadRecords`, `loadThreads`) subscribed to deps they did not read naturally via `void` expressions. The use layoutEffect refactored in this PR had test coverage — below are some tests that failed when the effect was commented out, and are now passing: - TestKnowledgeArticleTours.test_knowledge_article_comments see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2594700/build/114736861 `targetRef` was converted from a compat `useRef` to a native `signal.ref()`: `useEffect` runs before the DOM patch, so a compat ref's `.el` accessor is untracked and the popover effect never re-ran after mount; a signal ref triggers re-runs once the element is set.
The Gantt view was updated as part of Odoo's move to the newer Owl framework. This is an internal modernization that helps keep planning views reliable and ready for future platform changes, with no expected change for day-to-day users.
Original PR description
As part of the Owl 3 migration, replace onWillUpdateProps hook with the appropriate Owl 3 alternatives. `Why use bus ?` Replaces `onWillUpdateProps(this.computeDerivedParams)`. The model isn't reactive, so we recompute the derived state on its synchronous "update" event. This ensures it's ready before the next render. Effects run too late.
This update modernizes how several Odoo screens refresh their interface content, removing an outdated internal mechanism. It helps keep dropdowns and embedded editor components more reliable and easier to maintain without changing day-to-day workflows.
Original PR description
- community: https://github.com/odoo/odoo/pull/276842 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Web Studio’s automated tests were updated to align with the newer Owl 3 framework. This is an internal maintenance change that helps keep future development and upgrades stable without changing day-to-day user behavior.
Original PR description
As part of the Owl 3 migration, replace deprecated onWillRender hooks with the appropriate Owl 3 alternatives. Community: https://github.com/odoo/odoo/pull/280936
The Knowledge calendar view was updated to use a newer underlying approach that remains compatible with the next version of Odoo's interface framework. A new automated test was added to help ensure this calendar behavior continues to work correctly.
Original PR description
Replaced `useLayoutEffect` with `useEffect` because `useLayoutEffect` is deprecated in OWL3. The useLayoutEffect refactored in this PR had NO test coverage, see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2596755/build/114855786 In this case I wrote a test to make sure the refactoring works (also tested in UI) community PR: https://github.com/odoo/odoo/pull/281002
15 changes
Enhancements to existing features
All signers can now choose whether to add a frame when adopting their signature, not only internal Odoo users. The signing dialog controls also have clearer borders, making the public signing experience easier to use and understand.
Original PR description
Version: 19.0 Before this PR: The 'Frame' checkbox in the 'Adopt Your Signature' dialog was only shown to internal Odoo users (users with the `base.group_user` group).Also, on the public signing page, the Full Name input, the Frame checkbox and the Auto/Draw/Load buttons had no visible border After this PR: The 'Frame' checkbox is now rendered for every signer in the 'Adopt Your Signature' dialog. The Full Name input, Frame checkbox and Auto/Draw/Load buttons now have a visible border. Taskid-4610728
Receipt printer selection in Point of Sale IoT now matches the broader printer filtering already used for preparation printers. This helps businesses use eligible printers more consistently without being limited by an overly specific printer type setting.
Original PR description
In odoo/enterprise#124306, we removed the subtype from the printer domain, but only for preparation printers. We also update it for receipt printers. Forward-Port-Of: odoo/enterprise#125648
Vendor bill product suggestions based on line labels now respect the setting that enables or disables this feature. This prevents unwanted suggestions for businesses that turned the option off, while keeping the default behavior for community users.
Original PR description
Context: There was an enterprise field `predict_bill_product` allowing users to toggle product prediction based on line label. Before this commit, product prediction by name was running without taking into account the value of this field, which could confuse users who had disabled the feature in settings. This commit makes product prediction by name depend on this field. For community users, the prediction will run by default. no-task --- I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr)
Resolved issues and error corrections
Batch picking test steps now wait for the first product quantity to update before moving to the next item. This prevents quantities from being assigned to the wrong line during rapid barcode scanning, helping ensure picking results remain accurate.
Original PR description
Problem: When scanning the first product, the second move line is clicked immediately after.…
Problem: When scanning the first product, the second move line is clicked immediately after. https://github.com/odoo/enterprise/blob/bfb8bab7636a84c829f16087771e00bf31ad2cce/stock_barcode_picking_batch/static/tests/tours/tour_test_barcode_batch_flows.js#L1529-L1541 If this happens before the first scan has finished, its quantity is incorrectly applied to the second move line that is clicked. This causes a 0 - 3 split instead of a 1 - 2 split, which results in there only being 6 move lines instead of 7. We updated our quantity on the `currentLine` https://github.com/odoo/enterprise/blob/bfb8bab7636a84c829f16087771e00bf31ad2cce/stock_barcode/static/src/models/barcode_model.js#L1478 When finding `currentLine`, we go through `_findLine` and use `this.selectedLineVirtualId`, which is the one that is currently selected in the UI https://github.com/odoo/enterprise/blob/bfb8bab7636a84c829f16087771e00bf31ad2cce/stock_barcode/static/src/models/barcode_model.js#L1705-L1712 Purpose: By adding this step, we wait until the first line’s quantity to be updated before it moves on and clicks on the second product. runbot-941211 Forward-Port-Of: odoo/enterprise#126847 Forward-Port-Of: odoo/enterprise#124162
This fixes an issue where Instagram posts without a media URL could stop Social Marketing from syncing and show an error when the app opened. The system now safely handles missing media links so Instagram content continues to sync as expected.
Original PR description
The fix introduced in https://github.com/odoo/enterprise/commit/9e9c99712ad4b9d58dc7601da41a852e457ad097 didn't account for the fact that `post.get('media_url') ` could return a None value, which in…
The fix introduced in https://github.com/odoo/enterprise/commit/9e9c99712ad4b9d58dc7601da41a852e457ad097 didn't account for the fact that `post.get('media_url') ` could return a None value, which in turn would raise en error when trying to concatenate the value later.
This in turn:
- will block syncing of instagram instagram posts
- will raise a traceback when you open the Social Marketing module and the auto-sync kicks in.
### Example traceback
```
Traceback (most recent call last):
[...]
File "/home/odoo/src/enterprise/saas-19.2/social_instagram/models/social_stream.py", line 86, in _fetch_stream_data
return self._fetch_instagram_posts()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/social_instagram/models/social_stream.py", line 64, in _fetch_instagram_posts
values['message'] = (values['message'] + "\n" + post.get('media_url')).strip()
~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
TypeError: can only concatenate str (not "NoneType") to str
```
### Solution:
Fallback to an empty string if `post.get('media_url')` yields a None value.
OPW-6449357
Forward-Port-Of: odoo/enterprise#127049
Forward-Port-Of: odoo/enterprise#126987Fixes a DHL Express shipping issue where international deliveries with multiple packages could be blocked during validation even though the carrier response was valid. The system now treats DHL Express's multi-package rate notice as informational, while still blocking real shipping errors.
Original PR description
Steps to reproduce --- 1. Configure a `delivery_easypost` shipping method using the DHL Express carrier. 2. On an international delivery, use Put in Pack to create two or more packages. 3. Validate…
Steps to reproduce --- 1. Configure a `delivery_easypost` shipping method using the DHL Express carrier. 2. On an international delivery, use Put in Pack to create two or more packages. 3. Validate the delivery. Issue --- Validation is blocked with `DHLExpress: rate_error -- DHLExpress multi-shipment rate includes this shipment.` For an EasyPost multi-shipment order, DHL Express returns the aggregate rate on the first (master) shipment only and adds an informational `rate_error` on the order stating that this rate already covers the whole order, so the remaining shipments carry no rate of their own. The message is not a real error, but `send_shipping` raises on any carrier message whose type is not exempt: https://github.com/odoo/enterprise/blob/534b42def8ae5dc884da4398377f828c49557d6e/delivery_easypost/models/easypost_request.py#L359-L364 `_post_process_ship_response` already detects and clears exactly this harmless message, but only for a hardcoded carrier allowlist introduced in a2de5bc5a14 (`Purolator`, `DPD UK`, `UPS`) that was never extended to DHL Express, so for DHL Express the message survives, reaches the raise, and aborts an otherwise valid shipment: https://github.com/odoo/enterprise/blob/a2de5bc5a14f99b8674c3ee234e4d221b406da0f/delivery_easypost/models/easypost_request.py#L416-L434 `DHL Express` is added to that allowlist so the harmless multi-shipment `rate_error` is posted on the picking and cleared instead of raised. The guard still requires a single `rate_error` carrying the "multi-shipment rate includes this shipment." text with the rate present only on the master shipment, so genuine DHL Express errors keep blocking validation. opw-6450365
VoIP calls now wait longer to complete connection setup, reducing cases where one side cannot hear the other. Additional debug logging helps support teams diagnose audio connection issues faster when problems occur.
Original PR description
The 1-second ICE gathering timeout was often too short to complete a
STUN round-trip, especially for agents answering an incoming call. When
it expired, SIP.js sent the SDP answer with only local/private ("host")
candidates, missing the public (srflx) one.
In debug mode, forward the RTCPeerConnection events relevant to
ICE/media issues (onicecandidate, onicecandidateerror,
oniceconnectionstatechange, onicegatheringstatechange,
onnegotiationneeded, onsignalingstatechange, onconnectionstatechange) to
the console, wired as soon as the SessionDescriptionHandler exists so
gathering-time events aren't missed.
Also periodically (every 5s) log a summary of getStats() while the call
is ongoing, to see whether RTP packets are actually flowing in each
direction.
task-6450278Fixes an issue where completing a field service task could freeze or fail after a delivery was returned and then re-delivered. The system now avoids repeatedly checking the same stock movements, preventing memory errors and keeping task completion reliable.
Original PR description
## **Steps to reproduce:** 1. Create a Service product with Create on Order set to Task and Project set to Field service project. 2. Create a Sales Order containing a storable product and a service…
## **Steps to reproduce:** 1. Create a Service product with Create on Order set to Task and Project set to Field service project. 2. Create a Sales Order containing a storable product and a service product. 3. Confirm the Sales Order to generate the project, task, and delivery order. 4. Validate the delivery order. 5. Create and validate a return for the delivery. 6. Create a return of the return to deliver the products again, but do not validate this new delivery. 7. Open the related task and click on Mark as Done button. ## **Issue:** In a delivery -> return -> return of return workflow, the stock move goes into this code https://github.com/odoo/enterprise/blob/59b86f106862c3a364ba633a1580d9051f2fe7ca/industry_fsm_stock/models/project_task.py#L89-L90 the traversal repeatedly revisits the same stock moves through move_dest_ids, causing the loop to alternate between the same move recordsets indefinitely. As a result, the loop never terminates, eventually exhausting the memory and raising a `MemoryError`. ## **Solution:** Track the stock moves that have already been visited and continue the traversal only with unseen destination moves. Runbot Video : [Video](https://drive.google.com/file/d/1wiqggjx8T-Mtl4T1JgCsfwBbgQU18nYF/view?usp=drive_link) OPW - 6420961
Employees on flexible schedules can now record short time off periods without the system treating the entire day as leave. This keeps overtime and Time Off calendar views accurate, so worked hours and leave hours are reported correctly.
Original PR description
Problem: On a flexible working schedule, a time off of a few hours (neither a full nor a half day) was treated as a full day off. The Attendance list then reported the whole day's attendance as…
Problem: On a flexible working schedule, a time off of a few hours (neither a full nor a half day) was treated as a full day off. The Attendance list then reported the whole day's attendance as overtime, and the Time Off gantt grayed out the entire day instead of only the leave's hours. Steps to reproduce: 1. Give an employee a flexible working schedule (e.g. 8h/day) with an overtime ruleset based on the contract's expected hours. 2. Record a 2-hour time off, then an 8-hour attendance on the same day. 3. Observe the attendance reports 8 hours of overtime instead of 2. Current behavior: A partial time off makes the whole day count as extra hours. Expected behavior: Only the hours actually taken off reduce the day's expected hours. Cause: For a flexible schedule, _handle_flexible_leave_interval expands a leave to the whole day. The override already narrows full-day and half-day leaves, but any other number of hours fell through to that full-day expansion. The expanded interval is subtracted from the day's expected hours in _work_intervals_batch, so they drop to zero and every worked hour becomes overtime. Fix: A leave of an arbitrary number of hours should only remove the hours it actually covers, so it keeps its requested interval instead of being stretched to the whole day. opw-6291536
Dutch SBR tax return exports now use the Tax Unit VAT number when a Tax Unit is selected, instead of incorrectly using the individual company OB number. This prevents rejected XBRL filings for fiscal unity registrations while keeping the company OB number behavior for single-company reports.
Original PR description
**Steps to reproduce:** * Install the **Netherlands - SBR** (`l10n_nl_reports_sbr`) and **Netherlands - SBR OB Nummer** (`l10n_nl_reports_sbr_ob_nummer`) modules. * Create two companies with Dutch…
**Steps to reproduce:** * Install the **Netherlands - SBR** (`l10n_nl_reports_sbr`) and **Netherlands - SBR OB Nummer** (`l10n_nl_reports_sbr_ob_nummer`) modules. * Create two companies with Dutch localization. * Go to **Accounting → Configuration → Tax Units** and create a Tax Unit with its own **Tax ID** (e.g. `NL826317558B01`), adding both companies. * On the main company form, fill in the **Omzetbelastingnummer** field (e.g. `123456782B90`). * Go to **Accounting → Reporting → Tax Return**, select the Tax Unit in the filter, and click **XBRL → Download XBRL File**. **Observed behavior:** * The `<xbrli:identifier>` in the exported XBRL file contains the company's **Omzetbelastingnummer** (`123456782B90`) instead of the Tax Unit's VAT (`826317558B01`). * The tax authority rejects the return because the identifier does not match the fiscal unity registration. **Cause:** * `_get_sbr_identifier()` in `l10n_nl_reports_sbr_ob_nummer` unconditionally returns `self.env.company.l10n_nl_reports_sbr_ob_nummer` before consulting the Tax Unit. * The `super()` call, which correctly routes to `tax_unit.vat` via `report.get_vat_for_export()`, is only reached when the company field is empty — so the Tax Unit's VAT is never used when a company OB-number is set. **Fix:** * When a Tax Unit is active in the report options, delegate immediately to `super()._get_sbr_identifier()`, which resolves `tax_unit.vat` through the existing `get_vat_for_export()` logic. * The company-level `l10n_nl_reports_sbr_ob_nummer` override is preserved as a fallback for the `company_only` (no Tax Unit) case. opw-6350840 Forward-Port-Of: odoo/enterprise#126999 Forward-Port-Of: odoo/enterprise#125167
The fix ensures Google Reserve never receives more open booking spots than the total spots available. This avoids confusing availability data in rare cases where appointment resources are configured inconsistently.
Original PR description
This commit makes sure that we never send more "spots_open" than there are "spots_total" when Google Reserve asks for availabilities. This could happen in very rare case when customers create configurations that do not make sense (for example a table of 6 but no management of capacities and configuring 125 spots per resource). Task-6449615 Forward-Port-Of: odoo/enterprise#126855
Fixes an issue where Uruguayan electronic delivery guide PDFs did not include a separate addenda page when the addenda text was too long for the standard box. This ensures legal delivery documents show all required additional information, improving compliance and document completeness.
Original PR description
**Description** When printing the legal PDF of a CFE, the report can request a dedicated addenda page (`adenda=true` report parameter) when the addenda does not fit in the small box of the standard…
**Description** When printing the legal PDF of a CFE, the report can request a dedicated addenda page (`adenda=true` report parameter) when the addenda does not fit in the small box of the standard report (roughly 6 lines of 140 characters). `l10n_uy_edi_document._get_report_params()` computed the addenda by calling `self.move_id._l10n_uy_edi_get_addenda()` directly. For e-remito EDI documents created from stock pickings, `move_id` is not set, so the addenda was always empty and the dedicated addenda page was never requested for delivery guides. **Changes** - Resolve the addenda from the document origin record: reuse the existing `_get_origin_record()` abstraction. Add it on `l10n_uy_edi.document` (returns the move) and let `l10n_uy_edi_stock` extend it to fall back to `picking_id`; `_get_report_params()` now reads the addenda through it. - Remove a no-op `_get_pdf()` override in `l10n_uy_edi_stock`. - Add a unit test covering the dedicated addenda page threshold (6 lines x 140 chars) for delivery guides. **Note** This PR replaces branch `adhoc-dev:18.0-t-stock-edi-addenda-fix-kz` (original authorship preserved); resubmitted from a new branch to keep follow-up and tracking with the current maintainer. Forward-Port-Of: odoo/enterprise#124539
The IoT device list now opens device details using the standard navigation behavior, which restores pagination after it was disrupted by a previous change. This helps users browse and manage longer device lists reliably without getting stuck or seeing incorrect page behavior.
Original PR description
Since #72351, the pagination on IoT devices was broken due to how we were getting to the full device form when clicking on a record. We now change the override to use the existing method from the framework `switchToForm` which handles it better. opw-6058532 Forward-Port-Of: odoo/enterprise#126486
VoIP contact searches and keypad suggestions now also compare entered numbers with standardized phone numbers, not only the saved raw phone field. This helps users find the right contact even when country codes are automatically added or stored differently.
Original PR description
Before this fix, the keypad's callee suggestions only matched the search term against the raw `phone` field of contacts. When the user input was automatically prefixed with a country code (e.g. +86), the match could fail if the stored phone number lacked the international prefix. Now `phone_sanitized` is also sent to the frontend via the Store, and the callee suggestion matching falls back to the E164 sanitized number when the raw phone field does not match. Task-6395518 compr https://github.com/odoo/odoo/pull/278018
Dutch VAT correction filings will now be sent to Digipoort using the correct OBSUP message type instead of being treated as regular VAT reports. This prevents routing errors and helps ensure correction submissions reach the right destination.
Original PR description
Description of the issue this commit addresses: VAT corrections are sent to Digipoort as regular VAT reports, causing routing errors. --- Desired behavior after this commit is merged: This commit sends VAT corrections using the OBSUP message type. --- opw-6353166
2 changes
Resolved issues and error corrections
Sometimes the default_state remains in the context from a past action and when the subcontractor fills its components consumptions it will directly modify the quant's quantity. This trigger the automatic rules and generate an unwanted picking opw-6109661 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:
Original PR description
Sometimes the default_state remains in the context from a past action and when the subcontractor fills its components consumptions it will directly modify the quant's quantity. This trigger the automatic rules and generate an unwanted picking opw-6109661 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#280733
picking.location_dest_id falls back to the picking type's default (customer location) when moves have different destinations, so it missed the move actually routed to the transit location and never unpacked it. Check each move's own destination instead. Bug introduced by odoo/odoo#277133.
Original PR description
picking.location_dest_id falls back to the picking type's default (customer location) when moves have different destinations, so it missed the move actually routed to the transit location and never unpacked it. Check each move's own destination instead. Bug introduced by odoo/odoo#277133.
2 changes
Resolved issues and error corrections
When stock is installed, the default routes of a warehouse include a rule that does Vendor -> Stock. However, once purchase is installed, that rule is removed and replaced by a 'buy' rule, that requires a vendor set on the product to trigger correctly. So when `test_orderpoint_activity_portal_context_leak` ran without purchase installed, it would find an applicable rule to run the orderpoint and would not trigger a ProcurementException, and thus no activity on the product. runbot-941316
Original PR description
When stock is installed, the default routes of a warehouse include a rule that does Vendor -> Stock. However, once purchase is installed, that rule is removed and replaced by a 'buy' rule, that requires a vendor set on the product to trigger correctly. So when `test_orderpoint_activity_portal_context_leak` ran without purchase installed, it would find an applicable rule to run the orderpoint and would not trigger a ProcurementException, and thus no activity on the product. runbot-941316 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Miscellaneous changes
## The problem When computing `pos_order_count`, the query starts from `pos_order_line` and aggregates all reward-related order lines before filtering on the requested loyalty programs. On databases with large PoS order volume, this causes millions of irrelevant rows to be processed. ## The solution Start from the lower-cardinality `loyalty_reward` table and filter the requested programs before joining `pos_order_line`. Merge the redundant second CTE into the first one and count the order I
Original PR description
## The problem When computing `pos_order_count`, the query starts from `pos_order_line` and aggregates all reward-related order lines before filtering on the requested loyalty programs. On databases…
## The problem When computing `pos_order_count`, the query starts from `pos_order_line` and aggregates all reward-related order lines before filtering on the requested loyalty programs. On databases with large PoS order volume, this causes millions of irrelevant rows to be processed. ## The solution Start from the lower-cardinality `loyalty_reward` table and filter the requested programs before joining `pos_order_line`. Merge the redundant second CTE into the first one and count the order IDs directly from `pos_order_line`, removing the unnecessary joins through foreign keys. ## Benchmarks Benchmark on a customer database containing approximately 7.4 million `pos_order_line` records: ||Time|Plan| |--|--|--| Before|5.5 s|https://explain.dalibo.com/plan/3e7978hg8f757614 After|1.6 s|https://explain.dalibo.com/plan/g588aa31e2bc6729 **Note:** An index on `pos_order_line(reward_id)` would improve this further. As discussed in odoo/odoo#167386, that index is added in master, while this query optimization targets stable versions where adding the index is not possible. **opw-6370166**