Daily updates from Odoo
Wednesday, July 8, 2026
119 changes · saas-19.4
Security fixes and vulnerability patches
This update adds safeguards to prevent Sign's auto-write option from being enabled in situations where it could update records unintentionally or expose invalid fields. It also improves related checks and messaging so users get clearer feedback and sensitive information is better protected.
Original PR description
Fix scenarios where the auto-write feature could fail or be unsafe: - Prevent unsafe mass updates: Users could enable auto-write in bulk without proper awareness, leading to unintended behavior. Additionally, the field could be manually exposed even when no linked model/field is set. we add safeguards and constraints to prevent enabling it in invalid cases. - Improve test coverage: Update test cases to ensure correct behavior when users have access to partner records but must not be allowed to update sensitive fields (e.g., email) of other users through those records. task-6147410 Forward-Port-Of: odoo/enterprise#115118
Enhancements to existing features
This update adds missing translations for customer- and staff-facing messages across Point of Sale modules. It makes dialogs, errors, alerts, and warnings easier to understand for users working in supported languages.
Original PR description
pos* = All POS module In this commit: -------------------------------- Add missing translations for user-visible strings across POS modules. - Translated dialogs, errors, alerts, and other UI-visible messages - Updated Python-side UserError, ValidationError, and warning messages Task-5406947 Related PR-https://github.com/odoo/odoo/pull/239972 Forward-Port-Of: odoo/enterprise#122511 Forward-Port-Of: odoo/enterprise#102094
UK VAT returns now warn users when the selected company belongs to a tax unit and guide them to file using that tax unit. When a return covers a tax unit, Odoo uses the tax unit's VAT number for HMRC connection and submission, helping avoid filing under the wrong company VAT number.
Original PR description
BEFORE: - Before this commit, when the current company is a member of the tax unit, there is no blocking level error for the user to select the tax unit. - And the vat used while creating a connection to the HMRC or while sending a tax report to the HMRC is of the current company. AFTER: - After this commit, there is one blocking level error, which tells the user that the current company is part of a tax unit, and on confirmation, the tax unit will automatically be selected for the current report. - And if the return contains the data of a tax unit, then the vat set on the tax unit will be considered while establishing the connection and sending the tax report to HMRC. Task-5865605 Forward-Port-Of: odoo/enterprise#122965 Forward-Port-Of: odoo/enterprise#107253
Hong Kong payroll now participates in the automatic payroll data update process. This helps keep standard, unedited salary rules up to date without manual intervention, improving ongoing payroll accuracy and supportability.
Original PR description
Currently, the "Payroll: Update data" cron doesn't work for HK payroll as we never set up the _get_data_files_to_update. We can set up the list of data files to keep up to date to better support our users by automatically keeping non-edited salary rules up to date. task-6360339 Forward-Port-Of: odoo/enterprise#122777
Manufacturing shop floor users can now update the most recent timer entry or create one when no entry exists. This helps keep work order time tracking accurate when someone forgets to start or stop the timer.
Original PR description
The "Update Time Log" dialog inside shopfloor is added to increase the timer's reliability by manually entering the desired time. If someone forgot to start or stop the timer, this option now enables them to edit their last entry on the timer's list, or create a new one if none was found. Task: 6164336
The printer settings now only show the oBox IP field when it is relevant for ePOS printers. The interface also hides technical service details from the oBox view, making setup cleaner and easier for users.
Original PR description
This PR adapts the view to only allow the user to set obox ip if the type of printer used is epos as it doesnt matter otherwise It also hides the services installed on the obox as it's not useful for the user task-6330864
Belgian blackbox POS sessions now warn cashiers when they need to be closed within the required 24-hour window, helping businesses stay compliant with fiscal reporting rules. Session and sale detail reports also better reflect negative quantities and refunds, and self-ordering with a blackbox now requires the appropriate Belgian self-ordering module.
Original PR description
Belgian fiscal regulations require a blackbox POS session to be closed at least once every 24h so the Z reports are sent to the FDM. The POS now warns the cashier once the session should be closed. Also: - include negative lines of regular orders in the negative quantities summary of session reports, and show them as positive amounts in the refund tables of the sale details report as required by the SPF - require `l10n_be_pos_blackbox_self_order` when self-ordering (mobile/kiosk) is enabled with a blackbox community PR: https://github.com/odoo/odoo/pull/273994 Forward-Port-Of: odoo/enterprise#122411
The Azerbaijani Manat currency symbol has been updated to its official Unicode character, ₼. This improves consistency and makes currency display more accurate for users working with AZN.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 task-6112867 Forward-Port-Of: odoo/odoo#262471
The forum editor toolbar has been simplified by removing options that are not needed in that context, and its styling has been adjusted to stay consistent with the forum design. This update also fixes an issue that could cause errors when opening table editing tools, improving the editor’s reliability for forum users.
Original PR description
Description of the feature this PR addresses: - Remove unwanted toolbar features (heading, font_family, powerbuttons, undo/redo buttons) - Update toolbar styles in website_forum to keep them consistent - Fix table menu traceback by passing missing `localOverlayContainers` in `website_forum_wysiwyg` config task-6123698 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274139 Forward-Port-Of: odoo/odoo#263326
This change speeds up the creation of backorders when validating receipts with many operations. It reduces processing time and avoids database memory errors, so large warehouse receipts are much less likely to time out.
Original PR description
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of…
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of moves in the picking, and M is the number of moves being processed for valuation. This happened while computing price units for moves one by one: each move filtered all picking moves to find the ones with the same `product_id`. Another issue was a PostgreSQL `"memory exhausted"` error caused by generating a large number of OR'ed conditions, equal to the number of processed moves. ## The Solution The massive filtering was fixed by filtering moves of the `purchase_line` instead of the `picking`, which is typically associated with only a few moves. This is still correct as the loop just after already ignores moves that don't have the same `purchase_line_id` of `self` anyways. The PostgreSQL error was fixed by grouping moves by `location_dest_id` and generating one condition per location using an `in` clause, which is typically much smaller than generating one condition per move. ## Benchmark Benchmark on a customer database, validating a receipt with 10k+ operations by creating a backorder: ```text Time: timeout -> 6 min ``` OPW-6272667 Forward-Port-Of: odoo/odoo#273555 Forward-Port-Of: odoo/odoo#269350
This change makes the tax supply date available for German accounting documents. It helps businesses record taxes more accurately according to the relevant supply date, improving compliance and consistency in tax reporting.
Original PR description
Forward-Port-Of: odoo/odoo#272461
This update refreshes the web editing engine to the latest Owl version used by Odoo. It helps keep the platform aligned with the newest underlying framework changes and avoids issues caused by internal API changes in the editor.
Original PR description
Release notes: https://github.com/odoo/owl/releases/tag/v3.0.0-alpha.42 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 brings back automated tests for the French POS payment and invoicing flow that were temporarily removed during a previous merge. It helps ensure the process keeps working correctly and reduces the risk of regressions in future changes.
Original PR description
During the merge of l10n_fr_pdp e-reporting and e-invoicing, some tests had to be removed. Task-6296356 Forward-Port-Of: odoo/odoo#273913 Forward-Port-Of: odoo/odoo#271294
Resolved issues and error corrections
Odoo now saves the reply count returned by Twitter/X for social stream posts. This lets users see comment activity alongside other engagement metrics, giving a more complete view of post performance.
Original PR description
Twitter/X tweet metrics returned by the API include the number of replies in the `public_metrics.reply_count` field. This commit stores that value on social stream posts so the comments count can be displayed alongside other engagement metrics. API Documentation: https://docs.x.com/x-api/fundamentals/metrics#post-metrics Task-6251172 Forward-Port-Of: odoo/enterprise#120182
The scheduled process that updates Mexican electronic invoice statuses now correctly continues when more documents remain to be processed. This prevents leftover invoices from being skipped when processing runs in smaller batches.
Original PR description
Steps to reproduce ----------------- - Install l10n_mx_edi; - Switch to the mexican company; - Create 3 invoices for the mexican company (you will need to set an UNSPSC code on the products); - Send them to CFDI; - Go to the scheduled action "Automatic update of state on the SAT" and add "batch_size=2" to the method's parameters; - Manually run the cron; - Only two invoices will be updated, the cron is not retriggered to process the remianing one. Why is it hapening ------------------ We set a limit of batch_size + 1 in the search method, and the cron is retriggered if and only if the number of documents fetched is equal to the batch size, meaning there is no more documents to fetch. This should be triggered if we fetched more documents than the batch size. opw-6328118 Forward-Port-Of: odoo/enterprise#122659
Task progress in the Gantt view now shows the expected filled portion based on hours worked versus allocated hours. This makes scheduling and field service task tracking clearer, avoiding misleading progress bars that appeared almost empty despite substantial work being logged.
Original PR description
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same…
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same task for 10h 4. Navigate to FSM > My Tasks > Gantt view Observation: ------------------------------------------- Look at the task on the Gantt chart. The shading is barely visible because it covers only 0.5% of the bar, not 50% Issue: ------------------------------------------- In the commit https://github.com/odoo/odoo/pull/137570/changes/4a93d9aee957dd3feb3db0cb69eb3b8f0f4a4683 The progress field computation was changed from storing percentage values (0-100) to storing decimal values (0-1). Specifically, the `_compute_progress_hours` method was modified. This change was made to standardize the progress field storage format, with the understanding that the UI layer would multiply by 100 when displaying the value. While most views (form, list, kanban, etc.) were updated to multiply the progress by 100 for display purposes, the Gantt view's pill progress bar was missed. Solution: ------------------------------------------- Overrides the `enrichPill` method to multiply the `_progress` value by 100 before it's passed to the template. This ensures the Gantt pill progress bars display correctly without modifying the core web_gantt module. Before --------------------------- <img width="268" height="368" alt="image" src="https://github.com/user-attachments/assets/6d35927f-bd3f-47fc-9101-e2e188d419b8" /> After: -------------------------- <img width="250" height="371" alt="image" src="https://github.com/user-attachments/assets/fe7133e0-26d1-4c5f-b903-48826fda9488" /> opw-6038983 Forward-Port-Of: odoo/enterprise#122899 Forward-Port-Of: odoo/enterprise#111270
Fixes issues in subscription loyalty programs so invoices can correctly grant points, respect the configured point calculation mode, and avoid incorrect negative reward invoice lines. It also restores visibility of recurring options in loyalty rules and rewards, improving reliability for teams using recurring loyalty benefits.
Original PR description
This commit fixes the following problems in the new module: - New invoices sometimes could not grant points according to the specified rules. - The reward point mode was not being taken into account and was giving a flat amount of points. - Reward lines were being invoiced with a negative amount when there was no more points in the loyalty card. - The 'Recurring' option in conditional rules and reward were not showing sometimes for an unknown reason. task-6153127 Forward-Port-Of: odoo/enterprise#116713
The task Gantt view now loads correctly when grouped by Sale Order Item. This prevents an error caused by an outdated hours field name, allowing teams to review project work and sales-linked tasks without interruption.
Original PR description
### Steps to reproduce - Install `sale_timesheet_enterprise`. - Go to **Tasks → All Tasks**. - Switch to the **Gantt** view. - Group by **Sale Order Item** (`sale_line_id`). ### Issue A traceback is…
### Steps to reproduce - Install `sale_timesheet_enterprise`. - Go to **Tasks → All Tasks**. - Switch to the **Gantt** view. - Group by **Sale Order Item** (`sale_line_id`). ### Issue A traceback is raised when loading the Gantt view with group by `sale_line_id`: ```text ValueError: Invalid field 'planned_hours' on model 'project.task' for 'planned_hours:sum' ``` ### Root cause The Gantt progress bar computation for the `sale_line_id` grouping performs a `_read_group()` aggregation on the `planned_hours` field of `project.task`. However, `planned_hours` was renamed to `allocated_hours` during the saas-16.5 migration, so the former field no longer exists on `project.task`. As a result, the aggregation raises a `ValueError`. Migration reference: https://github.com/odoo/upgrade/blob/e638c6ce00d9d8936d034ad7130fef51565b9195/migrations/project/saas~16.5.1.2/pre-migrate.py#L10 Issued PR: https://github.com/odoo/enterprise/pull/49685 ### Fix Use `allocated_hours`, the renamed equivalent of `planned_hours`, when computing the Gantt progress bar. This restores the Gantt view when grouping tasks by **Sale Order Item** and prevents the traceback. Forward-Port-Of: odoo/enterprise#122994 Forward-Port-Of: odoo/enterprise#122297
Field service interventions now require both a start and end date before they can be marked complete. Send and publish actions are hidden when no date is set, helping teams avoid incomplete or incorrectly scheduled interventions.
Original PR description
After this PR: - Both dates are required to use the 'Complete' action button on an intervention - If the start date is set on an intervention, the end date should be required (and vice versa) - We hide the 'Send' and 'Publish' buttons if there is no date set task-6234939 Forward-Port-Of: odoo/enterprise#118411
This fix ensures Colombian electronic invoices using the Folder or Wave layouts display the company address properly in the PDF header. It also prevents the invoice title from overlapping with the QR code, improving document readability and compliance presentation.
Original PR description
Issue: On Wave and Folder layout, the address of the company doesn't appear on invoices. Steps to reproduce: - In a Colombian company, - Set company layout to Folder - Add a long tag line, - Create an invoice, - Send it to DIAN - Export to PDF Current behavior: - Company address is missing in the header Cause: Tag line + logo and address take 100% of the display width. However, loca add a QR code on the left, so it takes QR Code + 100% width. Therefore, address was out of the PDF. Moreover, for Folder layout, some resizing was done and as soon as there was a tag_line, the `rem` was downsized, allowing the invoice title: "Factura Electrónica de Venta SETP/*\*\*/\*\*\*\*" to be displayed entirely. The fix of the previous issue stopped the resizing, then the invoice title got overridden by the QR Code (same as without tag_line before this fix). opw-6239030 Forward-Port-Of: odoo/enterprise#119678
Fixes a problem where required country-specific customer details were missing when creating or editing customers from the Point of Sale. This ensures businesses in affected countries can capture the information needed for invoicing and compliance, while adding safeguards to prevent the issue from returning.
Original PR description
*: br,cl,ec,gt,it,ke,mx **Problem:** The POS "Edit/Create customer" Form was switched to a standalone, hardcoded form view (view_partner_form_pos_ui) that inherits nothing during [1], in the attempt…
*: br,cl,ec,gt,it,ke,mx **Problem:** The POS "Edit/Create customer" Form was switched to a standalone, hardcoded form view (view_partner_form_pos_ui) that inherits nothing during [1], in the attempt to simplify the view when accessed from the PoS. Every field that localizations and other modules add to the partner form by inheriting base.view_partner_form therefore disappeared when accessed from PoS. Some of the fields are required, for example, to invoice. **Solution:** Keep the simplified view as the default, but route the view selection through an overridable hook that localization can tweak case by case. The override is applied to the affected POS bridges (see module list). Add a test to prevent future regression. **Note:** Another possibility is to re-inherit for each localization the new standalone view, but this fix would need to update the module to work, while this one works with just a restart. There are still ongoing discussion with PoS team to see if we really want to go back to each localization needing to inherit backend views. [1]: https://github.com/odoo/odoo/pull/230721/changes#diff-66cd201e7e8cfff5218a9fa93efd72f0> opw-6244777 (many more) Forward-Port-Of: odoo/enterprise#119316
The timesheet assistant no longer shows an empty Unmatched section when all items in that group are filtered out as away-from-keyboard events. This avoids confusing users with a section header that has no visible content.
Original PR description
The Unmatched group's header renders even when its only entries are afk events, since those are filtered out at display time but still counted when checking if the group has content. With this PR, we first check if a group has visible content before displaying the header Task-6348666 Forward-Port-Of: odoo/enterprise#122900 Forward-Port-Of: odoo/enterprise#122858
The shop floor now respects manufacturing settings that block creation of new serial or lot numbers for components. This prevents operators from bypassing configured inventory controls and keeps manufacturing traceability rules consistent.
Original PR description
**Issue**: Even when creation of new Serial Numbers for components is disabled on the Manufacturing Operation Type, it is still possible to create them from the shopfloor application. **Steps to…
**Issue**: Even when creation of new Serial Numbers for components is disabled on the Manufacturing Operation Type, it is still possible to create them from the shopfloor application. **Steps to reproduce**: - Enable "Lots & Serial Numbers", on the global settings - Create two products, one tracked by unique serial number - Go to Inventory > Configuration > Warehouse Management > Operations Types - Select Manufacturing and disable "Create New Lots/Serial Numbers for Components" - Create and confirm a MO using the tracked product as component - Go to shopfloor - Click the "+" button next to the component, then "New" -> No error is raised when creating a serial number **Cause**: The `_check_create` constraint relies on `active_mo_id`: https://github.com/odoo/odoo/blob/494cdcfdf4ec166e0a643ee70a53c12c810d02b4/addons/mrp/models/stock_lot.py#L11-L19 However, the shopfloor does not pass this, in context: https://github.com/odoo/enterprise/blob/54c6252a0e13b11fc297b6828883923c0f89881a/mrp_workorder/static/src/mrp_display/mrp_record_line/stock_move.js#L193-L199 As a result, the check is bypassed. opw-6041241 Forward-Port-Of: odoo/enterprise#114641 Forward-Port-Of: odoo/enterprise#111408
Creating an approval request for a purchase quote no longer fails when a product has vendors the user is not allowed to access. This prevents unnecessary access errors in multi-company setups and lets users continue the approval process with the vendors available to them.
Original PR description
**Issue** Having supplier pricelists with at least one vendor inaccessible to the current user can trigger an access error when creating an RFQ approval request. **Steps to reproduce** - Have two…
**Issue** Having supplier pricelists with at least one vendor inaccessible to the current user can trigger an access error when creating an RFQ approval request. **Steps to reproduce** - Have two companies A and B and two users u1 and u2 - user u2 only have access to company A - With user u1: - Create two vendors v1 and v2 without any company assigned - Create vendor pricelists for a product for each vendor and assign the company A to the pricelist - Add the company B for the vendor v2 - With user u2: - Open approval application - Try to create an approval for an RFQ for that product (the vendor v1 will be automatically selected) - Save it -> An access error is thrown **Cause** Saving the approval request computes `has_no_seller`, which calls `_select_seller`: https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/views/approval_product_line_views.xml#L9 https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/models/approval_product_line.py#L32 https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/models/approval_product_line.py#L62-L70 Which filtered the right seller https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L759 By preparing the sellers: https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L721 https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L712 Please note that `self.seller_ids` contains both sellers (even v2) By filtering the suppliers: https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_supplierinfo.py#L104-L105 But at that point, one of the supplier in `self`, can be accessed, thus an access error is thrown while trying to access its associated `partner_id`. opw-6203910 Forward-Port-Of: odoo/enterprise#121008 Forward-Port-Of: odoo/enterprise#120251
Hong Kong payroll now calculates payment in lieu of notice based on the employee's actual contract start date instead of assuming a full 12 months of employment. This helps produce more accurate final pay amounts for employees with shorter service periods and adds tests for related edge cases.
Original PR description
Currently, the calculation of the payment in lieu of notice is assuming the employee worked a whole 12 months prior to it being paid. This is of course not always going the be case, and when it happens our calculation is often incorrect. We update the salary rule to calculate a more accurate total days (which is no longer based on a fixed 12-month period but takes into account the contract's start date). We also now calculate the number of months more accurately by taking, once again, the contract's start date into account. Also adding a few test cases to test a bit more some special case we didn't yet test correctly. task-6348903 Forward-Port-Of: odoo/enterprise#122580
Importing Belgian CODA bank files that include type 4 blocks now completes without an error. This prevents accounting users from being blocked when uploading affected bank statement files.
Original PR description
### Issue: After the fix in commit (https://github.com/odoo/enterprise/commit/3ef8ae7a6b8eb362e18c74dfab9aadce792b5dc2), importing a CODA file containing a type 4 block raises a traceback ### Cause: That commit introduced `communication_struct_by_ref_move`, which iterates over all lines and accesses `line['communication_struct']` Type 4 lines are not assigned a `communication_struct` value by the parser in `_get_coda_file_statements` Accessing the key directly raises a `KeyError` in `_get_coda_final_statements` in `communication_struct_by_ref_move` ### Steps to reproduce: - Install `l10n_be_coda` - Switch to the BE company - Create a Bank Journal with account `BE33737018595246` - Go to the Accounting Dashboard and import a CODA file containing a type 4 block (Like the one on the ticket) Before the fix, a traceback is raised on import opw-6363148 Forward-Port-Of: odoo/enterprise#123222
The point-of-sale Urban Piper test data now includes the required product category so order preparation checks can run correctly. This prevents a known automated test failure and helps keep future releases stable without changing customer-facing behavior.
Original PR description
This commit fixes a failing `pos.prep.order` test assertion by assigns a PoS category to the products used in the test orders. The failure occurs because the products used in the order lines do not have a PoS category assigned. As a result, the preparation order generation process fails when creating the corresponding `pos.prep.order`. Runbot Error-[242023](https://runbot.odoo.com/odoo/runbot.build.error/242023)
Employees without a fixed or average working schedule will no longer see misleading expected hours in the Timesheet Assistant or systray. Total hours remain visible, reducing confusion for teams using variable or no scheduled working hours.
Original PR description
**Steps to reproduce:** 1. Create an employee without a fixed working schedule. 2. Configure the employee with variable hours per day, per week, or no working hours at all. 3. Open the Timesheet Assistant or the Timesheet systray. 4. Observe that expected hours are displayed (over 0h 00m or over 24h 00m). **Cause:** Expected working hours were always computed and displayed, even for resources without a fixed schedule. **Fix:** Only compute expected working hours when the employee has a fixed or average schedule, and rely on the computed working hours to control the display of expected hours while keeping total hours always visible. task-6321760 Forward-Port-Of: odoo/enterprise#122859 Forward-Port-Of: odoo/enterprise#122232
Pasting document links into an empty message no longer adds an unnecessary blank line at the start. Existing message text still stays separated from pasted links, keeping messages neat and readable.
Original PR description
Before this commit, adding document links always prepended a line break before the generated links. When the composer was empty, this resulted in messages starting with an unnecessary blank line. This commit only inserts a line break when the composer already contains text, avoiding the extra spacing while preserving the separation between existing content and pasted links. task-[5947683](https://www.odoo.com/odoo/project/1519/tasks/5947683) Forward-Port-Of: odoo/enterprise#120952
The Timesheet Assistant now checks whether timesheets are allowed on a matched project before offering to add time. This prevents users from starting timesheet entries for projects where timesheet tracking has been disabled, reducing confusion and invalid actions.
Original PR description
Before this commit, the Timesheet Assistant would display the "Add" button and attempt to prefill timesheet forms for activities matched to projects where the `allow_timesheets` setting was set to `False`. This commit updates the Timesheet Assistant logic to evaluate the project's configuration. When an activity is matched to a project that has `allow_timesheets=False`: - The "Add" button is hidden from the suggestion list. - The system prevents prefilling the timesheet creation form. Task: 6306203 Forward-Port-Of: odoo/enterprise#123071 Forward-Port-Of: odoo/enterprise#120890
The website now shows the exact discount percentage configured by the merchant for subscription products, even when prices are displayed with tax included. This prevents customers from seeing an incorrect lower discount, such as 4% instead of 5%, during checkout or product selection.
Original PR description
Steps to reproduce: 1. Install eCommerce and Subscriptions. 2. Create a 21% Excluded tax. 3. Create a subscription product with a price of 45 with 21% tax and enable "Accept One-Time" in the…
Steps to reproduce: 1. Install eCommerce and Subscriptions. 2. Create a 21% Excluded tax. 3. Create a subscription product with a price of 45 with 21% tax and enable "Accept One-Time" in the Recurring Prices tab. 4. Publish the product on the website under the Sales tab. 5. Create a pricelist for 6 months recurring with two lines: - If min quantity is 0, then 0% discount - If min quantity is 2, then 5% discount 6. Set "Display Product Prices" to "Tax Included" in the Settings. 7. Open the product on the website, select the 6-month plan, and increase quantity to 2. Issue: The discount percentage displayed on the website shows 4% instead of the configured 5%. Why this happens: In `_get_additionnal_combination_info`, the discount is reverse-calculated from the tax-included price vs the tax-included sales price. When the 21% tax is included to both prices, it introduces a floating-point precision loss (4.9954..%), which floor() then truncates to 4%. Fix: When the pricelist rule uses 'percentage' discount, read `percent_price` directly from the pricing rule instead of reverse-calculating from tax-adjusted prices, as it represents the exact discount percentage the merchant configured with no floating-point involvement. opw-6224735 Forward-Port-Of: odoo/enterprise#121654
New planning shifts now default to 8 AM to 4 PM in the user's own timezone instead of being shifted by UTC conversion. This prevents schedules from appearing at the wrong hours for employees in locations such as Belgium.
Original PR description
Before: When creating a new shift, we set 8 AM - 4 PM as the default hours in UTC. With the timezone in Belgium, this becomes 10 AM - 6 PM. After: Change the timezone of the new shift to match the user's timezone. This will make the hours always be from 8 to 4 (working hours) --- task-6285596 Forward-Port-Of: odoo/enterprise#120062
This fixes cases where comments in Knowledge articles did not appear immediately after reopening an article or were shown in the wrong vertical position. Users can now reliably see comments where they belong without needing to switch articles or interact with comment areas to refresh them.
Original PR description
### [FIX] knowledge: load comments on first load There was an issue where comments are not displayed when opening an article containing some. How to reproduce: - create a new article, write some text…
### [FIX] knowledge: load comments on first load There was an issue where comments are not displayed when opening an article containing some. How to reproduce: - create a new article, write some text and add some comments. - reload the page Issue: - comments are not displayed, but they are when switching back and forth to another article Reason: Owl2 -> Owl3 refactoring: commit [1] replaced useRecordObserver by onWillUpdateProps, however the 2 are not equivalent, especially over the timing of the first call (useRecordObserver callback is called during setup). ### [FIX] knowledge: batch vertical dimensions computation once There was an issue where comments were not displayed at their correct position (height/top) in "handler" mode. How to reproduce: - create an article with 3 comments over 5 lines, following a given pattern: - one comment on the first line - one comment on the second line - keep the third line empty - one comment across the 4th and 5th lines - reload the page (issue 1) - click successively on the 3 comments zones (issue 2) Issue: - issue 1: the comments on reload overlap each other while they should not - issue 2: when clicking on the 3rd comment, the 1st and 2nd comments appear offset by an abnormal vertical distance (which should not exist) Reason: Owl2 -> Owl3 refactoring: Commit [1] replaced reactive + batched callback with `useEffect` executing that same batched callback, however `useEffect` is already batched starting from the second call, effectively batching twice, which resulted in the wrong dimensions being computed for knowledge comments in the comments_handler [1]: https://github.com/odoo/enterprise/commit/ab1e2cad9a214a1303e13fdff0e8a62781ef56ee task-6370985
This update fixes how eco vouchers are calculated in Belgian payroll, helping ensure employees receive the correct benefit amounts. It also updates related payroll checks to reduce the risk of incorrect payslips or reporting for Belgian employers.
Original PR description
Forward-Port-Of: odoo/enterprise#119074
This fixes several issues in how taxes are calculated and validated when switching tax modes on invoices, sales, and purchase documents. It also improves consistency for imported Italian invoices and removes a rounding inconsistency that could affect purchase totals.
Original PR description
- changing python constraint on document tax mode on account.move to SQL - style enhancements to the overlap_badge_tab and new component - removing inconsistent rounding in purchase.order - adding document tax mode logic to account.tax compute_all method - adding missing document tax mode ‘tax_excluded’ setting to l10n_it_edi during account.move creation of imported invoices odoo/odoo/pull/272730 Following up: https://github.com/odoo/odoo/pull/251800
This fix prevents delivery tracking from failing when EasyPost sends an empty tracker value. Users can continue working without seeing an error when opening or processing shipments affected by this carrier response.
Original PR description
The PR https://github.com/odoo/enterprise/pull/111833 handled the specific case when the tracker data is missing from the EasyPost response, however in certain cases `tracker` key exists, but it has a `None` value, which leads to a traceback when trying to access the stock move:
```
File "/home/odoo/src/enterprise/18.0/delivery_easypost/models/easypost_request.py", line 392, in get_tracking_link
public_url = shipment.get('tracker', {}).get('public_url')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'
```
This commit provides a fallback to avoid getting the error from the side of the user.
opw-6270242
Forward-Port-Of: odoo/enterprise#119400Popovers in dark mode now display secondary buttons and embedded forms with clearer, consistent styling. This makes actions easier to recognize and keeps screens such as event slot creation visually aligned with the rest of the interface.
Original PR description
Before this commit, content like form & secondary button rendered inside popovers had inconsistent styling in dark mode: - secondary buttons did not stand out properly from the popover background, making them look like plain text blocks rather than actionable buttons; - forms rendered inside popovers (such as the multi-create popover) kept their default background, which visually clashed with the popover background. This commit fixes these issues by: - adding dedicated secondary button background colors for popovers, including hover state; - aligning form backgrounds inside popovers with the popover background. task-6249985 Forward-Port-Of: odoo/enterprise#121631
Blank US checks now print the same stub detail lines that already appeared on pre-printed checks. The check layout was also adjusted so the full bottom section fits on a single page, reducing printing errors and wasted check stock.
Original PR description
See individual commits. task-6359599 Forward-Port-Of: odoo/enterprise#123144
The timesheet assistant now captures more time spent inside Odoo apps, even when the activity cannot be linked to a specific project, task, or ticket. This helps users see more complete time suggestions and fixes missed detections for some valid Odoo project URLs.
Original PR description
This PR adds support for tracking time spent in the Odoo apps in the assistant, for when we can't trace URLs to a project/task/ticket. The activities detected this way are marked as key events, such that each appears as an individual line in the assistant suggestions. With this, most of the time users spend working in their Odoo database should be reflected in the assistant suggestions. Task-6250449 Forward-Port-Of: odoo/enterprise#119096
Fixes an issue where mobile self-ordering could miss preparation receipt printing because it handled order updates differently from kiosk mode. Mobile self-ordering now uses the IoT Box websocket printing path, improving reliability when customers are not on the same network as the IoT Box.
Original PR description
Self ordering mobile now aligns on kiosk avoiding to update last order changes, which would prevent from printing preparation receipts. This is made possible by the IoT Box allowing to print receipts through websockets. We also take the opportunity to update the `iot_http` service in order to allow updating methods available on the service: it allows us adding a new method to disable longpolling for self ordering mobile, which would always fail, to end up using websocket (clients are not on the same network as the IoT Box). Forward-Port-Of: odoo/enterprise#121013
This fix prevents Hong Kong payroll payslips from crashing when a user clears the start or end date. The system now safely skips date-based wage and year-end pay calculations until the required dates are present, improving reliability during payroll editing.
Original PR description
Currently, an error occurs when a user removes the payslip date. **Steps to Reproduce:** - Install `l10n_hk_hr_payroll` with demo data. - Switch to the `Hong Kong` company. - Go to `Payroll` >…
Currently, an error occurs when a user removes the payslip date. **Steps to Reproduce:** - Install `l10n_hk_hr_payroll` with demo data. - Switch to the `Hong Kong` company. - Go to `Payroll` > `Payslips` > `Payslips`. - Create a `payslip` and remove the `start` or `end` period. **Error 1:** `TypeError: unsupported operand type(s) for +: 'bool' and 'relativedelta'` **Error2:** `AttributeError: 'bool' object has no attribute 'month'` When a user removes the start or end date of a payslip, the system computes the Average Daily Wage. Based on the payslip dates, it finds the previous year's payslips [1]. If the start or end date is not set, it raises an error [2]. For the second error, when computing whether to include EOY pay, it compares the company's EOY pay date with the end date's month. If the end date is not set, accessing its month raises an error [3]. This commit ensures that when retrieving previous-year payslips, if the start or end date is not set, it returns an empty payslip recordset. It also ensures that when computing whether to include EOY pay, if the end date is not set, `include_eoy_pay` is set to `False`. [1]: https://github.com/odoo/enterprise/blob/ec8a009794863090351d91650aff727e6fbeab7e/l10n_hk_hr_payroll/models/hr_payslip.py#L124 [2]- https://github.com/odoo/enterprise/blob/ec8a009794863090351d91650aff727e6fbeab7e/l10n_hk_hr_payroll/models/hr_payslip.py#L209-L215 [3]- https://github.com/odoo/enterprise/blob/ec8a009794863090351d91650aff727e6fbeab7e/l10n_hk_hr_payroll/models/hr_payslip.py#L141 Forward-Port-Of: odoo/enterprise#123135 Forward-Port-Of: odoo/enterprise#120586
Marketing Automation now shows the correct reason when a campaign participant is removed because they no longer match the campaign filter. This prevents users from seeing a misleading "Record deleted" message when the related record still exists, improving clarity during campaign follow-up.
Original PR description
`sync_participants` calls `action_set_unlink` on every participant whose record is no longer in the campaign domain, and `action_set_unlink` writes "Record deleted" on each scheduled trace. The…
`sync_participants` calls `action_set_unlink` on every participant whose record is no longer in the campaign domain, and `action_set_unlink` writes "Record deleted" on each scheduled trace. The removed bucket also contains records that still exist but no longer match the campaign filter, so the cancelled trace dialog shows "Record deleted" even when the record was only filtered out. In `sync_participants`, the to_remove participants are split between those whose record still exists in the database (filtered out by the campaign domain) and those whose record was actually deleted. `action_set_unlink` accepts an optional `trace_message` argument, defaulting to "Record deleted", and the filtered-out batch passes "Record no longer matches campaign filter" so the cancelled trace dialog reflects the real cause. Steps to reproduce: 1. Install Marketing Automation and CRM. 2. Open Marketing Automation, create a campaign on Lead with filter Stage = New. 3. Add a begin activity to the workflow. 4. Open CRM, create a Lead in the New stage. 5. Back in the campaign, click Generate Participants. 6. In the CRM pipeline, drag the Lead from New to Qualified. 7. Back in the campaign, click Generate Participants again. 8. Open the Participants smart button, click the participant for the moved Lead. 9. Click the cancelled activity in the workflow timeline. => The activity dialog shows "Error message: Record deleted" although the Lead still exists. Ticket [link](https://www.odoo.com/odoo/project/49/tasks/6251264) opw-6251264 Forward-Port-Of: odoo/enterprise#118692
A bug in the Accounting Accountant control panel was fixed so actions that need accounting data services no longer fail with an error. This helps users complete bank reconciliation actions from the control panel without interruption.
Original PR description
Fixed an issue where selecting any action from the control panel that would use orm would result in an error because the orm service was undefined. no task id
Easypost commercial invoices now use the sales order currency when it is available, instead of defaulting to the company currency. This helps ensure international shipping documents match the customer order and reduces currency mismatches during fulfillment.
Original PR description
Issue ----- When shipping internationally with Easypost, the currency on the commercial invoice does not always match the one of the sale order. Steps to reproduce ----- - Install Easypost - Create a…
Issue ----- When shipping internationally with Easypost, the currency on the commercial invoice does not always match the one of the sale order. Steps to reproduce ----- - Install Easypost - Create a new pricelist using a different currency from the company - Create a SO - Some product with a weight & HS code - Customer must be in another country from company (for commercial invoice) - Use the new pricelist - Add easypost delivery - Confirm SO - Validate linked picking > Commercial invoice uses company currency instead of SO's Cause ----- The currency being sent to Easypost is retrieved from the package in https://github.com/odoo/enterprise/blob/4c540f450d4de8b59b871662123f85ed54cca2a9/delivery_easypost/models/easypost_request.py#L146 The package object is actually created by calling the carrier's `_get_packages_from_picking` method https://github.com/odoo/enterprise/blob/4c540f450d4de8b59b871662123f85ed54cca2a9/delivery_easypost/models/easypost_request.py#L266-L270 Solution ----- We could be fixing this in `stock_delivery` by creating the package with the correct currency when calling `_get_packages_from_picking`. The problem with this approach is that this might negatively affect other carrier services, as discussed in https://github.com/odoo/odoo/pull/268224. Instead, we can apply a band-aid fix to take the currency from the picking's sale in the `delivery_easypost` module, which is the only one where the problem was reported. ----- Ticket: opw-6224883 Forward-Port-Of: odoo/enterprise#123083
The Turkish Central Bank currency rate provider now uses the official selling rate instead of averaging buying and selling rates. This improves accounting accuracy and supports compliance with Turkish customs valuation requirements for imports.
Original PR description
## Short fix summary: The TCMB (Central Bank of Turkey) provider computed the exchange rate as an average of the buying and selling rates (`2 / (ForexBuying + ForexSelling)`). This is inaccurate for real accounting flows and does not follow Turkish customs regulation (Customs Law No. 4458, Art. 30), which requires the Central Bank's selling rate for goods import valuation. This now uses the selling rate (`ForexSelling`) only. task-6227500 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#122770
The Peru Profit and Loss report now includes Other Operating Income when calculating gross profit and related totals. This ensures key profitability figures reflect all relevant income, giving businesses more accurate financial reporting.
Original PR description
**Steps to reproduce:** 1. Install `l10n_pe` and switching to the Peru company. 2. Create and post a journal entry with a line on account 7520000 (Other Operating Income). 3. Open the Profit and Loss report (PE). 4. The amount appears correctly under "Other operating income" (`PE_PNL_A_5`). 5. "Gross profit", "Operating profit" , "Result before taxes" and "Net Profit" do not change when this amount is added or removed. **Issue:** The "Other operating income" line is excluded from the Gross Profit calculation, and consequently from Operating Profit and every downstream total in the PE Profit and Loss report. **Why this happens:** Gross Profit (`PE_PNL_A_4`) balance expression uses the aggregation with formula `PE_PNL_A.balance - PE_PNL_A_3.balance`, which doesn't include `PE_PNL_A_5.balance` as a term opw-6283907 Forward-Port-Of: odoo/enterprise#123063
Payroll processing now checks only the warnings that apply to the payslips being computed. This avoids unnecessary work during payroll runs and helps keep payslip calculations more efficient without changing the payroll results.
Original PR description
Ensure that we do not evaluate unnecessary warnings by only evaluating the warnings relevant to the payslips being computed; instead of evaluating all of them. task-6371828
This fix keeps Knowledge file navigation working consistently after a Chrome browser change. It preserves the previous behavior so users do not experience unexpected issues when scrolling to file content or related elements.
Original PR description
Since Chrome 150, scrolling methods like `scrollIntoView()` return a Promise instead of `undefined`. This commit adds block braces to ensure the action returns `undefined` and keeps the same behavior as before. Reference: - https://chromestatus.com/feature/5082138340491264 - https://chromium.googlesource.com/chromium/src/+/50f3e3d0a9bc02aad8b8161dbdd59046991dd2c7 runbot-941309 Forward-Port-Of: odoo/enterprise#123231 Forward-Port-Of: odoo/enterprise#123031
Grid view list titles now show the user-friendly label for grouped selection fields instead of internal technical values. This makes drill-down results easier to understand when users click the magnifier on grouped grid cells.
Original PR description
When grouping a grid view by a selection field and clicking on the cell magnifier, the list title showed the technical name (e.g. non_billable) instead of the display name (e.g. "Non Billable"). This commit adds a condition specifically for selection fields, ensuring that their display names are used. task-5980035 Forward-Port-Of: odoo/enterprise#122303 Forward-Port-Of: odoo/enterprise#120894
DHL shipment validation no longer fails for addresses in regions whose province or state code is stored as a single character, such as Barcelona. The delivery integration now sends DHL-compatible province codes, helping users validate and create shipments successfully for affected countries.
Original PR description
Steps:
- Install delivery_dhl_rest
- Create a new customer with barcelona as address
- Create a new Delivery
- Set DHL
- Validate de delivery
- Validation error #/customerDetails/receiverDetails/postalAddress/provinceCode: expected minLength: 2, actual: 1
DHL requires `provinceCode` to be at least 2 characters. Several countries in `res.country.state` data use single-character codes (e.g. ES: B, M, A…; AR: C, B, S…; CN: 京, 沪…). This caused API validation errors when shipping from or to addresses in those regions.
Add `PROVINCE_CODE_MAP`, a dict keyed by `(country_ISO2, state_code)`, mapping each offending code to its ISO 3166-2 form (e.g. ('ES', 'B') -> 'ES-B'). Both `_get_consignee_vals` and `_get_shipper_vals` now look up the map before sending `provinceCode`, falling back to the raw code for countries not in the map.
links: https://developer.dhl.com/api-reference/mydhl-api-dhl-express#shipments
opw-6341745
Forward-Port-Of: odoo/enterprise#122138Fixed a problem that caused the appointment slot form to crash when users clicked the fields for limiting a slot to specific users or resources. This keeps appointment configuration usable and removes a broken filter that was not providing any benefit.
Original PR description
Clicking the "Restrict to User" or "Restrict to Resources" field on a slot crashed with:
invalid input syntax for type integer: "appointment_type_id.staff_user_ids"
The field domain was a quoted string instead of a list, so it was passed through as a literal value. Remove the domain: it never filtered anything and only broke the form.
opw-6349497
Forward-Port-Of: odoo/enterprise#122651The French Intrastat export wizard now opens only the journal entries that are actually missing required Intrastat information. This helps users resolve export warnings faster and avoids confusion from seeing unrelated entries.
Original PR description
Steps to reproduce: 1. Have a French company with intrastat report module installed 2. Create and validate a bill to another EU country, without filling out at least one of the required intrastat fields 3. Go to the intrastat report, and export it as XML DEBWEB2 4. In the export wizard, click on the internal links on the warning messages Issues: 1. In the Intrastat report in French localization, when there are missing values detected in the export, the Export Wizard shows internal links that lead to every journal entries - instead of showing only the relevant entries. The warning banner on the report uses the action action_invalid_code_moves which has a domain to limit what is shown on the view form. However in the method _fill_value_errors there was no domain. opw-6215339 Forward-Port-Of: odoo/enterprise#117997
This fixes an error that occurred when users clicked the Measure button in Shop Floor after creating a Measure step. The correction ensures the measurement dialog receives the right information, so operators can continue quality checks without interruption.
Original PR description
Steps to reproduce: - Open Shop Floor - Create a Measure step - Click on the Measure Button - Encounter the error Upon further observation, it was noticed that the properties were not passed correctly to the MrpMeasureDialog component. This happened due to incorrect property definition in OWL 3, while with OWL 2 it was correct. Property definition was changed to comply with OWL 3. task-6345156
This fix aligns the call debrief player tests with updated playback behavior, removing outdated timing workarounds. It helps ensure segment navigation in AI call debriefs remains reliable and reduces the chance of regressions in audio playback.
Original PR description
BACKPORT OF https://github.com/odoo/enterprise/pull/121951 The corresponding community commit has refactored the deferred seek synchronization in the CallDebrief component removing the reliance on the 'loadeddata' media event. Because of this, we don't need to manually trigger the event or wait for extra animation frames in this test anymore. This commit cleans them up to match the new behavior. task-6321435 Community counterpart https://github.com/odoo/odoo/pull/273733
Users can now close the installer and web watcher warning banners in the Timesheets Assistant without triggering an error. This keeps the interface responsive and prevents dismissed messages from staying visible unexpectedly.
Original PR description
Issue: - Closing the installer banner or the web watcher warning banner in the Timesheets Assistant raises an Owl error and leaves the banner visible. Cause: - Both buttons bind their handler with a bare method name, e.g. `t-on-click="onDismissConnectionWarning"`. Bare identifiers are resolved against the template rendering context, which no longer exposes component methods. Fix: - Reference the handlers through `this`. task-6373382
This fix ensures the mailing editor's snippet selection dialog stays visible and usable when the AI chatbox is open. It prevents the editor from appearing frozen and lets users continue adding content, saving, or discarding changes normally.
Original PR description
When an AI chatbox is active, all non-error dialog overlays are set to be behind the chatbox through their z-index. This causes an issue where the dialog overlay that adds new snippets to a mailing is placed behind the fullscreen mailing editor, preventing its use and freezing the use of some commands (save & discard). This commit restores the snippet dialog's z-index to its original value. Steps to reproduce: - Create a new mailing - Select a builder-enabled theme (such as Events Promo) - Open a new AI chat by clicking the AI icon in the top right - Open the fullscreen editor - Click on the Headers block category task-6321624 Forward-Port-Of: odoo/enterprise#123377 Forward-Port-Of: odoo/enterprise#123276
Fixed an issue where the Balance Sheet report could crash after adding certain Studio fields linked to journal items and then filtering by analytic account. This helps accounting users access reports reliably without hitting a recursion error.
Original PR description
Steps to reproduce ================== - Activate Analytic Accounting. - Go to Accounting > Accounting > Reconcile. - Open Studio. - Add a new many2many field. - Set Journal Item as the related model. - Go to Reporting > Balance Sheet. - Select an analytic account. => RecursionError: maximum recursion depth exceeded Cause of the issue ================== Calling `self.env['account.move.line'].fields_get()` will cause a recursion error. `account.report::_prepare_lines_for_analytic_groupby()` calls `account.move.line::_where_calc()` which in turns calls _prepare_lines_for_analytic_groupby again Solution ======== It turns out we don't actually need to retrieve the groupable attribute, thus bypassing the error. opw-6129149 Forward-Port-Of: odoo/enterprise#122244 Forward-Port-Of: odoo/enterprise#116251
Fixed an error that could appear in Live Chat when a chatbot tries to transfer a visitor to an operator but none are configured. Instead of crashing the conversation, the system now handles this case safely so the chat can continue without an interruption.
Original PR description
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install…
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install ``im_livechat`` module with demo data - Go to Live Chat > Configuration > Chatbots > Create a new chatbot > Add script > Step Type: Question > Set answers > Save > Add script > Step Type: Forward to operator > Only If: Set one of the above answers > Save - Go to Live chat > Channel > Click the configure channel on YourWebsite.com > Remove the operators > Save - Go to the chatbot > test > select the configured answer Traceback: ```py StopIteration ``` https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/im_livechat/controllers/chatbot.py#L65-L70 When the chatbot script reaches a Forward to operator step while no operator is configured in the live chat channel, no chatbot message is created. As a result, the generator iterates over an empty iterator, and the ``next()`` call raises a ``StopIteration`` exception, causing a traceback during the conversation. sentry-7435424405 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274615 Forward-Port-Of: odoo/odoo#261726
The Point of Sale screen now shows the change due to the customer with the correct sign and amount. This fixes cases where refunds or overpayments could display misleading values, helping staff clearly see what should be returned.
Original PR description
Steps to Reproduce ------------------------ - Install point of sale. - Do a order and pay more than the amount. Issue ------ - The change amount is displayed as a positive value on the UI. - Typically, amounts going out of the shop (like change given to the customer) should be shown as negative. Cause ------- - The change amount was not correctly represented in the UI. - Since the change flows in the opposite direction of the payment, it should be displayed as the negation of the original amount. FIX ----- - Updated the frontend to display the change amount with the correct (negative) sign. - No backend changes were required, as the correct value was already being handled during order synchronization Enterprise PR: https://github.com/odoo/enterprise/pull/112560 task: 6074620 Forward-Port-Of: odoo/odoo#274534 Forward-Port-Of: odoo/odoo#256776
This change updates a payment-related test to use a smaller, more targeted XML sample instead of generating a full XML file. It helps make the test more reliable and easier to maintain, reducing the chance of false failures in invoice import checks.
Original PR description
Move the partner retrieval bank account number test to the `test_ubl_import_bis3_invoice_be_retrieve_partner.py` file and use a partial XML instead of a generated XML. Forward-Port-Of: odoo/odoo#274591 Forward-Port-Of: odoo/odoo#269995
This update fixes several issues in the emoji editor so selected emojis replace typed text properly and mobile backspace behaves as expected. It improves the editing experience by keeping the cursor in the right place and preventing emojis from reappearing after deletion on mobile devices.
Original PR description
**Issue 1:** Step to reproduce: - Type ':wave' to open suggestion list - Now click on any emoji from the suggestion list Description of the issue: - The selected emoji gets inserted, but the…
**Issue 1:** Step to reproduce: - Type ':wave' to open suggestion list - Now click on any emoji from the suggestion list Description of the issue: - The selected emoji gets inserted, but the `searchNode` `:wave` does not get removed and remains beside the inserted emoji Cause: - When the user clicks an emoji from the suggestion list, focus shifts to the suggestion list item. As a result, `selection.extend()` is unable to properly select the searchNode in the editable area. Because the `searchNode` is not selected, `deleteSelection()` fails to remove it before inserting the emoji. Solution: - Added the `user-select-none` class to the suggestion list to prevent selection/focus shift on emoji click, ensuring the searchNode is properly selected and replaced by the selected emoji **Issue 2:** Steps to reproduce: - Open a To-do on a mobile device. - Type `:p` to create an emoji. - Press Backspace. Issue: - When using the SwiftKey keyboard, pressing Backspace after an emoji can result in an incorrect cursor position. Cause: - When Backspace is pressed, a selection snapshot is cached during the `keydown` event. - Later, `deleteBackward` converts the emoji back to its corresponding expression (:p) by triggering an undo operation, but the cached selection does not get updated. As a result, the previously cached selection is reused, causing the cursor to be placed incorrectly. Solution: - After performing the undo, update the cached selection to match the new cursor position. - This ensures that the latest selection is used instead of the outdated selection captured during `keydown`. **Issue 3:** Steps to reproduce: - Open a To-do on a mobile device. - Type `:p` to create an emoji. - Press Backspace. Issue: - Pressing Backspace on an emoji does not revert it to its matching expression (`:p`). Cause: - On mobile devices, `event.key` can be undefined in keydown. As a result, `deleteBackward` is triggered through the `beforeinput` event, which correctly reverts the emoji to its matching expression. However, after that, the `input` event is triggered and converts the expression back into the emoji again, making it appear as if the emoji was not reverted. Solution: - When the event type is `deleteContentBackward`, skip converting the expression back into an emoji and return early. task-6201173 Forward-Port-Of: odoo/odoo#272565 Forward-Port-Of: odoo/odoo#263777
The display of the Pakistan Rupee (PKR) has been updated so the currency symbol appears before the amount, matching local market practice. This helps make invoices and financial documents look more familiar and accurate for users in Pakistan.
Original PR description
This commit updates the symbol position of Pakistan's currency (PKR) to `before amount`, as previously it was displayed `after amount`, which is not the market practice; as shown over [here](https://drive.google.com/file/d/14pcqXTZSR0BygBXGvgQ6oCLRW0-4dYUh/view?usp=drive_link). This is a backport of [PR](https://github.com/odoo/odoo/pull/269204) task-6236452 Forward-Port-Of: odoo/odoo#271499
Invoices sent through Nilvera could get stuck in a temporary “Unknown” state and stop being checked again. This change keeps those invoices in the follow-up process until Nilvera returns a final status, reducing cases where invoice processing appears stuck.
Original PR description
## Short fix summary:
Nilvera reports `Unknown` as a normal, transient `StatusCode` value (their own e-Archive API docs
list the enum as `unknown`/`waiting`/`succeed`/`error`) right after a document is sent, before their
daily batch resolves the final status. But `_cron_nilvera_get_invoice_status`'s search domain only
matches `l10n_tr_nilvera_send_status in ('waiting', 'sent')`, so once an invoice lands on `unknown` it
is never polled again — even after Nilvera later resolves the real status on their side. This adds
`unknown` to that domain so these invoices keep getting polled until Nilvera reports a final status.
task-6328589
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274494
Forward-Port-Of: odoo/odoo#274311Customers paying through DPO will now be sent to the payment page successfully instead of reaching an invalid transaction error page. The fix preserves the payment token in the URL during the redirect, which prevents the payment flow from breaking and restores normal checkout behavior.
Original PR description
When a customer paid through DPO, they landed on the DPO error page ("Not Valid - this transaction is no longer valid") instead of the payment page, even though the transaction token was created…
When a customer paid through DPO, they landed on the DPO error page ("Not Valid - this transaction is no longer valid") instead of the payment page, even though the transaction token was created correctly.
The customer is redirected to `https://secure.3gdirectpay.com/payv2.php` with the transaction token passed as the `ID` parameter. `payv2.php` answers with a 302 redirect to `payv3.php`. Per HTTP semantics, a 302 turns the request into a GET and drops the body, so when `ID` is sent in the body of a POST it never reaches `payv3.php`: the customer arrives at `payv3.php?` with no token and DPO rejects it as invalid.
This regressed with 97ec8a3e72d9d48a0a9620c53feea533421b9d67, which moved redirect providers to the generic redirect form. Before that commit, the token was part of the action URL itself (`payv2.php?ID=<token>`), so it stayed in the query string across the redirect. The refactor moved `ID` into `url_params` rendered as a hidden input, and since `http_method` was left unset the generic form defaults to POST, putting `ID` in the body.
Set `http_method` to "get" so the token is serialized back into the query string and survives the `payv2.php` -> `payv3.php` redirect, restoring the pre-refactor behavior. This also matches DPO's documented convention of passing the token in the URL query string.
opw-6312732
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#272890The attendance timesheet report now explicitly identifies the database columns it uses, preventing errors when customer customizations add similarly named fields. This keeps the report reliable and avoids unexpected failures during report generation.
Original PR description
In `hr_timesheet_attendance_report`, the SQL query was using unqualified columns (e.g. `date` instead of `ts.date`)
It was not an issue in standard, but if a customer adds a `date` or `check_in` column to `hr_employee`, the query becomes ambiguous and fails.
To solve the issue, we explicitly qualify `ts.date` and `hr_attendance.check_in`.
upg-4445460
```python
File "/home/odoo/src/odoo/19.0/addons/hr_timesheet_attendance/report/hr_timesheet_attendance_report.py", line 24, in init
self.env.cr.execute("""CREATE OR REPLACE VIEW %s AS (
File "/home/odoo/src/odoo/19.0/odoo/sql_db.py", line 440, in execute
self._obj.execute(query, params)
psycopg2.errors.AmbiguousColumn: column reference "date" is ambiguous
LINE 44: AND date <= CURRENT_DATE
```
Forward-Port-Of: odoo/odoo#274482
Forward-Port-Of: odoo/odoo#274341This change fixes a stock handling issue where items could be lost from the process after being unreserved and reserved again during validation. As a result, package checks are now applied correctly for all relevant transfers, reducing the risk of incorrect stock validation results.
Original PR description
This reverts commit 5d70f75f1d27577ee4e2121497ce477cfa6cda53. `free_reservation` is called once per move line to validate. The goal is to unlink potential move lines that have the same reservation. After finding them, a force re-reservation is triggered. The idea of the previous commit was to call `check_entire_pack` (caused by the re-reservation) only once and not at each move line `free_reservation`. The issue is the stock move that has been unreserved then re-reserved are lost in the process and only the picking that had at least one move line validated are actually calling `check_entire_pack`. 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#273813 Forward-Port-Of: odoo/odoo#273658
The print button on customer invoices is being restored to its primary position. This removes a confusing change and keeps the button prominent unless the invoice has already been sent, where the secondary style still makes sense.
Original PR description
In task-6269645, the print button on customer invoices was set to secondary instead of primary. This is a mistake and it's confusing, so it's being reverted in this commit because it only needs to be secondary if the move is sent. task-6357618 Forward-Port-Of: odoo/odoo#273953
This fix restores PDF generation for Polish e-invoices when QR codes are included. A previous change caused the document creation step to fail, and this update removes the extra data encoding that was breaking the process.
Original PR description
Due to this (https://github.com/odoo/odoo/pull/244421/changes/546a4425884e61080a7a7e8d2b2a97c8a2e3f38e), PDF generation was broken. Removing the manual encoding of the data. Runbot [link](https://runbot.odoo.com/odoo/error/941292) runbot-941292 Forward-Port-Of: odoo/odoo#274424
The website title form now uses a style that can be edited in the visual editor, instead of a fixed alignment setting. This makes it easier for users to change how the title is displayed directly from the website editor.
Original PR description
`s_title_form` comes with the `text-center` utility class which forbids edition through the web_editor, it needs to use inline-style instead. task-6149380 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263334
This update adjusts a system setting so it points to the demo environment instead of a test one. It helps ensure the account EDI proxy uses the intended setup for the current users and avoids misconfiguration.
Original PR description
The system parameter is already brought to demo in account_peppol module. But the current users are not for pdp. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272462
Credit notes for returned drop-shipped tracked products will now show the correct lot or serial number on the invoice. This fixes a reporting error that could otherwise confuse customers and accounting teams when reviewing returns.
Original PR description
**Issue** Printing a credit note for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial…
**Issue**
Printing a credit note for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report.
**Steps to reproduce**
- Activate "Display Lots & Serial Numbers on Invoices"
- Create a product tracked by serial/lot and enable the dropship route
- Create two lots: "lot1" and "lot2"
- Create and confirm a SO for quantity 2
- Confirm the PO and validate the dropship for both lots
- Create and post an invoice
- Return "lot2" from the dropship picking
- Create and post a credit note for quantity 1
- Click on print -> The generated PDF displays "lot1" instead of "lot2"
**Cause**
While rendering `account.report_invoice_with_payments`, the report calls `_get_invoiced_lot_values` to determine which lot/serial numbers should be displayed:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L31-L32 `invoiced_qties = 1` since the credit is on a quantity of 1 https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L44 Three stock move lines are retrieved from the SO:
- the two original dropship deliveries,
- the return move for `lot2`. https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L63 However, none of them are considered as `is_stock_return` because the dropship locations use `supplier` instead of `internal`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L72-L76 As a consequence:
- The two original delivery move lines each keep quantity `1`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L69 they never pass through the return handling logic: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L77-L80 which would make it as -1 (since `qties_per_lot[sml.lot_id]` is 0 for the first iteration of `sml.lot_id`). Thus, it does not pass by this code (since quantity is greater than 0): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L87-L90 which would make it as 0.
- for the last one, `is_stock_return = False` as it should be, thus the quantity is 1 as it should be. The quantities are therefore accumulated as:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L92
resulting in:
`qties_per_lot = {lot1: 1, lot2: 2}`
instead of:
`qties_per_lot = {lot1: 0, lot2: 1}`
The report then selects the first matching lot and stops: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L94-L99
opw-6230281
Forward-Port-Of: odoo/odoo#268905
Forward-Port-Of: odoo/odoo#266716Credit note XML imports now keep quantities and tax amounts positive when bringing in Belgian e-invoices. This prevents taxes from being subtracted by mistake and ensures totals are calculated correctly for accounting users.
Original PR description
Steps to reproduce: 1. Install l10n_be and switch to BE company 2. Upload the XML document (found in ticket chatter) into the Accounting application as a Credit Note. Issue: - The line is imported as…
Steps to reproduce: 1. Install l10n_be and switch to BE company 2. Upload the XML document (found in ticket chatter) into the Accounting application as a Credit Note. Issue: - The line is imported as a negative value which is corrected with a rounding line. - The 6% tax rate is applied to the negative invoice line, resulting in a negative tax amount being deducted from the total (e.g., 449.32 + (-26.96) = 422.36) instead of being added (449.32 + 26.96 = 476.28) Expected behavior: price_unit, quantity and the related tax amounts should all be positive, matching a normal in_refund/out_refund line. Why this happens: - In `_import_ubl_invoice_line_add_price_unit_quantity_discount`, `BaseQuantity` was multiplied by file_document_sign, unlike `PriceAmount` from the same node which is left untouched. This flips price_quantity to -1, which later flips price_unit to negative when `price_unit = price_subtotal / price_quantity`. opw-6310442 Forward-Port-Of: odoo/odoo#271148
This update fixes a crash that could happen when signing customer invoices using the Egyptian ETA USB certificate. Invoice signing now correctly reads the certificate data, so users can complete the signing process without interruption.
Original PR description
Steps to reproduce: - Configure a thumb drive with a certificate read from the ETA USB tool, so l10n_eg_edi.thumb.drive.certificate is populated - Open a customer invoice, confirm it, then Sign…
Steps to reproduce:
- Configure a thumb drive with a certificate read from the ETA USB tool, so l10n_eg_edi.thumb.drive.certificate is populated
- Open a customer invoice, confirm it, then Sign invoice
Before this commit, signing crashed with:
`TypeError: encoded_data must be a byte string, not
odoo.orm.fields_binary.BinaryValueAttachment`
raised by `asn1crypto` in `x509.Certificate.load()`, called from `_generate_signed_attrs__` and identically from `_generate_signer_info__` and `_generate_cades_bes_signature`.
Reading an attachment-backed Binary field now returns a lazy `BinaryValueAttachment` wrapper rather than raw bytes, and `asn1crypto` rejects any value that is not a bytes instance. `set_certificate` and the `l10n_eg_eta_json_doc_file` reads were already moved to the new binary API but the three certificate loads were missed and still passed the wrapper straight to asn1crypto.
Load the certificate through `self.certificate.content`, which returns the stored DER bytes.
opw-6365281
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274658This update corrects the way Belgian eco-cheques are computed in payroll. It helps ensure employee payslips reflect the right amount after the related date-handling logic was adjusted.
Original PR description
Forward-Port-Of: odoo/odoo#267657
The Registration Desk now updates immediately whenever the Registration Summary dialog is closed, including when users press Escape or click outside the dialog. This prevents stale attendee information from staying on screen and ensures the Kanban and List views always reflect the latest status.
Original PR description
**Current behavior before PR:** Closing the Registration Summary dialog by pressing **Escape** or clicking outside the dialog does not refresh the Registration Desk view. As a result, the attendee state is not reflected until the view is manually reloaded. **Desired behavior after PR is merged:** The Registration Desk view is refreshed whenever the Registration Summary dialog is closed, regardless of whether it is closed using the **Close** button, by pressing **Escape**, or by clicking outside the dialog. This ensures the attendee information is always updated in both the Kanban and List views. Task - [#6333829](https://www.odoo.com/odoo/project.task/6333829) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272699
The restaurant POS onboarding flow now automatically loads the required product sample data when it is missing. This prevents the “Load Sample” option from failing in new databases and helps users get started without errors.
Original PR description
Since commit 8f5126e6e48f, pos_restaurant's demo data relies on product.pa_sides which is defined in product's demo data. If the database was created without demo data, clicking on 'Load Sample' in restaurant POS config fails because product.pa_sides is missing. This commit ensures product's demo data is loaded first if it's not already present, similarly to how it's done for furniture onboarding scenario. task-id: 6296056 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Stripe payments made with saved card tokens will now be labeled with the correct card brand instead of being marked as unknown. This improves payment accuracy and helps avoid confusion in payment records and reporting.
Original PR description
Before this commit, payment transactions created from a Stripe token were assigned the payment method with code `unknown` when processing the payment data, instead of the correct card brand (e.g.,…
Before this commit, payment transactions created from a Stripe token were assigned the payment method with code `unknown` when processing the payment data, instead of the correct card brand (e.g., VISA). This was due to the combination of two problems in Stripe's payment method resolution performed by `_apply_updates`: - It was comparing the transaction's initial payment method code to the primary payment method code "card", while transactions created from a token directly inherit their token's brand payment method (e.g., VISA). It then assumed that "card" was selected for payment. - Stripe's payment method mapping included an "unknown" <-> "card" correspondence meant for Express Checkout (this was never used), which wrongfully made `_get_pm_from_code` return and assign the "Express Checkout" to the transaction. With the commit, the payment method code comparison is always performed regardless of the initially assigned payment method, which allows finding "visa" as the selected payment method. It also removes the unused "unknown" <-> "card" entry to prevent erroneous mappings in the future.
This update corrects several issues around the new document tax mode switch so invoices, purchases, and related tax calculations behave consistently. It also fixes imported Italian e-invoices and removes rounding inconsistencies that could lead to incorrect totals in some cases.
Original PR description
- changing python constraint on document tax mode on account.move to SQL - style enhancements to the overlap_badge_tab and new component - removing inconsistent rounding in purchase.order - adding document tax mode logic to account.tax compute_all method - adding missing document tax mode ‘tax_excluded’ setting to l10n_it_edi during account.move creation of imported invoices odoo/enterprise/pull/122246 Following up: https://github.com/odoo/odoo/pull/251800
The point of sale now has a backup way to confirm Mollie payments when the real-time connection to the server is unreliable. Instead of leaving staff blocked and forcing them to use a manual override, the system checks payment status every few seconds so confirmation usually happens with only a short delay.
Original PR description
Due to the unreliability of the bus during peak server times, clients were missing the websocket payment confirmations from the backend. This meant they had to use the Force Done button to confirm the payment. This commit adds a polling mechanism similar to that used for Viva.com, which polls the backend directly every 5 seconds to check the status of the payment. This means that instead of being blocked, the client should only experience at most a 5 second delay, even when the websocket isn't working. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274713
The preview of the “2FA New Login” email template no longer fails with an error. This makes it possible for administrators to safely review or reset the template without running into a traceback.
Original PR description
Issue: ---------------------------------------- Clicking "Preview" on the template "2Fa New Login" causes an error. Steps to reproduce: ---------------------------------------- - Search for the mail template "Settings: 2Fa New Login" - Click "Preview" - Error in terminal - From 17.0+ the error shows in UI - From saas-18.3+, a traceback occurs whe resetting the template Cause: ---------------------------------------- There is an assert the method `_get_totp_mail_code()` to ensure it's used during 2FA. But when passing by rendering this template in preview we aren't in sudo and the assert in `_get_totp_mail_code()` raises. Solution: ---------------------------------------- We replace the `assert` by a `if` which will return fake results. opw-6333887 Forward-Port-Of: odoo/odoo#273914 Forward-Port-Of: odoo/odoo#273125
This update fixes a test related to Italian electronic withholding documents. It does not change the business behavior, but helps ensure the existing functionality is validated correctly and reduces the risk of false test failures.
Original PR description
This commit just want to correct a test of a PR already merged. Original commit: 78ffb5a2e63401123e4506056493e52cf3e69953 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274262 Forward-Port-Of: odoo/odoo#274062
This update ensures that refund lines in sale reports are accurately represented with positive amounts and taxes, aligning with how localizations like the 'l10n_be_pos_blackbox' handle refunds. Previously, refunds were displayed with negative values, creating confusion. This change provides a more consistent and accurate view of sales transactions, including refunds.
Original PR description
Amounts and taxes now consistently follow the order line sign, allowing localizations (e.g. l10n_be_pos_blackbox) to report negative lines of regular orders as refunds with positive amounts. enterprise PR: https://github.com/odoo/enterprise/pull/122411 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273994
This update resolves an issue preventing users from successfully uploading attachments or using drag-and-drop functionality when scheduling messages. The fix ensures proper attachment handling and enables the drag-and-drop feature, improving the scheduling workflow.
Original PR description
Steps to reproduce: 1. Create a log note or send a message on any record and open the full composer. 2. Set a date in the future to schedule the message for later and click schedule. 3. Click on the…
Steps to reproduce: 1. Create a log note or send a message on any record and open the full composer. 2. Set a date in the future to schedule the message for later and click schedule. 3. Click on the "Edit" button of the newly scheduled message. 4. Try dragging and dropping an image into the body, or add a file as an attachment using the button. Issue: - Dragging and dropping an image into the form does nothing. - Trying to add a file as an attachment using the button triggers a traceback: `TypeError: Cannot read properties of undefined (reading 'resId')` Why this happens: - The failure when adding explicit file attachments occurs because the `model` and `res_id` fields were omitted from the `mail.scheduled.message` form view layout in the commit 3b985d2. Without these field declarations, the `mail_composer_attachment_selector` widget cannot determine the record metadata parameters, causing the upload to crash. - The failure of the drag-and-drop mechanism occurs because the scheduled message edit view uses the default `FormController` class instead of `MailComposerFormController` which is used in the `mail_compose_message` view. Consequently, the underlying `useCustomDropzone` is never instantiated on the view, leaving drop events unhandled. Fix: 1. Specify `js_class="mail_composer_form"` to the scheduled message form view definition tag to handle drag and drop, as well as adding the missing fields 2. Assign the `resIds` variable based on the message type since it is defined as `res_id` instead of `res_ids` in `mail.scheduled.message`. opw-6273260 Forward-Port-Of: odoo/odoo#268515
This update resolves a validation error that occurred when installing the `l10n_uy` module on demo databases in version 19.3 and later. The issue stemmed from redundant data being written to journals, now corrected by removing the unnecessary setting from the module's account journal configuration.
Original PR description
**Issue:** Installing `l10n_uy` on a demo database raises a ValidationError from the `check_use_document` constraint since 19.3+. The error occurs because `ir_module.py:write()` re-applies…
**Issue:** Installing `l10n_uy` on a demo database raises a ValidationError from the `check_use_document` constraint since 19.3+. The error occurs because `ir_module.py:write()` re-applies module-specific template data to all companies with a matching chart template after installation. At that point, `demo_company_uy` already exists with `chart_template='uy'` and posted demo invoices, so `_load_data` ends up writing `l10n_latam_use_documents=True` to a journal that has validated entries. This write was previously suppressed by `_pre_reload_data`, which unconditionally removed journals from the data when found by xmlid. Commit 056b8e38ff84 (saas-19.3) narrowed that protection to only apply when `'type' in journal_data`. Since the module-filtered data never includes `type` (that field comes from `_get_account_journal` in the base `account` module, excluded by the module filter), the journal is no longer protected and the write triggers the constraint. **Versions:** 19.3+ **Fix:** remove `l10n_latam_use_documents=True` from `_get_uy_account_journal`. `l10n_latam_invoice_document` already sets this field for all LATAM companies via `_get_latam_document_account_journal`; l10n_uy was setting it redundantly. Task id: [6354499](https://www.odoo.com/odoo/project/49/tasks/6354499) Forward-Port-Of: odoo/odoo#273930
This update significantly speeds up the calculation of future timesheets based on public holidays. The previous process was slow and inefficient, particularly when many holidays were defined. This change optimizes the calculation process, resulting in faster timesheet generation and improved system performance.
Original PR description
**Problem:** When creating a new employee, the future timesheets due to public holidays are computed. If the number of public holidays is large (i.e. if the user creates them for each year, several…
**Problem:** When creating a new employee, the future timesheets due to public holidays are computed. If the number of public holidays is large (i.e. if the user creates them for each year, several years in the future), then it takes excessively long and the action may not complete. **Cause:** The pytz method `localize` and comparing times with non-static timezones is done repeatedly and unnecessarily which becomes costly with more records. **Solution:** Only localize the time when absolutely necessary (determining the date of the leave in the calendar timezone). **Performance Stats:** |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |100 |3.1s |393 |0.8s |117 | |1,000 |22.3s |2,090 |1.5s |183 | |10,000 |Timeout |N/A |6.7s |541 | opw-6087422 Forward-Port-Of: odoo/odoo#271690 Forward-Port-Of: odoo/odoo#263953
This update corrects a display issue in the journal entry preview. Previously, if a user didn't specify a currency, the credit amount incorrectly mirrored the debit amount. This change ensures the credit column accurately reflects the credit value, providing a more reliable preview for users.
Original PR description
In _move_dict_to_preview_vals(), when no currency is provided, the credit column falls back to the line's debit value, so any caller omitting currency_id would show the debit amount in both columns of the journal entry preview. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274594 Forward-Port-Of: odoo/odoo#269335
A bug in the website builder was causing images to fail to load, resulting in slow updates. This fix addresses an issue where the system incorrectly handled undefined image sources, leading to a 404 error. The update ensures images load correctly, improving the website builder's performance and user experience.
Original PR description
Commit [1] introduced a `headResponseCache` for images' src, later used in commit [2], which introduced `getFetchedMimetype`. While the former guards against an empty/undefined src, it is not the…
Commit [1] introduced a `headResponseCache` for images' src, later used in commit [2], which introduced `getFetchedMimetype`. While the former guards against an empty/undefined src, it is not the case of the latter. `headResponseCache.read`, which runs a `fetch`, is called within a try/catch, but it is still awaited: with an undefined src, it returns a 404 after stalling the thread for at least 1s. The bug can be seen from the website builder: - Drop a text/image snippet - Open your dev tools on the "network" tab - Click on the image => a failed fetch (404) appears and blocks the builder from being updated quickly. It happens because the element (in this case the `section` of the snippet) is neither an `img`, nor an element with a parallax, nor an element with a background-image, and `getImageSrc` returns an undefined src. [1]: https://github.com/odoo/odoo/commit/bf377f3d1c58aaeb39624700b3e4754d7a6d384b [2]: https://github.com/odoo/odoo/commit/b96a0769eeecd2e6ec14cc7a73105f8dfdb8842e task-6247171 Forward-Port-Of: odoo/odoo#274641
This update prevents Odoo from automatically re-pinning meetings when a call ends. Previously, this could create confusion and duplicate meeting entries. Now, meetings are only pinned when a new meeting is started, streamlining the meeting management process.
Original PR description
task-6373532 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 resolves an issue where website visitors couldn't see payment method images. The change restores necessary access permissions to retrieve these images, ensuring the 'Supported Payment Methods' snippet displays correctly for all users. This improves the user experience and functionality of the website payment process.
Original PR description
Steps to reproduce: - Add the "Supported Payment Methods" snippet on a website page - Open the page as a public (non-logged-in) visitor => An AccessError is raised: "You are not allowed to access…
Steps to reproduce: - Add the "Supported Payment Methods" snippet on a website page - Open the page as a public (non-logged-in) visitor => An AccessError is raised: "You are not allowed to access 'Payment Method' (payment.method) records". `get_supported_payment_methods` searched `payment.method` without `sudo()`, and its JSON response embeds `image` URLs that are fetched by the browser through the public `/web/image` controller, which requires either full read access on the record so a `_can_return_content` override granting content-level access. The root cause was introduced in [1]: that commit removed the blanket `base.group_public`/`base.group_portal`/`base.group_user` read grants on `payment.method`, replacing them with a `base.group_system`-only ACL plus a provider-scoped rule, as part of making payment methods provider-specific. It didn't account for the `website_payment` snippet controller, which relies on public read access to list the available payment methods and their logos. Fix by: - Using `sudo()` when searching `payment.method` in `get_supported_payment_methods` - Overriding `_can_return_content` on `payment.method` to allow public access to the `image` field only. [1]: bcfeed4b24f5155c111c3866e779bb2f119b9da8
This update resolves a technical issue where the call debrief player's segment seeking could be disrupted, leading to playback problems. The fix replaces an outdated callback system with a more reliable method that ensures the player correctly handles media loading and seeking, regardless of timing.
Original PR description
Backport of community PR https://github.com/odoo/odoo/pull/271300 `onMediaLoadedCallback` was a single shared hook consumed by whichever element fired `loadeddata` first. It could be mid-fetch at the moment the user clicked: it would fire `loadeddata` while still mounted (before OWL rendered), steal the callback intended for the incoming segment, and leave the new element at currentTime=0 Fixed by replacing the callback pattern with `useEffect` realizing `_pendingSeek` if any. The effect tracks the `mediaPlayer` signal and fires whenever OWL mounts a new media element, regardless of whether the file has loaded. Note: setting `currentTime` on the media element before `loadeddata` is valid. Browser stores the target and keeps `seeking=true` until data arrives, which naturally guards `onTimeUpdate` during the loading window. task-6321435 Enterprise counterpart https://github.com/odoo/enterprise/pull/122655
This update resolves an issue where the chatter displayed a misleading message ('This entry has been duplicated from') when reversing journal entries. The fix restores the previous behavior, ensuring accurate and consistent chatter messages for reversal moves. This improves clarity for users managing financial transactions.
Original PR description
This is a just a back-port of this commit https://github.com/odoo/odoo/commit/57b2a678ab0cc8a10d72825b1272fc0d1e0962cc --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a technical issue where the self-order POS system was experiencing errors due to tours prematurely ending before asynchronous processes completed. The fix ensures the system waits longer for these processes, preventing interruptions and improving stability.
Original PR description
Doesn't use setTimeout to wait for the rpc to finish, but await it instead even if it takes to long. The error was happening because the rpc was awaited for a maximum of 150 ms, sometimes in tours, the tour finish before the rpc is finished, which was causing the error.
This update fixes an issue preventing self-order kiosks (pay-at-counter) from correctly generating receipts. The previous change removed crucial payment method data, causing errors when users attempted to download receipts. This fix restores the payment method information, ensuring accurate receipt generation and a better user experience for self-order transactions.
Original PR description
Steps to reproduce: - Set up a kiosk with pay at counter - Order a product - Settle the order in backend - Go to my order on the self, try donwload the receipt - TB Issue: This commit https://github.com/odoo/odoo/pull/237553 removed the pos_payment_method from the _generate_return_values method. The fornt-end didn't had the necessary data to generate the receipt. Fix: Restore payment method in the _generate_return_values method. Task-6191379 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#274165 Forward-Port-Of: odoo/odoo#263515
This update resolves an issue where deleting a field in a model triggered an access error, even if the field wasn't directly linked to the website. The fix ensures the search for used fields is performed with elevated permissions, allowing the deletion to proceed smoothly. This improves stability and prevents unexpected errors during data management.
Original PR description
# How to reproduce - Install the Website module - Install another module that has atleast one model with one html field, sanitize=Flase or sanitize_form=False and groups - Remove the field's group…
# How to reproduce - Install the Website module - Install another module that has atleast one model with one html field, sanitize=Flase or sanitize_form=False and groups - Remove the field's group from the current user - Enable dev mode - Go to Settings > Technical > Database Structure > Models - Pick any model (e.g. sale.order.line) - Add a field to that model & Save - Delete the added field & Save > Note : Significantly harder to reproduce since : https://github.com/odoo/odoo/commit/9a336bbb94b0a4266d84f7554c024c3abd2d1e7c I am not sure a field as mentionned in the steps exists # The problem An access error is raised for the module wich access rights were removed, even if the module is not linked in any way with the picked model # Cause of the issue Deleting the field will endup calling the `unlink()` method of `BaseModel` on the `ir.model.fields` record. This function triggers all `@api.delete` methods defined on the model : https://github.com/odoo/odoo/blob/5538132d9d14c4cc5031fc50ac0388ad2ab0fc92/odoo/models.py#L4548-L4552 This will call the this method : https://github.com/odoo/odoo/blob/5538132d9d14c4cc5031fc50ac0388ad2ab0fc92/addons/website/models/website_form.py#L153-L154 That was introduced by : https://github.com/odoo/odoo/commit/c0a827519844ec43537e4487f6abe358bb82ba9a Which prevents a field from being deleted if it is actively used in any website form. But this method does a search on every model return by `_get_html_fields` which may contains models that are not accessible by the user, so we get an access error. # Proposed solution Since `_check_if_used_in_website_form` should perform the same independently from the user, we can do the search in sudo opw-6231951 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274332 Forward-Port-Of: odoo/odoo#265781
This update resolves a bug that caused the activity counter in the avatar card tour to fail due to incorrect time zone handling. By scheduling activities with a deadline one week in the past, the counter now accurately reflects activity states regardless of user or system time zones, ensuring consistent reporting.
Original PR description
The avatar card tour asserts the systray activity counter, which only counts activities whose state is today or overdue. The test scheduled its activities without an explicit deadline, so…
The avatar card tour asserts the systray activity counter, which only counts activities whose state is today or overdue. The test scheduled its activities without an explicit deadline, so activity_schedule fell back to context_today on the class environment, whose superuser has tz Europe/Brussels with demo data. When the test runs between 22:00 and 00:00 UTC, that deadline is tomorrow from a UTC point of view. The state of an activity is however computed in the timezone of its assigned user, and hr_user is created without one, falling back to the server date (UTC). Its activities were therefore planned instead of today, the counter stayed empty and the tour timed out. The admin iteration kept passing because demo data gives admin the same Brussels timezone as the environment that computed the deadline, which is why only half the runs failed (both occurrences at 23:56 and 23:31 UTC). Schedule the activities with a deadline one week in the past instead: an old deadline is overdue in every timezone, whatever timezone the scheduling environment or the assigned user has, making the counter deterministic at any time of the day. https://runbot.odoo.com/odoo/error/941407 Forward-Port-Of: odoo/odoo#274679
This update addresses a security vulnerability where standard users could access restricted data within the mail tracking system. The fix prevents unauthorized access to 'tracking_value_ids', ensuring data privacy and security. This resolves a previously identified issue impacting the integrity of mail tracking functionality.
Original PR description
Field is not accessible to standard users. Task-6368820 Part of Task-3704380 Forward-Port-Of: odoo/odoo#274989
This update resolves an issue where the product expiry warning displayed incorrect information before a lot was fully created. Now, the system correctly uses lot details entered during receipt creation, ensuring accurate expiry warnings are shown. This improves the user experience and prevents misleading alerts.
Original PR description
From saas-18.4, the expiration confirmation wizard can be triggered not only from expired lots, but also from stock move lines whose `removal_date` has passed. For incoming receipts, tracked products…
From saas-18.4, the expiration confirmation wizard can be triggered not only from expired lots, but also from stock move lines whose `removal_date` has passed. For incoming receipts, tracked products use the `lot_name` field when the user is entering the lot. The corresponding `lot_id` is only created later once the receipt is validated. As a result, it is possible for the expiration confirmation wizard to be displayed before the lot exists. In this situation, it attempts to display the product and lot information using `lot_id`, which is still empty, causing the message to show "False, False" instead of the actual lot name entered by the user. It should use the move line information as a fallback when no `lot_id` has been created yet so it still displays the correct product and lot name. Steps to reproduce 1. Enable Product Expiry. 2. Create a storable product with: - Tracking: By Lots - Use Expiration Date: enabled - Removal Time > 0 3. Create a receipt for the product. 4. Open Detailed Operations. 5. Enter a new lot number in the Lot/Serial Number field. 6. Ensure the removal date is in the past and validate the receipt. Related Tickets: opw-6303140 Forward-Port-Of: odoo/odoo#273970 Forward-Port-Of: odoo/odoo#273143
This update ensures that attachments added to email templates when scheduling messages correctly link to the scheduled message record. Previously, attachments weren't properly associated, causing access issues when viewing the scheduled message from a different user. This fix resolves a potential data inconsistency.
Original PR description
**Problem:** When scheduling a message using an email template with custom attachments, those attachments will not have their `res_model` and `res_id` updated to relate to the scheduled message…
**Problem:** When scheduling a message using an email template with custom attachments, those attachments will not have their `res_model` and `res_id` updated to relate to the scheduled message record. This can lead to access errors. **Cause:** When composing a message using an email template with attachments, those attachments are created with their `res_model` and `res_id` values corresponding to the mail composer record. However, when scheduling a message, only attachments with no `res_id` value (or a value of 0) are updated to correspond to the scheduled message record. https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mail/wizard/mail_compose_message.py#L1198-L1201 https://github.com/odoo/odoo/blob/30ca89b9e0d3c43d019167ec2de816c263f4bb92/addons/mail/models/mail_scheduled_message.py#L86 **Purpose:** Modify the `mail.scheduled.message` override of `create` to not require an attachment have no `res_id` value to be properly updated. **Steps to Reproduce in Runbot:** 1. Add an attachment to an email template. 2. Open a mail composer using that email template, then schedule the message for later. 3. Attempt to view the scheduled message with a different user. More specific example flow: 1. Add an attachment to the Sales: Send Quotation email template. 2. Create a Quotation and send it with the Send by Email button, selecting Send Later instead of Send. 3. Attempt to view the Quotation with a different user. opw-6293587 Forward-Port-Of: odoo/odoo#272261
This update resolves an issue where the counted inventory quantity in the Physical Inventory module was incorrectly resetting to zero after manual adjustments. The previous code automatically cleared the count when a user moved to a different line, regardless of input. Now, the quantity only resets to zero after the user has manually entered a value.
Original PR description
Versions -------- - 19.0+ Steps ----- 1. Open Physical Inventory; 2. click on a line; 3. click on a different line. Issue ----- Counted quantity automatically gets set to 0. Cause ----- Commit 3187030 changed the counted quantity widget to enable mutli-line edit. Part of this was done by ignoring the `onInput` hook, and always updating the counted quantity `onBlur`, making it so that the value is set to zero when clicking away, regardless of manual input. Solution -------- Use a `hasInput` state which gets set to `true` on user input. If not `true`, don't update the counted quantity on blur. opw-6365084 Forward-Port-Of: odoo/odoo#274987 Forward-Port-Of: odoo/odoo#274364
The 'View Meeting' button on the attendee calendar was broken, preventing users from opening meeting popups. This update corrects a technical error where the system incorrectly processed the meeting event ID, now correctly retrieving the event record and opening the meeting popover.
Original PR description
The "View Meeting" button of an activity in the attendee calendar popover did nothing when clicked. Its `onViewMeeting` callback is passed the activity's `calendar_event_id`, which is a record, but the handler treated it as an event id: it interpolated the record into the `.fc-event[data-event-id=...]` selector and used it to index `model.records`. Both lookups therefore missed, the `el && record` guard was never satisfied, and no meeting popover opened. Read the numeric id off the record (`calendarEvent.id`) so the event element and its record are found and the meeting popover opens. Forward-Port-Of: odoo/odoo#273438