Daily updates from Odoo
Friday, July 24, 2026
52 changes · master
New functionality added to Odoo
Mexican payroll now supports calculating the legally required seventh day payment proportionally for weekly and 14-day pay schedules. This helps employers pay rest-day compensation more accurately when employees have absences or different weekly rest-day arrangements.
Original PR description
By Mexican labor law, employees are entitled to at least one paid rest day per week (commonly known as the Seventh Day). Depending on the contract, some schedules provide two rest days. There are two…
By Mexican labor law, employees are entitled to at least one paid rest day per week (commonly known as the Seventh Day). Depending on the contract, some schedules provide two rest days. There are two ways to pay this concept: * Fixed amount: The employee receives the full daily salary regardless of absences (already supported). * Prorated amount: Applies strictly to weekly and 14-days schedule pays. The payment is proportional to the actual time worked during the period (new feature). The prorated seventh day is calculated using the following formula: `accrued_days * work_rate * daily_salary` Where: * Accrued days: Actual days/hours worked in the period. * Work rate: A proportional factor based on the rest days and working days per week: `rest_days / working_days_per_week`. Rest days are dynamically calculated using the `hours_per_day` and `hours_per_week` fields from the `resource_calendar_id`. * Daily salary: Retrieved from the `l10n_mx_daily_salary` field. EXAMPLE 1: WEEKLY SCHEDULE WITH 1 REST DAY For a wage of 7,000 MXN weekly (daily wage = 1,000 MXN), the rate is `1/6 = 0.16666`. The payment depends on the worked days: | Worked Days | Seventh Day Amount Paid | | ----------- | ---------------------------------- | | 1 | 1 * 0.16666 * 1,000 = 166.67 MXN | | 2 | 2 * 0.16666 * 1,000 = 333.33 MXN | | 3 | 3 * 0.16666 * 1,000 = 500.00 MXN | | 4 | 4 * 0.16666 * 1,000 = 666.67 MXN | | 5 | 5 * 0.16666 * 1,000 = 833.33 MXN | | 6 | 6 * 0.16666 * 1,000 = 1,000.00 MXN | EXAMPLE 2: WEEKLY SCHEDULE WITH 2 REST DAYS For the same daily wage, but with a 5-day workweek, the rate is 2/5 = 0.4. | Worked Days | Seventh Day Amount Paid | | ----------- | -------------------------------- | | 1 | 1 * 0.40000 * 1,000 = 400.00 MXN | | 5 | 5 * 0.40000 * 1,000 = 2,000.00 MXN | * Add test_cfdi_nomina_con_septimo_dia test target: master task-5259458
A new timesheet add-on introduces AI assistant support to help users refine timesheet descriptions. The assistant rules were also simplified so messaging-related work is categorized more consistently across tools like Discord, Google Chat, and Odoo Discuss.
Original PR description
- added new module to support ai assistant capabilities - changed the assistant rules task-6376442
Enhancements to existing features
The Chile and Mexico e-invoicing checkout flows now pass the current order into checkout step preparation. This helps ensure category-based extra checkout steps are applied correctly for localized online sales.
Original PR description
Pass `order` to `_get_checkout_step_values` in l10n-specific checkout controllers to support the extra-step category restriction. Community PR: https://github.com/odoo/odoo/pull/258042
Payroll users can now correct an entire validated or paid pay run in one action instead of manually reverting and recreating each payslip. The system creates a linked correction pay run with the necessary reversal and draft corrected payslips, improving efficiency and traceability at batch level.
Original PR description
There was previously no way to correct a complete pay run once it was validated or paid. Users had to manually revert and recreate payslips one by one, with no traceability at the batch level. Add a "Correct" action on validated (or paid) pay runs. Triggering it: - Creates a new pay run covering the same period, structure, and company as the original. - Reuses the existing per-payslip refund/correction logic (_action_refund_payslips/_action_correct_payslips) to generate, for each original payslip, a reverted payslip (validated) and a draft corrected payslip, both linked to their origin. - Moves all reverted and corrected payslips into the new pay run and routes the user directly to its Payslips step. Task: 6352855
Users can now create batch payments from the payment wizard even when the payment method is not SEPA. SEPA payments keep the existing flow, ISO payments can generate downloadable XML without initiation, and other methods can still be grouped into batches.
Original PR description
Since the new payment initiation features, we added a wizard in the payment list view to allow users to create a batch or start a payment initiation. But this was only possible for SEPA payments. This commit allows users to create batch payments from this wizard with any payment methods. This works like so: - If SEPA payment -> same as before - If any ISO payment -> Not allowed to initiate the payment but can download XML - If any other methods -> Just allowed to create a batch without XML task-6272798 Forward-Port-Of: odoo/enterprise#120976
Clicking a phone number now follows the company’s mobile calling preference when VoIP cannot place the call. Users may see the softphone to check connectivity, open the native phone dialer, or choose between options, reducing confusion and accidental duplicate actions.
Original PR description
…ability When the user clicks a phone number in a PhoneField widget but VoIP is not available (canCall = false), the behavior now depends on the how_to_call_on_mobile setting: - "voip": show the softphone so the user can check the connection - "phone": fall back to the base class default (native dialer) - "ask": show a selection dialog for the user to choose We also backport the code to prevent double click from [1]. [1]: https://github.com/odoo/enterprise/commit/fa6c8747d69ffee25a7f308d26baca8500226784 Forward-Port-Of: odoo/enterprise#123065
This update adjusts how product tags are managed in the AI website sales tools after related product page changes. It helps keep product editing and website product options working reliably as the underlying layout evolves.
Original PR description
**Purpose:** The template for the parent view "product.product_template_form_view" was modified with the product tags moving to another page. Then the field "l10n_pe_edi_tariff_fraction" cannot depend on the product tags position anymore. Task-5215982 See also: - https://github.com/odoo/odoo/pull/237565
When a user selects a project in the timesheet timer, Odoo now automatically fills in the task they most recently logged time on for that project. For Helpdesk projects, the same behavior applies to the most recent ticket, helping users start timers faster while still allowing easy changes.
Original PR description
When selecting a project in the timesheet timer, the task on which the user most recently logged time for that project is now prefilled, as they are most likely to keep logging time on it. If not, selecting a different task only requires one click. For Helpdesk projects, where the timer shows the ticket field instead of the task field, the most recently timesheeted ticket is prefilled in the same way. task-6359030 Forward-Port-Of: odoo/enterprise#124010
Self-order kiosk orders that will be paid at the counter are no longer sent to the Belgian blackbox before payment is completed. This prevents premature fiscal registration and supports mixed self-order payment flows more reliably.
Original PR description
This commits adapts the code in confirmation_page.js to not send the order to the blackbox from the kiosk if the order is not in paid state. task-id: 5960666 Forward-Port-Of: odoo/enterprise#123699 Forward-Port-Of: odoo/enterprise#117585
Uruguayan e-invoicing now lets users mark products as non-billable directly on the product record. This helps businesses report items such as manual rounding adjustments correctly to the tax authority using the required non-billable indicators.
Original PR description
Purpose: In UY e-invoicing, the DGI defines indicators 6 (positive non-billable) and 7 (negative non-billable). Currently, Odoo only supports down payment flows utilizing these indicators. However, indicators 6 and 7 are commonly used for other business cases, such as manual rounding adjustments. To support other flows outside of down payment, an explicit product-level flag is added to represent non-billable items/services in UY. Users will be able to set a product as non-billable in the Accounting tab. When an invoice containing non-billable products is sent to the DGII, it will be sent with the appropriate indicators, 6 or 7 and aggregated into MontoNf node of the CFE document. task-5904238
The automated clickbot now also verifies that screens meant to work offline still behave correctly when the network is unavailable. Several dashboards and views now open faster by showing cached information first, helping users avoid waiting while fresh data loads.
Original PR description
The clickbot only ever exercised the app while online. It now also checks that the views marked as available offline still work correctly once the network is cut, catching regressions that only show up in offline mode. task-id 6366264
The Employee Gantt view in Manufacturing now shows only employees who are currently assigned to active work orders or who worked on one in the last 30 days. This reduces clutter and helps planners focus on the employees most relevant to current production work.
Original PR description
Before, in Employee Gantt in MRP module, all employees of the company were shown, even if they have never done a work order. Now, the following employees are visible: - Employees currently assigned to any work order (not done, not cancelled) - Employee assigned to any work order in the last 30 days task-6276316
Event staff can now print attendee badges in A4 PDF format directly from the registration desk. The update also extends badge printing support to Point of Sale, making on-site event check-in and badge handling more flexible.
Original PR description
This PR adds the support for A4 pdf badge printing through the registration desk. Requested for OXP in Kenya See https://github.com/odoo/odoo/pull/275021 Forward-Port-Of: odoo/enterprise#123799 Forward-Port-Of: odoo/enterprise#123478
Spreadsheet users can now retrieve the visible label of a global filter, such as a customer name, instead of only its internal ID. This makes spreadsheet reports easier to read and share when filter values need to be displayed in a business-friendly way.
Original PR description
Before this commit: If you use ODOO.FILTER.VALUE and have a customer set in the global filter, it returns the id of the customer. That can be useful in some cases but in others you might simply want the label. Task: 6167605 Forward-Port-Of: odoo/enterprise#124746 Forward-Port-Of: odoo/enterprise#115984
Localized bank account details are now shown in a more consistent position across several country-specific modules. This keeps important banking and partner information grouped logically, making forms easier to review and maintain.
Original PR description
Since we have partner_id now on top of holder_name, we want to anchor localization specific fields on top of partner_id instead of holder_name. task-6275796
Resolved issues and error corrections
This update standardizes how Odoo decides whether a database save can happen during key accounting, localization, and social workflows. It helps prevent unintended saves during tests or sensitive actions such as bank statement imports, reducing the risk of inconsistent results or failed processes.
Original PR description
…flag The aim of this commit is to allow forbidding a commit in specific condition and uniformize the way we check if a commit can be done. Context: There are a few places where checking the module.current_test flag isn't enough. For example, some test monkey patch it for specific reason and some business flow like the import of a csv of bank statement can't afford a commit. task-id: None
The report layout now keeps the chatter panel visible at the right edge of the screen, even when financial reports are very wide. This helps users continue discussions and collaboration without needing to scroll horizontally across large reports.
Original PR description
Issue: - When reports are large/wide, the chatter component is pushed beyond the visible viewport, appearing only at the absolute right edge of the overflowing report rather than the right edge of the screen. Fix: - Updated the layout container to prevent the chatter from shrinking or overflowing with the report block, ensuring the main report scrolls independently while the chatter stays pinned to the screen viewport. Impact: - Keeps the chatter panel fully visible on the right side of the screen, allowing users to communicate without scrolling horizontally on wide reports. task-[6376792](https://www.odoo.com/odoo/project/967/tasks/6376792) Forward-Port-Of: odoo/enterprise#125126 Forward-Port-Of: odoo/enterprise#123734
This fix moves the express mention to the correct section of the French VAT report file sent to Aspone. It helps ensure submitted VAT declarations follow the expected format and are less likely to be rejected or mishandled.
Original PR description
in this commit: https://github.com/odoo/enterprise/commit/93c1a4fe15d1f09e4c3df3a5db0e06006121c027 we added a way to have an express mention in the xml sent to aspone. But we placed it in the "T-IDENTIF" zone, but this zone doesn't accept express mention. It should be located in the form it self. task-6253745 Forward-Port-Of: odoo/enterprise#124471 Forward-Port-Of: odoo/enterprise#123235
When a spreadsheet cannot be opened because its underlying model fails to load, Odoo now stops the follow-up synchronization step that depended on that missing data. Users still receive the intended error notification, but avoid an additional technical crash message.
Original PR description
Current behavior before PR: - In 4204ceb, model creation errors were caught and a notification was shown to the user. - However, syncSheetFromRouter() was still called afterward. Since it relies on model getters, it raise a traceback when no model existed. Desired behavior after PR is merged: - Call syncSheetFromRouter() only after the model has been created successfully. - This prevents accessing model getters when model creation fails and avoids the resulting traceback. Task: [6355245](https://www.odoo.com/odoo/project/2328/tasks/6355245) Forward-Port-Of: odoo/enterprise#124961 Forward-Port-Of: odoo/enterprise#122650
Belgian annual statement XBRL exports now preserve required true/false and unit values instead of translating them when the user language is Dutch. This prevents affected filings from being rejected by the National Bank of Belgium validator.
Original PR description
Steps to reproduce: - Set the user language to Dutch. - Go to Accounting > Reporting > Annual Statements. - Generate the XBRL export for a report other than the "company, abridged" (acon) balance…
Steps to reproduce:
- Set the user language to Dutch.
- Go to Accounting > Reporting > Annual Statements.
- Generate the XBRL export for a report other than the "company,
abridged" (acon) balance sheet/P&L combination, e.g. an association
(asso_a/asso_f) or "company, full"/"company, capital" report.
- Open the file: the `<met:bln1>` boolean facts are exported as
"onwaar" instead of "false", which is not a valid XBRL boolean
lexical value and gets rejected by the NBB validator.
Cause of the issue:
QWeb templates translate static text nodes by default. The base
module ships a generic `msgid "false" -> msgstr "onwaar"` translation,
used elsewhere in the UI, which silently hijacks the literal
"false"/"true" and unit tokens ("iso4217:EUR", "pure") in the XBRL
data templates whenever the file is generated in Dutch.
Solution:
Add `t-translation="off"` on the `<met:bln1>` boolean facts and the
`<measure>` unit tokens in the 5 remaining XBRL templates,
so these fixed-vocabulary XBRL values are never subject to translation
opw-6395785
Forward-Port-Of: odoo/enterprise#124945The appointment link copy confirmation now appears only after the copy action has actually been attempted. This prevents automated appointment CRM flows from moving ahead too early, making related tests and user interactions more reliable.
Original PR description
Prior to this commit, the success notification for copying an appointment link to the clipboard was triggered synchronously, while the actual `navigator.clipboard.writeText` execution was deferred inside a `setTimeout`. This caused a race condition (depending on the browser's cpu load) during tours (e.g., `appointment_crm_meeting_tour`). The tour would proceed and restore the mocked clipboard object (`oldWriteText`) before the deferred `setTimeout` block had a chance to execute. This commit fixes the issue by moving the notification logic inside the `setTimeout` callback. The tour is also updated to wait explicitly for the success notification before cleaning up the clipboard mock and proceeding to discard the slots. runbot-241004 Forward-Port-Of: odoo/enterprise#124439
Resetting a submitted tax return no longer changes the company-wide tax lock date, so closed periods are not unintentionally reopened for everyone. The update also supports companies that set the tax lock date before submitting a return, helping larger teams keep accounting periods controlled during VAT filing.
Original PR description
To reproduce the issue: 1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January 3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock…
To reproduce the issue:
1) Initialize a company in Belgium, create the tax returns 2) Submit the VAT return from January
3) Open the lock date wizard. The tax lock date is January 31st. 4) Add a lock date exception removing the tax lock date just for you, for 5 min. 5) Reset January's return
6) Reopen the lock date wizard.
====> Your exception is still there, but the tax lock date for everyone has been reset to December 31st.
This is plain wrong. Resetting a return should not automatically reopen the period for everyone. Lock dates exceptions/modifications are anyway required to reset the return ; they should pilot the whole flow. Nothing being magically hidden from the user means there can't be someone else mistakenly encoding something into the reopened period.
Another fix was required to make this one work: setting the tax lock date before submitting the return should work. In bigger environments, users might want to do that as a first step to reduce the number of people encoding data before actually doing the submission of the return. Therefore, the case where the tax lock date is already set at the date_to of the return when submitting it was supposed to be already supported, and allow the creation of the closing entry for that return, despite it being on the tax lock date. The test ensuring this was however badly written, and the feature didn't work: the closing was created at a later date than the lock date automatically, due to the Bills' Algorithm.
Forward-Port-Of: odoo/enterprise#124872
Forward-Port-Of: odoo/enterprise#124811Odoo now places certificates from emSigner correctly in signed PDF documents after recent changes on the emSigner side. This prevents visibly misaligned certificates and helps keep signed documents professional and readable.
Original PR description
Before: - Certificate added by emSigner was misaligned in the signed PDF after recent UI changes. After: - Updated coordinates to ensure the emSigner certificate is properly aligned and displayed correctly in Odoo. task-6105264 Forward-Port-Of: odoo/enterprise#113402
VoIP call recordings made from Apple mobile devices will no longer produce silent audio files. The recording settings were adjusted for Apple browsers so businesses can reliably review recorded calls when call recording is enabled.
Original PR description
Before this commit, recording a VoIP phone call from an Apple mobile device generated a silent audio file. This issue happened because the configured 8000 `audioBitsPerSecond` value was too low. Apple mobile browsers strictly respect this value, while other browsers ignore it and default to a higher bitrate to 128000. Increasing `audioBitsPerSecond` to 32000 on WebKit browsers fixes the issue on Apple mobile devices. How to reproduce: - Set up a DIDWW user. - Enable call recording. - Make a call. - Open the call and play the recording. opw-6046534 Forward-Port-Of: odoo/enterprise#124433 Forward-Port-Of: odoo/enterprise#117885
Fixed an issue where the payroll dashboard could crash after users dismissed the final warning on an empty dashboard. The screen now handles upcoming pay run dates correctly, allowing payroll teams to continue using the dashboard without interruption.
Original PR description
Steps to reproduce:- 1. Set schedule on payroll dashboard. 2. Dismiss every warning. 3. On dismissing last warning throws a traceback. Root cause:- `DashboardEmptyScreen` passed the raw closing_date value straight from the RPC response into formatDateLabel, which calls date.diff(...) assuming a Luxon DateTime. The RPC layer serializes it as a plain ISO string, so formatDateLabel crashed with "date.diff is not a function" any time the empty-dashboard screen rendered with upcoming pay runs. Fix:- added new method `formatClosingDate` to format `closingDate` seperately. task-6395553
Businesses can once again add comments when submitting Belgian VAT return XML files. This restores a previously available option that had been removed by mistake, helping teams include required context with filings.
Original PR description
This feature had been mistakenly removed. Forward-Port-Of: odoo/enterprise#124865
Shop Floor now places manufacturing orders with scheduled work ahead of orders that have no planned start time. This makes the work center view match the standard work order list and helps teams focus on jobs that are ready to proceed.
Original PR description
## Problem In shop floor, MOs with unplanned work orders get sorted before MOs that have planned operations, which contradicts the normal nulls last sorting for work orders. ## Solution We will…
## Problem In shop floor, MOs with unplanned work orders get sorted before MOs that have planned operations, which contradicts the normal nulls last sorting for work orders. ## Solution We will update the sorting logic in the MrpDisplay component to more gracefully handle falsy date_start values, sorting them to the end. ## Steps to reproduce (runbot 19) 1. Create 2 MOs with an operation (work order) involving a work center, we'll call them A and B. 2. Open Shop Floor and open the work center that the MOs' work orders belong to, and note they are ordered A, B (this is fine, neither are planned so the precedence falls back to id 3. Go back to MO B and plan it. This should give it precedence in Shop Floor 4. Under the work center in Shop Floor, note that the MOs are still ordered A, B, despite B's work order having a start date and A's work order not having one To further motivate this being unintended, you can go to Manufacturing > Operations > Work Orders, and you'll see MO B's work order sitting at the top of the list. opw-6303323 Forward-Port-Of: odoo/enterprise#123983 Forward-Port-Of: odoo/enterprise#121693
Barcode delivery operations now correctly warn users when the same package is scanned more than once, even when multiple packages are part of the transfer. This prevents duplicated package contents from being processed and avoids incorrect negative stock quantities.
Original PR description
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in…
Steps to reproduce --- 1. Enable Packages and turn on "Move Entire Packages" on the delivery operation type. 2. Create a storable product P and add 2 units in different package in stock: 1 in PACK001, 1 in PACK002 3. In the Barcode app > Operations > Delivery > New 4. Scan a first package PACK001, then a second different package PACK002 5. Scan the first package PACK001 again. Issue --- Re-scanning an already scanned package is meant to be rejected with a "This package is already scanned." warning, but the rejection stops working as soon as a second package is present in the transfer, so the package content gets added a second time and, once validated, the source quant goes negative (the package ends up holding a negative and a positive quant of the same product). Commit 23613c63947 added a canPackSomeLines flag that is set to true for every package line that is not the scanned one, so any other package in the transfer makes the alreadyDonePackId && !canPackSomeLines guard false and silently skips the warning. The scanned package already exposes whether it had something left to pack through scannedPackages, so gating the warning on that flag instead keeps the check working regardless of how many other packages are in the transfer. https://github.com/odoo/enterprise/blob/3cc1a162e61662814b0e52c0c720831952d208a8/stock_barcode/static/src/models/barcode_picking_model.js#L1976-L2006 opw-6279105 Forward-Port-Of: odoo/enterprise#125229 Forward-Port-Of: odoo/enterprise#121755
This fix keeps embedded views aligned correctly when they appear at the top of a Knowledge article. It prevents a visual spacing issue caused by editor selection placeholders, preserving the intended layout for users editing Knowledge content.
Original PR description
This commit updates the embedded view top-alignment selector to account for selection placeholders introduced by https://github.com/odoo/odoo/commit/edf7f7bb0c62978640c181eccb4934855d5d872d. This preserves the intended top-alignment behavior when an embedded view is the first editable element in the knowledge editor. Task-5951196 Forward-Port-Of: odoo/enterprise#125080
This fix prevents the report editor from continuing to run after its display frame has been removed. It reduces crashes and test failures during report preview or editing, making the Studio report editing experience more reliable.
Original PR description
In the ReportEditorIframe component, the iframe may be removed at some point, to be replaced by another one. The problem is that the editor is destroyed only when the new iframe is loaded, so there…
In the ReportEditorIframe component, the iframe may be removed at some point, to be replaced by another one. The problem is that the editor is destroyed only when the new iframe is loaded, so there is a period of time in which the previous editor is alive, but the iframe is destroyed. It can causes issues with plugins, which assumes that we have a valid editable zone. For example, here is a common traceback:
test_print_preview (odoo.addons.web_studio.tests.test_report_editor.TestReportEditorUIUnit.test_print_preview)
Error received after termination: TypeError: Cannot read properties of null (reading 'getComputedStyle')
at http://127.0.0.1:8069/web/assets/e9a3359/web.assets_web.min.js:16264:290
at Array.filter (<anonymous>)
at ToolbarPlugin.getFilteredTargetedNodes (http://127.0.0.1:8069/web/assets/e9a3359/web.assets_web.min.js:16264:201)
at ToolbarPlugin._updateToolbar (http://127.0.0.1:8069/web/assets/e9a3359/web.assets_web.min.js:16259:83)
at http://127.0.0.1:8069/web/assets/e9a3359/web.assets_web.min.js:5325:117
The fix is to subscibe to the removal of the iframe, and destroy immediately the editor.Shopee order lines now show the SKU for the specific product variant instead of the general product template when variants are used. This makes order details clearer for sales and fulfillment teams and reduces confusion when reviewing Shopee orders.
Original PR description
Currently, _prepare_order_lines_values resolves SKU as `item_sku or model_sku`. Shopee always sends item_sku (product.template SKU), so when a listing has variants the order line description shows the template SKU ([item_sku]) even though the correct variant is linked via `model_sku`. task_id: 6335110 Forward-Port-Of: odoo/enterprise#124428 Forward-Port-Of: odoo/enterprise#124031
This fixes how the point-of-sale barcode lookup feature checks whether a user may create new products. The permission is now evaluated immediately and consistently, helping avoid incorrect product creation options appearing during POS workflows.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420 Forward-Port-Of: odoo/enterprise#125237 Forward-Port-Of: odoo/enterprise#123073
AI tool failures caused by invalid automated inputs are now logged without long error tracebacks, reducing noise in system logs. Detailed traceback information remains available in debug logs for teams that need to investigate issues.
Original PR description
Tool failures from bad LLM arguments were logged at ERROR level with a full traceback, polluting the logs. I have changed the logger to log error not exception so we get rid of the traceback error added another debug logger to show the traceback also task-6250418 Forward-Port-Of: odoo/enterprise#124241 Forward-Port-Of: odoo/enterprise#120281
Delivery guides in Chilean localization no longer fail when a kit includes components measured differently from the kit product. The system now prices those component lines using their own product pricing, preventing unit conversion errors and allowing users to print delivery guides as expected.
Original PR description
When a kit is delivered, each component move is linked to the kit's sale order line. Pricing the delivery guide in "sale order" mode converted the component quantity into the kit's sale UoM. For a component sold in a different UoM category than the kit, this cross-category conversion raises a UserError. Steps to reproduce: - Create a BoM for a kit product with a component in a different UoM category - Create a customer with Delivery Guide Price = "From Sale Order" - Sold the kit in a sale order and deliver it - On the delivery, print the delivery guide -> error This fix makes the guide price for a component move to be "product" if the component's product is different from the related sale line product, avoiding the cross-category UoM conversion. opw-6327895 Forward-Port-Of: odoo/enterprise#125199 Forward-Port-Of: odoo/enterprise#122776
The asset Related Entries button is now labeled Related Items and opens directly as a list instead of leading users into an unhelpful journal item form. This makes reviewing the accounting items linked to an asset simpler and less confusing.
Original PR description
If you create an asset and confirm it, you can see the Related Entries using the smart button Related Entries. The list view that opens is clickable, but it opens a quite useless form view of the Journal Items. - Rename breadcrumb button to Related Items - Make it behave like action_account_moves_all, to not open form view Ticket: [6385260](https://www.odoo.com/odoo/project/967/tasks/6385260) Forward-Port-Of: odoo/enterprise#124672
This fixes an issue where companies using the Peru localization could be blocked from creating certificates when the Chile localization was also installed. The Chile-specific serial number requirement now applies only where appropriate, preventing unnecessary setup errors for other Latin American localizations.
Original PR description
With a l10n_pe company and having a l10n_cl company installed: - Try to create a certificate in the settings, there is a missing field error. The template certificate_certificate_view_form have a required subject_serial_number field in l10n_cl but it shouldn't in other latam localization. opw-6274126 Forward-Port-Of: odoo/enterprise#120211
The draft button in Uruguay electronic invoicing now returns a valid response when called remotely. This prevents an error that could interrupt users or integrations when resetting an invoice to draft.
Original PR description
Calling the method in RPC causes an error: ``` TypeError: cannot marshal None unless allow_none is enabled ``` Forward-Port-Of: odoo/enterprise#125285 Forward-Port-Of: odoo/enterprise#124653
Fixed an issue where closing a POS session could calculate a customer's remaining invoice amount incorrectly after a partial settlement. This prevents the POS from hiding settlement options or proposing and charging too much for outstanding invoices.
Original PR description
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on…
`pos_amount_unsettled` is a stored computed field defined as the invoice's residual minus the settle lines belonging to sessions that are not yet closed. Its compute method filters the lines on `order_id.session_id.state`, but that state is not in the compute dependencies. When closing a session holding a settle order, `_validate_session()` first reconciles the settle payment with the invoice (which lowers `amount_residual_signed` and flags the field for recomputation) and only then writes `state = 'closed'` on the session. If the pending recomputation is executed in that window (any flush of `account.move` does it: recomputing the field for any other flagged record drags the whole queue along), the settle line is deducted from the already reconciled residual, i.e. counted twice, and the field is stored as `residual - settled` instead of `residual`. Since the session state is not a dependency, writing `state = 'closed'` does not flag the field again and the wrong value is never corrected. The partner's `invoices_amount_due` then goes negative, which hides the "Settle invoices" option in the POS partner list and inflates the "Settle due amount" proposal (`remainingDue = total_due - pos_orders_amount_due - invoices_amount_due`): a customer owing e.g. 500 is proposed, and charged, 700. Steps to reproduce: 1. Post a customer invoice of 1000. 2. In the POS, select the customer > Settle invoices, pick the invoice, set the amount to 700 and pay in cash. 3. Close the session. The issue only occurs when the pending recomputation runs during the closing, which depends on the other operations performed by it (not deterministic in real usage; the regression test forces it with a flush after the reconciliation). 4. The invoice's "Amount To Pay In POS" shows -400 instead of 300 and the POS proposes to settle 700 instead of 300. Add the session state to the compute dependencies so that the field is recomputed once the session is closed, yielding the correct amount regardless of any intermediate recomputation. opw-6375095 Forward-Port-Of: odoo/enterprise#123783
Automated barcode tests for scrap operations were adjusted so entered quantities are kept correctly during screen updates. This reduces random test failures and helps keep inventory and manufacturing barcode workflows stable.
Original PR description
These barcode scrap tours randomly trigger "You can only enter positive quantities." on runbot: the quantity set with a raw input.value is dropped when the field re-renders before the scrap is saved, so it scraps 0. Dispatching an input event keeps the typed value. error-238911 Forward-Port-Of: odoo/enterprise#124952
Product managers can now use barcode lookup to automatically fill product details without needing full administrator access. This keeps product creation workflows efficient while avoiding unnecessary elevation of user permissions.
Original PR description
Currently when a user with a product manager rights that is not admin tries to look up the product with barcode information is not auto filled. ## Steps to replicate: - Install stock with demo data -…
Currently when a user with a product manager rights that is not admin tries to look up the product with barcode information is not auto filled. ## Steps to replicate: - Install stock with demo data - Barcode Database > Setup barcode lookup credentials - Users > Marc Demo > Give Marc Demo > Master Data > Products > Create - Login as `Marc Demo` - Products > Barcode: `850049670180` > Click anywhere else ## Observed Behaviour: Information on the product template is not autofilled, as it would be when using a System Admin user(Mitchell Admin). ## Root cause: This issue occurs because barcode lookup is gated behind a check for System Admin rights. Although users in the Product Manager group have permission to create products, they do not satisfy this condition, so the barcode lookup never executes at [1]. [1]- https://github.com/odoo/enterprise/blob/c66995fda83e19b28a38312af8efdc1601881cf0/product_barcodelookup/models/product_template.py#L17-L22 ## Why this is an issue: The original restriction (task [2] and commit [3]) was intended to limit barcode lookup to users who can create products, preventing unnecessary API calls. This was a valid assumption in 17.3-18.0, where creating products in POS required System Admin rights but now after commit [4] this is no longer the case. In v18, task [5] introduced the Product Manager group, making product creation independent of System Admin rights or module rights. Later, v18.3 exposed these Master Data access rights to non-debug users through commit [6]. As a result, there are users who are legitimately responsible for product creation and maintenance (regardless of POS usage) they can no longer use barcode lookup unless they are also granted full System Admin privileges, which provides broader access than required. ## Solution: Remove the group-based permission check so that access is determined solely by product edit permissions. This ensures that only users with the ability to modify products can use the API call, preserving the original security intent. As a result, users no longer need unnecessary administrative privileges toperform barcode lookups. [2]: https://www.odoo.com/odoo/project/49/tasks/3911024 [3]: https://github.com/odoo/enterprise/commit/444df3e48cb8d479d3b5d4a03a4bfefa48650910 [4]: https://github.com/odoo/odoo/commit/821bbc4504fd80a508e2412c7490ee60dd03f7b8 [5]: https://github.com/odoo/odoo/commit/d4886faf12ccaf63d5e899c20df2543d1ce046ab [6]: https://github.com/odoo/odoo/commit/e74eaf628498155243db73ea229eaf5e74c24f2a opw-6290999 Forward-Port-Of: odoo/enterprise#121915
Fixes an issue where testing a bank statement CSV import could fail because temporary records from the trial run were no longer available. This helps users validate bank statement imports reliably before applying them.
Original PR description
odoo/odoo#255059 made execute_import's savepoint flushing, so a dryrun rollback now properly invalidates the ORM cache instead of leaving it. That exposed a pre-existing bug here: we created the statement with line_ids pointing at .line records dryrun had already rolled back, raising "Record does not exist or has been deleted". To fix this issue we run as dryrun as False to allow the execute_import's savepoint do the work and rollbacked in finally. Steps to reproduce: - Just import a account.bank.statement.line OPW-6410352 Forward-Port-Of: odoo/enterprise#125389
Fixed an issue where importing a Chilean electronic tax document file containing multiple documents could put all invoice lines and references onto the first vendor bill. Each document is now handled separately, helping avoid incorrect bill totals and reconciliation problems.
Original PR description
When importing an EnvioDTE XML containing several DTEs (journal upload or incoming DTE mail server), one vendor bill is created per DTE, but the first bill receives the invoice lines and references…
When importing an EnvioDTE XML containing several DTEs (journal upload or incoming DTE mail server), one vendor bill is created per DTE, but the first bill receives the invoice lines and references of ALL the DTEs in the file, causing the total amount mismatch.
Cause: `_split_xml_into_new_attachments()` creates new attachments for the documents beyond the first one but leaves the original `file_data['xml_tree']` untouched; the decoder must scope itself to the first document (as l10n_it_edi and l10n_es_edi_facturae do), which `_l10n_cl_import_dte()` never did.
e.g. l10n_es_edi_facturae:633:
```python
# Only decode the first invoice of the Factura-e file.
tree = tree.xpath('//Invoice')[0]
```
Fix: scope the tree to the first DTE node before filling the bill. Kept behind a `len > 1` guard so files with a bare <DTE> root (matched by `xpath('//ns0:DTE')` but not by `findall('.//ns0:DTE')`) keep working.
Introduced in: https://github.com/odoo/enterprise/pull/75327.
opw-6378954
Forward-Port-Of: odoo/enterprise#124691Budget reports no longer time out when opened from budget records on databases with large accounting and purchasing volumes. The change makes report loading much faster by applying budget filters earlier, restoring usability for finance teams working with large budgets.
Original PR description
**Description** Opening the Budget Report from any budget record times out on databases with significant data volume. The request to `budget.report/formatted_read_grouping_sets` consistently times…
**Description**
Opening the Budget Report from any budget record times out on databases
with significant data volume. The request to
`budget.report/formatted_read_grouping_sets` consistently times out,
making the Budget Report completely unusable.
**Root cause:**
`budget.report` is an SQL view that consists of 5 UNION ALL branches.
When the list view loads, the ORM translates the `budget_analytic_id`
domain into a WHERE clause on the outer query wrapping the full UNION
ALL subquery. PostgreSQL cannot push this filter through a UNION ALL as
it's a hard optimization barrier. It must fully materialize the subquery
regardless of which budget is being viewed.
**Fix:**
Override _search on budget.report to extract budget_analytic_id and
budget_line_id conditions from the incoming domain using the Domain API.
budget_line_id is rewritten as Domain('id', op, value) so _to_sql()
correctly emits bl.id in the raw SQL. The resulting domain is injected
in context under budget_line_domain and read in _get_bl_query,
_get_aal_query (base module), and _get_pol_query (purchase module) to
filter budget_line rows inside each branch's LEFT JOIN ON clause.
This also removes the budget_report_budget_line_ids context key from
budget_line._compute_all, unifying both filters under one mechanism.
---
On customer DB (568k `account_analytic_line`, 27k `budget_line`,
116k confirmed `purchase_order_line`, 114k posted vendor bill lines
with purchase link):
| Budget | Before | After |
|---|---|---|
| 8 lines, 730d span | timeout | 2.27s |
| 14 lines | timeout | 2.39s |
| 14 lines, 1095d span | timeout | 1.63s |
- Before: https://explain.dalibo.com/plan/ehed5eb8de251426
- After: https://explain.dalibo.com/plan/db8aef35cag9hg6f
opw-6098047
Forward-Port-Of: odoo/enterprise#120707
Forward-Port-Of: odoo/enterprise#114692This fix ensures Colombian city postal codes with fewer digits are formatted correctly before being sent to the Envia delivery service. It helps prevent delivery failures for affected Colombian locations such as Antioquia, improving reliability for shipments to and from those cities.
Original PR description
Issue ----- Delivery does not always work from/to some cities in Colombia, like Antioquia. Cause ----- There was an oversight in fix 7654c55 where only 5 digit postal codes taken from the colombian…
Issue ----- Delivery does not always work from/to some cities in Colombia, like Antioquia. Cause ----- There was an oversight in fix 7654c55 where only 5 digit postal codes taken from the colombian localisation were padded in https://github.com/odoo/enterprise/blob/390acf532e8932fd9b9a708382a5e36cdbb35754/delivery_envia/models/envia_request.py#L726-L727 However, some of the colombian cities listed in `l10n_co_edi/data/res.city.csv` have 4 digit codes (like `SANTA FÉ DE ANTIOQUIA`, code `5042`). https://github.com/odoo/enterprise/blob/7cceddaf086d849b8e2121e1023ef3479397534f/l10n_co_edi/data/res.city.csv#L12 These 4 digit codes have to be right-padded to 5 characters before the left-padding to match the official colombian zip codes. See colombian gov official document (PDF download) where the code is actually `05042`. https://www.dane.gov.co/files/censo2005/provincias/subregiones.pdf ----- Ticket: opw-6248252 Forward-Port-Of: odoo/enterprise#123344 Forward-Port-Of: odoo/enterprise#120164
This fixes how the French VAT report fills the BA zone so it uses the required free-text field format instead of a numeric value. The change helps ensure generated VAT reports comply with the expected French reporting structure and reduces filing errors.
Original PR description
The value inside the BA zone needs to be a "TexteLibre1" and not a value no task id Forward-Port-Of: odoo/enterprise#125335
The timesheet percentage now stays current as users add, edit, or remove timesheet entries. This avoids confusion from outdated percentages remaining visible until the page is reloaded.
Original PR description
Issue: The percentage is only updated after reloading the page. Cause: The percentage computation is performed inside `loadTimesheets`, which is only called when the timesheets are loaded. Fix: Move the percentage computation into a helper function and invoke it whenever a timesheet is added, updated, or removed. task-6401186 Forward-Port-Of: odoo/enterprise#125312 Forward-Port-Of: odoo/enterprise#125074
Applying engineering change orders with attached documents now uses the correct attachment reference, preventing errors during the Apply Changes step. This helps manufacturing and PLM users complete product revision updates reliably when documents are involved.
Original PR description
When applying an ECO, `action_apply` copies each ECO document onto the product template and fills `origin_attachment_id` with `attach.id`. That field is a many2one to `ir.attachment`, but `attach` is a `product.document`. Steps to reproduce: - Create an `mrp.eco` record and start a new revision - Upload a document on the ECO, note its product.document id - Make sure no ir.attachment exists with that same id - Move the ECO to its final stage and hit "Apply Changes" - Observe the error The very same change was already applied on master by 3a39186f883, but was never backported. opw-6387343 Forward-Port-Of: odoo/enterprise#124950
The employee Documents button now correctly counts and opens signed contract documents, even when they are linked through employee contract versions. This helps HR users reliably find completed employee contract paperwork from the employee record.
Original PR description
[FIX] documents_{hr|sign}: employee docs button for signed contracts Bug reproduction: 1 - In saas-19.4, install documents_hr and hr_contract_salary with demo data 2 - As Mitchell Admin, go to…
[FIX] documents_{hr|sign}: employee docs button for signed contracts
Bug reproduction:
1 - In saas-19.4, install documents_hr and hr_contract_salary with demo data
2 - As Mitchell Admin, go to Employees, open one, click on "Offers - New"
3 - Select employee_contract.pdf as PDF Template
4 - Use the button "Salary configurator" to fill in the configurator, review it and sign it.
5 - Go back to the backend, find the contract in Sign and sign it.
6 - Go back to the Employee form view, the Documents stat button shows 0 document when it should be 1.
7 - Click the stat button and you see 0 documents in Documents when there should be one.
Bug cause:
1 - The document is created for the employee in documents app
but smart button cannot open those
2 - The res_model of the documents.document is hr.version for signed doc
-> it is not hr.employee
3 - In current implementation:
3.1 -> only hr.employee's documents appear after that smart button
Bug solution:
1 - _compute_document_count is reimplemented:
-> to count also documents with res_model as hr.version
2 - override _get_documents_domain:
-> to add version domain as an alternative with OR
-> to get documents with res_model='hr.version'
Test:
1 - Unit test is added
2 - Create documents with the archived versions of the employee
-> and observe the document count of the employee
Note:
-> Also, we changed the final document name in documents of the employee
task-6373620
Forward-Port-Of: odoo/enterprise#123763Users can now rename Studio fields with labels written in Arabic or other non-Latin scripts without triggering an invalid field name error. This prevents a confusing failure when creating or editing fields for multilingual users, while keeping the existing technical field name when a safe new one cannot be generated.
Original PR description
Steps: - Install web_studio - Add any field (example char field) to any view - Rename it in arabic, example `السَّلَامُ عَلَيْكُمْ` - Error Custom field names cannot contain double underscores Webclient (view_editor_model) escape every non-alphabetic chars, so new label value contains nothing but a space which will be replaced by a _ this new label value will be concatenated to `x_studio_`. Resulting to the string `x_studio__`. A solution should be to prevent changing the technical name if the new label value (escaped) is empty. opw-6311027 Forward-Port-Of: odoo/enterprise#125299 Forward-Port-Of: odoo/enterprise#121343
Account reports opened from the VAT return check screen no longer fail after a browser refresh. This prevents users from losing access to the report view due to missing page information in the refreshed URL.
Original PR description
Opening an account report through the VAT return button on an account.return.check record returns an inline client action whose report_id only exists in context. On refresh, Odoo will throw an error because it will try to rebuild the action context based off of the URL which is deficient. This will not effect reports opened via the menu since those follow a different pathway. This fix anchors the inline action to the "path" property stored on the client action. A helper method was added for deriving the action_id from a given report. opw-6366964 Forward-Port-Of: odoo/enterprise#125246 Forward-Port-Of: odoo/enterprise#124560
The My Planning calendar now visually marks draft planning entries with the expected hatched style. This helps users quickly distinguish draft plans from confirmed ones and reduces confusion when reviewing schedules.
Original PR description
Issue: Calendar entries appear plain even when they should appear hatched. (ex. while in draft status) Steps to reproduce: If you create any planning and set it to draft. Then go to Planning > Planning > My Planning, the newly created plan should be in hatched but it becomes plain. Cause: In the view planning.slot.my.calendar there was missing the element that causes the views to become hatched when in draft status. Solution: Added said element. opw-6260055 Forward-Port-Of: odoo/enterprise#119153
Code cleanup and technical improvements
This change updates several Odoo Enterprise apps to work with the newer web interface framework. It is mainly an internal compatibility cleanup that helps keep fields, widgets, and patched components working reliably without changing business workflows.
Original PR description
Owl 3 turns a component's `props` into an instance field built by `useProps(schema)`, so the static `SomeComponent.props` attribute no longer resolves. The web components whose schema was read from here now export it as a const, so spread that const instead:
static props = { ...Many2OneField.props }
props = useProps({ ...many2OneFieldProps })
The owl2 descriptors used by the overriding components are translated to the new `t.*` schema at the same time, and subclasses that only re-declared the parent schema without adding anything simply drop their declaration and inherit it.
Patches that used to extend a component's props through `patch(Comp, {props})` now extend the exported schema directly, since patching the static attribute no longer has any effect.