Tuesday, September 1, 2026
120 changes · master
Security fixes and vulnerability patches
Portal access tokens are now checked only by exact match, preventing partial or unintended token matches. This helps ensure shared portal links and protected records are validated more reliably.
Original PR description
Access tokens can only be matched by exact value. Accept `in` and `not in` operators. Task-6481193 Forward-Port-Of: odoo/odoo#285388 Forward-Port-Of: odoo/odoo#285218
New functionality added to Odoo
Belgian payroll now supports starter jobs, helping employers correctly manage payroll, declarations, and related reporting for eligible young employees. This improves compliance and reduces manual work across payslips, social declarations, and payroll tax documents.
Original PR description
task-6348319
Enhancements to existing features
A new automated test verifies that image previews refresh correctly after a user uploads a new image. This helps protect the image upload experience from future regressions in Odoo's web interface.
Original PR description
Purpose ======= Add a test that check that the preview of the `ImageField` is updated after uploading a file when the option `preview_image` is used. Task-6509975
Resolved issues and error corrections
The Guatemala electronic invoicing localization now uses the updated tax calculation for regular gasoline that contains 10% alcohol. This matters because, from August 22, only 90% of the gallons are taxable under the new government rule for new customer chart of accounts setup.
Original PR description
Starting August 22nd Regular Gasoline is changing to a version that contains 10% alcohol. Because of this, the government is only taxing 90% of the gallons since the 10% alcohol portion is exempt. This will update COA for new customers, any current dbs who need to use the new formula can manually update theirs to include the * 0.9 portion. task-6483303 Forward-Port-Of: odoo/enterprise#129483 Forward-Port-Of: odoo/enterprise#129412
Features or functions removed from Odoo
The employee planning portal and planning preview have been removed to simplify how employees access shift information. Internal users invited by email can still view and unassign shifts, and shift assignment emails now include a planning report attachment so employees can see shift details directly from the email.
Original PR description
**Remove employee planning portal** We are moving to a lightweight user flow, so the employee planning portal is removed. - Internal users (invited by email) can still view and unassign shifts. - Removed planning preview from the UI. - Added shift details report in the new shift email so users can easily see shift information. - This change helps keep the system simple and easy to use. **Attach planning report in shift assign email** When a shift assign email is sent,added the planning report as an attachment so resources can directly see shift details from the email without needing to add it to their calendar. If a shift has multiple resources, the same planning report (covering all assigned resources) is attached once per email, allowing employees to understand shared shift allocation. From a technical point of view, we do not create separate attachments for each resource, which helps save space. task-5259643
Code cleanup and technical improvements
This internal cleanup simplifies how several chat and messaging values are calculated, keeping the same behavior while reducing unnecessary processing steps. Users should not see functional changes, but the affected mail and live chat areas become easier to maintain and potentially more efficient.
Original PR description
Before this commit, eighteen fields derive their value from a compute option: the model runs it, stores the result in the field and settles it at the end of the update cycle. None of them is written from outside, observed through an onUpdate hook or patched by an addon, so the field exists only to hold what the compute returns. This commit declares them with this.computed(), which keeps the value in an owl computed of its own: same laziness, same memoisation, without a field and an update cycle around it. Two of them do explicitly what their field type did for them: editedDate deserializes the datetime it reads from the message body, and offline_since spreads the user dates into DateTime.max, which the compute handed an array.
Shift template suggestions now include generic templates even when a shift has a specific project or worksheet. This makes reusable templates easier to find and keeps scheduling behavior consistent with role-based template suggestions.
Original PR description
*_ = planning_field_service_worksheet - When a shift has a project or a worksheet, only templates matching that exact value were suggested. Roles already also include templates with an empty value. - Do the same for project and worksheet so generic templates remain available. task-6364228 Forward-Port-Of: odoo/enterprise#129004
Warehouse operators using the Barcode app can now be prompted to combine a receipt with related receipts when scanned products belong to another incoming order. This helps process mixed vendor deliveries without manually identifying each purchase receipt, while keeping the scanned product selected after the receipts are combined.
Original PR description
Purpose ======= When an operator is doing a vendor purchase receipt, they may receive items from different orders without having a direct clear view on which ones they are. They should be able to do…
Purpose ======= When an operator is doing a vendor purchase receipt, they may receive items from different orders without having a direct clear view on which ones they are. They should be able to do their receipt in the Barcode app without wondering about that and just get a suggested batch if items belong to different orders. Functionnality ============== When an operator scans a product which isn't reserved in the currently opened operation, a prop will be displayed to ask the user if they want to batch the receipt with another receipt which contains the scanned product. The user can either batch with another receipt, either add the product or either discard (do nothing, don't add the scanned product.) If they chose to batch with another receipt, both receipts (the current one and the selected one) will be batched together, either in a new batch (if none were already in a batch), either in one of the pickings' batch. If both receipts are already in a different batch, their both batches should be merged together (whihch can result in more than one added picking.) The same thing happens if the user tries to add a product with the `stock.move.line` form view (with the "Add Product" button), the same confirmation dialog will be displayed, and if the user choses to batch, the created move's `picking_id` will be set on the selected picking, and the batch will be opened instead of going back picking. Once the pickings are batched, one of the batched move lines for the scanned product will be incremented and after that, when the batch is opened in the Barcode app, this move line will be auto-selected. So, for the user, the product they scanned before batching the receipt isn't lost, they don't need to re-scan it. Note that this implementation is very basic, it doesn't handle scan of lot/serial numbers nor packages for now. Also note that this feature doesn't require to enable the batch setting, it should work even if this setting is disabled. How suggest receipts to batch are chosen ======================================== For a receipt to appear in the suggest batch pop-up, it should match following requirement - It must share with the opened receipt the same contact, the same company and the same state (to avoid to batch confirmed pickings with draft pickings); - It can't be done nor cancelled. [task-6154300](https://www.odoo.com/odoo/966/tasks/6154300)
This update refreshes demo data for purchasing, stock-related purchasing, and online store stock scenarios. It helps business users and evaluators see more representative examples when testing or demonstrating these Odoo apps.
Original PR description
Task: 6486305 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 update refreshes and expands demo content across purchasing, inventory barcode, manufacturing work orders, and quality control. It helps teams evaluate these workflows with more realistic sample data and clearer barcode examples, making demos and training easier.
Original PR description
Task: 6486305
Users can now delete removable circular nodes, such as Hang Up, directly from the VoIP flow editor with the mouse. The delete option also stays visible when focused, improving keyboard accessibility while keeping protected nodes like Start unchanged.
Original PR description
Circular flow nodes did not display the delete button available on rectangular nodes. As a result, Hang Up nodes could not be removed directly with the mouse. Display the delete button when hovering a removable circular node and keep it visible when focused for keyboard accessibility. Non-removable nodes, such as Start, remain unaffected.
Checkboxes with hidden labels can now use their description as the clickable text, making forms easier to use. This improves accessibility and reduces mistakes when users need to tick options with a very small clickable area.
Original PR description
It's possible to hide the label of a checkbox. The surface to tick it is then very small. Solution: Use the description as a substitute for the label when the latter is hidden. Task-6009931
The website setup wizard now downloads industry images in parallel instead of one by one. This shortens waiting time during website configuration, especially for customers hosted far from Odoo image servers or experiencing higher network latency.
Original PR description
The website configurator downloads 80+ industry images sequentially, making the image processing block highly sensitive to network latency to IAP. Download the images in parallel before creating…
The website configurator downloads 80+ industry images sequentially, making the image processing block highly sensitive to network latency to IAP. Download the images in parallel before creating their attachments, significantly reducing the time spent in this block. On Runbot, this brings the image processing time down from ~4.5s to ~0.8s, saving more than 3 seconds in the Website Configurator wizard. The improvement might seem small on Runbot due to its very low latency to the IAP servers, but it can be significantly higher for Odoo instances hosted farther away from the IAP servers. For example, on my local instance in Gujarat, India, the same block went from ~75s to ~10s. The exact improvement is still subject to the load on the IAP server and the network conditions between the IAP and Odoo servers. However, the parallel downloads significantly reduce the impact of network latency on this process. task-[6514167](https://www.odoo.com/odoo/project/974/tasks/6514167) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The project to-do screens have been tidied up to make searching and list browsing clearer. This should help users find and review their to-do items with less visual clutter and a smoother day-to-day experience.
Original PR description
task-6516822
The Timesheets section on project tasks now places the option to add a new line at the top of the list. This makes entering timesheet records quicker and more visible for users working on task details.
Original PR description
Recently, the framework merged a task allowing to configure the position of the "Add a line" in the list view. We build on this to change the position of the "Add a line" button to the top of the "Timesheets" notebook of Project tasks. task-6499912
Custom fields can now choose more precise database index types, helping improve search performance for different data needs. The update also ensures index changes are properly detected and rebuilt when needed, reducing the risk of stale database structures.
Original PR description
Allows custom fields to have a more specific index instead of just "True" which is a just btree. Check commits for more details task-6507120 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Helpdesk users can now add a new timesheet line from the top of the Timesheets section on a ticket. This small usability improvement makes time entry easier to find and faster to use when working on support tickets.
Original PR description
Recently, the framework merged a task allowing to configure the position of the "Add a line" in the list view. We build on this to change the position of the "Add a line" button to the top of the "Timesheets" notebook of Helpdesk tickets. task-6499912
Rental product pages can now support showing a crossed-out reference price when a discount applies. This helps shoppers better understand rental discounts and keeps pricing presentation consistent with regular products.
Original PR description
`_get_additional_combination_info` inlines the logic that decides whether a "before discount" reference price should be shown and how to compute it, directly against the pricelist rule that matched the current price. Rental products need to use a different method to compute the price before discount as multiple rules can be applied at the same time. This commit extracts that logic into its own `_get_price_before_discount` method so it can be overridden independently of the rest of `_get_additional_combination_info`. task-6279525 See also: - https://github.com/odoo/enterprise/pull/124483 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Online shoppers can now narrow product lists using a range slider for selected product attributes, such as ordered sizes or levels. This makes browsing large catalogs faster and more intuitive while keeping the displayed range labels updated as customers adjust the filter.
Original PR description
- Add support for range display type for product attributes - Render range slider using attribute sequence ordering - Add dynamic label update on frontend task-6059293
Date pickers can now show the day of the week alongside dates when enabled. This helps users quickly understand what weekday a selected date falls on, which is especially useful for appointment booking and scheduling flows.
Original PR description
It is sometimes relevant when showing the date to also quickly let the user know what day of the week it corresponds to. task-5072614
Appointment booking pages are easier to create and maintain with tools to copy existing slots or days, edit slots directly from the calendar, and generate fixed-duration time slots while dragging. A new sidebar centralizes booking page management and sharing options, making it simpler for organizers to configure availability and keep long-running appointments tidy.
Original PR description
Sometimes people want to share some specific slots one after the other without having to tediously set them one by one. ## Add a "clone last slot" / "clone last day" action in the list view This…
Sometimes people want to share some specific slots one after the other without having to tediously set them one by one. ## Add a "clone last slot" / "clone last day" action in the list view This eases the set up when most days look the same. The copying is done based on the timezone of the appointment so that the result is always consistent. ## Rework the slot editor ### Custom appointments Previously you could create an appointment via the calendar view, which would allow you to select some slots visually in the calendar before sharing them. We rework this system to be able to edit existing appointments, move and delete slots. This removes the appointment dropdown at the top of the calendar and replaces it with a sidebar where you can create and manage appointments where you are an organizer, which would previously have been listed in the dropdown. From there you can copy the url to share it, enter edition mode to make sure the correct slots are bookable, or edit some basic settings of the appointment type. In this settings form, a new duration field is available that will automatically create slots every X minutes as the user drags. Which is a common thing users want to do for example for house showings. To prevent users from accidentally creating way too many slots at once, this is limited to 24 hours at a time which should be more than sufficient. ### Recurring appointments It is also possible to edit recurring appointments by going to their form using a new stat button. It works very similarly to the custom appointments except slots are only split around midnight. Bookable slots (those shown in the frontend, called "subslots" in this code) are represented inside each slot. Depending on duration and "create slots every X hours" settings of the appointment type. ## Old slots garbage collection To avoid cluttering the slots for long-lived appointments, a new garbage collection mechanism is added to remove slots older ending over 1 week ago, always leaving the last 40 slots so users can have an idea of what the schedule was like on old unused appointment types. task-5072614
The Indian payroll contract template now hides the Tax Deductions section when Professional Tax is not enabled. This keeps payroll settings screens cleaner and prevents users from seeing empty or irrelevant sections.
Original PR description
Prior to this commit, the "Tax Deductions" group caption on the contract template view remained visible even when Professional Tax (PT) was not enabled in the Payroll settings. This commit updates the visibility condition of the "Tax Deductions" group on the contract template view to be hidden when PT is disabled (`not l10n_in_pt`), preventing empty settings sections from displaying to users. Task: 6514274 Forward-Port-Of: odoo/enterprise#129836 Forward-Port-Of: odoo/enterprise#129703
Course managers can now send an email only to the attendees they select, instead of messaging every attendee through mass mailing. The attendees list also has clearer progress filters, and related mail handling was made more reliable for records that do not use discussion threads.
Original PR description
**Purpose:** Allow sending an email to selected course attendees instead of contacting all attendees through the mass mailing action. **Specifications:** - Add a "Send Email" action in the Attendees list view for the selected attendees, with the same behavior as the Contacts app. - Add default "Not Started" and "Almost Done" filters. Task-6267552
Mobile users searching for projects will now consistently see the simpler project card designed for selection dialogs. This avoids occasionally showing the fuller Projects app card in the wrong place, making project selection clearer without changing the main Projects screens.
Original PR description
The many2one "Search More" dialog on mobile requests a kanban view for `project.project` without an explicit `view_id`, falling back to whichever primary kanban view resolves first. This accidentally depended on record id ordering, sometimes serving the rich Projects app card instead of the minimal one meant for this case. This commit sets an explicit lower priority on `project_view_kanban` so it is deterministically chosen for this fallback, leaving the Projects app and Configuration > Projects menus (which pin their own view_id) untouched. task-6131412
Customers can now enter a recipient email and send a purchased gift card directly from the order confirmation page or their portal order. The update also improves the gift card experience by adding copy functionality and better styling outside of the eCommerce-only flow.
Original PR description
The gift card section is displayed in two contexts: the order confirmation after checkout and the customer's portal order. The customer can now enter a recipient email and send the gift card directly from either one. The copy interaction is moved from website_sale_loyalty into sale_loyalty, as it would not work when eCommerce is not installed. task-6255032 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users now see a helpful dialog when they try to delete a record that is still used elsewhere, instead of a technical server error. The dialog explains what is blocking the deletion and, when available, offers archiving as an alternative so users know how to proceed.
Original PR description
Deleting a record that is still referenced elsewhere failed on a raw PostgreSQL RESTRICT violation, surfaced as a technical server error: nothing told the user which record was in the way, nor what…
Deleting a record that is still referenced elsewhere failed on a raw PostgreSQL RESTRICT violation, surfaced as a technical server error: nothing told the user which record was in the way, nor what to do about it. The web client's delete flows now go through `web_unlink()` (via the new `orm.webUnlink()`), so none of this affects `unlink()` calls made by other server-side code. On a blocked delete, it rolls back and retries the deletion record by record inside a savepoint that is always rolled back, to pinpoint which records are the actual problem, then raises `UnlinkBlockedError` with the blocking model's display name, whether the records can be archived, the selection and the blocked subset of it. Client-side, registering `UnlinkBlockedErrorDialog` under that exception's name is all it takes for the dialog to show up wherever the delete came from; no view has to catch anything. It proposes archiving instead when the records support it - on the whole selection, reloading the view afterwards - and is a plain "Close" otherwise. When only part of a bulk delete is blocked, it also links to the non-deletable records. task-4610830
This update improves the guided onboarding tours for Accounting, CRM, and Point of Sale so they work better in both automated checks and manual walkthroughs. It helps ensure new-user guidance remains consistent and easier to validate before release.
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
Deleting records from the Gantt view now uses the same deletion flow as other views. When a record cannot be deleted because it is still linked elsewhere, users see a helpful dialog instead of a raw server error.
Original PR description
Gantt deletes its records itself, through `unlink()`, so a delete blocked by a RESTRICT violation still failed there on a raw server error. Going through `orm.webUnlink()` gets the pill dialog and the multi-selection delete the same actionable dialog as the other views. task-4610830
Odoo now supports additional payroll work entry types for temporary unemployment, including cases involving public holidays and refused unemployment claims. This helps employers apply the correct pay and social contribution treatment in Belgian HR and payroll processes.
Original PR description
[IMP] {hr_holidays,hr_work_entry}: new work type entries for temporary unemployment
When a company put workers on temporary unemployment and a public holiday occurs during that period:
- By default it has to be paid
- if the temporary unemployment is long enough, the employer can pay only the taxable part (no onss)
Also it may happens that a technical unemployment is made by a company but then refused by the administration,
in that case the employer has to pay it but this day is still considered as a technical unemployment
in the computation of the ONSS contribution reduction.
Some hr_work_entry_types were created or updated:
LEAVE6665 is now selectable in timeoff.
LEAVE086 is created and acts as counterpart for LEAVE207 when the temporary unemployment is long enough.
Both LEAVE086 and LEAVE207 are acceptable on public holiday days.
LEAVE2049 is created (for refused temporary unemployment by administration)
enterprise-122476
task-6199998This update polishes the email marketing building blocks and templates used to create mass mailing campaigns. Users get more visually refined snippets, better template variety, and improved default images and branding, making it easier to produce attractive emails with less manual adjustment.
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
Website forms now better communicate invalid fields and their related error messages to screen readers. This improves accessibility for users relying on assistive technologies and helps them complete forms more confidently.
Original PR description
Screen readers could not link invalid inputs to error messages. Solution: Use aria-invalid and aria-errormessage to improve the screen reader experience. Task-6009931
Belgian payroll now handles public holidays that fall during a worker's temporary unemployment period more accurately. The system splits the absence and applies the correct paid holiday code, including whether social security contributions apply, helping employers follow payroll rules.
Original PR description
When a company put workers on temporary unemployment and a public holiday occurs during that period: - By default it has to be paid - if the temporary unemployment is long enough, the employer can pay only the taxable part (no onss) Upon validating a temporary unemployment leave that overlaps a public holidays, we split the leave into subsegments and we apply a specific code that takes precedence over the public holiday leave. It becomes either a LEAVE207 (with onss) or LEAVE086 (without onss). community-275356 task-6199998
Mexican eCommerce customers now choose invoicing through clearer buttons, and invoice details are only shown and required when needed. Company name and RFC collection is moved into the dedicated invoicing flows for checkout, address pages, and POS tickets, making invoicing data easier to capture and store correctly.
Original PR description
Improve the dedicated Mexican invoicing checkout step: - replace the "need invoice" Yes/No radios with two buttons, and only require and show the invoicing fields when an invoice is requested - add the Company Name field here and hide the B2B fields (Company Name + RFC) from the address form, both in checkout and in /my/address - read and save the invoicing data on the order's invoice contact (partner_invoice_id) instead of the main partner - POS ticket screen: Collect RFC through the localisation fields required to invoice task-[6234716](https://www.odoo.com/odoo/project/967/tasks/6234716)
Frontdesk automated checks were updated to match the newer visitor creation process, where notifications are sent as soon as a visitor is created. This helps ensure the visitor reception experience and related SMS notification behavior continue to work reliably.
Original PR description
Update frontdesk tests to follow the new visitor creation flow, where notifications are triggered when creating a visitor. Task-6388574
Job listings now only allow working schedules that match the job's company. This helps keep recruitment records consistent and reduces the risk of publishing or managing jobs with invalid schedule settings.
Original PR description
In order to maintain proper job listings and make sure all working schedules are valid, working schedule domain is now depeding on the job listing company. Task: 6408914 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#285407 Forward-Port-Of: odoo/odoo#282993
Job listings now only allow working schedules that are valid for the company linked to the job. This helps keep recruitment postings consistent and reduces the risk of choosing an incompatible schedule.
Original PR description
In order to maintain proper job listings and make sure all working schedules are valid, working schedule domain is now depeding on the job listing company. Task: 6408914 Forward-Port-Of: odoo/enterprise#129748 Forward-Port-Of: odoo/enterprise#128241
Several apps were updated to stay aligned with recent attachment handling changes in Odoo. This keeps opening and deleting attachments working consistently in areas such as Approvals, Documents, Recruitment, Spreadsheets, and Social Marketing.
Original PR description
Community `mail` reshaped AttachmentList's click handlers to the uniform `(ev, { attachment })` object form. These modules patch `AttachmentList.onClickAttachment` / `onConfirmUnlink`, so their overrides adopt the same signature and forward via `super(...arguments)` to keep matching the base.
https://github.com/odoo/odoo/pull/273646This update improves how several mail and calendar interface elements react to changes, especially in chatter, scheduled messages, attachments, polls, previews, and chat bubbles. It should make these areas more efficient and reliable by avoiding unnecessary refreshes and ensuring actions apply to the item the user actually selected.
Original PR description
Continue reading props as signals (`this.x()`) across more mail components via `propComputed`/`propSignal`: the chatter scheduled message and follower list, polls, link previews, the chat bubble and…
Continue reading props as signals (`this.x()`) across more mail components via `propComputed`/`propSignal`: the chatter scheduled message and follower list, polls, link previews, the chat bubble and the small leaf components (country flag, date section, priority, message link preview list).
A callback handed to a slotless list child is made `props.static` and bound once in the caller: a fresh closure every render makes the prop compare unequal and forces every item to re-render, whereas a stable reference lets unchanged items skip it. Done for `AttachmentList.unlinkAttachment` and
`ScheduledMessage.onScheduledMessageChanged`.
`ChatBubblePreview.chatWindow` is chained down as a `propSignal`: the parent already holds the value as a signal and now passes the signal itself, so the preview reacts to it directly.
Click handlers take the record they act on as a parameter, captured at render right before the handler (a scoped `recordAtRender` local) and passed as `(ev, { recordAtRender })`. A signal read inside a handler resolves at call time, so if the value changed since the render the user saw, the handler would act on a record different from the one displayed; the captured record keeps the action tied to what was clicked. A callback that runs later, such as a dialog confirmation, receives the same captured record instead of re-reading the signal.
A callback prop type shared between a child and the parents that pass it is defined once as an exported `(store) => t.function(...)` factory and reused rather than duplicated at each declaration.
https://github.com/odoo/enterprise/pull/122615The Belgian payroll module description now directs users to the official documentation for Dimona. This helps users find the most accurate guidance without changing payroll features or workflows.
Original PR description
Change the module description to refer to the official documentation. Task-6485101
Point of Sale can now use payment methods linked to different currencies, allowing shops to accept payments in more than one currency without blocking POS setup. Cashiers will see the relevant currency per payment method, while order totals remain shown in the POS configuration currency.
Original PR description
In some countries it's common to accept multiple currencies when making sales, but we don't let users open POS configs if they assigned to the POS payment methods for journals which use different currencies. This should let users create payment methods assigned to multiple currencies and then still open the POS. If there are multiple currencies set up on the POS, the payment screen will show the corresponding currency for each payment method. The totals are still shown in the config currency, but when selecting a payment method in a different currency there will be the price in the new currency between brackets on the payment line. Task-[5110998](https://www.odoo.com/odoo/project/1737/tasks/5110998) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixed an issue where timesheets could lose their connection to a replacement invoice after an invoice was reversed and recreated through a credit note. This helps ensure corrected invoices still show the right timesheet details for the related sales order, reducing billing confusion and manual cleanup.
Original PR description
### Description of the issue/feature this PR addresses: Fixes an issue where timesheets lose their invoice reference when reversing and re-creating an invoice via a credit note. ### Current behavior…
### Description of the issue/feature this PR addresses: Fixes an issue where timesheets lose their invoice reference when reversing and re-creating an invoice via a credit note. ### Current behavior before PR: When reversing an invoice tied to timesheets and creating a replacement via a credit note, the timesheets linked to the original invoice have their timesheet_invoice_id cleared. Because the modify_moves function builds the replacement invoice directly via copy_data()/create(), it bypasses the normal sale order invoicing flow. As a result, the unbilled timesheets are left permanently unlinked from the newly created invoice, leaving the new invoice with no reference to the timesheets linked to the original sale order. ### Desired behavior after PR is merged: When a replacement invoice is created, each timesheet is properly relinked to the corresponding line on the new invoice. This linkage matches on the sale order line (so_line) rather than line position, ensuring accuracy since line order and count are not guaranteed to be preserved between the original and modified invoices. opw-6449995 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285232 Forward-Port-Of: odoo/odoo#283104
Mobile invoice line cards now display the line description when no product is selected. This prevents blank cards and makes invoices easier to review on mobile devices.
Original PR description
Invoice lines can be created without a product. However, the mobile kanban view does not handle such lines properly and displays an empty card without a name or image. This commit adapts mobile kanban view to show invoice line's name when `product_id` is not set. Before | After -- | -- <img width="469" height="277" alt="image" src="https://github.com/user-attachments/assets/3b367581-b73d-4b12-a487-1a54c3b88470" /> | <img width="406" height="300" alt="image" src="https://github.com/user-attachments/assets/107d7294-90e8-49c6-826a-9be75c6b799f" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285608 Forward-Port-Of: odoo/odoo#284755
The QFPay point-of-sale refund flow now waits for the order process to complete before starting a refund, preventing incorrect refund links and related test failures. This helps keep payment refund checks stable and avoids errors in automated validation environments.
Original PR description
Due to the tour not waiting to click next order on the feedback screen, the refund was initiated too early causing the refunded line to not link properly. This resulted in multiple runbot errors depending on the installed modules. This commit fixes both the traceback by adding a conditional access, and the tour logic by adding a `clickNextOrder` step. runbot-939616, runbot-237992 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285887
The web test system now stops immediately when required test dependencies cannot be fetched, instead of waiting until a long timeout. This makes build failures clearer and faster to diagnose, reducing wasted CI time and improving reliability for development teams.
Original PR description
Before this commit, a unit test suite could go silent between two test files, and `browser_js` then waited out its whole timeout before failing with: [ERROR] TypeError: Failed to fetch at orm…
Before this commit, a unit test suite could go silent between two test files, and `browser_js` then waited out its whole timeout before failing with:
[ERROR] TypeError: Failed to fetch
at orm (web.assets_unit_tests.min.js)
FAIL: WebSuite.test_unit_desktop
AssertionError: Script timeout exceeded
This happens because `fetchDependencies` gives every addon a `Deferred` that only the success handler of the batched `all_dependencies` call resolves, and a loaded runbot host answers that call with `RuntimeError: can't start new thread`. Nothing then settles those deferreds, so the `Promise.all` waiting on them never returns, `stop()` is never called, and the browser holds the build until the timeout.
This commit rejects the deferreds of a failed batch and reports an error escaping `runTests` on the console, so the build fails on the fetch error instead of running out its timeout.
https://runbot.odoo.com/odoo/error/243504
Forward-Port-Of: odoo/odoo#285834
Forward-Port-Of: odoo/odoo#284980This fix prevents installation errors when the Ecuador electronic invoicing module is installed without optional automatic dependencies. It also keeps withholding pages displaying correctly by hiding an irrelevant paid badge only when that badge is present.
Original PR description
When installing l10n_ec_edi with --skip-auto-install we receive an error on Runbot. Anchored on the sidebar title (always present on account.portal_invoice_page) rather than div[name='invoice_paid_badge'], which only exists when account_payment (not a dependency of this module) is installed and inherits this view to add it. Hides the account_payment "Paid" badge, if present, without requiring it to exist. runbot-237864 Forward-Port-Of: odoo/enterprise#129291 Forward-Port-Of: odoo/enterprise#126918
The self-order kiosk confirmation page now correctly shows the company logo after an order is placed. This improves brand visibility and makes the final order confirmation screen look complete and professional for customers.
Original PR description
Steps to reproduce: -- - Open the kiosk. - Place an order and go to the confirmation page. Issue: -- - The company logo is not displayed on the confirmation page. Fix: -- - Use the logo content to correctly set the company logo image source. task-6511327 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The point of sale invoice search test now waits for order syncing to finish before closing the session. This reduces occasional automated test failures and helps keep development validation more reliable without changing customer-facing behavior.
Original PR description
In the tour `TestUi.test_order_invoice_search`, the POS was closed without waiting for the order syncing to finish, causing an occasional failure. This commit fixes the issue by explicitly waiting for orders to sync before closing the POS. runbot-946625 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes how a stock-related field is defined so Odoo can create its supporting database table consistently. It helps prevent upgrade failures for customers whose databases already contain a table with the conflicting name.
Original PR description
The `move_line_ids` field has been a computed Many2many field since its introduction. Starting from V19.0, it was changed to a regular Many2many field…
The `move_line_ids` field has been a computed Many2many field since its introduction. Starting from V19.0, it was changed to a regular Many2many field [Here](https://github.com/odoo/odoo/pull/171743).
The current field definition incorrectly passes the second positional argument as the [relation](https://github.com/odoo/odoo/blob/19.0/odoo/orm/fields_relational.py#L1255) table name. Since the relation name starts with an uppercase character, as the table store as "Products" In addition, the relation table is mistkanley defined (not sure) instead of letting the ORM generate the relation table.
Update the field definition to use the correct field parameters and let the ORM handle the relation table creation.
Issue:
- The standard convention for automatically generated Many2many relation tables is to use a `_rel` suffix.
- Some databases already have a custom relation table with the same table name Products as the one explicitly defined by this field. When upgrading such databases, the ORM attempts to create the conflicting relation table, which can cause the migration to fail.
This change avoids the conflict and makes the field definition consistent with the expected ORM behavior.
current behaviour
```
labo_19_2=# \d "Products"
Table "public.Products"
Column | Type | Collation | Nullable | Default
------------------------------+---------+-----------+----------+---------
stock_package_destination_id | integer | | not null |
stock_move_line_id | integer | | not null |
Indexes:
"Products_pkey" PRIMARY KEY, btree (stock_package_destination_id, stock_move_line_id)
"Products_stock_move_line_id_stock_package_destination_id_idx" btree (stock_move_line_id, stock_package_destination_id)
Foreign-key constraints:
"Products_stock_move_line_id_fkey" FOREIGN KEY (stock_move_line_id) REFERENCES stock_move_line(id) ON DELETE CASCADE
"Products_stock_package_destination_id_fkey" FOREIGN KEY (stock_package_destination_id) REFERENCES stock_package_destination(id) ON DELETE CASCADE
```
After fix
```
labo_19_2=# \d stock_move_line_stock_package_destination_rel
Table "public.stock_move_line_stock_package_destination_rel"
Column | Type | Collation | Nullable | Default
------------------------------+---------+-----------+----------+---------
stock_package_destination_id | integer | | not null |
stock_move_line_id | integer | | not null |
Indexes:
"stock_move_line_stock_package_destination_rel_pkey" PRIMARY KEY, btree (stock_package_destination_id, stock_move_line_id)
"stock_move_line_stock_package_stock_move_line_id_stock_pack_idx" btree (stock_move_line_id, stock_package_destination_id)
Foreign-key constraints:
"stock_move_line_stock_package_destinati_stock_move_line_id_fkey" FOREIGN KEY (stock_move_line_id) REFERENCES stock_move_line(id) ON DELETE CASCADE
"stock_move_line_stock_package_stock_package_destination_id_fkey" FOREIGN KEY (stock_package_destination_id) REFERENCES stock_package_destination(id) ON DELETE CASCADE
```
Ticket: 6485470
Upgrade pr :-https://github.com/odoo/upgrade/pull/11189
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-prThis fix updates spreadsheet and dashboard interface elements to match the newer Frost visual style. It also corrects a search bar display issue so the bar keeps a properly rounded end when no search menu is available, improving visual consistency for users creating spreadsheets from Documents.
Original PR description
- removed the rounded borders of the spreadsheet component - adapted the icons to the `<div class="o-icon><i class="oi"/></div>` structure to match o-spreadsheet expected rules Task-6511787 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
Odoo now treats common placeholder VAT values such as '/', 'NA', and 'na' as missing VAT numbers instead of valid entries. This improves accuracy in accounting, e-invoicing, and localization workflows, while also optimizing VAT lookup performance for large databases.
Original PR description
Before this commit- we used to check only if the vat has a value or not. But in odoo we also use `/`, `NA`, `na` as False values for the vat After this commit- We add a compute field `has_vat`, to check if the vat has any default falsy value or not Related PR- https://github.com/odoo/enterprise/pull/111396 task-5935566 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Odoo now treats common placeholder VAT entries such as '/', 'NA', and 'na' as missing VAT values, rather than accepting them as valid. This helps reports, tax filings, payroll, and electronic document flows make more accurate decisions when customer or company VAT information is incomplete.
Original PR description
Before this commit- we used to check only if the vat has a value or not. But in odoo we also use `/`, `NA`, `na` as False values for the vat After this commit- We add a compute field `has_vat`, to check if the vat has any default falsy value or not related PR- https://github.com/odoo/odoo/pull/248132/ task-5935566
Users can now generate lot or serial numbers from the Barcode app on receipts without the screen failing. This restores the expected workflow for receiving tracked products and prevents an error that blocked warehouse operations.
Original PR description
Issue: ------------------------------------------ Clicking the `+` button on a receipt in Barcode for a lot/serial tracked product gives traceback instead of opening the lot/serial generation dialog.…
Issue: ------------------------------------------ Clicking the `+` button on a receipt in Barcode for a lot/serial tracked product gives traceback instead of opening the lot/serial generation dialog. Steps to reproduce: ------------------------------------------ 1. Install `stock_barcode`. 2. Create product P1 with serial tracking. 3. Create receipt for P1. 4. Go to barcode and click on `+` button to generate serial number. 5. Traceback: `Cannot read properties of undefined (reading 'getRecord')` Cause of the issue: ------------------------------------------ `LineComponent.openDialog()` was trying to access `this.cache.getRecord(...)`, but `LineComponent` does not define a cache property. This issue was introduced by PR https://github.com/odoo/enterprise/pull/129521, which fixed a similar traceback when generating serial/lot numbers from Barcode for manufacturing orders. Solution: ------------------------------------------ Use `this.env.model.cache.getRecord(...)` when resolving the move before opening the dialog. This avoids the undefined access and allows the serial/lot generation dialog to open normally.
Spreadsheet dialogs and selectors now display with more consistent rounded borders, cleaner search bars, and top navigation styling aligned with the rest of the interface. This fixes visual layout issues after recent design updates, making spreadsheet creation and selection feel more polished and easier to use.
Original PR description
- merge the topbar menu style with the navbar - fix spreadsheet dialogs searchbars - align spreadsheet selector design with kanban standards (rounded borders) Task-6511787
Fixed an accounting issue where bank reconciliation could hide a vendor bill reference when exchange rate differences were involved. This helps users verify reconciled foreign-currency payments more clearly and reduces confusion during review.
Original PR description
In the bank reconciliation widget, a reconciled transaction matched with a bill and a loss exchange entry no longer displays the bill reference next to the reconciled line. Steps to reproduce: - Have…
In the bank reconciliation widget, a reconciled transaction matched with a bill and a loss exchange entry no longer displays the bill reference next to the reconciled line. Steps to reproduce: - Have company currency USD and foreign currency EUR - Create a vendor bill in foreign currency (100 EUR, rate 1 USD = 1 EUR) - Create a bank transaction in the foreign currency for less than the bill total, at a rate making the amount higher in company currency (90 EUR, 108 USD at 1 EUR = 1.2 USD) - Open the bank reconciliation widget, reconcile transaction and bill - Unfold the reconciled transaction Issue: A bill reference is missing Analysis: The exchange difference line is reconciled with the transaction line. Being reconciled with two lines (bill and exch), the widget relies on `*_reconciled_lines_excluding_exchange_diff` to show the fields. However, `count_reconciled_lines_excluding_exchange_diff` has been defined as boolean instead of int, faulting the comparison. opw-6479015 Forward-Port-Of: odoo/odoo#283855
The Point of Sale variant popup now shows the truly available free quantity, excluding stock already reserved by confirmed sales orders. This prevents staff from seeing misleading stock levels when choosing product variants, reducing overselling risk and inventory confusion.
Original PR description
## Steps to reproduce: - Create another warehouse - Create a product with a variant, like Color, values black and white - Track the product, add a qty on hand of 50 on the black product - Go to the…
## Steps to reproduce: - Create another warehouse - Create a product with a variant, like Color, values black and white - Track the product, add a qty on hand of 50 on the black product - Go to the sales app, make a quotation of 50 for the black product - Confirm the quotation - Go to the PoS, click on the product, check the available qty in the popup - It is still 50, even though the forecasted is correct at 0 ## Why the fix: Having the actual free qty was added in this commit 682bc82 to be able to check the qty that was really free instead of the available qty. This means that we subtract the reserved_qty from the qty_available to get the free_qty. The variant popup was forgotten in this commit, so it was still displaying the qty_available. This is why there was a difference in the qty if we press the product normally or if we long press it, because the variant popup was forgotten in said commit. opw-6382845 Forward-Port-Of: odoo/odoo#284321 Forward-Port-Of: odoo/odoo#280330
Uploading a product image now refreshes the preview right away instead of continuing to show the previous image until the record is saved. This helps users confirm they selected the correct image without an extra save step.
Original PR description
Bug === 1. Open the product form view 2. Upload an image -> You need to save to see the preview of the new image Technical ========= Before 23a7d8cc5b1d2f38eaee35a4f6729fe128c1b62b, it used `this.props.record.data[this.props.name]` in `getUrl` (so `image_1920`) and not `this.props.record.data[<preview_image>]` (`image_128`). When we upload a new image, we write on `image_1920`, but `image_128.content` is missing, and so it fallback to the old image. Task-6509975
Fixed monthly salaries in Belgian payroll are now prorated using the employee's expected hours for the full pay period, rather than a single week's hours. This prevents incorrect deductions and ensures employees are paid accurately when they work more or less than half of the period.
Original PR description
### Problem - Fixed salary payslips were not being prorated correctly. The 50% rule threshold was compared against `hours_per_week` (single week) instead of 50% of the theoretical hours for the…
### Problem
- Fixed salary payslips were not being prorated correctly. The 50% rule threshold was compared against
`hours_per_week` (single week) instead of 50% of the theoretical hours for the payslip period.
This led to incorrect salary deductions in all cases and the wrong computation path being taken when less than
50% of the month was worked.
### Solution
- Fix `_l10n_be_has_enough_paid_hours` to compare paid hours against
50% of theoretical hours instead of `hours_per_week` (which are calculated for the employee's `working schedule`)
### How it works
- For fixed salary (`wage_type = 'monthly'`), the quarterly hourly rule
is applied as follows:
- **Hourly rate** = `fixed_salary × 3 / 13 / theoretical_hours`
- **50% rule**:
- If more than 50% of theoretical hours were worked → deduct absences
from fixed wage
- If less than 50% of theoretical hours were worked → pay only the
hours worked
For variable salary (`wage_type = 'hourly'`), the employee is simply
paid for the number of hours worked during the period.
Task-6260378
Forward-Port-Of: odoo/enterprise#126600This change corrects an internal reference used when uninstalling the fleet stock integration. It prevents a build or uninstall error caused by an outdated module name, helping keep system maintenance reliable.
Original PR description
A reference to the `stock_picking_batch_action` was not updated in [^1] and still referred to `stock_picking_batch` instead of `stock`. runbot-build-error: [946649](https://runbot.odoo.com/odoo/runbot.build.error/946649) [^1]: https://github.com/odoo/enterprise/pull/128175
The data cleaning tool now correctly recognizes the database index details it relies on when checking linked records. This prevents missed references during merge or cleanup operations after a related platform change.
Original PR description
`ir.model.fields.index` now stores the exact index type instead of a boolean. Match B-tree index types when looking for indexed references. task-6507120 Related: https://github.com/odoo/odoo/pull/284668
The Point of Sale dashboard now keeps sales graphs aligned at the bottom of each card, even when cards show different amounts of information. This makes the dashboard easier to scan and gives users a cleaner, more consistent view.
Original PR description
In the POS config dashboard kanban view, cards could display a variable number of data lines (e.g. session dates, opening, sold, ongoing amounts, or closing date). Because the graph was placed right below the text content without vertical pushing, graphs across cards in the same row ended up vertically misaligned. Fix this by adding `d-flex flex-column` to the card template and `mt-auto` to the graph container wrapper so that graphs are always pushed to the bottom of the card, ensuring consistent alignment regardless of the number of displayed lines. task-id: 6424698 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279040
The HTML editor now correctly removes formatting, such as underline, from headings inside list items. It also prevents formatting applied to a parent list item from unintentionally affecting nested list items, making document editing more predictable for users.
Original PR description
**Current behavior before PR:**
1. Create a list with h1, have some text inside.
2. Select whole heading and apply underline style.
3. Click on remove format button.
You will notice that underline style is not removed from list.
**Desired behavior after PR is merged:**
Now, format is removed correctly from the list.
task-6348753
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273678Asset disposals with no depreciation no longer create unnecessary zero-value accounting lines. This keeps accounting entries cleaner and improves the accuracy of depreciation values by calculating them directly instead of relying on line order.
Original PR description
Purpose: When we try to dispose of an asset with 0 depreciation, we get a move line with 0 balance, this line is supposed to debit depreciated amount till date on asset depreciation account which in our case is 0. And line with 0 balance seems like a noise in accounting. Fix:- - When creating disposal move, create lines with either +ve or -ve balance and skip lines with 0 balance. - Computation of `depreciation_value` on `account.move` assumed that `move.line_ids[1]` will be always depreciated amount. Which is guess work and break if at that index there is some other line. So instead of guessing calculate here depreciation amount with the same logic as disposal move.
The shared time selection control has been moved into the main HR module so it is available even when Time Off is not installed. This prevents warning messages in HR Attendance tests and improves reliability across HR applications.
Original PR description
Using widget="float_time_selection" in hr_attendance triggered a missing widget warning during view tests when hr_holidays was not installed, as the widget was defined in hr_holidays. This move the float_time_selection component to the hr module so the widget is available across all HR applications. Task-6523568 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes automated tests for the HTML editor so they no longer depend on visual design settings that can vary between editions or themes. It helps keep quality checks stable while preserving the intended color contrast behavior for users.
Original PR description
The ContrastPlugin adjusts the colors of the content against the background the editable is drawn on, which it reads from a CSS variable whose value is a design decision: it differs between community and enterprise, as well as between light and dark mode. The tests asserting the exact adjusted colors pin that variable so as not to assert on the design of the assets they happen to run with, but they were still pinning its former name, which the follow-up below renamed to `--o-html-editor-background-contrast`. Pin the current name, on the white background the expected colors were computed against. This is the follow-up of: https://github.com/odoo/odoo/pull/285000 https://github.com/odoo/odoo/pull/285285 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
Rental product pages now show the original price before a discount more reliably. This helps shoppers better understand savings when rental pricing uses multiple rules across the rental period.
Original PR description
As multiple rules can be applied for rental products, the default computaion of the product price before discount is not computed correctly. This commit overrides `_get_price_before_discount` for rental products to fetch the product's price without pricelist. task-6279525 See also: - https://github.com/odoo/odoo/pull/276566
A Point of Sale automated test was corrected so it no longer tries to install the Restaurant feature unnecessarily. This prevents avoidable test failures and helps keep development validation reliable without changing customer-facing behavior.
Original PR description
`TestPosOrderReceipt.test_split_per_product_preserves_combo_children`: This test sets `module_pos_restaurant` to `True`, which causes the `pos_restaurant` module to start installing, leading to this error: ``` RuntimeError: Module operations inside tests are not transactional and thus forbidden. If you really need to perform module operations to test a specific behavior, it is best to write it as a standalone script, and ask the runbot/metastorm team for help. ``` The test does not in fact rely on any `pos_restaurant` behaviour, so the line can simply be removed. runbot-946164 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Responses to invoices received through France's PDP are now sent through only the PDP channel instead of both PDP and classic Peppol. This avoids duplicate messages and keeps invoice communication threads cleaner for users.
Original PR description
When responding to an invoice received through PDP, 2 responses were actually sent: one through PDP and the other through the 'classic' Peppol. This was done to allow more reliability, in case one channel is down when trying to respond, but this mainly creates cluttah' in the chattah' (call me busta rhymes yo) task-6522652 Forward-Port-Of: odoo/odoo#285596
Fixed an issue where reprinting a preparation receipt from the preparation display could fail with an error. This ensures staff can reliably reprint kitchen or preparation receipts when needed, avoiding interruptions during service.
Original PR description
Reprinting a preparation receipt from the preparation display was showing a traceback because the preparation template wasn't correctly loaded. task-6522158
The website now sends a visitor's saved cookie consent choice to Google before loading analytics settings on each page. This prevents tracking gaps between page views while continuing to respect visitors who declined cookies.
Original PR description
With Google Consent Mode V2, we have to set a default consent state, then update it according to the user's choice. While our setup worked fine with new users interacting with the cookies bar, on subsequent pages it would update the consents after pinging Google first. This meant that, from Google's point of view, there was a gap for a single user when switching pages. By updating it before setting the config, we make sure that Google handles the analytics as expected, without any hole, while keeping it safe for users who refuse the cookies. task-6471290
This fix prevents slow mobile-style taps in Odoo's web test tools from being incorrectly treated as long presses. It reduces random test failures, helping teams get more dependable build results and avoid false alarms during quality checks.
Original PR description
Before this commit, MobileWebSuite.test_unit_mobile failed at random on the mail test "HtmlMail add icon and save inline html", which taps the save button of an html_mail field and waits for the…
Before this commit, MobileWebSuite.test_unit_mobile failed at random on the mail test "HtmlMail add icon and save inline html", which taps the save button of an html_mail field and waits for the write:
[verifySteps] expected the following steps
> Expected: [
"web_save",
]
> Received: []
This happens because a tap held longer than `LONG_TAP_DELAY` counts as a long press, and `_pointerUp` then dispatches no click at all. That delay spans the synthetic pointerdown and pointerup of a single `click()`, so the work a listener does during the press counts towards that delay: tapping save blurs the html field, which converts the whole editor content to inline styles, and under the load of a runbot build that conversion alone takes longer than the delay.
One solution could have been to raise `LONG_TAP_DELAY`, but a listener slower than the new value suppresses the click again.
This commit counts a tap as long only when the test releases the pointer itself, with `pointerUp`, so the work a listener does during a `click()` no longer suppresses the click.
https://runbot.odoo.com/odoo/error/946581
Forward-Port-Of: odoo/odoo#285640
Forward-Port-Of: odoo/odoo#284971Users can now click links in read-only website content to open the link popover and inspect where the link goes. This fixes a case where non-editable article links appeared inactive, improving clarity without changing the content itself.
Original PR description
Problem: Clicking a non-editable link does nothing, making it impossible to open or inspect the link. Solution: Allow the link popover to open in read-only mode for non-editable links. Steps to reproduce: - Run `/article`. - Click on the inserted article link. - Observe that nothing happens. opw-6442026 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285445 Forward-Port-Of: odoo/odoo#280224
This fix prevents the HTML editor from accidentally deleting visible items that do not contain text, such as icons or images. It helps ensure saved website or document content keeps its intended visual elements.
Original PR description
#### Description of the issue this PR addresses: - Empty inline elements were detected using only their text content, causing visible non-text content (e.g. icons, images) to be removed. #### Desired behavior after PR is merged: - Remove the empty inline attribute when an inline element contains visible content by using `isVisible`. - Use `isVisible` to detect visible content instead of relying on text content. task-6391496 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276587
Belgian payroll test demo employee records have been cleaned up so they no longer create unnecessary empty versions. Employee identifiers, schedules, tags, wages, and worker codes now align with the stated demo records, making payroll test data more reliable.
Original PR description
Every employee record was also creating an empty version dated 2023-01-01, because hr.employee delegates to hr.version. Employees now carry their own first version, so those extra ones are gone. Fields the ORM was throwing away are removed, the NISS numbers are rebuilt from each birthday and sex, and the schedules, tags, wages and worker codes now match what the records claim. task-6519088
This fix prevents an error when users close the email composer after selecting more than 500 CRM leads. The composer now uses the selected records from the context when the usual stored list is intentionally unavailable, avoiding a disruptive crash during bulk email workflows.
Original PR description
Steps to reproduce: 1. Install `crm` 2. Create leads more than 500. 3. Select all and try to send email 4. Not close the wizard by "X" Issue: - Traceback occurs: `Uncaught Promise > Unexpected end of JSON input` Cause: - res_ids is not set on the composer when more than 500 records are selected. This is expected, as the compute method `_compute_res_ids()` does not write `res_ids` when the number of `active_ids` exceeds 500 (to avoid storing large payloads on the field). Because of this, the code trying to JSON.parse(res_ids) fails while dismissing the wizard at `onCloseWizardModal` Solution: - Fallback to context.active_ids when res_ids is not available opw-5891862 Forward-Port-Of: odoo/odoo#252670 Forward-Port-Of: odoo/odoo#248406
Audio messages in VoIP forms now open without crashing after a recent platform change to how files are stored. This keeps users able to access and update recorded audio content normally.
Original PR description
Since odoo/odoo#266082, binary fields use an object containing their content, filename and size. The `isBinarySize` helper was also removed.
The VoIP audio binary field still imported this helper and treated binary values as raw base64 strings. Opening an audio message form therefore crashed with:
TypeError: isBinarySize is not a function
Use the new binary value structure when reading and updating audio content.Users will now see a newly selected image right away when editing image fields with previews. This removes confusion where the old image stayed visible until the record was saved.
Original PR description
**Description of the issue/feature this PR addresses:** The uploaded image is not displayed immediately when using the `preview_image` option. **Current behavior before this PR:** The widget checks the preview field (e.g. `image_128`), which remains stale until the record is saved. As a result, the newly uploaded image is only displayed after saving. **Desired behavior after this PR is merged:** The widget checks the edited field itself instead of the preview field, allowing the newly uploaded image to be displayed immediately. **Related PR**: https://github.com/odoo/odoo/pull/266082
This fixes an issue where search filters and groupings could stop appearing correctly in the search menu after users switched views, even though the choices were still applied. The search interface now keeps its state properly updated, making filtering behavior clearer and more reliable.
Original PR description
Importing a state, as done when switching view, replaced the search model's query and searchItems by the raw values read from that state, dropping the reactivity of both containers. The search bar menu, whose content is rendered in a popover that the parent's render does not reach, then stopped reflecting the filters and group bys toggled in it, even though they were still applied. The fix populates the existing containers in place to preserve reactivity. task-6524460
The search bar filter labels now display their icons at a consistent height and with cleaner rounded styling. This small visual fix makes the interface look more polished and easier to scan without changing functionality.
Original PR description
Before this commit, the facet label never centered its children, so each icon compensated on its own (`align-middle`, `align-content-around`, `ms-1 mt-1`) and the three landed at different heights. The swap_vert overlay also had no radius, drawing a square over the rounded label. This commit centers each icon from its own container and rounds the swap_vert overlay. It also drops the pencil overlay's transparent border and `pe-2`, which only pushed it down and off-center, and an unreachable `!facet.icon` branch on the swap_vert span. requires: https://github.com/odoo/enterprise/pull/129724 task-6518046 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix stops Point of Sale restaurant orders from accidentally deleting order lines when the same order is handled across multiple devices. It helps ensure paid orders keep the correct items, totals, and audit trail after device synchronization.
Original PR description
Steps to reproduce: - Restaurant config with two POS devices on the same session - Device A: open a table, add two products, press Order (the order is synced as a draft, its lines get server ids) -…
Steps to reproduce:
- Restaurant config with two POS devices on the same session
- Device A: open a table, add two products, press Order (the order is synced as a draft, its lines get server ids)
- Device A: remove both lines, without syncing
- Device B: touch the same order, so device A re-reads it from the server through the synchronisation websocket
- Device A: pay and validate the order
Issue:
The order is saved as paid, with its total and its payment, but without any orderline. The lines are deleted on the server: odoo.models.unlink: deleted pos.order.line records with IDs: [...]
Cause:
Removing an orderline queues an unlink command in
models.commands['pos.order'].unlink['lines_<order id>'] (delete_ in related_models.js). That command is only discarded by clearCommands(), which syncAllOrders() calls after a successful sync, so it stays pending in between.
Any read of the order in that window puts the line back: a deleted record counts as missing in missingRecursive(), so it is fetched again and loadData() re-creates it with its server id.
serialize() then emits both the update of the live line and the still pending unlink, and sync_from_ui writes
lines: [[1, id, {...}], [3, id]]. The ORM applies commands in order, and pos.order.line.order_id is ondelete='cascade', so Command.UNLINK deletes the line right after writing it.
Fix:
Skip a removal command when the record is still linked to the parent at serialization time. A record cannot be both linked and removed in the same payload, so the pending command is stale and dropping it keeps the local state. Genuine removals, where the record is no longer linked, are still sent.
opw-6401146
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#285427
Forward-Port-Of: odoo/odoo#284695The Indian localization now hides the generic Self Billing option in journal settings. This prevents users from enabling conflicting invoicing options and helps keep the Indian Self Invoice process compliant with GST requirements.
Original PR description
With this commit:- The generic Self Billing option is hidden from the journal configuration for Indian localization, preventing users from enabling both Self Invoice and Self Billing, and ensuring the Indian Self Invoice flow and output remain compliant with the GST requirements. Related [Self Invoice PR](https://github.com/odoo/odoo/pull/269434) task-6505237
This fixes an automated mail test so messages containing emoji shortcuts are posted reliably. The change prevents the emoji suggestion popup from blocking the test action, reducing false failures in quality checks without changing user-facing behavior.
Original PR description
Before this commit, "[text composer] Posting message should transform relevant data to emoji." posted no message on runbot:
Failed to find 1 of ".o-mail-Message-body:text('test ...')"
(Timeout of 10 seconds). Found 0 instead.
This happens because "test :P :laughing:" leaves the emoji suggestion of the shortcode it just typed pending, and Composer.onKeydown returns without posting when the NavigableList takes the Enter. The fetch behind that suggestion is debounced by 250ms, so the test posts only while the debounce has not fired.
This comes from "[IMP] web,*: emoji loader": the search reads the emoji data the mail test helpers preload, so the list has an entry to offer where it had none.
This commit types a trailing space, which closes the suggestion and leaves the Enter to post.
https://runbot.odoo.com/odoo/error/946650
Forward-Port-Of: odoo/odoo#285616Event agenda pages with many items now scroll horizontally more smoothly in Firefox and Safari. This reduces shaking or stuttering when visitors browse busy event schedules, improving the attendee browsing experience.
Original PR description
On Firefox and Safari, horizontal scrolling on an agenda with many items stuttered. This was likely caused by triggering too many scroll events, without throttling them. Steps to reproduce: - On Firefox or Safari, run with demo data - Go to the "Design Fair Los Angeles" agenda (click on the event > Talks > Agenda. Alternatively, enter the URL directly: `/event/ID/agenda`, with the right event ID) - Resize the page (or open the dev tools) so that there is a horizontal scrollbar. - Scroll horizontally with a trackpad or with shift + mouse wheel. => The agenda stutters/shakes: as you go to the right, it sometimes slightly goes back left, and vice-versa. You might have to scroll from left to right and right to left a few times to see the issue. Forward-Port-Of: odoo/odoo#285237
This fixes an inventory issue where selecting a contact on a delivery transfer could incorrectly reset the destination from a custom customer stock location back to the generic Customers location. Businesses using tailored delivery operation types can now rely on their configured destination locations staying in place, reducing manual corrections and shipment errors.
Original PR description
### Steps to reproduce: - In the settings: Enable Storage Locations - Create a customer location "Customer stock" with "Customers" as its parent location - Create a delivery operation type "Deliver…
### Steps to reproduce: - In the settings: Enable Storage Locations - Create a customer location "Customer stock" with "Customers" as its parent location - Create a delivery operation type "Deliver Super Customer" and set its default destination location to "Customer stock" - Go to Inventory > Overview > Deliver Super Customer > New - Set a contact on the transfer #### > The destination location switches from "Customer stock" to "Customers" ### Cause of the issue: The `location_dest_id` of `stock.picking` depends on its `partner_id`. So that changing the partner recomputes the locations of the transfer. However, as soon as the destination of the operation type has a `customer` usage, the `property_stock_customer` of the contact replaces it unconditionally: https://github.com/odoo/odoo/blob/04f3a7bca99d0144a4ea871be9625db368b196ca/addons/stock/models/stock_picking.py#L949-L963 However, the `property_stock_customer` falls back to an `ir.default` pointing at the default `Customers` location when nothing is set on the contact: https://github.com/odoo/odoo/blob/1c40fab04b71def8f3645c4c4bb0c1441057f307/addons/stock/data/stock_data.xml#L71-L72vs The override comes from 8a0775aa1dd9, which replaced an `elif` fallback on the contact by an "unconditional" substitution as this fallback had become unreachable once `default_location_src_id` and `default_location_dest_id` were made required: https://github.com/odoo/odoo/blob/04f3a7bca99d0144a4ea871be9625db368b196ca/addons/stock/models/stock_picking.py#L34-L41 opw-6421090 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284873 Forward-Port-Of: odoo/odoo#280016
Customers who place self-order takeout or delivery orders now receive an email that actually provides access to their receipt. This fixes a mismatch where the email promised a receipt but did not include one, reducing confusion and support follow-up.
Original PR description
Currently, when takeout and delivery mails are sent out to clients the mention "Attached you will find you receipt" can be seen but no receipt is sent. Steps to reproduce: ------------------- * Modify restaurent config * Enable QR + self ordering * Add Online payment method * Open the self order * Make an order for delivery or takout * Pay the order * Check the emails sent > No attachment provided Why the fix: ------------ Since this commit https://github.com/odoo/odoo/commit/a0b567508ffeb572a3c36bf28ae085d766d95f18 we now send the email only from the backend but the receipt couldn't be rendered from the backend at that time. In this version it is now possible so we cans attach the receipts with the mail. opw-6197985 Forward-Port-Of: odoo/odoo#285241 Forward-Port-Of: odoo/odoo#266007
Polish e-invoices now correctly treat K_12 taxes, such as 0% EU U, as reverse charge transactions. This helps ensure KSeF XML submissions contain the right reverse charge indicator and tax base, reducing compliance and reporting errors.
Original PR description
**PROBLEM** K_12 taxes needs to be reported as reverse charge tax. **STEP TO REPRODUCE** 1. Create an invoice with the tax 0% EU U. 2. Send the invoice the ksef. 3. Open the xml, an notice P_18 value is 2 (meaning no reverse charge), and there is no tag P_13_10. expected behavior: P_18 = 1, P_13_10 = base for the tax. opw-6460338 Forward-Port-Of: odoo/odoo#281934
This fix gives localizations the option to refuse future confirmed leave requests instead of deleting them when an employee departure is recorded. It preserves relevant leave history where required while keeping the standard behavior unchanged for other localizations.
Original PR description
Before: * Future leaves were deleted when an employee departure was applied. * There was no way for localizations to preserve these leaves when they should remain in the employee's history. After: * Add `refuse_future_leaves` to `_cleanup_employee_departure_leaves()`. * Approved leaves are still cancelled when they extend beyond the departure date. * Future confirmed leaves can now be refused instead of deleted when requested by a localization. * Keep the existing deletion behavior by default for other localizations. Impact: * Allows localizations to preserve future leave records while keeping the existing generic departure behavior unchanged. Task: 6453718 Forward-Port-Of: odoo/odoo#284398 Forward-Port-Of: odoo/odoo#281493
This fixes resizing issues in the HTML editor when tables or columns are nested inside each other. Users can now resize or reset table columns without inner content overflowing or blocking further adjustments, making page editing more reliable.
Original PR description
### Steps to reproduce **Issue 1:** * Create a table inside another table (e.g. `/table`). * Resize the last cell of the inner table beyond the outer `td` boundary. * Then try to resize the outer…
### Steps to reproduce **Issue 1:** * Create a table inside another table (e.g. `/table`). * Resize the last cell of the inner table beyond the outer `td` boundary. * Then try to resize the outer table `td` containing the inner table. * The outer table `td` can no longer be resized. **Issue 2:** - Create a table in the editor - Inside any cell, create a nested table - Resize the nested table by dragging its last column to the left to give it a fixed width - Resize the outer column that contains the nested table to the left - Observe that the nested table overflows its parent cell **Issue 3:** - Create a table in the editor - Inside any cell, create a nested table - Resize the nested table columns to give it a fixed width - Double-click the outer column border to reset its width - Observe that the nested table overflows its parent cell ### Purpose of this PR Prevent resizable elements from growing beyond the bounds of their nearest resizable ancestor. This fixes resize behavior for nested resizable structures such as: * tables inside tables * text columns inside tables * tables inside text columns The resize logic now clamps width expansion once the nearest resizable ancestor boundary is reached. - When resizing an outer table column that contains a fixed-width nested table, the outer column could be shrunk below the nested table's width, causing the nested table to overflow its parent cell. - The fix computes an effective minimum size per column by inspecting any fixed-width nested tables in that column's cells before the resize begins. This effective minimum size is passed through the resize_target_processors resource so ResizePlugin remains generic. - When resetting an outer column width, any fixed-width nested table inside the affected cells is also reset so it adapts naturally to the new outer column width instead of overflowing its parent cell. task-6215674 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264633
Employee transport reimbursement details are now preserved when a company car is assigned. This prevents public transport, private car, and bicycle reimbursement information from being accidentally removed, supporting employees who use multiple commuting options.
Original PR description
When entering transport reimbursement values on an employee record, `_onchange_transport_mode` automatically resets public transport kilometers (bus, tram, metro), private car kilometers, and bicycle settings to zero whenever a company car is assigned. This commit removes the code that wipes alternative transport values when `transport_mode_car` or `car_id` is set, allowing employees to combine a company car with other transport reimbursement modes. task-6514557
Manufacturing bills of materials now prevent configurable combo products from being selected as components. This avoids using sales bundle items where physical manufacturing parts are expected, reducing setup errors in production planning.
Original PR description
Version: --------- - 19.0+ Steps to reproduce: ------------------- - Install `mrp` and `sale_management` - Create a product of type `combo` - Go to Manufacturing > Products > Bills of Materials - Create or edit a BoM - Add a component line - Select the combo product Issue: ------ Combo products can be selected as BoM components. Since combo products represent configurable sales bundles rather than physical products, they are not meaningful manufacturing components. Before Commit: ------------------- - It was possible to select a product of type 'combo' as a component in a Bill of Materials. After Commit: ----------------- - Combo products are filtered out of the component picker and cannot be added as BoM components --- opw-6425024 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278861
The AI assistant now avoids unnecessary follow-up questions in Website Builder and presents choices as valid answers instead of more questions. Users can still type free-text answers by default, see cleaner prompts without selected-count clutter, and receive auto-approval notices right away.
Original PR description
Prevent unnecessary follow-up questions in Website Builder and ensure choices are valid answers rather than questions. Keep free-text answers enabled by default, remove the selected-count display, and post the auto-approval notice immediately.
Belgian payroll now calculates home-work transport tax exemptions from the amounts actually taxed on payslips, rather than estimates from contract fields. This prevents employees from being overtaxed on some transport benefits or receiving unintended double benefits, improving legal compliance and payroll accuracy.
Original PR description
The withholding tax exemption for the employer intervention in home-work transportation costs (500 EUR/year - 41.70 EUR/month for income year 2026) was estimated from contract fields (car_atn,…
The withholding tax exemption for the employer intervention in home-work transportation costs (500 EUR/year - 41.70 EUR/month for income year 2026) was estimated from contract fields (car_atn, private_car_employee_kilometer) instead of the amounts actually taxed on the payslip. As a consequence: - The fuel card for daily commute was fully taxed: the employee never received the exemption they are legally entitled to. - The private car reimbursement was paid net, never added to the taxable base, yet it still granted the exemption on the yearly taxable: a double benefit. - A bike allowance paid above the exempt rate per km (0.37 EUR/km in 2026) was never taxed. The exemption is now computed from a new TRANSPORTATION_BASE salary rule category accumulating the taxable transportation amounts of the month: - ATN.CAR and FUEL_CARD_COMMUTE (already taxed) are tagged with the category. - New hidden rules CAR.PRIV.TAX and CYCLE.TAX fictively add the private car reimbursement and the above-rate bike excess to the withholding base, after ONSS and before the gross totals, while the reimbursements themselves remain paid net. - TRANSPORT_TAX_DED becomes -min(yearly taxable, yearly threshold, 12 x monthly transportation base), including the transport lines of already validated payslips of the same month so that non-periodic (regularisation) payslips preserve the monthly totals. The termination fees variant uses the category without x12, its base being annual. The obsolete helper _get_be_withholding_taxes_transport_deduction is removed, and the affected payslip validation expectations are updated to the corrected amounts. task-6388103 Forward-Port-Of: odoo/enterprise#124644
Belgian employee departures now avoid unintended archiving when no archive date is set, preserve company car assignments, and refuse future leave instead of deleting it. This protects important HR records and reduces accidental loss of employee-related information during offboarding.
Original PR description
Before: * Belgian employees without an "Archive Employee On" date were automatically archived after their departure. * Future leaves were deleted when applying an employee departure. * The employee's company car was automatically unassigned on departure. After: * Belgian employees without an "Archive Employee On" date are no longer automatically archived. * Future leaves are refused instead of deleted. * Company car assignments are kept when applying a Belgian employee departure. * Display "Don't archive" when no archive date is set. Impact: * Prevents unintended archiving and preserves future leave and company car information for Belgian employees. Task: 6453718 Forward-Port-Of: odoo/enterprise#129127 Forward-Port-Of: odoo/enterprise#127414
Secondary badges are now easier to read in both light and dark display modes. This improves clarity for users by ensuring badge labels stand out consistently across the interface.
Original PR description
Before this PR:- ========================== Secondary badges are barely visible in light and dark modes. <img width="500" height="200" alt="image" src="https://github.com/user-attachments/assets/552dd924-4ab4-4fd5-b0fe-b103697a0bb9" /> <img width="500" height="200" alt="image" src="https://github.com/user-attachments/assets/a199ad73-bd94-42dd-aa46-1fc7fb2f9436" /> After this PR:- ========================== Make the badge text and background clearly visible in both modes. <img width="1232" height="672" alt="image" src="https://github.com/user-attachments/assets/cbff2756-f2e4-42fa-97c6-669409fd4efb" /> Enterprise PR:- odoo/enterprise#129792
A mail testing helper now stops retrying after a timeout instead of continuing to report the same failure across later tests. This makes automated test results clearer and helps developers identify the real issue faster without misleading follow-on failures.
Original PR description
Before this commit, one test contains() reaching its 10 seconds budget made the 129 tests that ran after it fail with its own assertion, over 14 suites:
[HOOT] Test "@mail/message/link_preview/Delete all link previews at
once" failed:
Failed assertion:
3. [toBe] expected values to be strictly equal (Failed to find 1 of ".o-mail-Message-body:text(...)" (Timeout of 87 seconds). Found 0 instead.)
This happens because the tick re-schedules itself on the result of runOnce(), which is undefined on a failure, the crashing one included. The check keeps selecting every 500ms and logs its assertion against whichever test is running, until a tick lands between two suites and getFixture() throws.
This commit re-schedules a tick only while the check is not done, so the crashing one is the last.
https://runbot.odoo.com/odoo/error/946650
Forward-Port-Of: odoo/odoo#285585Mexican DIOT reports now show the remaining column headers in Spanish for Latin America instead of mixing Spanish and English. This makes the report easier and more consistent for Spanish-speaking users to read.
Original PR description
## Merge method squash --- ## Problem The DIOT report (`account_report_diot.xml`) uses inline `name@es_419` translations for Spanish (Latin America) column headers. However, the translations were…
## Merge method squash --- ## Problem The DIOT report (`account_report_diot.xml`) uses inline `name@es_419` translations for Spanish (Latin America) column headers. However, the translations were inconsistently applied: columns at 16% had them, while the equivalent 8% columns and several others were left without Spanish translations. **Columns missing `name@es_419` (before this fix):** | `id` | English name | Added es_419 | |---|---|---| | `diot_report_paid_8_n_wnc` | Paid 8 % Northern | Pagado al 8% Norte | | `diot_report_paid_8_n_r` | Refunds 8 % Northern | Devoluciones 8% Norte | | `diot_report_paid_8_s_wnc` | Paid 8 % Southern | Pagado al 8% Sur | | `diot_report_paid_8_s_r` | Refunds 8 % Southern | Devoluciones 8% Sur | | `diot_report_paid_16_r` | Refunds 16% | Devoluciones 16% | | `diot_report_paid_16_imp_r` | Refunds Importation 16% | Devoluciones Importación 16% | | `diot_report_paid_16_imp_int_wnc` | Intangible Imports 16% | Importaciones Intangibles 16% | | `diot_report_paid_16_imp_int_r` | Refunds Intangible Imports 16% | Devoluciones Importaciones Intangibles 16% | | `diot_report_paid_8_n` | Paid 8 % N. - Creditable | Pagado al 8% Norte - Acreditable | | `diot_report_paid_8_s` | Paid 8 % S. - Creditable | Pagado al 8% Sur - Acreditable | | `diot_report_paid_16` | Paid 16% - Creditable | Pagado al 16% - Acreditable | | `diot_report_paid_16_imp` | Importation 16% - Creditable | Importación 16% - Acreditable | | `diot_report_paid_16_imp_int` | Intangible Imports 16% - Creditable | Importaciones Intangibles 16% - Acreditable | | `diot_report_paid_8_n_nc` | Paid 8 % N. - Non-Creditable | Pagado al 8% Norte - No acreditable | | `diot_report_paid_8_s_nc` | Paid 8 % S. - Non-Creditable | Pagado al 8% Sur - No acreditable | | `diot_report_paid_16_imp_nc` | Importation 16% - Non-Creditable | Importación 16% - No acreditable | | `diot_report_paid_16_imp_int_nc` | Intangible Imports 16% - Non-Creditable | Importaciones Intangibles 16% - No acreditable | | `diot_report_exempt_imp` | Exempt Imports | Importaciones Exentas | | `diot_report_no_obj` | No Tax Object | No Objeto de Impuesto | ## Why this matters Mexican Odoo instances run with `es_419` locale. Without these inline translations, column headers in the DIOT report display in English for Mexican accountants, even though the equivalent 16% columns already had Spanish translations. This creates an inconsistent bilingual UI on the same report. ## Fix Adds `<field name="name@es_419">` entries to all column records that were missing them, following the same pattern already used by `diot_report_paid_16_wnc`, `diot_report_paid_16_nc`, `diot_report_withheld`, `diot_report_exempt`, and `diot_report_paid_0`. ## Files changed - `addons/l10n_mx/data/account_report_diot.xml`
Fixed an issue where adding all suggested products from the purchase catalog ignored the vendor-specific unit of measure. Purchase orders now use the correct vendor unit and matching suggested quantity, reducing ordering mistakes and manual corrections.
Original PR description
Issue ----- When adding all of the catalog's suggestions at once, the uom specified on the product's vendor lines is not respected. Steps to reproduce ----- - Create a product - Add a vendor line in…
Issue ----- When adding all of the catalog's suggestions at once, the uom specified on the product's vendor lines is not respected. Steps to reproduce ----- - Create a product - Add a vendor line in a different uom - Create a past outgoing shipment of 100 of the product - Create a PO (same vendor as vendor line) - Open the Catalog - Click "Add All" in the suggestion section on the left - Go back to the PO > The product is in units instead of the different uom Cause ----- Clicking the button calls `action_purchase_order_suggest` in Python directly https://github.com/odoo/odoo/blob/3aec1c317aad547b1ad0c85a21cc53f735c5cbfd/addons/purchase_stock/models/purchase_order.py#L131-L134 whereas clicking on a product will go through `addProduct` in JS https://github.com/odoo/odoo/blob/3aec1c317aad547b1ad0c85a21cc53f735c5cbfd/addons/purchase_stock/static/src/product_catalog/record/kanban_record.js#L20-L28 Which leads to `_update_order_line_info` where the purchase line is created https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/purchase/models/purchase_order.py#L1322-L1328 The uom is then retrieved in the create call through `_suggest_quantity` https://github.com/odoo/odoo/blob/f59783d43f891fea14d03f67d7c017d7ffbbe5a7/addons/purchase/models/purchase_order_line.py#L547-L549 Other issue ----- The quantity of the product also doesn't match the suggestion since the product `suggested_qty` is in the product's uom and not the vendor ones. ----- Ticket: opw-6417665 Forward-Port-Of: odoo/odoo#284841 Forward-Port-Of: odoo/odoo#280934
Website popups are now fully hidden before a page is saved, preventing popup display settings from being saved incorrectly. This makes page editing more reliable when popups are present.
Original PR description
The method `hide` of Bootstrap's `Modal` internally calls `_hideModal` asynchronously. When saving the page, the builder must hide the popups of the page. Calling `hide` does not work well, as the changes done in `_hideModal` are done after the ave is finished. This commit replaces the call to `hide` in the "clean for save" implementation of popup visibility plugin with the internals of `hide` that inpact the content of the saved element (without the delay): - removing the class `show` - calling `_hideModal`
This change ensures that when a business sets Monday as the first day of the week, reports and scheduling calculations consistently group all seven days into the correct week. It prevents weekly hours or limits from being split incorrectly in locales that normally start the week on Sunday.
Original PR description
**Description of the issue/feature this PR addresses:** `weeknumber` takes a `first_week_day` override, documented as `(0 = Monday, ..., 6 = Sunday). If None, derived from the locale.`, but tests it…
**Description of the issue/feature this PR addresses:** `weeknumber` takes a `first_week_day` override, documented as `(0 = Monday, ..., 6 = Sunday). If None, derived from the locale.`, but tests it with `if not first_week_day`, so Monday (`0`) is discarded and the locale's own day is used. `resource` passes `int(get_lang(self.env).week_start) - 1`, which is exactly `0` for Monday, at three call sites. #259600 added the parameter for the opposite case, a Monday locale with a Sunday-start user, and that direction works; this one never has. **Current behavior before PR:** With `en_US` (first day Sunday) and week start set to Monday, `resource_resource.py:299` builds `week_start_date` from Monday while `:303` buckets by Sunday. Monday 2026-08-24 to Sunday 2026-08-30 comes back as W35 for six days and W36 for the Sunday, so one week's hours are split across two buckets and the `hours_per_week` cap lands on the wrong days. **Desired behavior after PR is merged:** The override is honoured and those seven days are all W35. I checked this with a partition property: every day of a `first_week_day`-aligned week must share one `(year, week)`. Over 9 locales x 7 values of `first_week_day` x 12 years, 275940 combinations, 5 locales failed and every failure was in the `first_week_day=0` bucket. After the change there are none. I also diffed every output before and after, 315360 combinations of locale, `first_week_day` and date: 4460 rows change, all of them `first_week_day=0` on a non-Monday locale. `None` and values 1 to 6 are byte identical, so the change is contained to the broken case. Targeting 19.0 because that is the oldest branch carrying the parameter; 17.0 and 18.0 do not have it. AI-assisted: I used Claude to sweep the parameter space and write the tests. Forward-Port-Of: odoo/odoo#285706 Forward-Port-Of: odoo/odoo#285508
This fixes a pricing display issue where product variants could show fewer decimal places than the main product price in reports. Businesses using reports or Studio fields will now see consistent price formatting that respects the configured minimum precision.
Original PR description
Issue: --- Record's `min_display_digits` is not inherited in case of a model inheritance. e.g. `list_price` is inherited to `product.product` from `product.template`, however it renders with fewer decimals than `product.template.list_price` in reports. Steps to reproduce: 1- Set a product's Sales Price to 19.5. 2- Add `product.product.list_price` to a report using studio. The variant's field renders with 1 decimal while `decimal.precision` is 2. Cause: --- This is missed in ee32a17495a10af18f0b5de0a295283c5059d3c2 which introduces minimum precision. opw-6465159 Forward-Port-Of: odoo/odoo#285336 Forward-Port-Of: odoo/odoo#285064
Gantt charts using a weekly view now place tasks in the correct week based on the user's locale, such as weeks starting on Sunday. This prevents tasks from appearing in an extra or incorrect column and keeps planning views accurate for localized configurations.
Original PR description
In Gantt views, for a given focus date, the appropriate time interval is displayed by finding its start and end date, based on the scale. For example, if I focus on 18 may 2026 with a month scale,…
In Gantt views, for a given focus date, the appropriate time interval is displayed by finding its start and end date, based on the scale. For example, if I focus on 18 may 2026 with a month scale, then the whole month of may is displayed. The behaviour was as expected in standard code, because all localisations agree on the beginning of the available scales (day, month, year). In custom code, however, some customer requires to see the gantt charts with a weekly scale. The differences in start of the week based on the localisations and the inconsistencies of use of localStartOf breaks the view. For example, if the localization has the start of the week on a sunday, and a task on the first column starts on a sunday as well, it will get assigned to column before (because it considers sunday as the last day of the previous week). The column before the first column does not exist, so one empty column is created to put the task in it. This commit fixes these inconsistencies so that GanttRenderer behaves as expected with weekly scales, without changing the standard behaviour. Tests are written to check both that the task is assigned to the proper localized week (starting on Sunday) and column (1, not 0). Forward-Port-Of: odoo/enterprise#129408 Forward-Port-Of: odoo/enterprise#118625
DHL deliveries from a company different from the main company now send a valid commercial invoice number. This prevents DHL validation errors and helps international shipments proceed correctly in multi-company setups.
Original PR description
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end.…
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end. `content/exportDeclaration/invoice/number: expected type: String, found: Boolean` Steps to reproduce ----- - Create a Belgian company - Setup DHL - DHL Product D - Express Worldwide - Dutiable Material enabled - Create an amrican customer - Deliver a product to the american customer > Validation Error Cause ----- The field is populated in https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/delivery_dhl_rest/models/dhl_request.py#L204 The problem is that `next_by_code` uses the company found in the env, whereas the sequence's company is the main one, so it is not found when doing https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/odoo/addons/base/models/ir_sequence.py#L287 ----- Ticket: opw-6171886 Forward-Port-Of: odoo/enterprise#123170 Forward-Port-Of: odoo/enterprise#118379
The Kenya OSCU invoice form now hides the validation message area when there is no message to show. This removes an unnecessary blank space, making the form layout cleaner and easier to read.
Original PR description
When there is no validation message, an empty div causes a whitespace gap between the header and the sheet in the form view. This commit adds `invisible="not l10n_ke_validation_message"` to the div to prevent this issue. Forward-Port-Of: odoo/enterprise#129364 Forward-Port-Of: odoo/enterprise#129318
This update prevents an error when saving an employee payroll declaration before an employee has been selected. It makes the payroll reporting workflow more reliable by avoiding an unexpected crash in Belgian payroll individual accounts.
Original PR description
When creating an employee declaration without selecting an employee, a traceback occurs. Steps to reproduce the error: - Install ``l10n_be_hr_payroll`` module with demo data - Switch to Belgian…
When creating an employee declaration without selecting an employee, a traceback occurs. Steps to reproduce the error: - Install ``l10n_be_hr_payroll`` module with demo data - Switch to Belgian company - Go to Payroll > Reporting > Individual Accounts > Create a new Individual Account > Click on Eligible Employees > Create a new employee declaration without employee > Save Traceback: ```py ValueError: Expected singleton: hr.employee() ``` https://github.com/odoo/enterprise/blob/000544c3d5b93e194264e15bb73d9599525106e3/hr_payroll/models/hr_payroll_employee_declaration.py#L71 The ``_compute_version_id()`` method calls ``_get_version()``. When ``employee_id`` is empty, ``_get_version()`` is invoked on an empty ``hr.employee`` record, and its ``ensure_one()`` call raises the above traceback at [1]. [1]: https://github.com/odoo/odoo/blob/3c358ae2badad69b125695a97b4a14e8ab77fccd/addons/hr/models/hr_employee.py#L745-L750 Upgrade PR: https://github.com/odoo/upgrade/pull/11026 sentry-7625826444 Forward-Port-Of: odoo/enterprise#125175
The Indian payroll settings now validate EPF Employee IDs using the correct 15-character format. This helps payroll administrators enter compliant establishment identifiers and avoids accepting outdated or incorrect EPF values.
Original PR description
Steps to reproduce: - Install Indian localization, and use an Indian company - Go to Settings under Payroll > Indian Localization - Tick the "Employee Provident Fund (EPF)" - Insert a EPF Employee ID Issue: The "valid" format is not correct: XX/XXX/1234567/000/1234567 with the first series of 7 numbers having a flexible range from 1 to 7. The first series of 7 numbers must always equal to 7 (it represents the establishment ID), and the last series of number should be dropped as it represents the employee's unique PF account number. Solution: - Modify the constraint for the variable: - Remove last 7 trailing digits from the constraint. - Make the length of the first series of 7 digits strictly equal to 7. - Update placeholder value and help info. Task: 6482315 Forward-Port-Of: odoo/enterprise#128777 Forward-Port-Of: odoo/enterprise#128421
This fixes an issue where the online store could accidentally treat unrelated form fields as product option choices. The change helps ensure product selections behave correctly and avoids confusion during shopping.
Original PR description
The selector was matching unrelated inputs because it wasn't specific enough. Forward-Port-Of: odoo/odoo#283742 Forward-Port-Of: odoo/odoo#283464
This fix prevents an extra misleading error from appearing when web unit tests fail. It keeps the memory information in the logs but records it before the test result is finalized, making failed builds easier to diagnose.
Original PR description
Before this commit, a build whose unit tests suite fails collects a second runbot error on top of the real one: odoo.addons.web.tests.test_js.WebSuite.test_unit_desktop.browser: Error received after…
Before this commit, a build whose unit tests suite fails collects a second runbot error on top of the real one:
odoo.addons.web.tests.test_js.WebSuite.test_unit_desktop.browser:
Error received after termination: [MEMINFO] tests done (after GC)
- used: 220535896 - total: 341990868 - limit: 4395630592
Note that the figures themselves are fine (220MB used of a 4.4GB limit): the error is not about memory, only about when the line is logged.
This happens because the runner logs that line after `stop()`, and `stop()` is what reports the suite result: the server settles the test on that report and kills the browser. The final major GC outlasts the report. A passing build escapes because the browser dies within milliseconds; a failing one stays up for the screenshot, long enough for the GC to finish and the line to land after termination.
This commit fixes the issue by moving `stop()` after the final cleanups and their memory log: the [MEMINFO] line is still logged, but before the result report, while the server still waits on the browser.
https://runbot.odoo.com/odoo/error/229655
Forward-Port-Of: odoo/odoo#284957Closing an AI Livechat conversation no longer triggers an unexpected chat window showing the prior AI exchange. This improves the website visitor experience by keeping the close action clean and preventing confusing follow-up messages.
Original PR description
closing the chat with the ai agent on the ai_livechat snippet results in a chatwindow popping up which gives a bad user experience. Steps to reproduce: - Log in as Mitchell Admin. - Go to website. -…
closing the chat with the ai agent on the ai_livechat snippet results in a chatwindow popping up which gives a bad user experience. Steps to reproduce: - Log in as Mitchell Admin. - Go to website. - Click on edit and choose `Contact & Forms`. - Add the AI Livechat website snippet. - From the snippet options, add an AI Agent and choose a livechat team. Make sure that Mitchell Admin is configured as an operator for that livechat team (livechat channel). - Click on save. - Open an incognito tab. Log in as Marc Demo. - Go to Website. - Type a message inside the `ASK AI` text area and press enter. - Wait until you receive a response and then click close. - A chat window will popup with the messages of the conversation with the AI along with a message saying `Visitor has left the channel`. This happens because `close` button will call `closeConversation` => `livechatService.leave()` => `visitor_leave_session` => `_close_livechat_session` that posts a message that the visitor has left the channel. This commit solves the issue by setting the user who left the channel as the author of the `visitor left chat` message instead of OdooBot.
Breadcrumb navigation is restored on several customer portal pages, including signatures, subscriptions, field service, tickets, appointments, and equity pages. This helps users understand where they are and move around the portal more easily.
Original PR description
Problem: Since [this commit][1], breadcrumbs have not been visible from portal pages. Specifically, they have not been visible from the following: * /my/signatures * /my/subcriptions * /my/field-service * /my/tickets * /my/appointments * /my/equity Cause: The change split calls for `portal.portal_layout` and `portal.portal_searchbar`. Previously, `breadcrumbs_searchbar` was set to true just after portal layout was called and this spread into the portal searchbar call. After the commit, `breadcrumbs_searchbar` was no longer being passed to the portal searchbar. As this is what controls the visibility of breadcrumbs on a portal page, they were no longer displayed. Solution: Explicitly call portal searchbar with the `breadcrumbs_searchbar` in each of the above routes' portal page definitions. [1]: https://github.com/odoo/enterprise/commit/99d583d5d6362504b4e838c7825fe9ca8d2b342c task-6365169
This fixes an installation failure in the Brazilian AvaTax Sales module when automatic dependency installation is skipped. The module now includes the needed dependency so sales order tax fields are available, preventing setup errors for affected deployments.
Original PR description
When installing l10n_br_avatax_sale with --skip-auto-install, you'll get an error about the l10n_br fields listed in views/sale_order_views.xml, because these fields don't fully exist without sale_external_tax. This happens because they're defined on a mixin, which is an abstract model. Abstract models only add their fields to a model that actually lists them in `_inherit`. sale.order should list this mixin, but currently doesn't. Adding that dependency is an unstable fix, so it will be added in master (20.0, or 20.1) runbot-237866 Forward-Port-Of: odoo/enterprise#128142
AvaTax invoice PDFs now size section or divider rows correctly when the Taxes column is hidden. This prevents misaligned borders and avoids large blank gaps on longer printed invoices, improving the accuracy and appearance of customer documents.
Original PR description
Steps: 1. Turn on AvaTax for a company (connect it to Avalara). 2. In Settings > General Settings > Invoicing, set the Document Layout to Boxed (Box), just for a clear view. 3. Create a customer…
Steps: 1. Turn on AvaTax for a company (connect it to Avalara). 2. In Settings > General Settings > Invoicing, set the Document Layout to Boxed (Box), just for a clear view. 3. Create a customer invoice: - Use the customer with an AvaTax fiscal position and proper address details. - Add a product with an AvaTax category. - Add a section line (a divider/heading row). - Compute Taxes for the AvaTax. 4. Print the invoice as a PDF. 5. Look at the section/divider row. Its cell border does not line up with the other rows. On longer invoices, this can also cause a big blank gap at the bottom of a page. Cause: When an invoice is computed by AvaTax, the Taxes column is hidden from the PDF (this is intentional, since AvaTax shows tax differently). But a different part of the same template decides how wide the section row should be. This part does not know the Taxes column was hidden, so it still counts it. That makes the section row's width wrong by one column, which breaks the table layout in the PDF. Fix: Instead of hiding the Taxes column only in one place, fix it at the source: the variable that decides (does this invoice show a Taxes column) now also checks if the invoice is an AvaTax invoice. Every other part of the template that uses this variable (the header, the tax cells, and the section row width) automatically gets the right answer, since they all read from the same place. Result: - Section rows on AvaTax invoices now have the correct width. opw - 6455674 Forward-Port-Of: odoo/enterprise#129097
The Project activity menu now opens Project Updates filtered to the current user's own activities and the selected timing bucket, such as late or upcoming. This prevents users from seeing unrelated project updates when following activity counts, making the activity list clearer and more accurate.
Original PR description
**Problem:** Opening a Project Update activity from the activity menu (the clock icon in the systray) lists every project update of every user, instead of the ones carrying the current user's…
**Problem:**
Opening a Project Update activity from the activity menu (the clock icon in the systray) lists every project update of every user, instead of the ones carrying the current user's activities.
**Steps to reproduce:**
1. Schedule an overdue activity on a project update
2. Have a colleague create another project update with no activity
3. Click the clock icon in the systray
4. Under "Project Update", click the "Late" count
**Current behavior:**
The list opens unfiltered and shows all project updates, including the ones of other users and the ones carrying no activity at all.
**Expected behavior:**
The list shows only the updates carrying the user's own activities, restricted to the bucket that was clicked.
**Cause of the issue:**
The activity menu never builds a "my activities" domain. `openActivityGroup` in `mail/static/src/core/web/activity_menu.js` narrows the generic act_window it opens purely through context keys — `search_default_filter_activities_my` plus `search_default_activities_overdue` / `_today` / `_upcoming_all` — and the only domain it forwards comes from `_get_activity_groups`, which is limited to `[('active', 'in', [True, False])]`. A `search_default_<name>` key is resolved against a filter of that name in the model's search view, and is silently dropped when no such filter exists. `project.update`'s search view never declared them, so every key the menu sends is discarded and the action opens on an empty domain.
**Fix:**
`project.project` and `project.task` — the addon's two other `mail.activity.mixin` models — already declare this block of invisible activity filters, as does every other model reachable from the activity menu. Declaring them on `project.update` is what makes the menu's context keys resolvable, and keeps the model consistent with the rest of the codebase instead of special-casing `project.update` on the client side.
opw-6416397
Forward-Port-Of: odoo/odoo#281511This fix prevents an upgrade warning when employee records temporarily have no version information during migration. It helps upgrades complete more cleanly by handling that short-lived data state without raising an error.
Original PR description
### Issue: A warning `IndexError: tuple index out of range` is logged on RunBot when upgrading from 18.0 to 19.0 for employees without any version ### Cause: `_get_version` on `hr.employee` falls…
### Issue: A warning `IndexError: tuple index out of range` is logged on RunBot when upgrading from 18.0 to 19.0 for employees without any version ### Cause: `_get_version` on `hr.employee` falls back to `versions[0]` when no version matches the given date But if the employee has no versions at all, `versions` is empty and `versions[0]` raises an `IndexError` ### Steps to reproduce: - Create a database with `hr_attendance` installed in 18.0 - Upgrade to 19.0 Before the fix, a warning is logged during the upgrade ### Notes: An employee without any version is a transient state during upgrade `hr/saas~18.4.1.1/end-migrate.py` backfills a version for every employee still missing one (`current_version_id IS NULL`) once the whole upgrade chain is done Since it only runs at the very end, an employee can still be found without a version by earlier steps (e.g. modules reloading their demo data), which is when this warning was logged Confirmed on an upgraded RunBot database that employees without a version before the upgrade do end up with one once fully completed runbot-241187 Forward-Port-Of: odoo/odoo#284467
This update prevents unnecessary warning messages when Odoo uses newer operating system versions of certificate software. It keeps email and certificate-related connections working smoothly across different deployment environments.
Original PR description
pyOpenSSL 24.3.0 deprecated passing its own X509/PKey objects to Context.use_certificate()/use_privatekey(), and started accepting cryptography objects instead. Odoo pins pyopenssl 24.1.0, but the distro builds run the version shipped by the OS: since the test added by f0fb287c6502 covers that path, they now add a warning in the logs. Load the certificate and the key as cryptography objects when the installed pyOpenSSL supports them, keep the previous loaders otherwise. Reference: https://github.com/pyca/pyopenssl/commit/b0cb4b4 This fix is based on https://github.com/odoo/odoo/blob/a2b4f618328f3ce3f654fd2c1ee4410365706a7e/odoo/addons/base/models/ir_mail_server.py#L34-L46 runbot-944176 Forward-Port-Of: odoo/odoo#285569 Forward-Port-Of: odoo/odoo#277449
Restaurant table orders now keep the entered number of guests when opened from another device. This prevents staff from being asked to enter the same guest count again, reducing interruptions and keeping service flow smoother.
Original PR description
Steps to reproduce: - Enable presets on a restaurant PoS and tick "Amount of Guests" on the preset used for tables - On device A, open a table and enter the number of guests - On device B, open the…
Steps to reproduce: - Enable presets on a restaurant PoS and tick "Amount of Guests" on the preset used for tables - On device A, open a table and enter the number of guests - On device B, open the same table Issue: Device B pops the guest count numpad again, even though the guest count was already entered on device A. Cause: ensureGuestCustomerCount guarded the popup on order.uiState.guestSetted. uiState is only serialized to IndexedDB (SERIALIZED_UI_STATE_PROP, used by serializeForIndexedDB); it is never sent to the server, so the flag is local to one browser and a second device always considers the guest count as not yet asked. customer_count is synced and could carry that information, but PosStore createNewOrder pre-filled it with the table seats, so it was never 0 for a table order and could not tell "not asked" from "answered". Fix: Stop storing the seats default on the record and expose it from getCustomerCount() instead, so customer_count == 0 means "no guest count entered yet". ensureGuestCustomerCount now guards on that synced value, so an order whose guest count was entered on another device is not asked for it again. Every display goes through getCustomerCount(), so the values shown on the Guests button, the receipt and the preparation ticket are unchanged. opw-6470180 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285444 Forward-Port-Of: odoo/odoo#283002
This change removes obsolete project portal rating code that has not been used since the related website template was removed years ago. It reduces maintenance overhead without changing the visible project portal experience for users.
Original PR description
The `ProjectRatingImage` interaction targets `.o_portal_project_rating .o_rating_image`, but nothing renders those classes anymore: the only template setting them,…
The `ProjectRatingImage` interaction targets `.o_portal_project_rating .o_rating_image`, but nothing renders those classes anymore: the only template setting them, `website_project/views/project_rating_templates.xml`, was dropped in 14.0 by a256602915cc ([REM] website_project). The widget survived that removal because it lived in `project`, and it was even later converted to an Interaction by 22e777c04652, without anyone noticing it had already been dead for four years. Remove the interaction, the now empty `interactions/*` assets entry and the `.o_portal_project_rating` styles, whose inner classes came from that same deleted template and are unused as well. `.o_status` is kept as it is still needed on the frontend by `project_portal_project_task_templates.xml`, and the only other definition of it lives in `web/static/src/views/view.scss`, which is not part of `web.assets_frontend`. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
An obsolete styling setting for search facets was removed because the interface now uses a newer shared background style. This is a small cleanup that helps keep the codebase simpler without changing what users see.
Original PR description
--SearchBar-facet-background is not read anywhere anymore: the control panel frost restyle switched the facet background to the bg-100 utility. requires: https://github.com/odoo/odoo/pull/285359 task-6518046
This change simplifies the web tour code by moving small helper logic directly into the tour pointer component and removing an unused utility file. It should not change how users experience tours, but it reduces maintenance overhead for future updates.
Original PR description
tour_pointer.js was the only remaining consumer of tour_utils.js. 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 reorganizes how spreadsheet-related data is evaluated behind the scenes, including charts, filters, lists, pivots, currency, translations, and accounting spreadsheets. It should improve maintainability and help ensure the right spreadsheet components run in the right context, with minimal direct impact on day-to-day users.
Original PR description
This commit is the odoo counterpart of https://github.com/odoo/o-spreadsheet/pull/9439. Task: 6428159 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 update reorganizes how spreadsheet features access evaluated data and corrects related command handling. It helps keep spreadsheet surveys, pivots, comments, and sales field synchronization aligned with the latest spreadsheet engine behavior, reducing the risk of inconsistencies for users.
Original PR description
This commit is the odoo counterpart of https://github.com/odoo/o-spreadsheet/pull/9439. Task: 6428159
Several Odoo business apps were updated to align with the latest underlying web framework changes. This keeps key areas such as Documents, spreadsheets, payroll, manufacturing, and reporting compatible and easier to maintain, without introducing expected user-facing behavior changes.
Original PR description
*: account_reports,documents_spreadsheet,hr_payroll,mrp_mps, mrp_workorder,spreadsheet_edition
`viewService` has been converted to an OWL3 Plugin, so existing useService("view") call sites need to be rewritten. This commit is the result of the owl3-migration script.