Daily updates from Odoo
Wednesday, July 8, 2026
104 changes · saas-19.4
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
This update resolves an issue where project creation from sale orders wasn't correctly setting billable status and company context. Now, projects created from sale orders automatically inherit the correct billable status and are linked to the sale order’s company, ensuring accurate tracking and reporting. This improves the consistency of project data.
Original PR description
Fix 1 : project, sale_timesheet: remove default_allow_billable context in Create a Project --------------------- **Issue:** When a project is created from the sale app, it is not billable by default,…
Fix 1 : project, sale_timesheet: remove default_allow_billable context in Create a Project --------------------- **Issue:** When a project is created from the sale app, it is not billable by default, and the sale order / sale order line are not set. **Fix:** Remove default_allow_billable = False in the Create a Project **Note:** default_allow_billable = True already exists in action_view_project_ids, but that default context is replaced when opening the project directly from the view. This happens because default_allow_billable = False is set in the Create a Project action. Fix 2: sale_project: show only relevant project templates per company ---------------- **Steps:** - Install sale_project - Create two companies (A, B) - Create three project templates: - Template A (company A) - Template B (company B) - Template C (no company → visible to all) - Create a sale order for company A with a service product - Confirm the sale order - Create a project and try to select a template **Issue:** All project templates were visible even if the sale order had a company set. **Fix:** Added a filter (domain) on the project template field so only templates for the sale order’s company or templates with no company are shown. Users cannot select templates from other companies. task-5074893 Forward-Port-Of: odoo/odoo#274417 Forward-Port-Of: odoo/odoo#229309
This update fixes a bug where email bounces from mailing campaigns weren't accurately recorded for contacts. Now, the system correctly updates bounce counts when emails fail to deliver, ensuring more reliable tracking of email campaign performance and contact engagement. This improves the accuracy of mailing campaign analysis.
Original PR description
Previously, when a mailing campaign sent out an email to a mailing.contact, and that email bounced, the bounce would not increment the contact's bounce count. This commit makes it so that the bounce count is correctly updated when a mailing campaign sends an email that bounces. task-4893615 Forward-Port-Of: odoo/odoo#272648 Forward-Port-Of: odoo/odoo#226362
This update resolves an issue where users with access restricted to a 'branch' company were unable to properly validate manufacturing orders (MOs) involving components linked to a different 'company1' company. The fix ensures the system correctly handles valuation calculations for components associated with different company IDs, preventing access errors.
Original PR description
### Steps to reproduce: - Have a company with a branch say "company1" and "branch" - Create two products: Final product (FP), Component (Comp) - Set the company_id of FP to "branch" and of Comp to…
### Steps to reproduce: - Have a company with a branch say "company1" and "branch" - Create two products: Final product (FP), Component (Comp) - Set the company_id of FP to "branch" and of Comp to "company1" - Associate both products with a product category set to avco in company1 (the field is company dependant) - Create a bom for FP with company_id set to "branch": 1 X Comp - Impersonate a user whose only allowed and default is "branch" - Create and confirm an MO for 1 unit of FP - Set the qty_producing to 1 unit and validate #### > Access Error: Access to unauthorized or invalid companies. ### Cause of the issue: Validating the MO will, validate the component move and set its value: https://github.com/odoo/odoo/blob/f4d079cc5a9c47672cf1a6747bb073e8e74f7350/addons/stock_account/models/stock_move.py#L168-L173 But, in order to determine this value, it is necessary to determine its `property_cost_method`: https://github.com/odoo/odoo/blob/f4d079cc5a9c47672cf1a6747bb073e8e74f7350/addons/stock_account/models/product.py#L60-L69 Now, the issue is that the `product_template` of the component belongs to "company1" so that the user is unauthorized to read the valuation method of the product category for "company1". opw-6216141 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274108 Forward-Port-Of: odoo/odoo#272429
This update resolves an issue preventing users from changing a product's Bill of Materials (BOM) type when sales orders are already linked across multiple companies. The fix ensures data integrity by adjusting a check that previously didn't consider the company associated with the BOM. This change improves flexibility in managing sales orders within a multi-company Odoo setup.
Original PR description
### Steps to reproduce: - Have two companies: company1 and company2 - Create a producct P available in both company1 and company2 - with company1, create a kit bom for a product P - with company2,…
### Steps to reproduce: - Have two companies: company1 and company2 - Create a producct P available in both company1 and company2 - with company1, create a kit bom for a product P - with company2, create and confirm a sale order for 1 unit of P - with company1, change the bom type of P from kit to manufature #### > UserError: As long as there are some sale order lines that must be delivered/invoiced and are related to these bills of materials, you can not remove them. ### Cause of the issue: Changing the bom type from a kit (phantom type) to a non kit will launch a call of the `_ensure_bom_is_free` in order to ensure data integrity if the kit bom was used by a relevant sale order line: https://github.com/odoo/odoo/blob/f4c76be062bec47b68ee42505d7d42fed31ac0f2/addons/sale_mrp/models/mrp_bom.py#L15-L18 https://github.com/odoo/odoo/blob/f4c76be062bec47b68ee42505d7d42fed31ac0f2/addons/sale_mrp/models/mrp_bom.py#L24-L42 However, this check does not take the company of the bom into account and in the present flow, the company of the bom is different from the company of the supposedly problematic sol. opw-6290304 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273839 Forward-Port-Of: odoo/odoo#271119
This update addresses latency issues experienced when using the Point of Sale (POS) and self-ordering systems on iOS devices. The team optimized the user interface by adding styling to elements, resulting in a smoother and more responsive experience for customers.
Original PR description
There was some issues when touching elements in the POS and self. We added the parameter role="button" to the elements that were not already and a pe-none to the images. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260699 Forward-Port-Of: odoo/odoo#253583
This update fixes an issue where manufacturing orders were incorrectly created when a product lacked a Bill of Materials. The change skips MO creation when a BoM isn't found, ensuring that replenishment rules are triggered instead. This prevents unnecessary manufacturing steps and improves order processing efficiency.
Original PR description
Steps to reproduce: - unarchive the MTO route - Create a storable product "P1" with the MTO + Manufacture routes but set no Bill of Materials on it - Create a sales order with one unit of P1 and confirm it Problem: An empty draft MO is created even though no Bill of Materials exists. When no BoM is available, manufacturing orders should not be created, only replenishment rules are expected to handle this case. Fix: Added an early `continue` in `_run_manufacture` to skip MO creation when no BoM is found. opw-6174886 Forward-Port-Of: odoo/odoo#272064 Forward-Port-Of: odoo/odoo#263108
This update resolves an issue where local development URLs (like `http://localhost:8069`) were sometimes incorrectly ignored by the system. By removing the requirement for a Top-Level Domain, this change ensures that local development environments can reliably connect to the email system. This improves the development experience for Odoo users.
Original PR description
Before this commit, url like `http://localhost:8069` were ignored by the `urlRegexp` because it requires a Top-Level Domain. This commit makes the Top-Level Domain optional. Forward-Port-Of: odoo/odoo#274379
This update fixes an issue where the standard price of a product wasn't correctly calculated during subcontracting dropshipping. The change ensures that the product's value is accurately updated when a bill is posted, resolving discrepancies in pricing and accounting. This ensures accurate financial reporting for dropshipping subcontracting orders.
Original PR description
*: mrp_subcontracting_{dropshipping, purchase} ### Steps to reproduce: - In the settings: Enable subcontracting, dropshipping - Create a storable dropshipped product FP with a set vendor for 5$ and…
*: mrp_subcontracting_{dropshipping, purchase}
### Steps to reproduce:
- In the settings: Enable subcontracting, dropshipping
- Create a storable dropshipped product FP with a set vendor for 5$ and subcontracting BOM: 1 X COMP. Value this product in avco perpetual
- Set the component to resupply subcontractor and standard price to 2$
- Create and confirm a sale order for 1 unit fo FP
- Validate the resupply to the subcontractor and then the dropship
> The FP standard price shoul dhave been updated to 5$ + 2$ = 7$
- Create and post a bill from the PO for 10$ rather than 5
#### > The FP standard price should have been updated to 11$ rather than 12$
Cause of the issue:
Posting the bill will call the `_set_value` method to re-evaluate the product in terms of the newly recorded `account.move`: https://github.com/odoo/odoo/blob/161715c850496d3683baa5d1600380470d0b5ff5/addons/stock_account/models/stock_move.py#L393-L395 Now, the issue is that due to our config, there are two relevant moves linked to the `order_line`: the final move of the subcontracted production (which `is_in`) and the dropship move going from the subcontractor to the customer. When it comes to the subcontracted move, it is appropriately valuated at 12$ by the `_get_value_from_account_move` because of this override which adds the components value via the extra cost since the move has a `production_id`:
https://github.com/odoo/odoo/blob/161715c850496d3683baa5d1600380470d0b5ff5/addons/mrp_subcontracting_purchase/models/stock_move.py#L14-L38 However, the dropship move will not add this extra cost (as no override sets it to have the same value as the subcontracted production it comes from) so that this move is valuated at 10$. This explains why the value of the avco product is then updated to 11$ since (12 + 10) /2 = 11
Note that the issue is not reproducible in the case of regular subcontracting since in that case the receipt from `subcontractor` to `stock` is not valuated.
opw-6318035
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273137
Forward-Port-Of: odoo/odoo#272813This update fixes a recurring issue with the Odoo system's cache, specifically related to employee contract dates. By automatically updating a version number with the last write date, the system now ensures the cache is refreshed whenever an employee record is changed, preventing data inconsistencies. This improves the reliability of employee information displayed within Odoo.
Original PR description
There was yet another issue with the cache but related to the contract_date_start field. To prevent any issues like this to arise again, the version_revision will have the write_date to invalidate cache everytime the model has been written to. task-6326052 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#273932 Forward-Port-Of: odoo/odoo#272855
This update resolves an issue where the 'Remaining Extra Hours' value in the employee attendance summary was incorrectly displayed as 00:00. The fix adjusts the calculation to allow for negative values, aligning with the other extra hours metrics and ensuring accurate time-off tracking. This ensures the 'Time Off Taken from Extra Hours' value is correctly calculated.
Original PR description
## Issue In the attendance view of an employee, a recap of the current extra hours is displayed, showing four values: 1. Total Extra Hours Worked 2. Total Compensable Extra Hours 3. Time Off Taken…
## Issue
In the attendance view of an employee, a recap of the current extra hours is displayed, showing four values:
1. Total Extra Hours Worked
2. Total Compensable Extra Hours
3. Time Off Taken from Extra Hours
4. Remaining Extra Hours
Each of the above values can be negative but the last one, which can seem odd as it appears to be calculated from the other values.
<img width="299" height="168" alt="6293174-before" src="https://github.com/user-attachments/assets/4377e2fd-f5f2-41a4-a82b-6f2598378499" />
## Steps to reproduce
1. Install *HR Attendance Holidays* (`hr_holidays_attendance`)
2. In Settings, toggle *Absence Management* and *Display Extra Hours*
3. For an employee E:
- In the Payroll tab, set the Working Hours to the *Standard 40 hours/week* schedule
- In the Settings tab, set the Overtime Ruleset to the *Default Ruleset*, and toggle the *Give back as time off* action for the *Employee Schedule Rule* rule
4. Create an attendance for employee E:
- Any day where they are expected to work 8 hours
- From 10am to 5pm (6 hours with lunch)
5. In the Employees app, go to employee E and click the *Monthly Hours* smart button
6. __In the *Balance* recap above the list of attendances, the *Remaining Extra Hours* row shows 00:00, which seems wrong compared to the other fields above (*Total Extra Hours Worked* and *Total Compensable Extra Hours*) which appear negative.__
## Cause
The `unspent_overtime` (*Remaining Extra Hours* in the balance recap) is computed by adding positive values, making it strictly positive.
https://github.com/odoo/odoo/blob/30c9e8c5b1e34b94c8aab8681e2c051a3b70f013/addons/hr_holidays_attendance/models/hr_employee.py#L62-L65
This was added by https://github.com/odoo/odoo/commit/2144bcfba1ac53c82fc7f2870a72bb13abee97e4, with no justification on why this value needs to be positive.
## Impact on "Time Off taken from Extra Hours"
Before this change, after following the above steps, a value of `-2:00` would be displayed in the *Time Off Taken from Extra Hours* row. This is no longer the case after this fix, since the `'unspent_compensable_overtime'` (*Remaining Extra Hours*) value is used to compute that row:
https://github.com/odoo/odoo/blob/f7fb0a941d6bac39b7057db36f57be079559912c/addons/hr_holidays_attendance/static/src/views/extra_hours_list_view.js#L39-L42
Instead, a value of `00:00` is shown. Before, we were substracting 0 hour of `unspent_compensable_overtime` to the -2 hours of `compensable_overtime`, now we are subectracting -2 hours of `unspent_compensable_overtime` to the same -2 hours of `compensable_overtime`. This is a side effect that was ignored, as it seems to make at least as much sense as showing `-2:00`.
<img width="321" height="179" alt="6293174-after" src="https://github.com/user-attachments/assets/907d5fb8-0c36-4b2e-bca7-1cec41baf22b" />
opw-6293174
Forward-Port-Of: odoo/odoo#274172
Forward-Port-Of: odoo/odoo#271272This update fixes an issue where purchase order receipt deadlines weren't updating correctly after quantities were set to zero. The fix ensures that cancelled stock moves no longer incorrectly influence the calculated deadline, resulting in more accurate and reliable receipt timelines. This improves the accuracy of delivery scheduling.
Original PR description
Steps to reproduce the bug:
- Create a Purchase Order with 2 products and confirm it
- Note the receipt's deadline (= date_planned of both lines)
- Set the quantity of one PO line to 0
- Update the scheduled date (date_planned) of the purchase order
Problem:
the receipt deadline does not update.
The receipt kept the old deadline from the cancelled move. When a PO line qty is set to 0, `_merge_moves` cancels the corresponding stock move via `_action_cancel`. Then `_update_move_date_deadline` correctly skips cancelled moves (filtered by `state not in ('done', 'cancel')`), so the cancelled move retains its original `date_deadline`. However, `_compute_date_deadline` on `stock.picking` used
`move_ids.filtered('date_deadline')`, which not checks move state, so the stale deadline of the cancelled move was included in the min/max computation.
opw-6292600
Forward-Port-Of: odoo/odoo#271890
Forward-Port-Of: odoo/odoo#270985This update optimizes how Odoo forms respond to changes. Previously, opening a form triggered onchange methods multiple times for each field that changed, leading to slower performance. This fix reduces redundant calls within a single change event, resulting in a smoother and faster user experience.
Original PR description
When an onchange method depends on several fields that all change at once (for example two fields that both have a default value), opening the form triggers that method once per field, even though a single call would suffice. This adds a per-pass set of already-applied onchange methods so that, within the same batch of changed fields, each method is invoked only once. Note this does not guarantee a method is called exactly once overall: it may still run again in later onchange passes; we only remove the redundant calls within a single pass. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273843 Forward-Port-Of: odoo/odoo#251813
This update fixes a minor typo in the Odoo email system's code that affected how the interface displays on different screen sizes. This ensures a consistent and professional user experience across all devices, improving usability for our customers. The change was made to maintain code quality and prevent potential display issues.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274630 Forward-Port-Of: odoo/odoo#274343