Friday, August 21, 2026
178 changes · master
Security fixes and vulnerability patches
Once an IoT device is connected to a database, password resets can no longer be triggered directly from the local network. This improves security by requiring resets to be managed through the trusted database connection instead.
Original PR description
To increase security on the local network, we prevent password reset from the local network once a db is connected, and allow it only from db through ws. see odoo/enterprise#128620
The IoT Box password reset process now uses a more restricted communication channel instead of a publicly accessible route. This reduces the risk of unauthorized password resets and strengthens device security.
Original PR description
In order to improve security on the IoT Box we disable the possibility to reset the system password using a public controller. We now restrict it to websocket. see odoo/odoo#283598
New functionality added to Odoo
Adds a Philippine invoicing feature to apply legally required Senior Citizen and Persons With Disabilities discounts and VAT exemptions on customer invoices and credit notes. Businesses can configure eligible discounts, preview them per invoice line, and keep discount accounting separated for compliance and reporting.
Original PR description
In the Philippines, Senior Citizens (SC) and Persons With Disabilities (PWD) are legally entitled to statutory discounts (typically 20% or 5%) and VAT exemptions on eligible goods and services.…
Enhancements to existing features
The US sales tax report now captures more complete sales tax details, including exempt, non-taxable, taxable amounts, and tax rates by jurisdiction. This helps businesses prepare more accurate state-level tax reports and lays groundwork for future e-filing support in Odoo, including automated Avalara-based configuration.
Original PR description
*: account Purpose: Improve and enhance the US tax report framework to eventually support future e-filing directly within Odoo. To do so, the US sales tax report needs to capture all relevant…
Resolved issues and error corrections
This fixes a timing issue on mobile where selecting an item in a modal could target the wrong popup and cause a crash. It makes the affected flow more reliable for users and helps keep automated user journey tests stable.
Original PR description
…tour Scope kanban selection triggers to the active modal to avoid a race with Owl's async modal state, and make Many2XAutocomplete's onClose null-safe against a crash the race was masking. runbot-error-id~939488 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#279300
Code cleanup and technical improvements
The portal rating message display was updated internally to use a newer supported approach in Odoo's interface framework. This keeps the portal experience compatible with upcoming platform changes without changing what users see, and a new test helps prevent regressions.
Original PR description
Replaced `useLayoutEffect` with `useEffect` because
`useLayoutEffect` is deprecated in OWL3.
`richBodyRef` was already a `signal.ref()` from the t-ref migration
base. `useEffect` auto-tracks that signal read, so it re-runs
whenever the element enters/leaves the DOM — matching the old
`() => [this.richBodyRef()]` dep exactly. The null-guard
`if (el) {` handles the eager pre-mount call (no element yet).
When commenting out the useLayoutEffect there was no error,
the code we refactored had NO TEST coverage. A test was written
to ensure our fix was correct, and it was tested against the
previous useLayoutEffect:
- Passed with previous useLayoutEffect.
- Failed with previous useLayoutEffect commented.
- Passed with our OWL3 replacement.
see runbot build, green even with the useLayoutEffect commented out: https://runbot.odoo.com/runbot/batch/2681594/build/120349135In the Philippines, Senior Citizens (SC) and Persons With Disabilities (PWD) are legally entitled to statutory discounts (typically 20% or 5%) and VAT exemptions on eligible goods and services. Properly handling these transactions requires removing the standard VAT, recalculating the base price, and tracking the discount separately on the invoice. This commit introduces a "Discount Privileges" feature in a new `l10n_ph_invoice` module, applied directly on customer invoices and credit notes, so that companies not needing it (e.g. Odoo PH itself) don't have to deal with it. Key changes: * Privilege Model: `l10n_ph.discount.privilege` pairs a discount amount with its type (SC/PWD/special), the fiscal position mapping the line taxes to the SC/PWD VAT-exempt tax, the target account for the discount journal items, and the optional product categories it applies to. Names are unique per company and discount amounts are validated between 0 and 100%. * Shared Mixin: `l10n_ph.discount.privilege.line.mixin` stores the privilege and the original price-unit/tax/discount values on any document line and computes the regular and special discount amounts, with model-specific hooks to derive the gross amounts. * Invoice Line: `account.move.line` overrides `_compute_discount_allocation_needed` to route the discount journal items of privileged lines to the privilege account, and provides helpers to adjust the price unit and taxes from the privilege's fiscal position (restoring the original values when the privilege is removed). * Application Wizard: `l10n_ph.discount.privilege.wizard` offers per-line discount previews, scope filtering (all lines / categories / individual products) and apply / remove-all / single-line-remove actions on draft customer invoices and credit notes. * Localization Data (`l10n_ph`): added the "0% EXEMPT FOR SC/PWD USE" tax and the "Discount Privileges" fiscal position mapping the standard 12% VAT to it, renumbered the chart-of-accounts tax sequences for a logical ordering. Default privileges (20% SC, 20% PWD, 5% SC) are created when installing the Philippine chart of accounts with `l10n_ph_invoice` installed. * Configuration: the `l10n_ph` settings now offer a "Discount Privileges" toggle that installs the `l10n_ph_invoice` module directly. * Tests: coverage for the model, wizard flows, fiscal position mappings, and discount computations. Task-6032306 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Adds a dedicated Bill of Entry process for imported goods in India, helping users record customs duties from vendor bills and related stock receipts. The flow calculates duty charges across currencies, creates the required vendor bill, and automatically adds landed costs so inventory values reflect the true import cost.
Original PR description
**PURPOSE:** - Introduce a Bill of Entry (BOE) flow for imported goods to simplify the recording of import customs duty and ensure that the duty amount is included in the inventory cost through landed costs. **SPECIFICATION:** - Add a Bill of Entry creation flow from the Vendor Bill/Bills. - Validate the selected Vendor Bills before opening the BOE wizard. - Allow users to select the corresponding stock receipts and automatically populate receipt lines. - Allow users to compute charges from different currencies that can have different rates. - Generate a BOE Vendor Bill containing the customs duty charges (Total Amount - Total Assesable Value) so we get right journal entries. - Automatically create the corresponding Landed Cost record. task-3946649
AI agents can now be set up in a dedicated chat-based workspace, update their own instructions and skills from conversation, and create or manage scheduled automations. This makes agents more practical for business users by reducing setup friction and allowing routine follow-ups, summaries, and other workflows to run automatically while remaining inspectable in Discuss.
Belgian payroll can now include manual expense reimbursement amounts directly on payslips through a dedicated input and salary rule. The yearly total of these reimbursements is also reflected on the 281.10 tax form, helping payroll reporting stay complete and accurate.
Original PR description
. Add manual Expense reimbursement payslip input and its corresponding salary rule . Show the sum of all the values of the year on 281.10 task-6462236
The website builder AI can now read and update site navigation menus, including creating, renaming, moving, reordering, deleting, and linking menu items to page anchors. This helps users adjust website navigation through the AI assistant while keeping safeguards such as limited nesting and read-only mega menus.
Original PR description
Add two AI tools, "Get Website Menus" and "Edit Website Menus", so the website builder agent can read and modify the site navigation menu: create, rename, move/nest, reorder and delete menu items, including linking an item to an anchor within the current page. Update the skill instructions with the tool workflow and rules (two levels of nesting max, mega menus read-only, atomic operations), wire up the new server actions, and extend the builder plugin so the menu reloads after an AI edit to the menus, following the normal user behaviour. task-6143430
*: account Purpose: Improve and enhance the US tax report framework to eventually support future e-filing directly within Odoo. To do so, the US sales tax report needs to capture all relevant information, such as exempt sales, taxable sales, non-taxable sales, and the tax rate. It supports both Avalara and non-Avalara users. Configuration: Users can configure taxes specifically for the US jurisdiction by setting the jurisdiction type, the following information required by the type (state, county, city). If the tax is an exempt or nontaxable of a standard tax rate, then it can be added to the standard tax rate on its exempt and nontaxable tax field. For Avalara users, the configuration is automatically handled based on the Avalara response. The following tax types are supported: - Fully exempt taxes (ex. 0% exempt tax) - Fully nontaxable taxes (ex. 0% nontaxable tax) - Rate-reduction taxes (ex. 6% rate reduced to 4% tax) Report: The US tax report will organize the taxes based on its state. Per state, it lists the taxes in order based on its jurisdiction type: state, special, county, city. The header will total the columns based on the base lines to avoid double-counting. Per tax row, the column values include its linked exempt and nontaxable taxes. - Gross should be a sum of exempt, nontaxable, and taxable values. - Exempt displays the amount that are exempted. - Nontaxable displays the amount that are nontaxable. - Taxable displays the amount that are taxable. **Note: Rate-reduced taxes will not have its own row and are aggregated into its parent tax. Additional changes: To support city jurisdiction type on taxes, the res.city.csv file needs to be moved from l10n_us_hr_payroll to l10n_us for access. task-6223342 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update refreshes the core web interface library used by Odoo. It helps keep the platform aligned with the latest framework improvements, supporting maintainability and future user interface enhancements without introducing a direct business workflow change.
Original PR description
Release notes: ttps://github.com/odoo/owl/releases/tag/v3.0.0-alpha.46 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#282871
The Point of Sale customer display can now open directly on a connected secondary screen when the browser supports it and permission is granted. If that is not possible, it still opens normally on the same device, giving shops a smoother customer-facing display setup without disrupting existing workflows.
Original PR description
In this commit: ================= When a secondary screen is detected via the `Multi-Screen Window Placement API`, the customer display opens there; otherwise it falls back to opening in a new window on the same device. The Multi-Screen Window Placement API (`window.getScreenDetails()`) lets the browser report all connected displays along with their position and size, so the customer display window can be placed precisely on an external screen instead of just opening on the same monitor as the POS. It requires user permission and is only supported in Chromium-based browsers, so the feature gracefully falls back to opening on the same device when the API is unavailable, no secondary screen is found, or permission is denied. Task: 6305983
The mail interface now supports customized tab views in areas like discussions and the messaging menu. This gives teams more flexibility to organize communication views in ways that better fit their workflows.
Original PR description
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
The Attendance menu now avoids an unnecessary data request when opened. This should make the check-in/check-out menu feel more responsive without changing how employees use it.
Original PR description
This avoids a useless blocking rpc call when opening the systray. Task-6131386 Forward-Port-Of: odoo/odoo#278153 Forward-Port-Of: odoo/odoo#269797
The user invitation email template in the signup flow has been improved. This helps make invitations clearer and more effective for recipients who need to activate or access their accounts.
Original PR description
task-id:6470158 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update expands automated checks for several onboarding flows and fixes issues those checks uncovered, including outdated screen targets and unreliable form entry behavior. This helps make first-time setup experiences in apps like Frontdesk, Expenses, Appointments, Subscriptions, Payroll, and Sales more dependable for users.
Original PR description
Add frontdesk_tour, hr_expense_extract_tour, appointment_tour, sale_subscription_tour and payroll_tours to the onboarding tours test, fixing the tours themselves where the robot-mode replay uncovered real bugs: obsolete selectors, incomplete many2one selections, dirty-form-on-save races, and (for payroll_tours) a full rewrite of the contract-creation flow to match the hr.version model that replaced the old hr.contract-based UI. Also fix searchOrCreateMany2X: always type the field value explicitly in the "Create and edit" dialog instead of relying on its async pre-fill on desktop, which can lose the race against the next tour step on heavier form views. 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
Sales users can now adjust the quantity or unit of a section or subsection once, and Odoo applies the change across all related order lines. This makes large quotes and sales orders faster to update, while keeping section quantities and units visible in order previews and PDFs when relevant.
Original PR description
Currently, there is no way to quickly update all quantities within a section or subsection at once. This change introduces a new quantity field displayed on sections and subsections when hovering…
Currently, there is no way to quickly update all quantities within a section or subsection at once. This change introduces a new quantity field displayed on sections and subsections when hovering over them. When this value is modified, a multiplier is computed (new value / old value) and applied to every line within the corresponding section or subsection. For example, if the quantity of a subsection is changed from 6 to 3, all quantities of the lines under that subsection are divided by 2. The same behavior is implemented for the unit column. If the unit of a section or subsection is changed and a conversion factor can be determined between the two units, that factor is applied to all lines within the corresponding section or subsection. For example, changing from m^2 to cm^2 divide all subline quantities by 10,000. Furthermore, if a section is configured to hide the composition, we still display the unit and quantity in the PDF and preview. If the user changes the unit or quantity of a section or subsection, we also display them on pdf and preview. We do all these changes on order but not on invoice. Enterprise PR: https://github.com/odoo/enterprise/pull/127420 Upgrade PR: https://github.com/odoo/upgrade/pull/10417 task-6075605
HR users can now create employee versions for several employees at the same time through a guided wizard. This reduces repetitive work and helps teams manage employee record changes more efficiently across groups of staff.
Original PR description
This commit introduces a new wizard in the HR module that allows users to create employee versions for multiple employees at once. TaskID: 6471477
Website pages can now have translated URLs, so visitors see localized page addresses and are redirected to the right language version. This improves multilingual website navigation, menu behavior, and language setup reliability for businesses running localized sites.
Original PR description
[IMP] website: enable to translate static page url The goal of this commit is to add the possibility to translate page url. Here is an example to illustrate the case: A website page has the url…
[IMP] website: enable to translate static page url The goal of this commit is to add the possibility to translate page url. Here is an example to illustrate the case: A website page has the url `/page-en`. If the user adds "French (BE)" as a language on its website, he can now translate the `page-en` website url into `page-fr`. If the language of the website and its default language is English, the url of the page will be `/page-en` but if the language of the website is French, the url of the page will be `/fr_BE/page-fr`. If the language of the website is in English and the user is searching for `/page-fr`, the system detects that the requested page exists but redirects the user to the English version of the page as the language of the website is in English. However, if the user is searching for `/fr_BE/page-fr`, it will be redirected to the French version of the page and the language of the website will switch to French whatever the original language of the website was. When a user translates a url, it is slugified and made unique. Concerning the website homepage url, if it is a page url, it has to be the one of the default website language. When a user modifies a page url, the website homepage url is updated if the modification of the url is done in the website default language and if the original url was the default website url. This commit also modifies the url field of the `website.menu` model: the `required` and `default` properties are removed; if a menu is linked to a page, no `url` is needed at record creation. However, the `compute` method of the field fallbacks on `#` and a `constrains` has been added on the `url` to ensure it is always set. The field is also not stored: as the `url` might be the one of the website page that could be translated, it should be recomputed each time we access it. Because a menu url could be the one of an external url, another field `manual_url` is introduced to store it. task-3355343 ------------------------------------------------------------------------------------------------------------------------------------- [FIX] website: reload web client when installing new language Steps to reproduce: - On a website with only 'English' installed, enter in edit mode and add a new language. - Go to 'Site' > 'This page' > 'Properties'. - Hover the 'Page URL' field -> It is not possible to translate the url. The problem is that, when a new language is installed, the iframe is reloaded but not the web client. Due to it, `TranslationButton` has a wrong version of `localization`. task-3355343 ------------------------------------------------------------------------------------------------------------------------------------- [IMP] website: correctly display the redirect button at url change Now that the url can be translated, we only want the redirect button to appear if the url has been changed in the website default language. task-3355343 ------------------------------------------------------------------------------------------------------------------------------------- [IMP] website: update cache to avoid extra SQL queries Since [1], the `all_menus` variable contains website specific menus and generic menus (not linked to a website). However, the `_update_cache()` of `child_id` was only applied on website specific menus. The problem is that due to the previous commits, the `url` field of `website.menu` is not a stored field anymore and depends on `child_id`. Because `_compute_visible()` in `website_sale` requires the menu's url, an extra SQL query was triggered to determine the `child_id` of the generic menus. To solve the problem, this commit performs the `_update_cache()` of `child_id` on all the generic and specific menus at `_compute_menu()` of a specific website. [1]: https://github.com/odoo/odoo/commit/aa5bbab0183b1d61d64bd2292cacbff82befeaf1 task-3355343 ------------------------------------------------------------------------------------------------------------------------------------- [IMP] website: only rewrite page url for internal links Steps to reproduce: - Create a new page and add it to the website menu. - Edit the menu item and change its URL to an external one (e.g. https://www.odoo.com/). - Save. -> Clicking on the menu item does not open the external url. Because the menu is linked to a page, changing the menu url rewrites the page url. This is not the expected behavior if the new url is external. Note that this problem became visible thanks to the previous commits that made menu url not stored. Indeed, before those commits, changing the menu url still rewrote the page url but as the url was a stored field of the menu record, clicking on the menu led to the external url. task-3355343
This update makes a small internal improvement to Odoo's test tooling around translation checks. It helps maintain development quality without changing day-to-day user workflows.
Original PR description
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
This change reduces unnecessary database work when Odoo checks internal data constraints during startup. By grouping updates together, registry initialization can run more efficiently without changing business behavior.
Original PR description
Constraint reflection loaded the xmlid of every unchanged constraint individually. It also updated xmlids separately for each reflected model, causing unnecessary queries during registry initialization. Return every reflected constraint record and collect their xmlids across all requested models before updating them in a single batch. task-6484654 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Kanban cards no longer show their action menu when displayed inside a selection dialog. This keeps the selection experience cleaner and prevents users from seeing actions that are not relevant in that context.
Original PR description
In this commit, we hide the kanban card menu only when rendered in a SelectCreateDialog. Task~6452824
The help and participant-list messages have been updated to be clearer for users. The option to leave a conversation is now handled consistently through the conversation action menu rather than a typed command, with wording that fits all conversation types.
Original PR description
* = im_livechat Updated `/help` description and `/who` message. Moved leave conversation eligibility logic to channel model. Renamed "Leave Channel" to "Leave Conversation" so that it works for all channel types. Removed /leave command. task-[6008262](https://www.odoo.com/odoo/project/1519/tasks/6008262) enterprise: https://github.com/odoo/enterprise/pull/112959
This update improves how Odoo recalculates inventory values and cost of goods sold when past purchases, bills, landed costs, manufacturing, subcontracting, or dropshipping events change. Businesses get clearer audit trails and more accurate margins because historic cost impacts are replayed into the related stock and accounting entries instead of being lumped into broad period-end adjustments.
Original PR description
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
Time off requests that span multiple calendar days are now treated as multi-day ranges even if only one working day is deducted. This prevents employees from incorrectly choosing morning or afternoon options for requests that cover a broader date range.
Original PR description
Purpose: When taking a range which results in only 1 day taken (because it overlaps with a non working day or another time off), you only see the selector of morning / afternoon like for a unique day, but you shouldn't be able to select morning or afternoon. - changed the computed field `last_several_days` to indicate lasting for several calendar days task-id: 6456270 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Website forms now automatically include required fields when a form action is changed to a less-common model, preventing silent submission failures. Long single-choice fields are shown as dropdowns for easier use, and empty date fields display cleanly instead of showing undefined values.
Original PR description
Selecting an action from "More Models" emptied the form: those models have no registered fields, unlike curated actions. Without the model's mandatory fields, the form silently fails at submission. Now those fields are added and flagged model-required (non-removable), so the form stays submittable. task-4952094
The tasks dashboard now uses conditional formatting to make important values and trends easier to spot at a glance. This helps managers review timesheet-related task information more quickly and identify areas that may need attention.
Original PR description
This commit adds some conditional formatting on the tasks dashboard. Task: 6478487 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
Spreadsheet scorecards now define their main value and baseline using formula syntax, making them more consistent with spreadsheet behavior. This improves reliability and clarity when scorecards are configured or displayed, including in dashboard views.
Original PR description
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
Manufacturing teams can now update the recorded work order duration for a specific employee. This helps keep employee time logs accurate for production tracking and related costing.
Original PR description
Now the work order duration for a specific employee can be updated.
The employee setup screen now hides the Time Off and History buttons until an employee record has been saved. This reduces confusion during onboarding by only showing actions that are relevant and usable.
Original PR description
Currently, during the creation of first employee, we can see Time Off smartbutton displayed even the employee record isn't saved and also History smartbutton displayed when only 1 versions. This PR is expected to update the visibility of these buttons: - Time off -> Displayed only after the employee record has been saved. - History -> Displayed only when the employee record has been saved. task-6438703 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
Backend refund orders now follow the same limits as the Point of Sale frontend. Staff can still adjust quantities, delete lines, add customer notes, and specify lots, but cannot change key commercial details such as products, prices, discounts, or add new lines, reducing refund errors and inconsistencies.
Original PR description
In the frontend the refund process is limited to only certain actions/ modifications. However if you refund from the backend multiple fields are editable. Currently you are allowed to change the product, its unit price, the discount, add a new product line,... We block all those actions and we keep: - editing the quantity - deleting order line - customer note (why not?) - lot (allows to specify which lot we return) task-6445165
The employee form now shows a Discuss chat option directly next to the employee name, making it easier to start or access conversations from the employee record. This improves day-to-day HR collaboration by placing communication closer to the employee details users are already viewing.
Original PR description
Add the `hr_employee_chat` widget directly inside the header next to the employee name field in the employee form view. Task: 6409961 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Date filters in the search bar now include quick choices like Today, This Week, This Month, This Quarter, and This Year, with arrows to move to the previous or next period without reopening menus. This makes planning, reporting, and reviewing records by time period faster while reducing duplicated custom filters across apps.
Original PR description
## Navigable smart-date filters in the search bar <img align="right" width="382" height="328" alt="image" src="https://github.com/user-attachments/assets/6e527849-0837-412e-aba3-bbddd6bab59c" /> ###…
## Navigable smart-date filters in the search bar <img align="right" width="382" height="328" alt="image" src="https://github.com/user-attachments/assets/6e527849-0837-412e-aba3-bbddd6bab59c" /> ### What Date filters (`<filter date=.../>`) now offer built-in smart-date options — **Today**, **This Week**, **This Month**, **This Quarter**, **This Year** — and each active one gets **prev/next arrows** to shift the period on the fly from the searchbar facet (eg. `This Week` → last week → next week). We keep the existing month and quarter features, and also add a new **"Custom Date…"** shortcut in each date-filter menu, opening the editor pre-filled with the right field. <br> ### Why Filtering by a relative date range was a common need, that devs were hardcoding in views (see commit `[REM] *: remove duplicate relative ranges from filters`). Furthemore, other views (eg. gantt view, custom accounting views...) also had this navigable filter logic (but as an extra section below the search bar). We decided to integrate that feature at the framework level, allowing users to navigate filters faster for example when planning day-by-day or reviewing quarter-by-quarter, while saving vertical space compared to a gantt-style navigator. (we keep the existing gantt view navigator for now as it has a couple more features, it was just an example) ### Also - Active relative filters keep their menu section **unfolded**, so the selected option stays visible w. - Period options and smart dates are **mutually exclusive** — picking one clears the other. ### Notes - Smart-date facets are **not** click-to-edit like other facets (intentional) ### Technical - Decided to model the new relative filter type as a top level filter even if its always a children of a date filter. I did this because it makes it easier to add custom behavior with the existing code structure (domain, label, navigation..). The only downside is that it makes it a bit more complex to display. task#6260555 Documentation PR: https://github.com/odoo/documentation/pull/18866 Enterprise PR: https://github.com/odoo/enterprise/pull/122986 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The emoji picker is now easier to use with clearer search guidance, a better-positioned search icon, and a quick button to clear searches. Frequently used emojis also stay in a stable order while the picker is open, making selection more predictable for users.
Original PR description
This commit improves the emoji picker UX by: - changing the search placeholder to 'Find the perfect emoji'. - moving the search icon to the left. - adding an `oi-filled` button to clear the emoji picker search. - preventing frequent emojis from being reordered while the picker is open. Task-[5879855](https://www.odoo.com/odoo/project/1519/tasks/5879855) <img width="337" height="407" alt="image" src="https://github.com/user-attachments/assets/cb832b4e-376b-4a1f-9d0b-b308186e2eb2" /> <img width="337" height="407" alt="image" src="https://github.com/user-attachments/assets/70652df6-a64f-4dd6-b589-00854d0f54b7" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Website editors now manage mega menus directly from each menu item using a checkbox instead of a separate add action. The update also adds easier content drop areas and a blank template, making it faster to build and customize large navigation menus.
Original PR description
1. Remove + mega menu item and make it a checkbox on menu item instead 2. Add dropzones before & after each template 3. Remove size on the editor for mega menu and rely on general layout 4. Add a blank template last task-6171291 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update adds automated checks for the Mollie payment option in Odoo Point of Sale. These tests help reduce the risk of future changes breaking Mollie card payment handling, improving reliability for businesses using this payment provider.
Original PR description
This commit adds both Python and JS unit tests for the Mollie POS payment method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282259 Forward-Port-Of: odoo/odoo#281742
The US sales tax report now captures a fuller breakdown of gross, exempt, nontaxable, and taxable sales by jurisdiction, helping businesses prepare for more complete sales tax compliance reporting. Avalara users get this configuration automatically from Avalara responses, while non-Avalara users can configure US tax jurisdictions manually.
Original PR description
*: hr_payroll, reports, reports_avatax Purpose: Improve and enhance the US tax report framework to eventually support future e-filing directly within Odoo. To do so, the US sales tax report needs to…
*: hr_payroll, reports, reports_avatax Purpose: Improve and enhance the US tax report framework to eventually support future e-filing directly within Odoo. To do so, the US sales tax report needs to capture all relevant information, such as exempt sales, taxable sales, non-taxable sales, and the tax rate. It supports both Avalara and non-Avalara users. Configuration: Users can configure taxes specifically for the US jurisdiction by setting the jurisdiction type, the following information required by the type (state, county, city). If the tax is an exempt or nontaxable of a standard tax rate, then it can be added to the standard tax rate on its exempt and nontaxable tax field. For Avalara users, the configuration is automatically handled based on the Avalara response. The following tax types are supported: - Fully exempt taxes (ex. 0% exempt tax) - Fully nontaxable taxes (ex. 0% nontaxable tax) - Rate-reduction taxes (ex. 6% rate reduced to 4% tax) Report: The US tax report will organize the taxes based on its state. Per state, it lists the taxes in order based on its jurisdiction type: state, special, county, city. The header will total the columns based on the base lines to avoid double-counting. Per tax row, the column values include its linked exempt and nontaxable taxes. - Gross should be a sum of exempt, nontaxable, and taxable values. - Exempt displays the amount that are exempted. - Nontaxable displays the amount that are nontaxable. - Taxable displays the amount that are taxable. **Note: Rate-reduced taxes will not have its own row and are aggregated into its parent tax. task-6223342
The employee Gantt view in Manufacturing work orders now shows the progress bar again. This makes it easier for teams to quickly see work progress and plan shop floor capacity without opening extra details.
Original PR description
Since 19.4 the progress bar has been hidden for employee gantt. This commit makes sure it is visible. task-6459190 Forward-Port-Of: odoo/enterprise#127647
Cached website generation requests now schedule a quick follow-up process instead of calling webhooks immediately. This helps ensure downstream notifications happen after generation is safely saved, without tying up system workers.
Original PR description
When a request is cached a webhook won't be called because if we did it immediatly it might arrive before the generator commited. And we don't want to delay the webhook call to not stall a worker just for that. So we simply scheldule a trigger if a request was cached. Forward-Port-Of: odoo/enterprise#128206
Helpdesk field service teams can now plan interventions from the standard Planning view, see all shifts, and open scheduled work filtered to the current ticket. The update also separates scheduled and completed shift counts, making it easier to understand upcoming and finished work at a glance.
Original PR description
- "Plan Intervention" now opens the standard Planning view showing all shifts. - "Scheduled" opens the Planning view filtered on the current ticket. - Open the Gantt view on the next scheduled shift, or the most recent shift when no upcoming shift exists. - Display scheduled and completed shift counts separately. task-6267783
Worksheet section titles are now shown when worksheets are printed as PDFs and viewed in the portal. This preserves the worksheet structure for customers and field service users, making forms easier to read while keeping folded sections working as before.
Original PR description
Previously, worksheet sections were not displayed in printed PDFs or on the portal UI, causing the worksheet structure to be lost. This change ensures that section titles are rendered in both the printed PDF and the portal UI while preserving the existing behavior for folded sections. task-6314616
The timesheet timer menu now loads more quickly by avoiding repeated background requests and reusing information that has already been prepared. This should make opening and using the timesheet systray feel smoother, especially for users who track time frequently.
Original PR description
This PR removes some blocking RPC calls and caches information to make the loading of the systray as lightweight as possible. Changes include: - Move `field_get` to the lazy session info, so the field metadata is available client-side without a dedicated round-trip. - Cache the pre-filled form: it does not change as long as the task / project context stays the same, so it is computed once and reused. - Drop the `get_server_time` RPC and rely on the client-side clock. - Add a client-side systray cache service to avoid redundant requests. Task-6131386 Forward-Port-Of: odoo/enterprise#125368 Forward-Port-Of: odoo/enterprise#120429
The account selection wizard in online bank synchronization now displays its text with better alignment. This makes the setup screen easier to read and gives users a more polished experience when connecting accounts.
Original PR description
No task ID
The VoIP softphone now opens directly to a pre-filled keypad when launched from a form with an available phone number. Calls made without changing that number are automatically logged against the related record, helping teams save time and keep customer activity history accurate.
Original PR description
``` [IMP] voip: auto-fill keypad with partner phone and create call activity on form record When the softphone is opened from the systray while a form view is active, automatically switch to the keypad tab and pre-fill the partner's phone number if the record has a partner_id with a phone field. Falls back to the record's own phone fields (via _phone_get_number_fields) when no linked partner is found or the partner has no phone number. If the user dials the pre-filled number without modification, the form record context (res_id, res_model) is passed to makeCall so that a phonecall activity is created and linked to that record. ``` Task-6365445
UK companies now submit HMRC VAT returns from the tax return itself instead of the tax report screen. This makes the filing process more intuitive and avoids generating unnecessary returns from the UK tax report.
Original PR description
Before this commit: - The tax return submission to HMRC for UK companies is done in the tax report view itself. - Even the returns are being generated for the UK tax report, but the filing process is handled in the tax report, which is unintuitive. After this commit: - The UK tax return filing to HMRC has been moved to the tax return itself. - So there are no more useless returns generated for the UK tax report. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10198 Task-5865605
Rental sales order sections now align with recent sales order layout changes, allowing quantity and unit fields to be managed consistently for grouped section items. This helps keep rental order editing reliable and coherent after the related community update.
Original PR description
We added quantity and UoM fields on the section to easily update all elements of a section. To do this, we stack two fields in a `<column>` tag. To stay consistent, we need to retarget all XPath expressions referencing `<field>` to `<column>`. Community PR: https://github.com/odoo/odoo/pull/267933 Upgrade PR: https://github.com/odoo/upgrade/pull/10417 task-6075605
Website editor users will now see an AI badge next to individual blocks that were generated or changed with AI. This helps set expectations that some standard editing options may behave differently for those blocks.
Original PR description
This commit shows an icon next to the name of snippets edited with the AI so users know standard builder options may behave differently. The flag `containsAiContent` was only set on the zone, but the icon is shown per snippet, so it is now stamped on each generated block instead. task-6251800
Belgian payroll now includes salary rules for handling gift vouchers. This helps payroll teams calculate and report these benefits more consistently within Odoo.
Original PR description
Task: 6424079
The PLM engineering change process now makes product and BoM version updates clearer and easier to complete. Users can see where products are used, update related parent items during approval, and work with a simpler ECO form, reducing manual tracking and improving change control.
Original PR description
PLM ECOs are currently centered around BoM revisions, while product versioning and parent-product impact tracking remain difficult to manage from the ECO flow. This change improves the ECO workflow…
PLM ECOs are currently centered around BoM revisions, while product versioning and parent-product impact tracking remain difficult to manage from the ECO flow. This change improves the ECO workflow around product and BoM revisions by making version updates explicit, exposing where a product is used, and simplifying the ECO form. This commit's changes: - Add Product Revision and New Product Introduction ECO types using the standard PLM stages. - Remove the ECO Apply On/type selection field and rely on the selected product and optional BoM instead. - Replace the separate Update Version action with an Update Versions wizard opened from Apply Changes. - Allow the wizard to update the product, revised BoM, parent products, and parent BoMs, with chatter logs on all updated records. - Apply the ECO from the version wizard. - Add Used In navigation on ECOs to show parent products that use the ECO product through active BoM hierarchies. - Add Versions navigation on products to show products linked through BoM revision chains. - Keep BoM selection optional on ECOs and show "No BoM Change" when no BoM is selected. - Simplify the ECO form by hiding the ECO type when only one type exists, moving the kanban state into the title area, and simplifying the Revision smart button. - Remove obsolete PLM document kanban code after the document refactor. - Adapt PLM workorder integrations after removing the ECO `type` field. - Extend tests for ECO version updates. task-6213679
The Belgian payroll module now includes a salary rule for calculating an additional net salary component. This helps payroll teams handle this type of compensation more directly and consistently within Odoo.
Original PR description
This commit introduces a new salary rule to the Belgian HR payroll module, allowing for the calculation of an additional net salary component. task-6409188
This update makes VoIP call flow configuration easier by simplifying key forms, improving record selection, and making call group and queue names clearer. It also improves audio message handling with easier upload, recording, text-to-speech preview, and fixes stale node data after edits.
The salary configurator now avoids duplicate background work and reduces database lookups when users update salary offers or benefits. This should make salary simulations faster and more efficient without changing the user-facing process.
Original PR description
In the salary configurator (`/update_salary` and `/onchange_benefit` routes), `create_new_version()` was executing a redundant second call to `offer._get_version()`. This caused an extra dummy `hr.employee` and `hr.version` record to be created in memory, triggering an unnecessary nested `hr_version_context` savepoint. Fix: Pass the existing `version.payroll_properties` record into `create_new_version()` directly to avoid the second `_get_version()` call and eliminate the nested savepoint cycle. `_get_compute_results()` was executing multiple separate `search()` queries on `hr.contract.salary.resume` for different value types. Combine these searches into a single query per request to reduce database round-trips. Task: 6226629
This update streamlines Odoo VoIP setup and daily use by simplifying call flows, queues, groups, IVR, voicemail, audio messages, and user forwarding settings. It also improves phone number onboarding notices and fixes several issues where call flow nodes or audio settings could become outdated or invalid, making configuration more reliable for users.
WhatsApp conversations now keep at least one internal agent assigned by hiding options that would let the final agent leave. This helps ensure customer conversations remain accessible, supported, and manageable by the business.
Original PR description
Prevent last agent from leaving the conversation by hiding the Leave conversation action and /leave channel command. This prevents scenarios where a Whatsapp channel becomes orphaned with only the external Whatsapp customer remaining, which would make the conversation inaccessible and unmanageable. task-[6008262](https://www.odoo.com/odoo/project/1519/tasks/6008262) community: https://github.com/odoo/odoo/pull/257521
Time off requests made from the Gantt view now handle multi-day date ranges more consistently. When a selected range effectively counts as one working day due to weekends, non-working days, or overlapping leave, users are no longer shown misleading half-day choices.
Original PR description
Purpose: When taking a range which results in only 1 day taken (because it overlaps with a non working day or another time off), you only see the selector of morning / afternoon like for a unique day, but you shouldn't be able to select morning or afternoon. - added selection for request periods in the gantt for day ranges similar to the one in form view task-id: 6456270
Updates internal website editing tests so they continue to reflect a recent form behavior change. This helps maintain release quality without changing the customer-facing website experience.
Original PR description
A form action change now fetches the model's authorized fields (see the change in community), so stub that RPC to keep the tests passing. task-4952094
Helpdesk reports and ticket groupings now show the total time spent instead of the average time. This gives managers a clearer view of workload and effort across tickets, periods, and reporting groups.
Original PR description
Previously, the average number of hours spent was displayed in the Ticket Analysis and SLA Status Analysis reports. The grouped view in both My Tickets and All Tickets also showed the average time rather than the total time, making it difficult to understand the actual time spent. From this commit onward, the total time spent will be displayed instead of the average. This provides a clearer view of how much time has been spent over a specific period or based on the selected grouping criteria. Task-4652757
Helpdesk and timesheet dashboards now use conditional formatting to make important values stand out automatically. This helps teams spot trends, exceptions, or areas needing attention more quickly when reviewing dashboard data.
Original PR description
…d CF This commit adds some conditional formatting on the helpesk and timesheet dashboards. Task: 6478487
The manufacturing work order time log dialog now updates the employee's total logged time instead of only the most recent entry. This makes the displayed time better match what users expect and reduces confusion when tracking work on production tasks.
Original PR description
Before, the update time log dialog was targeting the last employee time log entry, causing confusion as it didn't match the total time spent on the task. The employee total time is defined as the sum of its time log entries without checking if they overlap, unlike the work order duration. Task-6467195
WhatsApp message templates can now use meaningful placeholder names, such as customer name, instead of only numbered fields. This makes templates easier to read and keeps Odoo compatible with newer WhatsApp Cloud API template formats.
Original PR description
This commit introduces support for named parameters in WhatsApp templates, allowing users to use descriptive placeholders like `{{customer_name}}` in addition to the standard positional `{{1}}` format.
This change ensures compatibility with newer template formats supported by the WhatsApp Cloud API and improves template clarity.
Documentation: https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/overview#parameter-formats
Task-5871301Return types must now always have a workflow selected, preventing configurations that could make return screens inaccessible. This reinforces the intended setup and helps avoid broken return processing caused by an empty workflow value.
Original PR description
It should have been since the beginning. Since setting it to None entirely breaks the returns (views are not accessible anymore), we assume no one was doing that, and don't merge add an upgrade script to this PR.
Financial report filter choices are now remembered separately for the companies currently selected, rather than using the user's default company. This helps users working across multiple companies return to reports with the right saved settings and reduces confusion from reused filters.
Original PR description
Report options are cached in the HTTP session for future reaccess, so that previously selected filter values can be restored. To do that, we relied on a cache key, built from the report targeted by the option triggering the loading and the user's default company. Using the default company doesn't make sense: this company is very unlikely to change (it's just the default that opens when logging in). What was probably intended with that line was to depend on the active company. We fix that, and now depend on the companies in the selector (which don't especially match what is taken into account by the report, but we consider it's enough like this, as it's simpler and should be equivalent in actual cases and not just theoretical testing).
Payroll setup now offers a clearer closing-date selection, including the 15th of the month, ordered from month-end backwards. Employee onboarding screens show only relevant actions at the right time, and missing employer category warnings appear earlier on the dashboard so payroll issues can be addressed before payslip processing.
Original PR description
In this PR expected to update Payroll closing date in payroll config, where before picking the day of payroll fells weird because of the order and also not possible to choose the 15 og the month. Update to list all possible options from the last day ot the month below in decreasing order. During creation first employee, there are smartbuttone that better to show with specific condition - Salary adjustment -> Displayed only when an active contract exists. - Time off -> Displayed only after the employee record has been saved. - History -> Displayed only when the employee record has been saved. Update warning missing employer category, where before only visible in the payslip. Display the warning on the dashboard so users are awated upfront than discovering it later on Individual payslip. task-6438703
Appointment rescheduling now keeps the existing booking active until the user confirms a new date, time, or resource. This prevents accidental cancellations when users abandon rescheduling, while paid appointments continue to follow the existing non-reschedulable flow.
Original PR description
**Purpose:** Currently, when we reschedule an appointment, current booking gets cancelled. It has the same flow as cancelling appointment. **Specifications:** When a user reschedules an appointment, the old booking should only be deleted after the user selects a new slot. If the user does not select a new slot, the existing appointment should remain unchanged. Users should only be allowed to update the date, time, or resource of the appointment. After confirming the new slot, the old appointment will be updated, and the user will be redirected to the appointment details page for the new slot. The current flow will remain the same for paid appointments, they are not reschedulable. For cancel appointments, we changed the flow to open the cancellation page instead of letting users select new slots. Task-5913349
Rescheduling tasks in the Gantt view now keeps the same number of working hours between the planned start and end dates. This helps project schedules remain accurate when tasks are moved, reducing manual corrections for planners and managers.
Original PR description
When rescheduling tasks from gantt view, we should keep the number of working hours between the start and end dates of the task when rescheduling it --- task-5376423
Australian payroll can now include post-tax deductions on payslips that reduce net salary without being reported through Single Touch Payroll. The change also supports separate accounting treatment for different deduction types and refreshes year-to-date opening balances when new salary rules are added.
Original PR description
This commit allows post tax deductions to be added to the payslip without impacting STP. This also allows automatically creating opening balances entries for new salary rules. task - 6236042 Forward-Port-Of: odoo/enterprise#119952
Search date filters now include ready-made choices like Today, This Week, This Month, This Quarter, and This Year, with arrows to move to the previous or next period directly from the search bar. This makes it faster for users to review work, planning, reports, or records by date without needing custom filters in each view.
Original PR description
## Navigable smart-date filters in the search bar <img align="right" width="382" height="328" alt="image" src="https://github.com/user-attachments/assets/6e527849-0837-412e-aba3-bbddd6bab59c" /> ###…
## Navigable smart-date filters in the search bar <img align="right" width="382" height="328" alt="image" src="https://github.com/user-attachments/assets/6e527849-0837-412e-aba3-bbddd6bab59c" /> ### What Date filters (`<filter date=.../>`) now offer built-in smart-date options — **Today**, **This Week**, **This Month**, **This Quarter**, **This Year** — and each active one gets **prev/next arrows** to shift the period on the fly from the searchbar facet (eg. `This Week` → last week → next week). We keep the existing month and quarter features, and also add a new **"Custom Date…"** shortcut in each date-filter menu, opening the editor pre-filled with the right field. <br> ### Why Filtering by a relative date range was a common need, that devs were hardcoding in views (see commit `[REM] *: remove duplicate relative ranges from filters`). Furthemore, other views (eg. gantt view, custom accounting views...) also had this navigable filter logic (but as an extra section below the search bar). We decided to integrate that feature at the framework level, allowing users to navigate filters faster for example when planning day-by-day or reviewing quarter-by-quarter, while saving vertical space compared to a gantt-style navigator. ### Also - Active relative filters keep their menu section **unfolded**, so the selected option stays visible. - Period options and smart dates are **mutually exclusive** — picking one clears the other. ### Notes - Smart-date facets are **not** click-to-edit like other facets (intentional) ### Technical - Decided to model the new relative filter type as a top level filter even if its always a children of a date filter. I did this because it makes it easier to add custom behavior with the existing code structure (domain, label, navigation..). The only downside is that it makes it a bit more complex to display. task#6260555 Documentation PR: https://github.com/odoo/documentation/pull/18866 Community PR: https://github.com/odoo/enterprise/pull/122986 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Opening the Time Off Type details from a new leave request no longer saves or submits the request before the user is finished. This prevents accidental confirmations or approvals and also avoids related display errors that could hide newly created leave requests until refresh.
Original PR description
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls…
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls `willOpenRecordInDialog()`, which defaults to `record.save()`. For a new leave request, this triggered `hr.leave.create()`'s validation logic, auto-confirming (or even auto-approving) the request before the user had finished the wizard. This premature save was also the root cause of two related bugs, both fixed as a side effect: closing the Time Type dialog threw `TypeError: Cannot read properties of undefined (reading 'focus')` (the save re-rendered the parent, leaving `Many2One`'s `onClose` pointing at a stale component), and that crash aborted the promise chain before it could reload the calendar, leaving a newly-created leave request missing from view until a manual refresh. Adds a `many2one_no_save` field widget overriding `willOpenRecordInDialog` to skip the save, applied to `work_entry_type_id` on the base `hr_leave_view_form` so all inheriting views are covered. task-6452848 Forward-Port-Of: odoo/odoo#281263
This change restores expected internal metadata for a Point of Sale popup so automated tests no longer fail unnecessarily. It does not change cashier workflows or business functionality, but helps keep the Point of Sale module stable during validation.
Original PR description
### Issue: In 19.3, the following hoot tests fail with a RunBot error: - "called at right time (when canceling order)" - "called at right time (when canceling order never sent to blackbox)" - "called…
### Issue:
In 19.3, the following hoot tests fail with a RunBot error:
- "called at right time (when canceling order)"
- "called at right time (when canceling order never sent to blackbox)"
- "called at right time (when canceling a combo order)"
### Cause:
Commit 0dfd71b9f4 removed `close` from `ControlButtonsPopup` as the Dialog patch now handles closing via `this.data.close()` With no remaining props to declare, `static props` was removed entirely
Without `static props`, Owl skips all prop validation but emits: "Component 'ControlButtonsPopup' does not have a
static props description"
`mountWithCleanup` forces `warnIfNoStaticProps` to `true` in hoot tests, causing the tests to fail
`close` is declared as optional since `dialog_service.js` always injects it via `subProps: markRaw({ ...props, close })` at runtime, but the component no longer uses it directly
### Steps to reproduce:
- Install `l10n_be_pos_blackbox`
- Enable Developer mode
- Open the JS test UI
- Run one of the failing tests
runbot-941231
Forward-Port-Of: odoo/odoo#277790Sale orders now keep combo product totals consistent when switching between tax-exclusive and tax-inclusive views. This prevents inflated order totals and gives sales teams and customers accurate pricing for combo items.
Original PR description
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines…
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines (e.g. 160.00). 4. Switch the document tax mode from "Tax Excl." to "Tax Incl." using the toggle at the top of the Order Lines tab. **Issue:** - After switching to "Tax Incl." mode, the total on the sale order is higher than the previous untaxed amount (e.g. shows 266.00 instead of the 160.00). - The same switch works correctly on regular (non-combo) product lines **Expected behavior:** - the new total should equal the previous untaxed amount. **Why this happens:** - `_onchange_order_line` is triggered on every `order_line` change, including when switching `document_tax_mode` causes `price_subtotal` to update on existing lines. - The unconditional write to `product_uom_qty` and `discount` on all combo item lines was calling '_compute_price_unit` even when neither value had changed. - `_compute_price_unit` then called `_reset_price_unit` under the new `document_tax_mode`, which re-calculated the stored `price_unit` instead of leaving it untouched for `_compute_amount` to reinterpret correctly. **Fix:** - Only sync `product_uom_qty` and `discount` to the combo item lines whose current values actually differ from the parent line. When no value has changed, no write occurs, so `_compute_price_unit` is not called. opw-6427963 Forward-Port-Of: odoo/odoo#280019
This fix restores automatic SInvoice submission for Vietnamese POS orders when the invoice option is selected. Businesses no longer need to manually send these e-invoices after validating a point-of-sale order, reducing missed submissions and extra admin work.
Original PR description
### Expected behavior: When an e-invoice is created from POS using SInvoice, existing behavior is to directly submit it ### Current behavior: When a POS order with "Invoice" ticked is confirmed in a…
### Expected behavior: When an e-invoice is created from POS using SInvoice, existing behavior is to directly submit it ### Current behavior: When a POS order with "Invoice" ticked is confirmed in a VN company, the e-invoice is NOT automatically submitted to SInvoice. Users must manually trigger the send wizard. ### Steps to reproduce: 1. Install l10n_vn_edi_viettel_pos, activate VN company 2. Make an order from POS and check the invoice box 3. Observe SInvoice subsmission error ### Cause of the issue: - caused by commit https://github.com/odoo/odoo/commit/4f30306ccc9ff82911f90ed8b3714b212e4b77dc, which decoupled invoice PDF generation from POS order validation by setting `generate_pdf=False` in context when `use_download_invoice` is False (default) - `_generate_pos_order_invoice()` to skip `_generate_and_send()`, which skips VN SInvoice submission. ### Fix: Override `_generate_pos_order_invoice()` to force generating PDF when auto-send to SInvoice is enabled, restoring `_generate_and_send()` during order validation opw-6427675 Forward-Port-Of: odoo/odoo#280932
Authorize.net refunds now correctly handle payments originally made by eCheck/ACH, not just credit cards. This prevents refund failures for settled bank-account payments and helps businesses process customer refunds more reliably.
Original PR description
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm…
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm it and create the invoice 4. Pay the invoice with an eCheck (ACH) payment method through the Authorize.net provider 5. Wait for the payment to be settled by Authorize.net (_around 24 hours_) 6. Initiate a refund of the payment **Issue:** The refund fails with error `E00003: "The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardNumber' element is invalid - The value XX is invalid according to its datatype 'String' - The actual length is less than the MinLength value` **Expected behavior:** The refund should be processed successfully regardless of whether the original payment was made by credit card or eCheck (ACH) **Why this happens:** - The `refund()` method in `AuthorizeAPI` builds the refund request using a `creditCard` payment payload - When the original transaction was an ACH/eCheck payment, the `creditCard` key is absent from the transaction details returned by Authorize.net - The resulting request is rejected by Authorize.net because it does not satisfy the minimum length constraint for `cardNumber` **Fix:** - Detects whether the original payment used `creditCard` or `bankAccount` from the transaction details and build the appropriate payload according to Authorize.net API documentation: https://developer.authorize.net/api/reference/index.html#payment-transactions-credit-a-bank-account opw-6359726 Forward-Port-Of: odoo/odoo#282810 Forward-Port-Of: odoo/odoo#277742
The website setup flow now handles missing theme snippet templates more safely, so one unavailable snippet does not break the whole configurator. This improves reliability for website setup and strengthens the related automated checks.
Original PR description
Fix for the runbot nightly error 944444. bug: The website configurator crashed entirely if one theme snippet's template was missing, instead of just skipping that snippet. steps: Only visible while running `test_01_configurator_translation` fix: Catch MissingError, alongside ValueError, when generating and rendering configurator snippet content. task-6325919 Forward-Port-Of: odoo/odoo#278609
This change makes an automated web test more reliable by allowing extra time for an uploaded image to appear. It helps reduce random test failures during high system load, supporting smoother development and release validation without changing end-user behavior.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 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#281200
Self-order purchases for event tickets now keep the selected ticket details through checkout and use the configured ticket price when recalculating totals. This prevents prices from unexpectedly changing to the underlying product price on the payment page, keeping customer charges consistent.
Original PR description
In this commit: - Ensure event ticket information is preserved during self-order processing and use the configured ticket price when recomputing order line prices. - This prevents ticket prices from being replaced by the product price after proceeding to payment and keeps the amounts consistent across the payment page. Task:6375899 Forward-Port-Of: odoo/odoo#282530 Forward-Port-Of: odoo/odoo#275645
The live chat statistics cards now use the full available screen width on mobile devices. This removes awkward empty space and gives users a cleaner, more consistent view when managing live chat from a phone.
Original PR description
Previously, the live chat statistics section did not use the available width on mobile devices, leaving unnecessary empty space and resulting in an awkward layout. This PR makes the statistics cards take the full available width on mobile, providing a cleaner and more consistent interface. <table> <tr> <th>Before</th> <th>After</th> </tr> <tr> <td> <img width="372" height="805" alt="image" src="https://github.com/user-attachments/assets/6934927b-f744-4c93-b63e-1f49ecd33004" /> </td> <td> <img width="382" height="734" alt="image" src="https://github.com/user-attachments/assets/24f8b7e4-9fe7-4fa0-bf64-5d7917623830" /> </td> </tr> </table> --- Task ID - 6372787 Forward-Port-Of: odoo/odoo#274945
The hidden avatar count badge now expands properly when the number reaches double digits, such as '+10'. This keeps agent or user counts readable in Live Chat and other screens using avatar lists.
Original PR description
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This…
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This causes the text to get cut off, making the exact number unreadable. Solution: This commit updates the badge container to properly accommodate larger numbers. The text now fits entirely within the badge without overflowing, ensuring the hidden tag count remains fully readable. Steps to reproduce (runbot v19.3): 1. Open the Live Chat app (or any view using the many2many_avatar_user widget). 2. Add enough agents to a session so the remaining count hits double digits (10 or more). 3. Observe that the badge showing the remaining agent count (e.g., "+10") overflows the badge container, cutting off the text and making it unreadable. opw-6453976 <img width="2655" height="1111" alt="avatar_tag_193_before" src="https://github.com/user-attachments/assets/9c31007d-5300-4bb7-a703-01a13b5bdd10" /> <img width="2655" height="1112" alt="avatar_tag_193_after" src="https://github.com/user-attachments/assets/7b2a4074-3738-4a6c-9649-f6652601f3f3" /> Forward-Port-Of: odoo/odoo#281570
Point of Sale now handles sale orders with existing down payments correctly when another down payment is made. This prevents confusing positive and negative duplicate lines on POS orders, improving order accuracy for staff and customers.
Original PR description
When making a downpayment in the PoS on a sale order that already contained another downpayment, there would be multiple downpayment lines created in the PoS order (1 positive and 1 negative). Steps to reproduce: ------------------- * Create a sale order in the sales app * Make a downpayment in the sales app * Open the PoS and make a downpayment on the same sale order > Observation: Two lines are added to the order, 1 negative and 1 positive Why the fix: ------------ When creating the baseLines for the downpayment we should not consider the previous downpayments and only consider the other lines. opw-6354823 Forward-Port-Of: odoo/odoo#281397 Forward-Port-Of: odoo/odoo#275653
This fix ensures electronic invoices use the correct tax category when transactions involve a supplier or customer in the EEA, such as Swiss suppliers invoicing German customers. It helps avoid incorrect exemption labels and improves compliance for ZUGFeRD/Factur-X invoice reporting.
Original PR description
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax…
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax <ram:CategoryCode> is incorrectly set to 'E' (Exempt) instead of 'G' (Export). ### Steps to reproduce the issue: 1. Download Accounting and l10n_ch 2. Set the VAT for the CH company 3. Create an invoice for a German customer with 0% tax setted (for which you have to set as electronic invoicing the ZUGFeRD template into the Accounting tab of his contact) 4. Send it and see that the tag <ram:CategoryCode> is setted as E instead of G ### Cause of the issue: The logic assigning the 'G' and 'K' tax category codes was only triggered if the supplier was located within the EEA. If the supplier was outside the EEA, the code bypassed this block entirely and fell back to the default 'E' code for 0% taxes. ### Reason to introduce the fix: Update the condition to trigger when either the supplier or the customer is in the EEA. This ensures that cross-border transactions involving at least one EEA party correctly evaluate and apply the 'G' (Export outside the EU) category code. Also the case supplier not in eea with VAT filled in + customer in eea + RC tax with amount != 0 is fixed now (letter G reported instead of S). ### Documentation: [eInvoicing technical guidance document_v1.pdf](https://github.com/user-attachments/files/30831749/eInvoicing.technical.guidance.document_v1.pdf) opw-6407399 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283027 Forward-Port-Of: odoo/odoo#281245
The point of sale customer display now hides the company logo whenever a background image or QR code is shown. This keeps the screen cleaner and prevents the logo from overlapping more important customer-facing content.
Original PR description
Before this commit: --- The company logo is displayed above the background on the customer display. After this commit: --- The company logo is displayed only when there is no background or QR code to display. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281749 Forward-Port-Of: odoo/odoo#281406
The portal now decides whether to show the payment methods card using the same rules as the saved payment methods page. This prevents customers from seeing a card that leads to no available payment methods, or missing access when methods are actually available.
Original PR description
Commit bcfeed4b24f51 introduce `ResPartner._get_payment_tokens` method to determine which tokens are available for a specific partner, in case that method is overridden in some way, the portal card will not be visible/hidden correctly. This commit, use that method to align the portal card visibility with the tokens that will effectively be shown on the `/my/payment_method` page. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283173
Generated ISO 20022 payment files now include the state or province and second street line from partner and employee address records. This helps banks, especially in North America, accept wire transfers when complete beneficiary address details are required.
Original PR description
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street…
_get_all_addr() feeds the postal address block of generated pain.001 payment files, but does not return the partner's state nor the second street line. The beneficiary state/province and street complement (suite, unit, ...) therefore never appear in the generated file, even when they are set on the partner, and there is no way to fix it from the record. Some North American banks reject wire transfers whose beneficiary address lacks the state/province, so those payments fail regardless of how complete the vendor record is. Return the state code and street2 alongside the other address components, from the partner for the base implementation and from the employee private address for the hr one, so the payment engine can write them in the PstlAdr block. Steps to reproduce: - Install Accounting and enable a generic ISO 20022 payment method on a bank journal - Create a vendor located in the US or Canada with a complete address, including the state and a second street line - Register a vendor payment, add it to a batch and generate the pain.001 file - The creditor PstlAdr has no state/province, and its street line only carries the first street field: the street2 part is dropped Companion enterprise PR emitting the state in the generated file: odoo/enterprise#127958 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282620 Forward-Port-Of: odoo/odoo#282518
This fix restores several point-of-sale payment flows that stopped responding correctly after an internal payment method change. It prevents pending or waiting payments from getting stuck for Mercado Pago, Cashdro, Cashmatic, Safaricom, and bank QR code payments, improving checkout reliability for stores.
Original PR description
*: point_of_sale,pos_mercado_pago,pos_cashdro,pos_cashmatic, pos_safaricom d7a627160372 renamed the client-side payment interface attached to a pos.payment.method from `payment_terminal` to…
*: point_of_sale,pos_mercado_pago,pos_cashdro,pos_cashmatic, pos_safaricom d7a627160372 renamed the client-side payment interface attached to a pos.payment.method from `payment_terminal` to `payment_interface`, moved integrations off `payment_method_type` onto `payment_provider`, and renamed the `qr_code` type to `bank_qr_code`. Several call sites were left behind and now read attributes or compare against values that no longer exist, so they silently never match. Mercado Pago calls a method straight off the missing attribute, so an incoming webhook raises a TypeError and the payment line stays pending forever. The rest degrade silently: Cashdro and Cashmatic never cancel on Force Done, Safaricom never resolves the payment promise, and Bank QR lines left in `waiting` are no longer reset to `retry` when the session restarts, leaving them stuck. Use the existing `useBankQrCode` getter for the type check rather than repeating the literal. opw-6372208 Forward-Port-Of: odoo/odoo#278977
The product catalog now handles long unit of measure names more gracefully when adding products to sales orders. This prevents text from being cut off, making product quantities and units easier to read for users working with customized unit names.
Original PR description
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the…
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the catalog. Issue: --- - Long UoM names are not fully visible in the catalog view. Root cause: --- - The outer `<div>` has `d-flex` but lacks `w-100`, causing it to overflow its container. Solution: --- - Added `w-100` to the outer `<div>` to prevent overflow. - Adjusted the quantity selector layout for better visibility. Before: --- <img width="388" height="141" alt="image" src="https://github.com/user-attachments/assets/dafae08a-3c9d-4163-8894-daa2e4d26f62" /> After: --- <img width="382" height="154" alt="image" src="https://github.com/user-attachments/assets/abd6f034-be4b-49bf-be9c-c9779de0f30d" /> Enterprise PR: https://github.com/odoo/enterprise/pull/121139 opw-6253382 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282821 Forward-Port-Of: odoo/odoo#267118
When settling a sales order in Point of Sale, extra product attribute add-ons are now preserved on the resulting POS order line. This prevents missing add-on details and helps keep customer orders accurate at checkout.
Original PR description
Before this commit: --- - When a sale order line contained extra attribute addons, those values were not transferred to the POS order line while settling the sales order. After this commit: --- - Preserved extra attribute addons when creating POS order lines from SO. task-6204583 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282160 Forward-Port-Of: odoo/odoo#276143
Point of Sale sample products now load required product attribute information first, preventing an error when setting up sample data after attributes were changed. This helps businesses create demo shops or registers more reliably without manual troubleshooting.
Original PR description
## Steps to Reproduce: 1. Install the **PoS** and **Sales** modules without demo data. 2. Settings > Enable **Variants**. 3. Sales > Products > Attributes > Delete "**Brand**" attribute. 4. Create a **Clothes Shop** and open the register. 5. Load the **Sample** products. ## Error: `ParseError - while parsing /home/odoo/src/odoo/saas-19.4/addons/product/data/product_attribute_demo.xml:5, somewhere inside...` ## Cause: The `product_attribute_demo.xml` file references attributes that do not exist when the demo data is loaded, which raises an error. Before 19.4, the attributes were defined in the same file. After this commit https://github.com/odoo/odoo/commit/56942bcf34785e869c7648cf100c8818c5da0b6d, the attributes are defined separately in the `product_attribute_data.xml` file. ## Fix: This commit loads the data file before, ensure the referenced attributes are available when the demo file is processed. sentry-7640019804 Forward-Port-Of: odoo/odoo#281461
The HTML editor now prevents users from opening the dynamic field selector when no target model has been selected, showing a clear notification instead. It also handles outdated or invalid saved field selections more safely, reducing interruptions and avoiding editor crashes when templates or model choices change.
Original PR description
The dynamic field editor assumes that an `Applies To` model is always selected and that existing dynamic fields are always valid for the current model. As a result, trying to insert or edit a dynamic field without selecting a model raised an error. Editing an existing dynamic field after changing the selected model could also crash the field selector when the stored field path was no longer valid. Show a notification when users try to insert or edit a dynamic field without selecting a model, and handle invalid field paths when initializing the field selector to avoid UI crashes. Task-6365420 Forward-Port-Of: odoo/odoo#278544
Clicking a related field in the HTML editor now inserts its readable name by default instead of its internal ID. This makes generated placeholders more useful for users, while still allowing the ID to be selected when needed.
Original PR description
Before this commit: when clicking a field having sub fields (canFollowRelationFor is true), we just return this field's id, which is not very useful in most cases. After this commit: We created subclass of DynamicPlaceholderPopover, EditorDynamicPlaceholderPopover, which uses EditorModelFieldSelectorPopover. We use the display name of the followable field by default and if the user really want the id, they may choose the id subfield. We also show the followable field's name as the default placeholder instead of "Display name". task-6265223 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Uzbekistan accounting setup now classifies current-year and period profit/loss accounts correctly so they are not counted twice in the balance sheet. This improves the accuracy of the Equity section in local financial reports.
Original PR description
Accounts 8710 (Current Year Profit/Loss) and 9910 (Net Profit for the Period) were equity_unaffected, causing their balances to be picked up both by the retained earnings tag-based formula and by the current-year-earnings domain formula in l10n_uz_reports, double- counting them in the balance sheet's Equity section. This commit changes both accounts' type to Equity and adds the BS Line 0540 tag to 9910 (8710 already carried it), so their balances are captured through the tag alone. see https://github.com/odoo/enterprise/pull/128124 see https://github.com/odoo/upgrade/pull/11048 task-6361059
Fixed a minor display issue where some form view button icons could include an unintended “undefined” styling label in the page markup. This keeps the interface markup cleaner and avoids possible styling confusion without changing user workflows.
Original PR description
The `iconClass` prop of `ViewButton` was declared optional with no default value, so it resolved to `undefined` whenever a button arch had an `icon` but no `icon_class` attribute — which is the case…
The `iconClass` prop of `ViewButton` was declared optional with no default value, so it resolved to `undefined` whenever a button arch had an `icon` but no `icon_class` attribute — which is the case for the large majority of stat buttons. The template concatenates that prop into the icon's class string: `this.icon.class + ... + ' ' + this.props.iconClass` so `undefined` was stringified and rendered literally, producing `class="o_button_icon oi undefined"` on the icon element. Give the prop an empty-string default, consistent with `className` in the same props definition. This also covers the components spreading `viewButtonProps` (MultiRecordViewButton, and the Studio button variants in enterprise). Only form views were affected: list and kanban buttons go through `getButtonInfo` in views/utils.js, which already falls back to `""`. Introduced by: https://github.com/odoo/odoo/commit/c5a40a608280017ae9ea8f9e9e1c59f778d629ae task-6485741 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Repair orders under warranty can now be completed when they include service lines linked to a quotation or invoice. The related sales or invoice line is correctly set to a zero price, preventing errors and ensuring warranty services are not charged.
Original PR description
Currently, an error occurs when user tries to end repair that has a service line and is linked to a sale order or invoice. Steps to replicate: - Install `repair` with demo. - Create a new repair…
Currently, an error occurs when user tries to end repair that has a service line and is linked to a sale order or invoice.
Steps to replicate:
- Install `repair` with demo.
- Create a new repair order with a customer and check `Under Warranty`.
- Click on the `Services` page and add a product.
- Click on `Quote` button.
- Return to the repair order through breadcrumbs.
- Click `Confirm Repair` > `Start Repair` > `End Repair`.
Error:
```
File '/home/odoo/odoo19/community/addons/repair/models/repair_service_line.py', line 120, in _update_repair_sale_order_line
self.price_unit = 0.0
^^^^^^^^^^^^^^^
AttributeError: 'repair.service.line' object has no attribute 'price_unit'
```
Cause:
- The error was introduced after a recent improvement [PR].
- The `repair.service.line` model does not contain a `price_unit` field, which causes the error.
- The `price_unit` field is present in the related Sale Order Line or Invoice Line.
Solution:
- The price of the linked Sale Order Line or Invoice Line is now set to zero when the product is under warranty.
[PR]: https://github.com/odoo/odoo/pull/260278/files#diff-1ff5f0c96411a07c366ef6410fc4580798593205b57d5740fbb4a56259341c98R102
sentry-7620551626
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278591This update fixes how simplified Italian electronic invoices are generated, including support for virtual stamp duty and correct use of the simplified format when selected. It also prevents simplified invoices from being used for unsuitable recipients, reducing compliance errors for Italian invoicing.
Original PR description
- Added the BolloVirtuale in the Simplified invoice template - Now it's possible to force the Simplified format on exported invoice when the `l10n_it_document_type` is set to a simplified one - Factored the Italian partner recognition (_l10n_it_edi_is_italian) - Added a check on the invoice, no simplified format for non-domestic / PA partners Task [link](https://www.odoo.com/odoo/project.task/6226436) task-6226436 Forward-Port-Of: odoo/odoo#283154 Forward-Port-Of: odoo/odoo#274493
Fixed an incorrect styling reference that made titles appear at the wrong size in the website theme preset preview. This helps users see a more accurate preview when choosing or configuring a website theme.
Original PR description
When the conflict of the forward port [1] was resolved, an error was introduced when the class `fs-4` was replaced by `fs-h4`. This commit fixes the class. [1] https://github.com/odoo/odoo/pull/279324 Forward-Port-Of: odoo/odoo#281995
When users try to archive an accounting journal that still has draft entries, the error message now points them to the correct place where those entries can be found and handled. The journal form button was also renamed so it accurately describes that it opens journal items, reducing confusion and helping users complete the archive process.
Original PR description
> Replaces https://github.com/odoo/odoo/pull/282286, which GitHub closed automatically after a bad force-push on my side: the branch was pushed from a shallow clone and its head lost its parent…
> Replaces https://github.com/odoo/odoo/pull/282286, which GitHub closed automatically after a bad force-push on my side: the branch was pushed from a shallow clone and its head lost its parent commit, leaving no common ancestor with 18.0. A PR in that state cannot be reopened, so this one continues from a clean branch with the exact same change. The review discussion is in that PR, and the rename asked for there is included here. ### Steps to reproduce 1. Go to `Accounting > Customers > Invoices` and create an invoice on a given journal, leaving it in draft. For the clearest case, leave it with no invoice line. 2. Go to `Accounting > Configuration > Journals`, open that journal and archive it. 3. `_check_auto_post_draft_entries` raises: *"You can not archive a journal containing draft journal entries. To proceed: 1/ click on the top-right button 'Journal Entries' from this journal form 2/ then filter on 'Draft' entries 3/ select them all and post or delete them through the action menu"*. 4. Follow those steps: click the `Journal Entries` smart button on the journal form. ### Current behaviour The list comes up empty, so the user concludes the error message is wrong, while the draft entries do exist. The instructions cannot be followed: - The smart button opens `action_account_moves_all_a`, which is named **"Journal Items"** and targets **`account.move.line`**, not `account.move`. The label of the button and the name of the action it opens do not match. - That action defaults to `search_default_posted: 1`, so no draft record is listed. - Draft entries with **no line at all** — commonly created through the incoming mail alias of a journal — have no `account.move.line`, so they stay invisible in that view even after switching the filter. - The action menu of a move line list offers no way to post or delete the entries, and the action sets `create: 0`. - The filter is labelled **"Unposted"**, not "Draft". The offending entries are only reachable through `Accounting > Accounting > Journal Entries`, filtering by journal and by "Unposted". ### Expected behaviour The error should point to a view where the records blocking the archiving are actually listed and actionable. ### This PR Two changes, the validation itself is unchanged: - The error message now points to `Accounting > Accounting > Journal Entries` and uses the real filter name, "Unposted". - The smart button of the journal form is renamed to **"Journal Items"**, so its label matches the action it opens and no longer suggests it lists journal entries. This was asked for in the review of the previous PR. Targeted at 18.0 because that is where the misleading message is being hit in practice; it is identical on 19.0 and master. If a translatable string change does not qualify for the stable series, tell me and I will retarget to master. Forward-Port-Of: odoo/odoo#282956
The attendance kiosk no longer loads a presence status component that is not used in that view. This keeps the kiosk experience leaner and avoids unnecessary background resource loading without changing visible functionality.
Original PR description
This commit removes the hr_attendance_presence_status.js file from the kiosk bundle, as it is not needed in the kiosk view and can cause unnecessary loading of resources. task-6468972 Forward-Port-Of: odoo/odoo#282987 Forward-Port-Of: odoo/odoo#282410
Fixes invoice reports so returned dropshipped products no longer show incorrect lot or serial numbers. This helps customers and staff see accurate product tracking information on invoices and credit-note scenarios.
Original PR description
**Issue** Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial…
**Issue**
Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report.
**Steps to reproduce**
- Activate "Display Lots & Serial Numbers on Invoices"
- Create a product tracked by serial/lot and enable the dropship route
- Create two lots: "lot1" and "lot2"
- Create and confirm a SO for quantity 2
- Confirm the PO and validate the dropship for both lots
- Create and post an invoice
- Return "lot2" from the dropship picking
- Create and post a credit note for quantity 1
- Click on print on the invoice
-> The generated PDF displays "lot1 & lot2" instead of "lot1"
**Cause**
While rendering `account.report_invoice_with_payments`, the report calls `_get_invoiced_lot_values` to determine which lot/serial numbers should be displayed:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L31-L32 `invoiced_qties = 2` since the invoice is on a quantity of 2 https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L44 Three stock move lines are retrieved from the SO:
- the two original dropship deliveries,
- the return move for `lot2`. https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L63 However, none of them are considered as `is_stock_return` because the dropship locations use `supplier` instead of `internal`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L72-L76 As a consequence:
- The two original delivery move lines each keep quantity `1`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L69 they never pass through the return handling logic (as they should be): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L77-L80
- for the last one, `is_stock_return = False` while it should not, thus the quantity is 1 instead of 0. Furthermore, it does not pass by this code:
https://github.com/odoo/odoo/blob/8759429547e42e9f63b15a7c80475be46ef437e2/addons/sale_stock/models/account_move.py#L79 which would make the quantity for lot2 equalled to 0 (1-1) The quantities are therefore accumulated as:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L92
resulting in:
`qties_per_lot = {lot1: 1, lot2: 2}`
instead of:
`qties_per_lot = {lot1: 1, lot2: 0}`
The report selects both lots since it starts with lot1 (qty of 1): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L94-L99
opw-6236855
Forward-Port-Of: odoo/odoo#271282
Forward-Port-Of: odoo/odoo#270599Kiosk receipts no longer show the table tracker number twice. This keeps customer receipts clearer and avoids confusion for staff and guests using self-ordering.
Original PR description
This removes the duplicate table tracker number on the receipt when ordering on kiosk. There is already a floating_order_name field that shows the table tracker number on the receipt when ordering on kiosk. task-6439063 Forward-Port-Of: odoo/odoo#280309
When users update analytic distributions on multiple journal items and create a new distribution model, the creation dialog now remains open so they can finish and save it. This prevents failed or interrupted bulk updates in accounting workflows.
Original PR description
When mass-editing the Analytic Distribution field on several records at once, and creating a new distribution at once, will close the creation dialog before the user could fill it in. Steps to reproduce: - Enable Analytic Accounting - Open Accounting > Journal Items - Enable the Analytic Distribution column - Select 2 journal items and click on the Analytic Distribution - Click on 'Update', fill a distribution, then click "New Model" - Confirm the multi-edit update Issue: The create Analytic Distribution model dialog closes on its own instead of staying open, so the model can never be saved. Analysis: After https://github.com/odoo/odoo/commit/12a61fa5ab7c56a42020c50c683df8ed52f1fb01, in multi-edit, save() ends reloading the list, unmounting the AnalyticDistribution widget, that closes the model dialog it just opened. opw-6405219 Forward-Port-Of: odoo/odoo#281141
This fixes automated checks so Point of Sale sales are validated correctly whether or not stock features are installed. It helps avoid false test failures and keeps invoicing and delivery behavior verified in the right modules.
Original PR description
`test_settle_order_with_different_uom` asserted that settling a sale order line sold in dozens sets `qty_delivered` to 1.0 on the sale order line. That only holds when `pos_sale_stock` is installed: it is its `_prepare_qty_delivered` override that reports the quantities sold in the PoS as delivered, converted back into the unit of the sale order line. `pos_sale` alone only feeds `qty_invoiced`, and since `point_of_sale` does not depend on `stock`, `sale_stock` is not installed either, so `qty_delivered_method` stays 'manual' and the field remains 0.0. Assert `qty_invoiced` instead, which covers the same unit conversion with the modules `pos_sale` actually depends on, and move the `qty_delivered` check to `pos_sale_stock`, where the delivery is created. It is added as its own test since the tests inherited from `TestPoSSale` are not collected by the `pos_sale_stock` suite. runbot-946054 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When shoppers sort product listings after applying filters, those filters now remain in place instead of being cleared. This makes browsing more consistent and helps customers refine products without repeating their selections.
Original PR description
Before this commit, changing the sort order after applying shop filters would clear the active filters because the sort links were not updated with the current query parameters. This commit ensures that the sort controls preserve the active filters when changing the sort order. task-6422290
Mega menu layouts now avoid using heading styles where they do not represent real page structure. This keeps the same visual appearance while improving accessibility and helping search engines better understand website pages.
Original PR description
### Issue: Mega menu templates were using heading tags purely for visual styling. This introduces an incorrect document outline, as these elements do not represent actual content hierarchy. It can negatively impact SEO and accessibility. ### Fix: Avoid using heading tags in mega menu templates for visual styling. Use existing CSS classes to preserve the appearance. task-[6116253](https://www.odoo.com/odoo/project/974/tasks/6116253) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes several issues with light users so their role, account status, and employee confirmation indicators behave correctly. It also prevents light users from requesting app installations and adds a demo light user for easier testing and demonstration.
Original PR description
Following light users merge, a few points need to be fixed or modified: - Fix User status Search method - Unstore user role and add search method. - Fix confirmed icon in employee_user_status widget - Remove Apps icon for light users - Switching to light user role is setting the role to user back immediately. - Add Demo Light User More details in commit messages. Task-6476390
Customers editing their portal address in Morocco now receive a clear error when entering an invalid ICE identifier, instead of the save failing silently and logging a backend validation error. This improves the self-service address update experience and reduces confusion or support requests.
Original PR description
Steps: - Install l10n_ma module. - Go to Address page in portal. - Select Morocco country. - Set any random invalid value for ICE input. Issue: - It wont allow to save address and will not give any error or suggestion instead it raises validation error in logger. Cause: - Since recent [fix](https://github.com/odoo/odoo/pull/271969) invalid additional_identifier raises an error for invalid values and in portal we can't display those error directly. Fix: - Validate `additional_identifier` in validate address values and and mark those identifier as invalid field for invalid values to give proper error message and not raise validation error. Also skip `_validate_identifier` for `no_vat_validation` context in creation since we already validate those identifier values. Forward-Port-Of: odoo/odoo#279308
The link preview popover now makes the magic wand edit control easier to click and gives clearer hover feedback. This improves accessibility and usability for users editing links, including in dark mode.
Original PR description
According to accessibility recommendations, the magic wand icon link inside the link preview popover is too small. This commit makes it clickable on an area of 24px x 24px, and adds the missing effect to provide feedback on hover. task-6373506 Forward-Port-Of: odoo/odoo#283050 Forward-Port-Of: odoo/odoo#276929
Spreadsheet pivot side panels now reflect changed row, column, or measure order immediately. This prevents a brief display of outdated information, making pivot configuration feel smoother and more reliable for users.
Original PR description
Current behavior before PR: - The runtime definition was rebuilt only after load() resolved. - When the row/column/measure order changed without an RPC reload, the side panel kept reading the stale runtime definition. - This caused the side panel to briefly show the old order before updating to the new one. Desired behavior after PR is merged: - Rebuild the runtime definition synchronously in onDefinitionChange. - The side panel now reflects the new order immediately after coreDefinition is updated. Task: [6427932](https://www.odoo.com/odoo/project/2328/tasks/6427932) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes an accounting issue where reposting an opening journal entry after resetting it to draft could duplicate related bank statements, statement lines, and payment moves. This helps keep opening balances accurate and prevents extra cleanup work for finance teams.
Original PR description
When the Opening journal entry is reset to draft and then posted again, it duplicates the statement, statement lines, and payment moves linked to the opening balance. This commit ensure no duplicate is created task-6395990
The online shop now avoids showing an extra blank space when a product has no unit of measure label. This creates a cleaner, more polished product availability display for shoppers while preserving unit labels when they are available.
Original PR description
Remove duplicated space when there is no uom_name. Activate the UOM feature in tests to display the uom_name. Following [PR274085](https://github.com/odoo/odoo/pull/274085) where uom_name became conditional. runbot-241108
The record selector now keeps its dropdown indicator from changing the field width when users hover or focus it. Clicking the indicator also opens suggestions as expected, making report filters feel more reliable and easier to use.
Original PR description
Steps to reproduce: - Install Accounting. - Open Reporting > Balance Sheet. - Open the Comparison filter. - Hover the "Percentage of" record selector. - The dropdown width shifts when the caret appears. - Clicking directly on the caret does not open the suggestions. RecordSelector and MultiRecordSelector only displayed their caret on hover/focus, which causes a small layout shift. The caret also acts as a dead click target instead of opening the autocomplete dropdown. Reserve space for the caret in the input, render it without affecting layout width, and make it ignore pointer events so clicking it behaves like clicking the input. task-[6268556](https://www.odoo.com/odoo/project/967/tasks/6268556) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The call debrief panel no longer shows a confusing red error when call timing details are not yet available during ringing or ongoing calls. It also avoids showing temporary speech-to-text processing files as duplicate playable audio, while still keeping real error feedback for loading problems.
Original PR description
Previously, missing start/end datetimes on the parent record displayed a bright-red error banner: "CallDebrief widget needs start and end datetime from the parent record." Since missing dates are expected during ongoing or ringing calls, this message is confusing and unappealing. The widget now silently skips timing initialization, collapsing cleanly until the call is completed. We preserve the error state logic for other actual database or loading failures so that users still receive proper feedback when those occur. Task-6478747 **Enterprise Sibling https://github.com/odoo/enterprise/pull/128185**
This fixes an inventory issue where reducing a delivery quantity could leave the wrong amount reserved when the order and operation lines used different units of measure. Businesses get more accurate stock reservations and transfer quantities, especially when products are handled in packs, dozens, or individual units.
Original PR description
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move…
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move unit and the line unit converted a value to its own unit, hence did nothing. Steps to reproduce: - create a product in Units with available stock - create a delivery for 2 Dozen of it and mark it as todo - in the detailed operations, change the unit of the move line to Units (24) - lower the move quantity from 2 to 1 Dozen The move line ends up with 23 Units instead of 12: the decrease of 1 Dozen is applied as 1 Unit on the line and considered fully processed. The remaining 11 units stay reserved and counted on the transfer. Convert the remaining decrease from the move unit to the line unit when taking it from a line, and the taken quantity back to the move unit when updating the remaining decrease. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278411 Forward-Port-Of: odoo/odoo#276774
This update makes Latin American check management clearer and more reliable by improving labels, list behavior, and the visibility of key check details. It also fixes how the system determines whether a check is still on hand, reducing reporting mistakes and preventing changes that could leave checks recorded in the wrong location.
Original PR description
### Commit 1: [IMP] l10n_latam_check: improve UX/usability of checks - The creation of third party checks was not correctly disabled on some list views. - Align labels of the partner_id to…
### Commit 1: [IMP] l10n_latam_check: improve UX/usability of checks - The creation of third party checks was not correctly disabled on some list views. - Align labels of the partner_id to Customer/Vendor depending on the context. - Display the memo and the initial payment's date on the 3rd party checks views. task-5247520 ### Commit 2: [FIX] l10n_latam_check: base checks location on a real on_hand field **Problem 1: On Hand** Whether a check was still on hand had no field of its own: it was computed based on the current_journal_id of the check, while the "On hand" filter approximated it through the payment methods of the check's current journal. The two could disagree, and neither could be searched or grouped on. Expose it as an on_hand computed field, with a compute_sql counterpart so it stays searchable. A check is On Hand if its last posted operation was registered on a cash journal. **Problem 2: Last operation** The sorting of the operations of a check was mostly relying on the payment_date then the write_date and finally the ID. For payments that are registered on the same day, the computation was often wrong as soon as an older payment was edited afterwards, which sent the check back to the journal it had already left. This commit adds a key to the sorting: we now secondly rely on the Journal Entry ID of the payment, which should always exists for posted payments with a check, and is created at posting of the payments so it somehow acts as timestamp of the posting, it also won't re-order if the payments would be reset to draft and re-posted. Finally, and even with changes above, we decided that resetting or cancelling an operation in the middle of the chain of operations should be prevented. It left the check recorded where it no longer was. Note that it is still possible to reset the whole chain at once, or the last operation(s). task-5247520
This fixes an error that could block French branch companies from activating PDP electronic invoicing when their parent company was also selected. Branches now correctly use the parent company's accounting setup, allowing the activation settings to save successfully.
Original PR description
**Steps to reproduce:** * Create a **French** parent company and a branch. * Activate **Electronic Invoicing (PDP)** for the parent company. * Switch to the branch while keeping both the **parent…
**Steps to reproduce:**
* Create a **French** parent company and a branch.
* Activate **Electronic Invoicing (PDP)** for the parent company.
* Switch to the branch while keeping both the **parent company** and the **branch** selected in the company switcher.
* Go to **Settings → French Localization → Activate Electronic Invoicing**.
* Activate **Electronic Invoicing (PDP)** for the branch.
* Select the **Participate in the pilot phase** checkbox and try to save settings.
**Observed behavior:**
* A traceback occurs with the error: `psycopg2.errors.SyntaxError: syntax error at or near ")"` on `IN ()` in the SQL query inside `_force_update_l10n_fr_f10_moves`.
**Cause:**
* `_force_update_l10n_fr_f10_moves` searches for receivable/payable accounts using `company_ids IN companies.ids`.
* A branch company has no accounts assigned directly to it — accounts belong to the parent company — so the search returns an empty list.
* Passing an empty tuple to `IN %(account_ids)s` generates `IN ()`, which is invalid PostgreSQL syntax.
**Fix:**
* Replace `('company_ids', 'in', companies.ids)` with
`('company_ids', 'parent_of', companies.ids)` in the account search
inside `_force_update_l10n_fr_f10_moves`.
* This ensures that accounts owned by a parent company are correctly
found when the given companies are branches, since branch companies
inherit their parent's chart of accounts.
opw-6394650
Forward-Port-Of: odoo/odoo#282849
Forward-Port-Of: odoo/odoo#277232DIN 5008 business documents now show dates in the expected day.month.year format for Germany, Austria, and Switzerland, regardless of the user's language settings. Footer company register details are also shown more appropriately, avoiding Germany-specific wording where it does not apply.
Original PR description
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document…
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale
**Steps to reproduce:**
* Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`)
* Set the document layout to **DIN 5008** and generate any PDF report (invoice, quotation, purchase order, etc.).
**Observed behavior (date format):**
* All dates in the information block (Invoice Date, Due Date, Delivery Date, Order Date, etc.) are rendered in `yyyy-mm-dd` format instead of the expected `dd.MM.yyyy` format used in DE, AT, and CH.
**Observed behavior (commercial register):**
* The footer always shows `HRB-Nr.:` regardless of whether the company has a commercial register entry.
* The abbreviation `HRB-Nr.:` appears even for Austrian and Swiss companies, where the commercial register number is a German-specific concept.
* In the company form view, the field is labeled generically as "Company ID" instead of "Commercial Register Number" for German companies.
**Cause (date format):**
* All `t-options="{'widget': 'date'}"` directives across the DIN 5008 template family rely on the active user's language locale for date formatting. If the user language is not `de_DE`, dates render in the locale's default format (e.g. `yyyy-mm-dd` for `en_US`).
**Cause (commercial register):**
* The footer renders `company.company_registry` unconditionally with no country guard and no label.
**Fix (date format):**
* Add `'format': 'dd.MM.yyyy'` explicitly to all `t-options` date widgets across all DIN 5008 report templates (`l10n_din5008`, `l10n_din5008_sale`, `l10n_din5008_purchase`, `l10n_din5008_sale_subscription`, `l10n_din5008_repair`, `l10n_din5008_account_followup`, `l10n_din5008_industry_fsm`).
* This is correct for all three countries using DIN 5008 (DE, AT, CH), which all follow the `dd.MM.yyyy` convention.
**Fix (commercial register):**
* Remove the hardcoded `HRB-Nr.:` label from the footer and instead render `company.partner_id.company_registry_label` (which is country-aware).
* Update the duplicate contact warning message to use the country-aware label via `company.partner_id.company_registry_label`, backed by a new `_get_company_registry_labels` override in l10n_de that registers `Commercial Register Number` for `DE`.
* In the company form view (`l10n_de`), hide the generic "Company ID" field for German companies and show a relabeled instance with `string="Commercial Register Number"` instead.
opw-6392649
Forward-Port-Of: odoo/odoo#283315
Forward-Port-Of: odoo/odoo#279085The website editor now shows dynamic snippet filter names in the editor user's preferred language instead of the website's default language. This avoids confusion for editors working on multilingual websites where the public site language differs from their own interface language.
Original PR description
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the frontend request language (see: `frontend_pre_dispatch()`), so the ORM context lang is set to the website language. As a result, translated fields such as name are read in that language. Force `request.env.user.lang` in the context when fetching the filters since their names should be displayed in the editor's preferred language. task-5979540 Forward-Port-Of: odoo/odoo#282804 Forward-Port-Of: odoo/odoo#275390
This fix prevents Odoo IoT printer handling from trying to cancel a print job that CUPS has already cancelled. It reduces unnecessary printer errors and avoids follow-up failures when tracking cancelled jobs.
Original PR description
Before this commit, if the status of a CUPS job was checked when that job was already cancelled, we would treat it as a generic error and then try to cancel the job again. This would result in an error from CUPS ('client-error-not-possible'). There would then be a secondary exception caused by trying to remove the job ID from the list a second time in the exception handler.
After this commit, we avoid trying to cancel the job again. We also use a set instead of a list to keep track of the job IDs, which prevents duplicates and allows us to discard IDs without causing an error if they are already removed.
sentry-IOT-1J
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283227This fix ensures Malta tax grid assignments are updated correctly when databases are upgraded. It prevents taxes from keeping outdated reporting grids, helping future journal entries and tax reports use the correct Maltese localization setup.
Original PR description
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids…
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids remain unchanged after the upgrade and do not reflect the modifications introduced in [1]. The tax definitions are loaded from CSV data and don't happen during upgrade or module update it did through try_loading". Since the account tags already exist in upgraded databases, the changes are not applied during module loading and the updated grid assignments are not assigned to taxes. **Fix:** Apply the grid update directly through SQL during the upgrade or module update. The change is limited to tax grid assignments and does not require a full tax reload using ``try_loading`` or ``load_data``. **Before fix:** <img width="1458" height="724" alt="image" src="https://github.com/user-attachments/assets/eaac5e3f-d551-4ec0-b282-bb39a50438f9" /> **After fix:** <img width="1240" height="583" alt="image" src="https://github.com/user-attachments/assets/74409c53-dce0-45b2-a6b5-e60f5c2d826d" /> Note: why this fix is needed because existing upgrade script do update move line grid but still tax have the old grid which is weird and will cause issue when journal entry will create. [1]: https://github.com/odoo/odoo/pull/254894/changes/8921186850e31c53072d49a5dc760192f3edb902 opw-6325845 upg-4391393 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272038
Self-order now more reliably checks that combo items belong to the correct parent combo line. This prevents incorrect combo selections from being accepted, helping orders stay accurate for customers and staff.
Original PR description
Be sure that combo product of the current line belong to its combo parent line. Forward-Port-Of: odoo/odoo#283284 Forward-Port-Of: odoo/odoo#281741
A leftover “Request Appraisals” action that caused an error has been removed. Employees can still request appraisals in bulk using the existing “Launch Campaign” option, avoiding confusion and failed workflows.
Original PR description
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it…
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it raises AttributeError: 'hr.employee' object has no attribute '_create_multi_appraisals'. #### Current behavior before PR: Commit 8845eb2ac29 replaced the multi-appraisal flow with hr.appraisal.campaign.wizard: it deleted _create_multi_appraisals and repointed the employee list header button to action_open_appraisal_campaign_wizard, but left the action_create_multi_appraisals record in hr_appraisal/views/hr_employee_views.xml. Its code is now the only reference to the deleted method, so the action crashes whenever it is run. #### Desired behavior after PR is merged: The dangling action is gone. Requesting appraisals for several employees at once is done with the "Launch Campaign" button already present in the Employees list view; action_open_appraisal_campaign_wizard reads active_ids when active_model is hr.employee and pre-fills the selected employees. Nothing references the removed xml id, and the record is not noupdate, so _process_end removes it from existing databases on update; no migration script is required. Verified on a 19.0 database: with the orphan record loaded, updating hr_appraisal with this change deletes it. opw-6408609 Forward-Port-Of: odoo/enterprise#127983 Forward-Port-Of: odoo/enterprise#125630
This fix prevents errors when Odoo displays names for multiple salary attachments at the same time. Payroll users can view salary attachment records more reliably without unexpected crashes.
Original PR description
Currently, an error occurs when the display name is computed for multiple salary attachments. `ValueError: Expected singleton: hr.employee(58, 56)` After [recent commit], when computing the display name, the employee's display name is accessed through multiple attachment records at once. This results in accessing the display name of multiple employees simultaneously, which raises a singleton error. This commit ensures that the employee is accessed from each individual attachment record when computing the display name. [recent commit]: https://github.com/odoo/enterprise/commit/d9648ef695903113d6ed2f40cd4fcfdd68221fa8 [1]- https://github.com/odoo/enterprise/blob/d913de3097d06e723a08d24907024f83769b1fb8/hr_payroll/models/hr_salary_attachment.py#L150-L153 sentry-7665634830 Forward-Port-Of: odoo/enterprise#127765
Fixed an issue where switching the AI agent to a pivot view could cause the view to crash or open without selected measures. The pivot view now waits until it is ready before AI adjustments are applied, preserving default measures when none are requested.
Original PR description
When the AI agent switched from another view to a pivot view, the pivot view could crash or open without any active measures. The AI controller patch applies the agent's adjustments upon receiving…
When the AI agent switched from another view to a pivot view, the pivot view could crash or open without any active measures. The AI controller patch applies the agent's adjustments upon receiving the `APPLY_AI_ADJUST_MODEL` bus event. However, the event could be processed while the pivot model was still executing `_loadData()`. In that case, the following sequence occurred: * `_loadData()` started and awaited. * The controller patch was executed. * The patch called `toggleMeasures()`. * `toggleMeasures()` waited for `_loadData()` to complete. * `_loadData()` finished and updated the metadata with the available measures. * `toggleMeasures()` resumed and wrote back the metadata snapshot it had taken before waiting. Since `toggleMeasures()` operates on a snapshot of the metadata, the measures populated by `_loadData()` were lost when the snapshot replaced the current metadata, leaving the pivot model without its `measures` metadata and causing the view to crash. Prevent this race condition by waiting for the pivot model initialization to complete before applying the AI adjustments. Also preserve the default active measures when the AI agent does not explicitly request any measures instead of clearing them and opening an empty pivot view. task-6384368 Forward-Port-Of: odoo/enterprise#125897
Employees opening a contract offer will now see Yes/No benefit options, such as medical insurance, correctly pre-selected when the benefit is already included. This prevents confusion during offer review and helps ensure the salary package shown matches the actual contract offer.
Original PR description
Issue: When an employee opens the salary configurator for a contract offer, optional benefits configured with Yes/No radio choices (such as Medical Insurance) fail to pre-select 'Yes' even when the benefit is already included in the offer. Steps to Reproduce: 1. Go to Salary Configurator and open a contract offer that has an active benefit 2. Observe that 'Yes' is not selected for the benefit on initial load. Fix: Ensure that when a contract offer includes a benefit, the salary configurator automatically defaults the radio selection to `Yes`. task-6392064 Forward-Port-Of: odoo/enterprise#127544
The India salary simulation now avoids running an unnecessary tax calculation when the popup opens. This prevents newly entered values from being cleared and stops misleading missing-field errors for users testing regular pay structures.
Original PR description
Steps :- - On opening the Simulation when India: Regular pay structure is selected, throws "Missing required fields" when fields are changes on form view. Fix:- - For Indian company, the TDS calculation ran in the background while opening the popup, and it was clearing the values just entered. This calculation isn't needed for a simulation, so it is now skipped. task-6392171 Forward-Port-Of: odoo/enterprise#126483
Goal templates in Appraisals will now be created without automatically assigning an employee. This ensures templates appear correctly in the goal template library and can be reused as intended.
Original PR description
Steps to reproduce: - Go to Appraisals > Configuration > Goals > Library and create a goal template. - Or open an employee goal and click "Save as Template". - The created goal template is not visible in the goal template list view. Reason: An employee was set by default on new goal templates upon creation. Solution: Do not assign a default employee when creating a goal template. Task-6443339 Forward-Port-Of: odoo/enterprise#126816
Sendcloud return labels now avoid printing the customer's house number twice in the origin address. This keeps return shipping labels clearer and reduces confusion for customers and warehouse teams processing returns.
Original PR description
Issue ----- On return labels, the house number of the origin address (so the customer) is printed twice. Steps to reproduce ----- - Setup sendcloud - Select a return service - Enable "Generate Return Label" - Create a delivery using sendcloud - Validate the delviery > The return label has the house number printed twice Cause ----- For the origin address shown on labels, Sendcloud prints both the address line and the house number. There doesn't seem to be any parsing made on the address line to extract the house number. For the WH -> Customer label, the "from" address is taken directly from the Sendcloud account's configuration. For the Customer -> WH return, we provide it in the `from_` fields of the request. Note that, when including the house number on the address line in Sendcloud, the issue is also present. ----- Ticket: opw-6405054 Forward-Port-Of: odoo/enterprise#127855 Forward-Port-Of: odoo/enterprise#126250
Approval rules in Studio now handle empty rule conditions consistently, avoiding ambiguity about which records should be affected. This helps ensure approvals apply as intended and reduces the risk of incorrect approval requirements.
Original PR description
Before this commit, there was an ambiguity with the usage of filtered_domain ie ``` self.assertTrue(record.filtered_domain(False)) self.assertFalse(record.filtered_domain(Domain(False))) ``` This is because in that case the API of filtered_domain was not respected After this commit, there is no ambiguity as we cast to a Domain the value we obtain from the rule: - False or None: all records should be impacted by the rule => Domain(True) - otherwise, let the domain do its job opw-6431607 Forward-Port-Of: odoo/enterprise#128160 Forward-Port-Of: odoo/enterprise#127676
Kenyan POS receipts now generate the tax authority QR code whenever the required signature is available, instead of depending on an order status that could prevent the URL from appearing. This helps ensure customers receive receipts with the expected SCU information after validated POS orders.
Original PR description
The original issue coudn't be reproduced. But based on what was reported on the ticket, this should improve the behavior of the order receipt. Steps to reproduce: ------------------- * Setup the…
The original issue coudn't be reproduced. But based on what was reported on the ticket, this should improve the behavior of the order receipt. Steps to reproduce: ------------------- * Setup the l10n_ke module in 'production' mode * Make an order in POS and validate it > Observation: The receipt doesn't contain the SCU information and QR Why the fix: ------------ Based on the receipt screenshot shared on the ticket (from Odoo 19.3) we can see that some informations are shown on the ticket. The information shown are the one received from the etims api, it means the call went through and the response was received. As the qrCode URL only needs `l10n_ke_oscu_signature` to be generated, we can assume that if this field is set we can safely generate the URL and generate the QR code. https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_pos/models/pos_order.py#L252-L256 Based on this assumption we can change the condition to return the URL or not based on the presence of `l10n_ke_oscu_signature` instead of the state of the order being `sent`. In 19.0, the receipt is showing no info at all (when 19.3 is showing some info like the signature). This is also happening because the URL was falsy. And when that is the case we do not show any SCU information https://github.com/odoo/enterprise/blob/ee7e6894ed313db844aeff5ba5e19de3ad94898e/l10n_ke_edi_oscu_pos/static/src/overrides/components/order_receipt/order_receipt.xml#L56 opw-6352120 Forward-Port-Of: odoo/enterprise#127045
The vehicle salary tab now shows the Benefit In Kind amount with the correct yearly label instead of a monthly one. The label placement was also adjusted so it appears neatly beside the value, improving clarity without changing any payroll calculations or data.
Original PR description
The Benefit In Kind (BIK) amount on the vehicle model salary tab was labelled "/ month" while the underlying value is yearly, mismatching the other fields (CO2 fee, Cost, Total Cost) correctly suffixed. The unit label div was also missing the o_hr_narrow_field class used everywhere else in the module, so the unit label stretched to the far right of the row instead of sitting next to the value. Purely visual fix, no behavior or data change. task-6428222 Forward-Port-Of: odoo/enterprise#127652
This fixes Belgian payroll sick leave handling so a second long sickness period is split correctly after the first 30 days when it is not marked as a relapse. It helps ensure leave classification and payroll calculations follow the expected rules for independent sickness periods.
Original PR description
Steps to reproduce: - Create a STO for an employee of more than 30 days -> this period is split in 30 days STO and x days SGS. - Within the relapse period, create a second STO of more than 30 days and leave the relapse field empty (which is fine if the second STO is not related to the first sickness) -> the period should be split after the first 30 days just like the first STO, but it remains an STO for the whole duration. task-6296152 Forward-Port-Of: odoo/enterprise#128101
This fixes an internal automated test that could fail when Field Service Planning was checked together with another planning-related module. The change keeps the test focused on the intended screen behavior and helps maintain more reliable release validation without changing user-facing functionality.
Original PR description
On runbot, the `test_onchange_break_time_after_removing_dates` test was failing during the "all" build due to the `planning_slot_check_datetimes_set_or_plannable_slot` SQL constraint introduced by the sale_planning module. The test previously used `odoo.tests.Form` as a context manager, which implicitly triggered a database save and flushed the dateless test shift to PostgreSQL. Can resolved this by instantiating the Form in memory to validate the frontend `@api.depends` logic without triggering the cross-module database constraint. runbot-6463625 Forward-Port-Of: odoo/enterprise#127859
Belgian payroll now values assimilated absence periods using the employee's salary at the time of each absence, rather than applying one later salary to all periods. This ensures departure holiday attestations and December double holiday regularizations are calculated more accurately when salaries change during the year.
Original PR description
### Problem - The fictitious remuneration used for departure holiday attest and December double holiday regularization was computed using the salary applicable at the end of the previous year for all…
### Problem - The fictitious remuneration used for departure holiday attest and December double holiday regularization was computed using the salary applicable at the end of the previous year for all assimilated absence periods. **For an employee with:** - 20 days of assimilated absence in February with a salary of 2,000. - A salary increase to 3,000 in June. - Another 20 days of assimilated absence in November. ``` The previous computation was: (40 × 3,000) × (3 / 13 / 5) ``` - where all assimilated absence days were valued using the wage applicable on the last day of the previous year. - Instead, the remuneration should be computed using the wage applicable ``` during each assimilated absence period: ((20 × 2,000) + (20 × 3,000)) × (3 / 13 / 5) ``` - Compute the fictitious remuneration using the contract wage applicable to each payslip period so that each assimilated absence is valued with the correct monthly salary before applying the holiday formula. task-5932817 Forward-Port-Of: odoo/enterprise#122848
The Timesheet Assistant now includes time from very small events by adding it to matching larger events instead of ignoring it. This helps suggested timesheets reflect a more accurate total time for users.
Original PR description
## Previous Behavior Before this PR: When events were to small to suggestion Timesheet Assistant would completely discard these events. This lead to a suggestion haveing a lower total time than it should. ## New Expected Behavior After this PR: When an event is too small to suggest and shares its name and group with one or more larger event, the duration of the smaller event is added to the last event with the same name and groupe. task-[6452987](https://www.odoo.com/odoo/project/4105/tasks/6452987) Forward-Port-Of: odoo/enterprise#127915 Forward-Port-Of: odoo/enterprise#127167
The Timesheet Assistant no longer interrupts ongoing always-active activities, such as meetings, with away-from-keyboard entries. This gives users cleaner suggestions, more accurate away-time durations, and corrected Google Meet descriptions.
Original PR description
## Previous Behavior Before this PR: Users could have their always-active event split by an AFK event inside of Timesheet Assistant. AFK event durations were also inaccurate, and the Google Meet…
## Previous Behavior Before this PR: Users could have their always-active event split by an AFK event inside of Timesheet Assistant. AFK event durations were also inaccurate, and the Google Meet description was incorrect. ## Steps to Reproduce: 1. Generate an always-active event (e.g., join a meeting in Google Meet). 2. Generate non-key events (e.g., visit a website without an ActivityWatch rule). 3. Go AFK. 4. Generate a new non-key event. 5. The Timesheet Assistant will show three suggestions in the following order: an always-active suggestion, an AFK suggestion, and another always-active suggestion for the same activity. ## New Expected Behavior After this PR: The Timesheet Assistant now blocks the creation of AFK suggestions when the previous key event is marked as always-active. AFK event durations have been updated to ensure their values are accurate. The Google Meet description has also been corrected. task-[6431526](https://www.odoo.com/odoo/project/4105/tasks/6431526) Forward-Port-Of: odoo/enterprise#127299 Forward-Port-Of: odoo/enterprise#127028
This fix ensures salary package benefit fields can be selected correctly, including country-specific benefit fields that were previously excluded. It also prevents an error when saving public benefit field selections, improving reliability for HR salary configuration.
Original PR description
1- The benefit fields related to the hr.version have a domain that limits them to the whitelisted fields used to copy values from a template, which does not always include benefit fields. The…
1- The benefit fields related to the hr.version have a domain that limits them to the whitelisted fields used to copy values from a template, which does not always include benefit fields. The advantage of the whitelist is that it factored in for the allowed countries, so instead of duplicating this logic to benefit fields and implementing it in every l10n, we can check which module the field comes from.
example:
The field [`company_car_total_depreciated_cost`](https://github.com/odoo/enterprise/blob/ce691cd6aaacfb86cd866698d2fcc3fe930912cb/l10n_be_hr_payroll_fleet/models/hr_version.py#L62) cannot be selected as `res_field_id` when it should be possible as we see in the [data](https://github.com/odoo/enterprise/blob/ce691cd6aaacfb86cd866698d2fcc3fe930912cb/l10n_be_hr_contract_salary/data/hr_contract_salary_benefit_data.xml#L6), it is not whitelisted because we dont want to copy its value from a template.
2- Another fix is the inverse of the public field, there's a traceback because the selection field is always converted to a string and cannot be used to browse as is.
```py
File "/data/build/enterprise/hr_contract_salary/models/hr_contract_salary_benefit.py", line 238, in _inverse_res_field_public
record.res_field_id = self.sudo().env['ir.model.fields'].browse(record.res_field_public)
^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/fields.py", line 1890, in __set__
write_value = self.convert_to_write(value, records)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/orm/fields_relational.py", line 387, in convert_to_write
return value.id
^^^^^^^^
File "/data/build/odoo/odoo/orm/fields_misc.py", line 115, in __get__
raise ValueError("Expected singleton: %s" % record) from None
ValueError: Expected singleton: ir.model.fields('1', '7', '3', '8', '4')
```
Forward-Port-Of: odoo/enterprise#128275
Forward-Port-Of: odoo/enterprise#127743When Planning billing is enabled with Field Service, the system now automatically selects the expected default project. This prevents setup confusion and helps ensure billable planning work is linked to the right project from the start.
Original PR description
Steps to reproduce: - 1. Create a new database and install Planning and Field Service. 2. Open the Planning settings and enable Billing. Issue: - Billing is enabled but no default project is selected. Cause: - The default of `res.company.planning_project_id` references the module's own `fsm_project` xmlid, but it is evaluated before the module's data files are loaded. The ref resolves to nothing and no value is written. Fix: - Set the project in the post-init hook, once the data files are loaded. task-6460106 Forward-Port-Of: odoo/enterprise#127656
ISO 20022 payment files now include the vendor's state or province and second address line when available. This helps prevent North American bank transfer rejections caused by incomplete beneficiary address details.
Original PR description
The PstlAdr block written into pain.001 files never contains the partner's state/province nor the second street line, even when they are set on the record: _get_all_addr() now returns them, but…
The PstlAdr block written into pain.001 files never contains the partner's state/province nor the second street line, even when they are set on the record: _get_all_addr() now returns them, but _get_PstlAdr() also needs to write them out. Some North American banks reject wire transfers whose beneficiary address lacks the state/province, so those payments fail regardless of how complete the vendor record is. Emit CtrySubDvsn when the address has a state, before Ctry as required by the element order of the PostalAddress schema, and append street2 to the street address line. Steps to reproduce: - Install Accounting and enable a generic ISO 20022 payment method on a bank journal - Create a vendor located in the US or Canada with a complete address, including the state and a second street line - Register a vendor payment, add it to a batch and generate the pain.001 file - The creditor PstlAdr has no state/province, and its street line only carries the first street field: the street2 part is dropped Requires odoo/odoo#282518, which makes _get_all_addr() return the state and street2. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#128021 Forward-Port-Of: odoo/enterprise#127958
Payroll validation now correctly opens any required follow-up screen, such as a wizard for missing employee information, instead of silently doing nothing. This helps payroll users understand and resolve validation blockers immediately.
Original PR description
action_validate() called action_payslip_done() without returning its result. When action_payslip_done() returns a client action (e.g. a wizard to fix missing employee data instead of raising), that action was lost and the Validate button appeared to do nothing, with no error or warning shown. task-6373549 Forward-Port-Of: odoo/enterprise#127668
Swiss payroll now uses the employee’s requested time off dates when calculating absence days for flexible schedules. This prevents a one-day leave from being counted as two days due to timezone conversion, helping keep regular wage and accident salary calculations accurate.
Original PR description
Issue: Swiss payslips count one extra absence day for employees without a working schedule. A one day accident leave can therefore be prorated as two days, reducing the regular wage and overstating…
Issue: Swiss payslips count one extra absence day for employees without a working schedule. A one day accident leave can therefore be prorated as two days, reducing the regular wage and overstating the accident salary. Steps to reproduce: * Install Swiss Payroll. * Configure a monthly employee without a working schedule. * Assign one day of accident time off. * Generate the payslip for that month. Cause: The Swiss wage computation derives absence boundaries from the date portion of the leave's UTC datetimes: https://github.com/odoo/enterprise/blob/16c29e1bab34b5bcb2b001477d928ec5eb294a97/l10n_ch_hr_payroll/models/hr_payslip.py#L313-L330 A fully flexible employee's full day leave starts at local midnight. In timezones ahead of UTC, that start is stored on the previous UTC date, so the inclusive calendar day computation adds an extra day. Solution: We need to use the requested time off dates for both payslip range filtering and absence proration. These fields preserve the calendar days selected by the user independently of timezone conversion, while leaving the UTC datetimes and half-day handling unchanged. opw-6435086 Forward-Port-Of: odoo/enterprise#127849 Forward-Port-Of: odoo/enterprise#127513
The Timesheet Assistant now recognizes time spent in spreadsheets and suggests it as "Working in Spreadsheet" instead of grouping it under Documents. This helps users review and submit timesheets with clearer, more accurate activity suggestions.
Original PR description
## Behavior Before the Commit When a user spent time working in a spreadsheet, the Timesheet Assistant grouped this time under "Working in Documents". This occurred because "Spreadsheet" is a module rather than an application, and the Assistant only creates suggestions for applications. As a result, it attempted to fall back to an application and frequently defaulted to the "Documents" application. ## New Expected Behavior After this Commit: When a user spends time in a spreadsheet, the Timesheet Assistant now generates a "Working in Spreadsheet" suggestion. This is enabled by a dedicated list of non‑application modules that allows specific modules to be recognized even when they are not applications. task-[6438536](https://www.odoo.com/odoo/project/4105/tasks/6438536) Forward-Port-Of: odoo/enterprise#128038 Forward-Port-Of: odoo/enterprise#126390
Database neutralization for TikTok Shop data now keeps each shop record uniquely identifiable while removing real shop references. This prevents cleanup failures when multiple active TikTok shops exist, making test or sanitized database preparation more reliable.
Original PR description
Steps to produce: --- - Install sale_tiktok module. - Create two active tiktok.shop records. - Run the database neutralization command. Issue: --- - Neutralization fails with a PostgreSQL error:…
Steps to produce: --- - Install sale_tiktok module. - Create two active tiktok.shop records. - Run the database neutralization command. Issue: --- - Neutralization fails with a PostgreSQL error: ```py duplicate key value violates unique constraint tiktok_shop_unique_active_shop` DETAIL: Key (tiktok_shop_ref)=(1) already exists. ``` Root cause: --- - At [1], we are setting `tiktok_shop_ref = 1` for all `tiktok_shop` records. Because `tiktok_shop` enforces a partial unique constraint on `tiktok_shop_ref` for active shops [2], setting the same reference value `1` on multiple active shops violates this constraint. Solution: --- - Update sql to assign a row-unique string to each shop. This strips the real shop reference while maintaining uniqueness across active shop records so neutralization completes cleanly. [1]https://github.com/odoo/enterprise/blob/85754b0354b76da8b4d87a3a81dd19679ed35d15/sale_tiktok/data/neutralize.sql#L1-L8 [2]https://github.com/odoo/enterprise/blob/85754b0354b76da8b4d87a3a81dd19679ed35d15/sale_tiktok/models/tiktok_shop.py#L136-L139 opw-6451715 --- Forward-Port-Of: odoo/enterprise#127532
This fix prevents errors when sales planning data is grouped by customer in setups where the customer field is not stored directly. Businesses get more reliable planning reports, especially when viewing sales order related planning information without the Field Service configuration that stores this field.
Original PR description
Before this commit, #122034 converted the related non-stored `partner_id` field in `planning.slot` into a compute non-stored field with a search method, the problem is that field was used as groupby inside a read_group which causes a traceback since the field is no longer reachable in SQL. This commit alters the groupby in problematic _read_group methods to use partner_id field when it is stored (when field service is installed) otherwise the groupby should be `sale_order_id.partner_id`. Forward-Port-Of: odoo/enterprise#128540
Indian payroll contract validation now shows the wage period that matches the employee contract instead of always referring to a monthly wage. This reduces confusion when allowance totals exceed the wage for contracts using a different pay schedule.
Original PR description
**Steps to reproduce:** - Create an indian employee. - Put total allowance `(basic salary + HRA + standard ALW + Perf bonus + travel ALW) > wage` - We will get validation error in employee stating that allowance sum can't be greater than wage. **Before:** - We were always showing monthly wage in the validation error, which was confusing to the end user. **After:** - We will use field `version.shedule_pay` to show dynamic validation error message. Task: [6449791](https://www.odoo.com/odoo/project/1251/tasks/6449791) Forward-Port-Of: odoo/enterprise#127477
The product catalog opened from Field Service tasks now gives more space to the unit of measure column. This makes item details easier to read and keeps the Enterprise interface aligned with the related Community update.
Original PR description
Steps to produce: --- - Install `Field service` module. - Create a task and open it. - From the task open the catalog from smart button. Update the Product Catalog UI to match the Community PR changes. community PR: https://github.com/odoo/odoo/pull/267118 opw-6253382 --- Forward-Port-Of: odoo/enterprise#128146 Forward-Port-Of: odoo/enterprise#121139
Fixed an issue where the online cart could crash after a rental product was changed back into a regular sales order by removing its rental period. The cart now only shows rental period details when the order is actually still a rental, improving checkout reliability for affected customers.
Original PR description
Currently, an error occurs when a user adds a rental product to the cart, opens the corresponding sales order, removes the rental period, and then opens the cart again. Steps to replicate: - Install…
Currently, an error occurs when a user adds a rental product to the cart, opens the corresponding sales order, removes the rental period, and then opens the cart again. Steps to replicate: - Install `website_sale_renting` with demo. - Open website > shop > add the product named `Projector`. - Click Ecommerce in the menu bar > Orders . - Remove the `Confirmed` filter > Click on the top order (should be containing the projector product.) - Remove the `Rental Period` and go to the cart. Error: ``` QWebError: Error while rendering the template: AttributeError: 'bool' object has no attribute 'time' Template: website_sale.shorter_cart_summary ``` Cause: - When the user removes the rental period (`rental_start_date` and `rental_end_date`), both fields are set to `False`. When the cart is opened again, these values trigger the error in [line]. - Since the rental period has been removed from the order, the order is converted to a regular Sales Order (see [PR] and its [task]). Therefore, the Rental Period should no longer be displayed. Solution: - Use `is_rental_order` to determine whether to render the rental period instead of `has_rentable_lines`, since `has_rentable_lines `only checks whether the product is rentable [1], which is determined by the product's `rental_periodicity` [2]. - `is_rental_order` is a better check here because it indicates whether the rental period is actually defined on the order [3]. [line]: https://github.com/odoo/enterprise/blob/7c80c9ffa9e7812267f2ac285e3a3fc5ca501814/website_sale_renting/views/templates.xml#L207 [task]: https://www.odoo.com/odoo/all-tasks/6003684 [PR]: https://github.com/odoo/enterprise/pull/106381/commits/56ec41d81f7536f047a1586a12ea6f6e8414b844 [1]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order.py#L140-L143 [2]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order_line.py#L61-L64 [3]: https://github.com/odoo/enterprise/blob/f23ef9c604d8ce6be152d5e5bf6f72bd68b31451/sale_renting/models/sale_order.py#L135-L138 sentry-7663524549 Forward-Port-Of: odoo/enterprise#128084
The Uzbek balance sheet now includes unclosed profit or loss from the current year in the Equity section. This prevents the report from appearing unbalanced before year-end closing while preserving the official report line numbering.
Original PR description
The Uzbek balance sheet was unbalanced because the current year's unclosed profit/loss was not reflected in the Equity section. This commit restructures '[0540] - Retained Earnings' into an aggregate of three lines: realized retained earnings (existing tag-based formula), current year unallocated earnings, and previous years' unallocated earnings, the latter two computed from income, expense and equity_unaffected accounts, scoped to the current and prior fiscal years respectively. This keeps the balance sheet correct both before and after year-end closing, without changing the report's official line numbering. see https://github.com/odoo/odoo/pull/282779 see https://github.com/odoo/upgrade/pull/11048 task-6361059
A test for tax return navigation was updated to work with the latest page layout. This helps keep automated checks reliable so issues in tax return access are caught before release.
Original PR description
Description of the issue this commit addresses: Commit 18a9f995ec52d655803aa436e6367bd8bbb353be added layout wrappers around return cards. The tour still expected kanban records to be direct children so it could not find the DUMMY_TAX return. --- Desired behavior after this commit is merged: This commit changes the selector so the tour can open the tax return with the new layout. --- runbot-[945519](https://runbot.odoo.com/odoo/error/945519)
Mexican payroll processing now handles companies that do not have a tax ID set without crashing. This keeps payslip checks running reliably and avoids blocking payroll work because of an optional company field.
Original PR description
`res.company.vat` is not required and can be `False`. Guard the `len()` call so `_issue_mx_warnings` doesn't crash on payslips for companies without a VAT set.
```py
File "/home/odoo/src/enterprise/saas-19.3/hr_payroll/models/hr_payslip.py", line 1936, in _compute_issues
issues = generate_issue(slip, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py", line 235, in _issue_mx_warnings
if not slip.company_id.l10n_mx_curp and slip._l10n_mx_is_curp_needed():
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py", line 325, in _l10n_mx_is_curp_needed
or len(self.company_id.vat) == 13
^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: object of type 'bool' has no len()
```
Forward-Port-Of: odoo/enterprise#128216This fix adds a required customer scheme identifier to SEPA direct debit payment files. It helps ensure files are accepted by banks that require this field, such as Nordea in Sweden, reducing payment processing failures.
Original PR description
We are missing a SchmeNm node in the InitgPty node. This is mandatory for Nordea in Sweden at least. Such as: ```xml <SchmeNm> <Cd>CUST</Cd> </SchmeNm> ``` task-6385960 Forward-Port-Of: odoo/enterprise#124693
This fixes an internal automated test for account reports by using the correct mock PDF generation step. It helps keep report validation reliable without requiring the real PDF engine during testing, reducing false failures in the release process.
Original PR description
Description of the issue this commit addresses: Commit d3b4294a56a5ead3f5ea60714eccdba586f72ef0 changed `_run_wkhtmltopdf` into a subprocess wrapper. A later FW, 64f46c270e062df94d4ce37e3065b3e0a0ba68db, did not account for that change and continued mocking the method with PDF bytes. When the wkhtmltopdf path is reached, reading from those bytes crashes. --- Desired behavior after this commit is merged: This commit mocks `_run_pdf_engine_without_processing`, whose contract is to return PDF bytes, so the tour can validate without invoking a real PDF engine. --- runbot-[944189](https://runbot.odoo.com/odoo/error/944189) Forward-Port-Of: odoo/enterprise#126634
A typo was corrected in the tax unit filter within accounting reports. This improves the clarity and professionalism of the reporting interface without changing functionality.
Original PR description
https://github.com/odoo/enterprise/pull/112607/changes/a96b12df4c9de580041d9f9421441de0b7bc7b2e The typo is coming from this commit. Task-no task
Several guided onboarding flows were corrected so automated walkthroughs work reliably in robot mode. This helps keep appointment scheduling, expense scanning, payroll, and subscription setup guidance stable and reduces the risk of broken first-use experiences.
Original PR description
… fix onboarding tours for robot mode Fix the JS tours of appointment_tour, hr_expense_extract_tour, payroll_tours and sale_subscription_tour, uncovered by adding them to web_tour's onboarding tours test (community-side commit): - appointment_tour: clipboard-close dialog, gantt cell/button selectors, missing attendee/name selection, sample-data-mode interactions. - hr_expense_extract_tour: wrong CSS classes, an obsolete manual receipt-selection step, and menu navigation. - sale_subscription_tour: missing product/customer/plan selections, wrong field name, and a dirty-form-on-save race after selecting the recurring plan.
This update fixes several usability issues in the Sign and Documents Sign flows, especially on mobile and small screens. Users can now more reliably upload, select, send, and cancel signing requests without empty menus or misaligned controls getting in the way.
Original PR description
- show the sample document button on mobile - do not open an empty signer list when there is only one signer - hide the settings menu when it is empty - allow a signer to cancel the request while signing - align the signer rows in the send request wizard - select the document instead of opening it when importing from Documents - fix the Upload button on the empty page task-6395329
This change makes Belgian payroll configuration tests use a fixed date so results stay consistent over time. It helps prevent false test failures and supports more reliable payroll maintenance without changing user-facing behavior.
Original PR description
Runbot: 945950
The Philippine payroll module now calculates employer cost using cash earnings, employer contributions, and 13th month pay. This gives businesses a more complete and accurate view of employment costs for payroll accounting and reporting.
Original PR description
Calculate employer cost as the sum of all rules under the Cash Earnings, Employer's Contributions categories and 13th month pay. task-6371975
Employer cost totals on Hong Kong payroll payslips have been corrected so they better reflect the employer-paid amounts used in payroll reporting. This helps businesses review payroll costs more accurately, including special payments, reimbursements, expenses, and non-employee salary handling.
Original PR description
The employer cost shown on payslips was incorrect. Employer cost is now the sum of the Gross-Cash, SLSP, ERMPF, FEE, and COMP categories, reflecting cash wages, severance and long service payments, the employer's own MPF contributions, non-employee fees, and other employer-paid benefits. task-5964455
The timesheet timer now only shows entries linked to the user's active companies. This prevents users from running into access errors when editing timesheets that belong to another company context.
Original PR description
### before: get all timesheets in the timesheet systray, this cause access error when trying to edit a timesheet not inside the active company ### after: only the timesheets linked to active companies should be displayed in the timer --- task-6216931
This fix updates internal test setup for VoIP sales and subscription features so required records are created with the right permissions. It helps keep automated checks reliable after a recent change to test user access, reducing false failures in validation pipelines.
Original PR description
With commit https://github.com/odoo/enterprise/commit/a452ee4de2927327b56ae6922f395482e3dbd50f, now test methods run as a dedicated `_test_user` whose groups are limited to the ones defined by `_test_user_groups`. As a result, tests may lack the required groups when setting up their own data. To solve, we create data with sudo(). failing runbot: runbot-945764 runbot-945763
Fixed an issue in Belgian payroll where dismissing the company car update confirmation could leave the backend unresponsive. Users can now safely cancel the prompt without needing to refresh the page, preventing disruption during payroll and DMFA workflows.
Original PR description
Discarding the "Update Company Car" confirmation froze the whole backend: no button reacted anymore and only a page refresh recovered it. Steps to reproduce: - Validate a payslip for a Belgian…
Discarding the "Update Company Car" confirmation froze the whole backend: no button reacted anymore and only a page refresh recovered it. Steps to reproduce: - Validate a payslip for a Belgian employee - Create a DMFA covering that quarter and mark it as done - Change the company car of that employee and save - Click Discard (or the cross) on the confirmation dialog onWillSaveRecord is called from within Record._save, which itself runs inside the model mutex. Awaiting record.discard() from there queued the discard behind the very save that was waiting for it, so neither promise ever settled. Since the save was dispatched through executeButtonCallback, every button of the view and of the overlay container stayed disabled, and the mutex stayed blocked for the rest of the page life, making any later save or discard hang as well. Fire the discard without awaiting it, the way account's currency form controller already does: the hook returns false, the save releases the mutex, and the queued discard then reverts the record. task-6463069
The Project Gantt view no longer shows misleading progress bars on individual task rows when tasks are grouped by assignee in sparse mode. Instead, task rows show allocated hours, making workload information clearer and avoiding incorrect visual cues.
Original PR description
## Current behavior: In the task gantt view grouped by assignees and displayed in sparse mode, task leaf rows reuse the row progress bar and display a misleading visual indicator on each task. ## Expected behavior: It would make more sense to not display anything for the progress bar of each task, rather display the allocated_hours per task ## Steps to reproduce: 1. Open Project tasks in Gantt view 2. Group by Assignees 3. Enable sparse display so each task appears on its own row 4. Notice that task rows show a progress bar that is not meaningful for the task itself ## Cause of the issue: Each task rows currently hasno meaningful progress-bar semantics, bu they still inherit the generic row progress-bar rendering ## Fix: Override the task gantt renderer to hide progress bars, and only show `allocated_hours` for each task opw-6352260 Forward-Port-Of: odoo/enterprise#124618
A minor issue in the Sign app was fixed to prevent the system from trying to use a missing logging component. This helps avoid unnecessary errors during document signing operations and supports smoother reliability.
Original PR description
See https://github.com/odoo/enterprise/pull/121960 Forward-Port-Of: odoo/enterprise#128748
This update fixes issues in Point of Sale screens caused by a framework upgrade. Users can now type in the ticket search box without their input being reset, and order status changes are handled more reliably.
Original PR description
OWL3's useEffect takes one argument, so the OWL2 deps callback is dropped: typing in the ticket-screen search box was overwritten by the default term. From odoo/enterprise#111749 (pos_urban_piper) and #122791 (pos_enterprise). useOnChange for searchInput, which is user-writable and cannot be derived. pos_enterprise needed no effect: isStageChanging = computed(...) replaces it.
Updating spreadsheet pivots now keeps the details side panel stable instead of briefly showing an invalid model message. This improves the user experience by preventing confusing flickers while pivot data refreshes.
Original PR description
Current behavior before PR: - Updating a pivot caused the side panel to flicker. - The panel briefly showed an 'invalid model' error. - Owl 3 rendered the panel while the pivot data was still reloading, exposing its transient loading state. Desired behavior after PR is merged: - Fetch the model validity and label once in the onWillStart hook. - Updates now render correctly without flickering. Task: [6427932](https://www.odoo.com/odoo/project/2328/tasks/6427932)
This fix corrects how negative manufacturing movements are handled in enterprise reporting. It helps keep manufacturing cost reports accurate when products or costs move out negatively, reducing the risk of misleading financial analysis.
This fixes extra spacing in rental product availability messages when the unit of measure is not shown. The change keeps the online shop display tidy and updates tests to cover the intended unit display behavior.
Original PR description
Remove duplicated space when there is no uom_name. Activate the UOM feature in tests to display the uom_name. Following [PR274085](https://github.com/odoo/odoo/pull/274085) where uom_name became conditional. runbot-241108
This fixes several issues in call debriefing and VoIP transcription, including a crash when requesting a transcription, duplicate audio playback during pending transcription, and failed transcription requests caused by inconsistent audio file formats. Business users should see a smoother, more reliable call review experience with fewer interruptions.
Original PR description
Prior to this commit, clicking the "Request Transcription" button crashed the client because `t-on-click="onClickTranscribe"` was missing the `this.` prefix. This commit adds `this.` to the click handler in the template so that Owl correctly finds and calls the method on the component. task-6478747 **Community Sibling https://github.com/odoo/odoo/pull/282908**
This fixes an error that could occur when simulating Belgian payroll ONSS data after payroll configuration versioning was introduced. The system now uses the current payroll settings version instead of outdated company-level settings, helping payroll workflows continue reliably.
Original PR description
With the launch of payroll config versioning, fields were moved from res.company to its versions, this file was trying to reference a field directly from the company instead of its current settings version Task-6485680
DIN 5008 PDF documents now consistently show dates in the expected day.month.year format for Germany, Austria, and Switzerland, regardless of the user’s language settings. This prevents invoices, quotations, purchase orders, follow-ups, and field service documents from displaying confusing or non-compliant date formats.
Original PR description
* = din5008_account_followup, din5008_industry_fsm **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document layout to **DIN…
* = din5008_account_followup, din5008_industry_fsm
**Steps to reproduce:**
* Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`)
* Set the document layout to **DIN 5008** and generate any PDF report (invoice, quotation, purchase order, etc.).
**Observed behavior (date format):**
* All dates in the information block (Invoice Date, Due Date, Delivery Date, Order Date, etc.) are rendered in `yyyy-mm-dd` format instead of the expected `dd.MM.yyyy` format used in DE, AT, and CH.
**Cause (date format):**
* All `t-options="{'widget': 'date'}"` directives across the DIN 5008 template family rely on the active user's language locale for date formatting. If the user language is not `de_DE`, dates render in the locale's default format (e.g. `yyyy-mm-dd` for `en_US`).
**Fix (date format):**
* Add `'format': 'dd.MM.yyyy'` explicitly to all `t-options` date widgets across all DIN 5008 report templates (`l10n_din5008`, `l10n_din5008_sale`, `l10n_din5008_purchase`, `l10n_din5008_sale_subscription`, `l10n_din5008_repair`, `l10n_din5008_account_followup`, `l10n_din5008_industry_fsm`).
* This is correct for all three countries using DIN 5008 (DE, AT, CH), which all follow the `dd.MM.yyyy` convention.
opw-6392649
Forward-Port-Of: odoo/enterprise#128453
Forward-Port-Of: odoo/enterprise#126006Fixed an issue where DHL return label creation could fail when a sales order included incoterms. The system now sends the required incoterm code correctly, helping users complete deliveries without errors.
Original PR description
Issue ----- When "return" is enabled, users get a traceback if the SO has incoterms. Steps to reproduce ----- - Set up DHL - enable return labels - Create a SO with incoterms & confirm it - Confirm the delivery > Traceback Cause ----- The request sent for the return label contains the incoterm record instead of its' code like in `dhl_rest_send_shipping` https://github.com/odoo/enterprise/blob/f6c94d4ca3ef4211a5ab00bf0b39f6a7675c8f79/delivery_dhl_rest/models/delivery_dhl.py#L371-L372 Which is not JSON serializable ----- Ticket: opw-6430371 Forward-Port-Of: odoo/enterprise#126459
Payroll payment files for Swiss Revolut accounts now include the beneficiary name where required. This helps avoid payment processing issues and supports smoother salary payments through Swiss payroll workflows.
Original PR description
Forward-Port-Of: odoo/enterprise#126632
Users can now move through return items in the kanban view with the up and down arrow keys without triggering an error. This makes reviewing and selecting returns smoother and prevents an interruption in the accounting workflow.
Original PR description
In returns kanban view, a traceback occurs when pressing down. Fix this by adding the support for up/down keyboard navigation for returns selection. task-6281033 Forward-Port-Of: odoo/enterprise#128308 Forward-Port-Of: odoo/enterprise#125164
This update modernizes how the web interface keeps navigation items current, reducing the risk of menus or keyboard navigation starting with missing items. It preserves existing behavior while making the underlying navigation logic more reliable for future platform updates.
Original PR description
Split out of #282959, which is now the ~10 purely mechanical `useLayoutEffect` → `useOnChange` sites. `useNavigation` is the one that is not mechanical, so it gets its own PR. The two touch no files…
Split out of #282959, which is now the ~10 purely mechanical `useLayoutEffect` → `useOnChange` sites. `useNavigation` is the one that is not mechanical, so it gets its own PR. The two touch no files in common. ### Why this one is different Everywhere else in the migration the dependency list is nothing but refs, which makes the swap timing-neutral: a ref signal is written during the DOM patch, so the effect's microtask fires straight after it with the patched DOM already in place, where the shim's `onPatched` ran it. `useNavigation` is the only hook in the series that hands state back to the caller for a lifecycle hook to read: ``` time (down) useLayoutEffect useOnChange -------------------- ---------------------- -------------------- patch DOM - effect queued onMounted (hook) update() -> items not registered onMounted (consumer) reads items[0]: ok reads items[0]: [] microtask - update() -> items ``` `onMounted` never runs again, so the missed `setActive()` is lost rather than merely delayed. This is what broke the 7 `navigation_hook` tests on the first attempt. ### What this does instead The first version of this fixed the ordering by calling `navigator.update()` from an extra `onMounted` inside the hook. @seb-odoo's review comment on #282959 was that the actual problem is that `Navigator` is not reactive, and that is right: `items` was a plain field reassigned by `update()`, sitting outside the reactive graph, so *something* had to push a refresh in at the right moment. So `items` is derived instead, and the ordering question disappears rather than being answered: - `_elements` — a computed over `options.getItems()`, memoised on a shallow comparison. Every signal that callback reads (the container ref, an `isOpen()` state) is tracked, so the list re-derives on its own. - `_items` — a computed over it that reconciles `NavigationItem`s, reusing the instance of an element that is still there so its listeners survive. - `items` — a getter over that. Reading it from anywhere, including a consumer's own `onMounted`, derives against the DOM as it is at that moment. - `update()` — now just an invalidation, for the DOM, which is the one input that cannot notify us. It still syncs eagerly, so `update(); this.items` keeps working for `dropdown.js`. - `_syncActiveItem()` — the active-item reconciliation, `onUpdated` and `shouldFocusFirstItem` move out of the derivation, because they move focus and a plain read of `items` must not do that. Idempotent per derivation, which is what the hand-rolled `didUpdate` flag bought. ### Blast radius `navigation.js` only, plus one test. No consumer changes: `items`, `update()` and `onUpdated` keep their signatures, and enterprise never constructs a `Navigator` nor calls `update()`. Nothing reads `items` during a render — every read across both repos is a hotkey callback or an event handler. That matters now that `NavigationItem` construction, which attaches listeners and writes `ariaSelected`, happens inside a computed. It is a constraint the code satisfies today rather than one it enforces. The destroy test stepped on `update()`, which no longer runs on mount at all, so it steps on `_syncActiveItem` instead. ### For review - `onUpdated` and `shouldFocusFirstItem` now fire from an effect (a microtask after patch) for signal-driven changes, where `useLayoutEffect` fired them inside `onPatched`. Explicit `update()` callers are unaffected. This is the same class of timing shift that broke the tests the first time, so it is the thing to look at hardest. - `activeItem` / `activeItemIndex` are still plain fields. Making those reactive is the other half of "properly reactive" and is deliberately not in here. Draft until CI has had a go at it.
Point of Sale customer displays now communicate with terminals more directly and only when a display is actually connected. This reduces unnecessary background activity, improves reliability after startup or reload, and makes future display-related changes easier to maintain.
Original PR description
pos*: point_of_sale, pos_loyalty, pos_hr, pos_online_payment, pos_stock, l10n_in_pos, l10n_id_pos Refactor the customer display communication to make it more efficient, decouple the terminal and…
pos*: point_of_sale, pos_loyalty, pos_hr, pos_online_payment, pos_stock,
l10n_in_pos, l10n_id_pos
Refactor the customer display communication to make it more efficient,
decouple the terminal and display sides, and avoid unnecessary requests
when no display is connected.
- Replace the effect on `pos_service` with targeted listeners on order-related events.
- Split `customerDisplayService` into two OWL plugins: `CustomerDisplayTerminalPlugin` for the PoS terminal and `CustomerDisplayPlugin` for the customer display.
- Centralize payload generation through `GeneratePrinterData` and remove the deprecated `CustomerDisplayPosAdapter`.
- Replace `device_uuid` with a `device_identifier` generated by `DeviceIdentifierSequence`.
- Use a registration route to track connected customer displays: displays announce themselves with `ADD` and `REMOVE`, while terminals use `PING` to discover displays after startup or reload.
- Skip payload generation and requests when no customer display is connected.
- Refactor customer display tests to exercise the real application flow and assert against system-generated payloads.
```mermaid
flowchart LR
POS([PosStore])
UI([Customer display UI])
subgraph Terminal["CustomerDisplayTerminalPlugin — app/plugins"]
direction TB
initT["init({ identifier, models, scale, bus, ... })"]
sendOrder["sendOrder(order)"]
build["_buildDisplayPayload()"]
send["send(payload)"]
sendOrder --> build --> send
end
subgraph DisplaySide["CustomerDisplayPlugin — customer_display"]
direction TB
initD["init({ bus })"]
onData["_onDataReceived()"]
data[("data — signal")]
onData --> data
end
POS -->|initCustomerDisplay| initT
POS -->|order or screen changed| sendOrder
UI -->|mounted| initD
send -->|"update_customer_display — bus"| onData
send -.->|"BroadcastChannel — only if the request fails"| onData
data -->|render| UI
```
Task-5911881This internal cleanup makes mail record lists follow the same structure as related records. It improves consistency for future maintenance without changing how users interact with Odoo.
Original PR description
Before this commit, the record list holds its proxy get and set traps inline in its constructor and its localIds in a `data` own property. The record holds the same logic on its internal, `RecordInternal`. This commit moves the traps to `RecordListInternal.proxyGet` and `proxySet` and the localIds to `RecordListInternal.data`, so that the list and the record have the same shape. Note that the set trap thereby runs untracked: the untrackFunctions list of `RecordListInternal` already names `proxySet`, like the record's. This commit also stores the record list on its internal and drops the record list parameter of the internal methods: every caller passed the list whose internal it calls, so the parameter only repeated `this.recordList`.
The mail module now manages record lists through a dedicated internal mechanism, making updates easier to track consistently. This is a behind-the-scenes refactor intended to preserve behavior while improving maintainability and future performance reliability.
Original PR description
Before this commit, a record list keeps its records in a plain `RecordListInternal.data` array and gets its reactivity from the owl proxy wrapping the list, so a read has to travel through that proxy to register the observer, and every mutator routes its writes through `recordList._proxy` for the observers to hear them. This commit moves the array into its own signal behind a `data` accessor of the internal, whose reads return the array as an owl proxy, so a read observes the list from any receiver and the list needs no owl proxy of its own: `_proxyInternal` merges into `_proxy`, and the `gettingField` flag and the mutators' routing through `recordList._proxy` go with it. Note that the granularity stays per key: a replacement notifies through the signal, an in-place mutation through the proxy's key atoms. One solution could have been `signal.Array`, but it holds one atom for the whole list, so any write re-runs every reader (owl issue 1991).
This update replaces an older internal screen update mechanism with the newer approach required by the next version of Odoo’s web framework. It helps keep several user interface areas maintainable and ready for future upgrades without changing expected business workflows.
Original PR description
Changes `useLayoutEffect` to `useOnChange` for all `useLayoutEffect` with **only references** as dependency list. WHY: Because useLayoutEffect is deprecated in OWL3 NOTE: Because every dependency list contains nothing but refs, it makes these timing-neutral by construction. A ref signal is written during the DOM patch, so the effect's microtask fires straight after it with the patched DOM already in place -- where the shim's onPatched ran it. `initialRun: false` drops the setup-time run where the ref is still null The untrack() in six dep lists had to go. useOnChange turns the dependency function into a computed, and untrack leaves that computed with no source, so the effect would fire once and never again.
Point of Sale customer display updates are now handled through a centralized communication component instead of depending on broader service activity. This should reduce unnecessary processing and make connected display and scale integrations more consistent across supported POS setups.
Original PR description
pos*: pos_iot, pos_mobile, l10n_eu_iot_scale_cert Customer display previously relied on an effect on `pos_service` to dispatch updates, which was inefficient and unnecessarily dependent on the full service lifecycle while only order data was required. This commit refactors and centralizes the customer display logic: - Replace effect-based updates with targeted event listeners on order-related events to reduce overhead and improve performance - Make `customerDisplayService` the single source of truth for all customer display communication (send/receive) - Standardize payload generation using `GeneratePrinterData` And remove deprecated `CustomerDisplayPosAdapter` - Replace `device_uuid` with `device_identifier` generated via `DeviceIdentifierSequence` for consistent device identification Task-5911881 Related PR: - https://github.com/odoo/odoo/pull/257781
The Knowledge article template picker was updated to use the newer supported behavior in the underlying interface framework. This keeps the feature compatible with upcoming platform changes and adds test coverage to help prevent regressions.
Original PR description
Replaces `useLayoutEffect` with a `useEffect` because useLayoutEffect is deprecated in OWL3 Note: I added a test because when the useLayoutEffect was commented out no test broke. see: https://runbot.odoo.com/runbot/batch/2596681/build/114854277
The barcode inventory screens were updated to use a newer internal framework method, replacing an approach that is being retired. This helps keep the stock barcode module compatible with the next Odoo web framework version without changing day-to-day user behavior.
Original PR description
Changes `useLayoutEffect` to `useOnChange` for all `useLayoutEffect` with *untracked* *references* as dependency list. WHY: Because useLayoutEffect is deprecated in OWL3 NOTE: Because every dependency list contains nothing but refs, it makes these timing-neutral by construction. A ref signal is written during the DOM patch, so the effect's microtask fires straight after it with the patched DOM already in place -- where the shim's onPatched ran it. `initialRun: false` drops the setup-time run where the ref is still null The untrack() in six dep lists had to go. useOnChange turns the dependency function into a computed, and untrack leaves that computed with no source, so the effect would fire once and never again. Community PR: https://github.com/odoo/odoo/pull/282959
The Knowledge app comments panel was updated to use a newer internal mechanism, replacing deprecated code without changing how users interact with it. A new automated test was added to help ensure this area continues to work reliably in future updates.
Original PR description
Replaces the deprecated `useLayoutEffect` with `useOnChange` (the only difference between both is useOnChange triggers a bit earlier, which is irrelevant here because we don't access the DOM) This feature was not tested, so a new HOOT test is introduced.